Identity & Security
Azure identity in this repo spans three distinct concepts that are easy to confuse. This page is the cross-repository reference for the dashboard and orchestration identity model.
The three identity concepts
Section titled “The three identity concepts”| Concept | Type | Auth | Used in |
|---|---|---|---|
App Registration Service Principal (visory-dashboard) |
Azure AD App + SP, client-secret based | Not used by the dashboard runtime | CI or other explicitly supported automation |
| Container App User-Assigned Managed Identity (UAMI) | Managed identity, passwordless | ManagedIdentityCredential with AZURE_CLIENT_ID |
Production Container Apps |
| Developer Azure CLI identity | Developer’s signed-in Azure identity | AzureCliCredential |
Local Docker development |
| Container App resource | Azure resource, not an identity | N/A | Hosts the app; can have a UAMI assigned to it |
The recommended model is UAMI in production and the developer’s Azure CLI identity locally. The dashboard selects the credential explicitly: AZURE_CLIENT_ID selects the UAMI, and its absence selects AzureCliCredential.
Single-identity dashboard architecture
Section titled “Single-identity dashboard architecture”The dashboard (apps/mx_fuels_reporting_app/apps/web/) follows one application = one identity = one vault:
Next.js Dashboard Identity: UAMI in production, developer Azure CLI identity locally Vaults: web-kv reads; cne-kv credential writes only Env vars: AZURE_CLIENT_ID in production; none locally │ ├─→ Key Vault (web-kv) ├─→ Databricks SQL Warehouse (RBAC: CAN_USE) ├─→ PostgreSQL Flexible Server (Azure AD auth) ├─→ Azure Storage Blob (RBAC: Contributor) ├─→ Azure Service Bus (RBAC: Data Sender) └─→ Microsoft Graph (VDR / SharePoint)This replaced an earlier dual-identity model where the dashboard and orchestration could potentially cross-load vaults. The security boundary is now explicit:
| System | Vault | Identity | Purpose |
|---|---|---|---|
| Orchestration/Pipelines | visory-dev-scus-ds-kv |
Analytics SP | Airflow DAGs, ETL |
| Dashboard | visory-dev-scus-web-kv + visory-dev-scus-cne-kv |
UAMI or Azure CLI identity | Application reads and regulator credential writes |
Never cross-load — each system accesses exactly one vault.
Environment variable mapping
Section titled “Environment variable mapping”External config exports the vault URLs for local development. The production Container App deployment
workflow sets both URLs as runtime environment variables and sets AZURE_CLIENT_ID for the attached
UAMI. Local compose.js.yaml deliberately does not pass a client ID, so the dashboard uses the
mounted Azure CLI session:
environment: - WEB_KEY_VAULT_URL=${WEB_KEY_VAULT_URL} - CNE_CREDENTIALS_KEY_VAULT_URL=${CNE_CREDENTIALS_KEY_VAULT_URL} - AZURE_USERNAME=${AZURE_USERNAME}Atomic credential resolution
Section titled “Atomic credential resolution”apps/web/src/lib/keyVault.ts selects one credential mode for the process. It uses ManagedIdentityCredential when AZURE_CLIENT_ID is present and AzureCliCredential otherwise. The dashboard never mixes fields from two identity configurations.
Local Docker vs. production
Section titled “Local Docker vs. production”- Local/Docker:
.envrcexports vault URLs, and the mounted Azure CLI session authenticates the developer. - Production: the deployment workflow sets both vault URLs and
AZURE_CLIENT_IDon the Container App. Missing Key Vault URLs fail explicitly.
RBAC reference
Section titled “RBAC reference”Grants needed for the dashboard identity are documented in the MX Fuels RBAC & Identity reference:
| Resource | Role/Grant |
|---|---|
| Azure Storage Blob | Storage Blob Data Contributor |
| Azure Service Bus | Azure Service Bus Data Sender |
| PostgreSQL | Database role named after the identity + GRANT CONNECT/USAGE/SELECT |
| Databricks SQL Warehouse | CAN_USE |
Grant resource roles to the production UAMI. Grant equivalent roles to a developer’s Azure CLI identity only when local feature testing needs them. Do not grant the legacy App Registration service principal unless a separate automation job explicitly requires it.
See also
Section titled “See also”Onboarding → Environment & Secrets for the full credential resolution chain (.envrc → Dynaconf → Key Vault → OS keyring) on the Python pipelines side.