Skip to content

Key Vault References

Inject secrets directly into App Service environment variables using Key Vault References, while keeping Flask code simple.

Architecture

flowchart TD
    App[App Service platform]
    Setting[Key Vault reference app setting]
    Env[Resolved environment variable]
    MI[Managed Identity]
    KV[(Azure Key Vault)]

    App --> Setting
    App --> Env
    App -.-> MI
    MI -.-> KV
    KV --> Env

Solid arrows show runtime data flow. Dashed arrows show identity and authentication.

Prerequisites

  • Managed identity enabled on App Service
  • Key Vault with required secrets
  • Key Vault RBAC role: Key Vault Secrets User for the app identity

Step-by-Step Guide

Step 1: Configure Key Vault reference app settings

Reference syntax:

  • @Microsoft.KeyVault(SecretUri=https://<vault-name>.vault.azure.net/secrets/<secret-name>)
  • @Microsoft.KeyVault(VaultName=<vault-name>;SecretName=<secret-name>)
az webapp config appsettings set \
  --resource-group "$RG" \
  --name "$APP_NAME" \
  --settings \
    DB_PASSWORD="@Microsoft.KeyVault(VaultName=<vault-name>;SecretName=db-password)" \
    REDIS_ACCESS_KEY="@Microsoft.KeyVault(SecretUri=https://<vault-name>.vault.azure.net/secrets/redis-access-key)"
Flag Description
--resource-group "$RG" Targets the resource group that contains the web app.
--name "$APP_NAME" Selects the web app that should receive the Key Vault reference settings.
--settings DB_PASSWORD="@Microsoft.KeyVault(VaultName=<vault-name>;SecretName=db-password)" REDIS_ACCESS_KEY="@Microsoft.KeyVault(SecretUri=https://<vault-name>.vault.azure.net/secrets/redis-access-key)" Writes app settings whose values are resolved from the specified Key Vault secrets.

Step 2: Read secrets from os.environ in Python

import os
from flask import Flask, jsonify

app = Flask(__name__)


@app.get("/api/config/check")
def config_check():
    db_password = os.environ.get("DB_PASSWORD")
    redis_key = os.environ.get("REDIS_ACCESS_KEY")

    return jsonify({
        "db_password_loaded": bool(db_password),
        "redis_key_loaded": bool(redis_key)
    })

Complete Example

import os
import pyodbc


def build_connection_string() -> str:
    return (
        f"Driver={{{os.environ.get('SQL_DRIVER', 'ODBC Driver 18 for SQL Server')}}};"
        f"Server=tcp:{os.environ['SQL_SERVER']},1433;"
        f"Database={os.environ['SQL_DATABASE']};"
        f"Uid={os.environ['SQL_USER']};"
        f"Pwd={os.environ['DB_PASSWORD']};"
        "Encrypt=yes;TrustServerCertificate=no;"
    )


def connect_with_secret():
    return pyodbc.connect(build_connection_string())

Troubleshooting

  • Environment variable contains literal @Microsoft.KeyVault(...):
    • Reference resolution failed; verify identity and Key Vault permissions.- Secret not found or stale value:
    • Check secret name/version and remember updates may take time to refresh.- Works in one slot, fails in another:
    • Confirm slot-specific app settings and identity assignments.

Advanced Topics

  • Combine with slot settings to isolate staging vs production secrets.
  • Prefer Key Vault References for non-SDK consumers; use SDK + managed identity for dynamic secret operations.
  • Rotate secrets in Key Vault without code changes or repo updates.

Run It in the Portal

After granting the app's managed identity access to the vault, use Pull reference values or Refresh in the Environment variables toolbar to re-evaluate reference state. Use Show value on a reference row to confirm the resolved secret is returned instead of the literal @Microsoft.KeyVault(...) syntax.

See Also

Sources