Skip to content

BYOSA setup

This guide walks you through configuring AppGantry to store your build artifacts in your own Azure Blob Storage account instead of ours. The platform owns the metadata and audit trail; you own the bytes.

For an overview, see the BYOSA concepts page. BYOSA is most useful when you hit one of: heavy distribution (typically $100+/mo in download metering), a compliance requirement, or a data-residency constraint.

Prerequisites

You need:

  • An Azure tenant where you (or a tenant admin you can reach) can admin-consent applications.
  • An Azure subscription with billing enabled.
  • The Admin role on your AppGantry organization. If you signed up and created the org, you already have it.
  • Your AppGantry login (BYOSA management is gated on a short-lived JWT, not a PAT).

You don't need:

  • To share a storage account key with us.
  • To share a SAS token with us.
  • To configure a service principal client secret or certificate.
  • To rotate anything on a schedule.

Our auth model is secret-less: see Step 1 for how that works.

Overview

The flow has two phases:

  1. Azure side (self-service): admin-consent our app, create a storage account + container, grant our app the right role.
  2. AppGantry side (operator-mediated): send us your three identifiers; an operator validates and flips your org to BYOSA.

The flip is operator-mediated by design.

Phase 1: Azure side

This creates an enterprise-app service principal in your tenant. It carries no credentials. It exists so you can assign it a role on your storage container.

Have a tenant admin visit (replace {your_tenant_id} with your Azure AD tenant ID):

https://login.microsoftonline.com/{your_tenant_id}/adminconsent?client_id=63c04479-2f32-4a1d-909c-b546d98bc4c8

About that client ID

63c04479-2f32-4a1d-909c-b546d98bc4c8 is the application (client) ID of our multi-tenant app, AppGantry BYOSA Access. It is a public identifier, not a secret. Confirm it matches our published trust anchors page before consenting.

The admin reviews the permission request and clicks Accept. After this, an enterprise app named AppGantry BYOSA Access appears under Azure Portal → Enterprise applications. Note the object ID of this enterprise app; you'll grant a role to it in Step 3.

Tip

If your tenant has a Conditional Access policy that blocks consent, work with your AAD admins to allow it for this single client ID. Admin consent is a one-time event; the policy doesn't need to permit interactive sign-in for this app.

Step 2: create a storage account and container

Standard Azure procedure. Choose:

  • Region: close to where your developers and testers live.
  • Redundancy: LRS is fine for most cases; pick GRS if you need cross-region durability.
  • Performance tier: Standard (Hot access tier).

Then create a container inside the account:

  • Name: must satisfy Azure rules: 3-63 chars, lowercase alphanumeric and hyphens, must start with a letter or digit, no consecutive hyphens, not a reserved name ($logs etc.). We recommend appgantry-builds so support recognises it at a glance, but you choose.
  • Public access level: Private (no anonymous access). AppGantry mints time-limited signed URLs for every download.
  • Reserve the container for AppGantry. We write files under our own path scheme ({project_id}/{build_id}.bin) and assume nothing else writes to it.

Step 3: grant our app the right role

In the storage account's IAM blade:

  1. Navigate to your container (not the account root, ideally).
  2. Access Control (IAM) → Add → Add role assignment.
  3. Role: Storage Blob Data Contributor.
  4. Assign to: User, group, or service principal.
  5. Search for AppGantry BYOSA Access (the enterprise app from Step 1). Select it.
  6. Save.

Container scope, not account scope

Account scope works (and we'll validate against it), but it grants our app data-plane access to every container in the account. Container scope keeps the blast radius tight.

Reader is not enough

Storage Blob Data Reader lets us retrieve blobs but not upload them; setup validation will fail at the marker-write step with a clear error message.

AAD role propagation takes about 5 minutes. If you retry setup immediately after granting the role you may see a token-exchange or 403 error. Wait and retry.

Phase 2: AppGantry side

Step 4: gather your three identifiers

You'll send these to support:

Where to find it
Tenant ID Azure Portal → Microsoft Entra ID → Overview → Tenant ID
Account URL e.g. https://acmebuilds.blob.core.windows.net
Container name The container you created in Step 2

Step 5: request the flip

Send your three identifiers to support (or your AppGantry operator contact). An operator runs setup, which executes a five-stage validation pipeline against your Azure setup before committing anything in our database:

  1. Token exchange: verifies admin consent landed and the federated trust is reachable.
  2. Container existence: verifies the container exists. We will not auto-create containers in your tenant.
  3. Marker write: uploads a small marker blob to verify write permission.
  4. Marker delete: removes the marker to verify delete permission.
  5. Residue check: confirms the marker is actually gone (catches soft-delete retention swallowing the purge).

If anything fails, setup returns a structured remediation report:

{
  "success": false,
  "failure_stage": "put_marker",
  "responsibility": "customer",
  "summary": "Couldn't write a marker blob to 'appgantry-builds'. The most common cause is that the role grant is Storage Blob Data Reader instead of Storage Blob Data Contributor...",
  "remediation": [
    "Confirm the role assignment is Storage Blob Data Contributor...",
    "Verify the role binding is scoped to the container...",
    "Wait ~5 minutes for AAD propagation..."
  ],
  "docs_url": "https://docs.appgantry.com/guides/byosa-setup/",
  "failure_detail": "<raw Azure SDK error text for reference>"
}
  • responsibility: "customer": something on your Azure side needs fixing. The remediation list is concrete steps.
  • responsibility: "platform": something on our side failed. Contact support; include failure_detail and failure_stage.

Failed setup attempts do not write to our database and do not pollute your audit log; there's no cost to iterating.

A successful setup flips your org to byosa. From this point, every build upload lands in your container, and every download streams through a time-limited SAS URL we mint against your storage account.

After setup

Verify

Confirm the current config any time:

GET /api/v1/organizations/{organization_id}/byosa

Run a diagnostic to re-validate end-to-end (e.g. after an Azure outage):

POST /api/v1/organizations/{organization_id}/byosa/diagnose

The diagnostic returns the same structured report shape as setup, with success: true when everything works.

Rotating to a different container or account

Send support the new identifiers. If you change the container_name or account_url and your organization already has builds, those builds' download URLs will 404 after the rotation, because their storage paths point at the previous container. The operator will confirm you accept this before running it. If you want to keep existing build downloads working through the rotation, the blob data has to be copied between accounts; support coordinates that manual flow.

Tenant ID rotation alone (same account, same container) does not move any bytes.

Teardown

To move back to hosted storage, contact support. Teardown is blocked by default if your organization has live builds, because their download URLs would 404 after the flip back to hosted, so you'll either delete the affected builds first or explicitly accept the breakage.

After teardown you'll get a customer-side cleanup checklist for the dangling enterprise-app SP in your tenant:

  1. Azure portal → Enterprise applications → search for AppGantry BYOSA Access.
  2. Properties → Delete.
  3. Optionally remove the role assignment on your container.

We cannot remove the enterprise app from your tenant for you; we don't have Microsoft Graph permissions in your tenant.

See also