Recipe: Key Vault Secret References in Azure Container Apps
Use managed identity and Key Vault references so your Python app receives secrets as environment variables without embedding secret values in deployment manifests.
flowchart TD
C[Client] --> I[Container Apps Ingress]
I --> APP[Container App]
APP -.-> MI[Managed Identity]
MI -.-> ENTRA[Microsoft Entra ID]
MI -.-> KV[Azure Key Vault]
KV -.-> SEC["Secrets (env vars)"]
SEC -.-> APP
Prerequisites
- Existing Key Vault name (
$KEYVAULT_NAME) - Existing Container App (
$APP_NAME) and resource group ($RG) - Azure CLI with Container Apps extension
az extension add --name containerapp --upgrade
| Command | Why it is used |
az extension add ... | Installs or updates the Container Apps Azure CLI extension. |
Create Key Vault and add secrets
az keyvault create \
--name "$KEYVAULT_NAME" \
--resource-group "$RG" \
--location "$LOCATION"
az keyvault secret set \
--vault-name "$KEYVAULT_NAME" \
--name "db-password" \
--value "replace-with-real-value"
| Command | Why it is used |
az keyvault create ... | Creates or inspects Key Vault resources used by managed identity or secret references. |
az containerapp identity assign \
--name "$APP_NAME" \
--resource-group "$RG" \
--system-assigned
export PRINCIPAL_ID=$(az containerapp show \
--name "$APP_NAME" \
--resource-group "$RG" \
--query "identity.principalId" \
--output tsv)
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" \
--assignee-principal-type ServicePrincipal \
--role "Key Vault Secrets User" \
--scope "$(az keyvault show --name "$KEYVAULT_NAME" --query id --output tsv)"
| Command | Why it is used |
az containerapp identity assign ... | Assigns or inspects managed identity configuration for the Container App. |
Add a Container Apps secret with Key Vault reference
Key Vault reference syntax:
keyvaultref:https://<key-vault-name>.vault.azure.net/secrets/<secret-name>
CLI example:
az containerapp secret set \
--name "$APP_NAME" \
--resource-group "$RG" \
--secrets "db-password=keyvaultref:https://$KEYVAULT_NAME.vault.azure.net/secrets/db-password,identityref:system"
az containerapp update \
--name "$APP_NAME" \
--resource-group "$RG" \
--set-env-vars "DB_PASSWORD=secretref:db-password"
| Command | Why it is used |
az containerapp secret set ... | Manages Container Apps secrets without exposing secret values in plain configuration. |
Access referenced secrets in Python
import os
from flask import Flask, jsonify
app = Flask(__name__)
@app.get("/config-check")
def config_check():
password = os.getenv("DB_PASSWORD", "")
return jsonify(dbPasswordConfigured=bool(password)), 200
Secret rotation patterns
- Rotate the Key Vault secret value (
az keyvault secret set with same name). - Restart or revise app workloads to pick up updated secret values.
- For controlled rotation, deploy a new revision and shift traffic after validation.
Bicep example for Key Vault reference
resource app 'Microsoft.App/containerApps@2023-05-01' existing = {
name: appName
}
resource appSecrets 'Microsoft.App/containerApps@2023-05-01' = {
name: app.name
properties: {
configuration: {
secrets: [
{
name: 'db-password'
keyVaultUrl: 'https://${keyVaultName}.vault.azure.net/secrets/db-password'
identity: 'system'
}
]
}
template: {
containers: [
{
name: 'app'
image: imageName
env: [
{
name: 'DB_PASSWORD'
secretRef: 'db-password'
}
]
}
]
}
}
}
Troubleshooting common 403 errors
- Confirm app identity is enabled and principal ID exists.
- Verify role assignment is on the Key Vault scope and propagated.
- Check Key Vault firewall/private endpoint settings.
- Ensure secret URL path and version are correct.
az containerapp logs show \
--name "$APP_NAME" \
--resource-group "$RG" \
--follow false
| Command | Why it is used |
az containerapp logs show ... | Runs the Azure CLI operation required by the documented step. |
Advanced Topics
- Use user-assigned identities for shared access policies across multiple apps.
- Separate secret vaults per environment to reduce blast radius.
- Pair Key Vault reference with revision validation for zero-downtime rotations.
See Also
Sources