Skip to content

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.

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.

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.

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}

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: .envrc exports vault URLs, and the mounted Azure CLI session authenticates the developer.
  • Production: the deployment workflow sets both vault URLs and AZURE_CLIENT_ID on the Container App. Missing Key Vault URLs fail explicitly.

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.

Onboarding → Environment & Secrets for the full credential resolution chain (.envrc → Dynaconf → Key Vault → OS keyring) on the Python pipelines side.