Corporate Tenant Registry¶
ENTERPRISE Feature
The Corporate Tenant Registry requires an ENTERPRISE license. It is not available on STARTER or PRO tiers.
Manage multiple Azure AD (Entra ID) tenants that belong to the same organisation. CertifyClouds discovers, monitors, and rotates credentials across all of them from a single deployment.
Overview¶
A typical enterprise spans more than one Entra ID tenant: a primary ("home") tenant for day-to-day operations and additional tenants for subsidiaries, acquired companies, geographic regions, or environment boundaries (dev / staging / production). The Corporate Tenant Registry lets you onboard those additional tenants so CertifyClouds can:
- Discover and monitor Key Vault secrets, certificates, and keys across every onboarded tenant
- Rotate App Registration credentials in any onboarded tenant
- Surface all assets in the unified inventory with a per-tenant badge
- Alert on expiring credentials regardless of which tenant they live in
Corporate Tenants vs B2C Registry¶
| Aspect | Corporate Tenant Registry | B2C Registry |
|---|---|---|
| Tenant type | Full Entra ID / Azure AD tenants with Azure subscriptions and Key Vaults | Azure AD B2C tenants (identity-only, no Key Vaults) |
| What is discovered | Key Vault secrets, certificates, keys, and App Registration credentials | App Registration secrets and certificates |
| Rotation | Key Vault secrets / certificates / keys + App Reg credentials | App Reg credentials only |
| License | ENTERPRISE | PRO or ENTERPRISE |
One organisation, multiple tenants
The Corporate Tenant Registry is for a single organisation that spans multiple Entra ID tenants. It is not a multi-customer isolation model. CertifyClouds runs as one deployment; the registry extends its reach across your organisation's tenant boundary.
Concepts¶
Home tenant¶
The tenant in which CertifyClouds itself is deployed. Its Managed Identity (or Service Principal) is the deployment credential. The home tenant is added to the registry automatically at first start; you cannot delete it. Discovery, rotation, and sync for home-tenant assets use the deployment credential as before.
Onboarded tenant¶
Any additional Entra ID tenant you register in the Corporate Tenant Registry. Each onboarded tenant gets its own dedicated Service Principal (provisioned by the onboarding script) whose client secret is stored encrypted at rest. Credential operations on onboarded-tenant assets always use that tenant's own credential - they never reuse the home deployment credential.
Credential routing¶
Every Azure write operation resolves its credential at the point of execution:
- Home assets use the deployment credential.
- Onboarded-tenant assets use the per-tenant
ClientSecretCredential, wrapped in a bounded wrapper that enforces a wall-clock timeout per token acquisition. Credentials are cached with tenant-scoped keys so SP rotation invalidates the cache automatically.
Before any write is executed, the platform verifies that the credential's actual token tid matches the intended tenant. A mismatch is a hard refusal - the write is never sent.
Prerequisites¶
- ENTERPRISE license (the
multi_tenantfeature entitlement) - Azure CLI (
az) installed on the machine running the onboarding script jqinstalled (brew install jqon macOS,apt install jqon Debian/Ubuntu)- Admin access in the target (onboarded) Entra tenant to create an App Registration and grant admin consent for Microsoft Graph permissions
Step 1: Provision the Service Principal (onboarding script)¶
Run onboard-corporate-tenant.sh (included in your CertifyClouds delivery package; contact support@certifyclouds.com if your package predates it) in the target tenant to create the App Registration, Service Principal, client secret, and role assignments CertifyClouds needs.
Sign in to the target tenant¶
The Azure CLI creates App Registrations in the tenant of the current session. You must sign in to the target tenant before running the script:
The script validates that your current session matches --tenant and refuses to run if they differ, preventing accidental provisioning in the wrong directory.
Preview first (no changes)¶
By default the script is a dry run - it prints every az command it would execute without making any changes:
Review the output, then add --apply to actually provision:
Flags¶
| Flag | Purpose |
|---|---|
--tenant <guid> | (Required) Target Entra tenant GUID |
--apply | Execute the changes. Without this the script only previews |
--with-rotation | Also grant write permissions for credential rotation (see below) |
--with-resource-updates | Also grant Contributor on consuming resources for full-stack rotation (opt-in, broad) |
--subscription <guid> | Scope role grants to one subscription. Repeatable. Omit to grant across all subscriptions in the target tenant |
--display-name <name> | App Registration display name. Default: CertifyClouds Corporate Tenant Workload (Production) |
Grants by mode¶
| Grant | Scope | Purpose |
|---|---|---|
| Reader | Subscription | Enumerate subscriptions, vaults, resources |
| Key Vault Reader | Subscription | Read vault and secret/certificate/key metadata |
Microsoft Graph Application.Read.All | Tenant-wide | Read App Registrations and Service Principals |
All discovery grants, plus:
| Grant | Scope | Purpose |
|---|---|---|
| Key Vault Secrets Officer | Subscription | Create/update secret versions |
| Key Vault Certificates Officer | Subscription | Create/update certificate versions |
| Key Vault Crypto Officer | Subscription | Rotate keys, KV-to-KV replication |
Microsoft Graph Application.ReadWrite.All | Tenant-wide | Rotate App Registration credentials |
All rotation grants, plus:
| Grant | Scope | Purpose |
|---|---|---|
| Website Contributor | Subscription | Update App Service configuration after rotation |
| SQL Server Contributor | Subscription | Update SQL Server connection strings after rotation |
| Container Apps Contributor | Subscription | Update Container Apps secrets after rotation |
| Logic App Contributor | Subscription | Update Logic App connections after rotation |
Subscription-scoped write access
The write roles above are granted at subscription scope, meaning they cover every resource of that type in the subscription. If your security policy requires least-privilege, re-create the role assignments at resource-group or vault scope after provisioning and remove the subscription-scoped ones.
Admin consent for Microsoft Graph permissions¶
Application.Read.All (and Application.ReadWrite.All when --with-rotation is used) are application permissions that require tenant-wide admin consent from a Global Administrator. The script attempts to grant consent automatically. If your account lacks that role, it prints the portal steps to hand to an admin:
- Azure Portal > Microsoft Entra ID > App registrations
- Open the app (e.g.
CertifyClouds Corporate Tenant Workload (Production)) - Go to API permissions
- Click Grant admin consent for [Tenant Name] and confirm
Key Vault and subscription discovery work without consent. App Registration discovery in the onboarded tenant requires consent before it returns results.
Script output¶
On a successful --apply run, the script prints the values to paste into the CertifyClouds UI:
Tenant ID (GUID): xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Tenant domain: yourcompany.onmicrosoft.com
App (client) ID: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
Client secret: <secret value>
Secret expires: <date>
Copy the client secret now
The client secret value is shown once and cannot be retrieved again. Copy it immediately into the CertifyClouds form, or store it in a vault.
Key Vault firewalls on onboarded tenants¶
CertifyClouds can enumerate a Key Vault resource with Azure RBAC while still receiving data-plane 403 (ForbiddenByFirewall) responses when it tries to list secrets, certificates, or keys. If the vault firewall is off (properties.networkAcls.defaultAction is Allow, or the vault has no network ACLs), there is nothing to configure. If it is Deny, grant the CertifyClouds deployment a network path using one of the three options below. All three keep the vault firewalled to everyone else.
Which option to choose:
| Your situation | Use |
|---|---|
Deployment subnet has the Microsoft.KeyVault service endpoint (the usual case — it does whenever your home-tenant vaults use subnet rules) | Option 1 — virtual-network rule (recommended, simplest) |
| Deployment subnet has no service endpoint, and you can route outbound through a stable public IP | Option 2 — NAT gateway + IP allowlist |
| You need a fully-private path (no public Key Vault endpoint at all), or neither of the above fits | Option 3 — Private Endpoint |
Option 1 (recommended): cross-tenant virtual-network rule
A Deny vault admits CertifyClouds when its networkAcls.virtualNetworkRules lists the subnet the CertifyClouds deployment runs on. The subnet lives in your home (deployment) tenant; the vault lives in the onboarded tenant. Because the Corporate Tenant Registry is one organisation spanning several Entra tenants (not separate companies), an administrator with rights in both tenants adds the rule directly — Key Vault virtual-network rules do work across the Entra tenants of one organisation.
The Azure portal can't add this rule: its "Add a virtual network" picker only lists subnets in the vault's own subscription, so a cross-tenant deployment subnet cannot be selected there. Add it with the CLI below (or the onboarding script), using the subnet's full resource ID.
Prerequisite: the deployment subnet has the Microsoft.KeyVault service endpoint enabled (already true whenever your home-tenant vaults use subnet rules).
az keyvault network-rule add \
--name <onboarded-vault> \
--subscription <onboarded-subscription> \
--subnet "/subscriptions/<home-sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<deployment-subnet>"
The onboarding script automates this: ./onboard-corporate-tenant.sh --tenant <GUID> --subnet <deployment-subnet-id> --apply.
Keep defaultAction=Deny — the rule grants access only to the CertifyClouds subnet, so the vault stays firewalled to everyone else while CertifyClouds reads its secrets, certificates, and keys using the onboarded tenant's Service Principal.
Option 2: NAT gateway + public IP allowlist
Key Vault IP rules only match a public source IP. That works only when the deployment subnet does not have the Microsoft.KeyVault service endpoint — otherwise traffic reaches the vault over the Azure backbone with no public source IP (the audit log shows CallerIPAddress 0.0.0.0) and an IP rule can never match.
To use IP allowlisting deliberately: attach a NAT gateway with a static public IP to the deployment subnet (and do not enable the Key Vault service endpoint on that subnet), so all outbound traffic egresses via that one stable IP. Then allowlist it:
# find the deployment's stable egress IP (NAT gateway public IP; Container Apps: outboundIpAddresses)
az containerapp show --name <app> --resource-group <rg> --query properties.outboundIpAddresses
az keyvault network-rule add --name <onboarded-vault> --subscription <onboarded-subscription> --ip-address <egress-ip>/32
The onboarding script automates the IP-rule add: ./onboard-corporate-tenant.sh --tenant <GUID> --ip-address <egress-ip>/32 --apply. Note: Azure Container Apps NAT-gateway/custom egress requires a workload-profile environment; a consumption-only environment has a large rotating egress pool that cannot be allowlisted, so use Option 1 or 3 there.
Option 3: cross-tenant Private Endpoint (fully private)
Gives the onboarded vault a private IP inside your deployment VNet, so the vault can disable public network access entirely and CertifyClouds still discovers and reads its contents over the private endpoint.
- Create a Private Endpoint in the CertifyClouds deployment VNet (a dedicated subnet with private-endpoint network policies disabled), targeting the onboarded-tenant vault, in manual-request mode.
- A Key Vault admin in the onboarded tenant approves the pending private-endpoint connection.
- Add a
privatelink.vaultcore.azure.netprivate DNS zone linked to the deployment VNet, with an A record for the vault name pointing at the Private Endpoint's private IP, so the deployment resolves the vault privately. - Optionally set the vault's
publicNetworkAccesstoDisabledonce the Private Endpoint is confirmed working.
This is a multi-party manual flow (two tenants, DNS), so it is not automated by the onboarding script — follow the steps above per vault.
Symptom of a missing network path
Vaults appear in discovery, but the items inside them show zero results, or discovery logs show Key Vault data-plane 403 (ForbiddenByFirewall) responses.
Step 2: Register the tenant in CertifyClouds¶
- Go to Settings > Corporate Tenants
- Click Add Tenant
-
Enter the values from the script output:
Field Value Tenant ID Target tenant GUID Tenant Domain e.g. yourcompany.onmicrosoft.comDisplay Name A friendly name for the tenant Client ID App Registration (client) ID Client Secret Secret from the onboarding script -
Click Test Connection to verify. A successful test confirms CertifyClouds can authenticate to the tenant.
- Click Register Tenant to save.
Step 3: Run discovery¶
After registering a tenant, trigger an initial discovery scan:
- All tenants at once: go to Assets > Discovery and click Start Scan. The scan runs across the home tenant and all active onboarded tenants sequentially.
- Via the API:
POST /api/assets/discovery/scanwith{ "corporateTenantId": <id> }to scan a single onboarded tenant.
Discovered assets are tagged with their owning tenant. The unified inventory shows all assets together; filter by tenant using the tenant switcher in the header or the corporateTenantId filter on the Assets page.
Per-tenant discovery¶
The platform discovers each onboarded tenant using that tenant's own Service Principal credential. The home subscription allow-list does not apply to onboarded-tenant scans - each onboarded tenant is scanned across all subscriptions visible to its Service Principal.
Assets inherit their tenant from their subscription: after a scan, each asset's corporate_tenant_id is set to match the subscription it lives in. This tag propagation is idempotent and only updates rows whose tag is stale.
Per-tenant rotation¶
Rotation for onboarded-tenant assets follows the same flow as home-tenant rotation (confirm dialog, real-time progress stream, grace window, history entry with a tenant badge), with the routing layer ensuring the correct credential is used:
- The rotation engine resolves which tenant owns the operation's legs (vault, subscription, App Registration). If any leg belongs to an onboarded tenant, the routing resolves to that tenant's credential.
- Before each Azure write, the token
tidis verified to match the intended tenant. A mismatch is a hard refusal. - The rotation record is stamped with the resolved
corporate_tenant_idso the history table reflects which tenant was written.
Cross-tenant operations (where rotation legs span more than one tenant) are refused. Each rotation job is single-tenant.
Tenant isolation model¶
| Layer | Isolation mechanism |
|---|---|
| Credential storage | Per-tenant SP client secret stored encrypted at rest. The home tenant has no stored secret; it uses the deployment credential. |
| Credential routing | Every Azure write resolves its credential from the tenant tag on the target resource. The home credential is never used for onboarded-tenant writes. |
| Token verification | Before each write, the platform decodes the acquired token's tid claim and refuses if it does not match the intended tenant. |
| Discovery isolation | Each onboarded tenant is scanned with its own credential. The vanished-asset reconcile is scoped to (subscription, vault), so a scan for one tenant never disables assets belonging to another. |
| Scope | Within-organisation isolation: prevents wrong-tenant writes. Not a network isolation or data-residency boundary. |
Service Principal expiry¶
The onboarded tenant's Service Principal secret has a 2-year validity by default. The tenant card in Settings > Corporate Tenants shows the expiry date alongside a status badge so you can see at a glance when renewal is due.
CertifyClouds does not currently monitor this expiry or rotate it automatically. Set a calendar reminder before the expiry date. If the secret expires, discovery and rotation for that tenant will fail until it is renewed by re-running the onboarding script with --apply and updating the client secret in the tenant registration form in the UI.
Troubleshooting¶
| Symptom | Likely cause | Resolution |
|---|---|---|
| "Connection failed" on test | Wrong Client ID or secret | Re-run the onboarding script with --apply to mint a fresh secret |
| No App Registrations discovered | Admin consent not granted | Grant consent in the Azure portal (API permissions page) |
| Assets not appearing for onboarded tenant | Discovery not run after registration | Run a scan from Assets > Discovery |
| Rotation refused for onboarded-tenant asset | --with-rotation grants not provisioned | Re-run the onboarding script with --with-rotation --apply |
| "Multi-tenant rotation is disabled" | Operational kill-switch off | Enable the ENABLE_MULTI_TENANT_ROTATION flag under Settings > Advanced > App Behaviour |
| "Tenant not on allowlist" | Tenant allowlist configured | Add the tenant GUID to the MULTI_TENANT_ALLOWLIST environment variable on the deployment (a JSON array of tenant GUIDs, e.g. ["<guid>"]). Unset or empty means all onboarded tenants are allowed — this only appears if your deployment set the variable. |
Security best practices¶
- Least privilege: use
--with-rotationonly if you need CertifyClouds to rotate credentials in that tenant. Discovery-only onboarding does not require write grants. - Rotation write grants are subscription-scoped: after onboarding, narrow them to a resource group or vault if your security policy requires least-privilege.
- Monitor SP expiry: the onboarded tenant's SP secret expires in 2 years. The expiry date is shown on the tenant card. Set a calendar reminder and renew by re-running the onboarding script with
--apply, then updating the client secret in the tenant registration form. - Review access: periodically review the CertifyClouds App Registration in each onboarded tenant's Azure portal to confirm permissions remain as expected.
Related¶
- B2C Registry - monitor App Registration credentials in Azure AD B2C tenants
- Secret Rotation - rotation mechanics for Key Vault secrets and App Registrations
- Asset Discovery - how CertifyClouds scans your Azure estate