Azure Key Vault — Secrets, Keys, and Certificates Management
Your application needs a database connection string, an API key, and a TLS certificate. Right now those are in environment variables, config files, or worse — hardcoded in source code. One leaked credential and your entire infrastructure is compromised. Azure Key Vault gives you a centralized, auditable, hardware-backed vault for secrets, encryption keys, and certificates so credentials never live where they should not.
Key Vault Concepts
Azure Key Vault manages three types of objects:
| Object Type | What It Stores | Example |
|---|---|---|
| Secrets | Any string value (passwords, connection strings, API keys) | db-connection-string, stripe-api-key |
| Keys | RSA or EC cryptographic keys for encrypt/decrypt/sign/verify | data-encryption-key, jwt-signing-key |
| Certificates | X.509 certificates with automatic renewal | api.myapp.com TLS cert |
Secrets are the most commonly used. Keys are for cryptographic operations where the key material never leaves the vault (the vault performs the operation for you). Certificates combine a key pair with certificate metadata and can auto-renew through integrated CAs like DigiCert or Let's Encrypt (via manual process).
Creating a Key Vault
# Create a resource group
az group create \
--name rg-security \
--location eastus
# Create a Key Vault with RBAC authorization
az keyvault create \
--name kv-prod-2025 \
--resource-group rg-security \
--location eastus \
--enable-rbac-authorization true \
--enable-soft-delete true \
--retention-days 90 \
--enable-purge-protection true \
--sku standard
Key flags explained:
--enable-rbac-authorization true— Use Azure RBAC instead of vault access policies (recommended)--enable-soft-delete true— Deleted secrets are recoverable for the retention period--enable-purge-protection true— Even admins cannot permanently delete secrets before retention expires--sku standard— Standard tier; usepremiumfor HSM-backed keys
Access Policies vs RBAC
Azure Key Vault supports two authorization models. You choose one when creating the vault.
| Feature | Access Policies (Legacy) | Azure RBAC (Recommended) |
|---|---|---|
| Granularity | Per-vault (all-or-nothing per object type) | Per-secret, per-key, per-certificate |
| Management | Configured on the vault directly | Managed through Azure IAM |
| Audit | Limited | Full Azure Activity Log integration |
| Conditional Access | Not supported | Supported via Entra ID |
| Scope | Vault-level only | Subscription, resource group, vault, or individual object |
RBAC is the clear winner. It lets you grant access to a single secret without exposing the entire vault.
# Grant a user read access to secrets only
az role assignment create \
--role "Key Vault Secrets User" \
--assignee user@company.com \
--scope /subscriptions/<sub-id>/resourceGroups/rg-security/providers/Microsoft.KeyVault/vaults/kv-prod-2025
# Grant an app full secret management
az role assignment create \
--role "Key Vault Secrets Officer" \
--assignee <app-object-id> \
--scope /subscriptions/<sub-id>/resourceGroups/rg-security/providers/Microsoft.KeyVault/vaults/kv-prod-2025
Common RBAC roles for Key Vault:
- Key Vault Secrets User — Read secrets (for applications)
- Key Vault Secrets Officer — Full CRUD on secrets (for admins)
- Key Vault Crypto User — Use keys for encrypt/decrypt (for applications)
- Key Vault Certificates Officer — Manage certificates (for ops teams)
- Key Vault Administrator — Full access to all vault objects
Storing and Retrieving Secrets
# Store a secret
az keyvault secret set \
--vault-name kv-prod-2025 \
--name db-connection-string \
--value "Server=sql-prod.database.windows.net;Database=appdb;User Id=appadmin;Password=S3cur3P@ss!"
# Store a multi-line secret from a file
az keyvault secret set \
--vault-name kv-prod-2025 \
--name tls-private-key \
--file ./certs/private.pem
# Retrieve a secret value
az keyvault secret show \
--vault-name kv-prod-2025 \
--name db-connection-string \
--query value \
--output tsv
# List all secrets (names only, not values)
az keyvault secret list \
--vault-name kv-prod-2025 \
--query "[].name" \
--output tsv
Secrets are versioned automatically. Every time you update a secret, Key Vault creates a new version while preserving the old one. You can reference a specific version or always get the latest.
Managed Identity Integration
Managed identities eliminate the need for credentials entirely. Azure automatically provides an identity to your resource that can authenticate to Key Vault.
# Enable system-assigned managed identity on a VM
az vm identity assign \
--resource-group rg-prod \
--name vm-web-01
# Get the identity's principal ID
PRINCIPAL_ID=$(az vm identity show \
--resource-group rg-prod \
--name vm-web-01 \
--query principalId \
--output tsv)
# Grant the identity access to Key Vault secrets
az role assignment create \
--role "Key Vault Secrets User" \
--assignee $PRINCIPAL_ID \
--scope /subscriptions/<sub-id>/resourceGroups/rg-security/providers/Microsoft.KeyVault/vaults/kv-prod-2025
Now the VM can retrieve secrets without storing any credentials. The identity token is managed by Azure and rotated automatically.
App Service Key Vault References
App Service has native Key Vault integration. Instead of putting secrets in application settings, you reference Key Vault directly.
# Enable system-assigned identity on App Service
az webapp identity assign \
--resource-group rg-prod \
--name myapp-prod
# Grant access to secrets
az role assignment create \
--role "Key Vault Secrets User" \
--assignee $(az webapp identity show --resource-group rg-prod --name myapp-prod --query principalId --output tsv) \
--scope /subscriptions/<sub-id>/resourceGroups/rg-security/providers/Microsoft.KeyVault/vaults/kv-prod-2025
# Set an app setting that references Key Vault
az webapp config appsettings set \
--resource-group rg-prod \
--name myapp-prod \
--settings "DB_CONN=@Microsoft.KeyVault(VaultName=kv-prod-2025;SecretName=db-connection-string)"
The @Microsoft.KeyVault(...) syntax tells App Service to resolve the value from Key Vault at runtime. The secret never appears in the App Service configuration blade and stays in one place.
AKS CSI Driver Integration
For Kubernetes workloads, the Secrets Store CSI Driver mounts Key Vault secrets directly into pods as files or syncs them to Kubernetes Secrets.
# secret-provider-class.yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: azure-kv-secrets
spec:
provider: azure
parameters:
keyvaultName: "kv-prod-2025"
tenantId: "<tenant-id>"
objects: |
array:
- |
objectName: db-connection-string
objectType: secret
- |
objectName: api-key
objectType: secret
usePodIdentity: "false"
useVMManagedIdentity: "true"
userAssignedIdentityID: "<managed-identity-client-id>"
secretObjects:
- secretName: app-secrets
type: Opaque
data:
- objectName: db-connection-string
key: DB_CONN
- objectName: api-key
key: API_KEY
Reference it in your pod spec:
# deployment.yaml
spec:
containers:
- name: myapp
image: acrprod2025.azurecr.io/myapp:v1.0
volumeMounts:
- name: secrets-store
mountPath: "/mnt/secrets"
readOnly: true
env:
- name: DB_CONN
valueFrom:
secretKeyRef:
name: app-secrets
key: DB_CONN
volumes:
- name: secrets-store
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "azure-kv-secrets"
Key Rotation
Key Vault supports automatic key rotation for cryptographic keys and notifications for secrets nearing expiry.
# Set a rotation policy on a key
az keyvault key rotation-policy update \
--vault-name kv-prod-2025 \
--name data-encryption-key \
--value '{
"lifetimeActions": [
{
"trigger": {"timeAfterCreate": "P90D"},
"action": {"type": "Rotate"}
},
{
"trigger": {"timeBeforeExpiry": "P30D"},
"action": {"type": "Notify"}
}
],
"attributes": {"expiryTime": "P180D"}
}'
# Set expiry on a secret (for manual rotation tracking)
az keyvault secret set-attributes \
--vault-name kv-prod-2025 \
--name stripe-api-key \
--expires 2025-12-31T23:59:59Z
For secrets, use Azure Event Grid to trigger an Azure Function or Logic App when a secret is about to expire. The function retrieves a new credential from the external service, updates Key Vault, and the consuming application picks up the change on next access.
Certificate Management
Key Vault can issue, store, and auto-renew TLS certificates.
# Create a self-signed certificate (for testing)
az keyvault certificate create \
--vault-name kv-prod-2025 \
--name api-tls-cert \
--policy '{
"issuerParameters": {"name": "Self"},
"keyProperties": {"keyType": "RSA", "keySize": 2048, "reuseKey": false},
"secretProperties": {"contentType": "application/x-pkcs12"},
"x509CertificateProperties": {
"subject": "CN=api.myapp.com",
"subjectAlternativeNames": {"dnsNames": ["api.myapp.com", "*.myapp.com"]},
"validityInMonths": 12
},
"lifetimeActions": [
{"trigger": {"daysBeforeExpiry": 30}, "action": {"actionType": "AutoRenew"}}
]
}'
# Download the certificate
az keyvault certificate download \
--vault-name kv-prod-2025 \
--name api-tls-cert \
--file ./api-tls-cert.pem
For production certificates, integrate Key Vault with DigiCert or GlobalSign as a certificate issuer. Key Vault handles the CSR, validation, issuance, and renewal automatically.
Networking and Private Endpoints
By default, Key Vault is accessible over the public internet. For production, restrict access using private endpoints or firewall rules.
# Disable public network access
az keyvault update \
--name kv-prod-2025 \
--resource-group rg-security \
--public-network-access Disabled
# Create a private endpoint
az network private-endpoint create \
--name pe-keyvault \
--resource-group rg-security \
--vnet-name vnet-prod \
--subnet snet-private-endpoints \
--private-connection-resource-id $(az keyvault show --name kv-prod-2025 --query id --output tsv) \
--group-id vault \
--connection-name kv-connection
# Create a private DNS zone for Key Vault
az network private-dns zone create \
--resource-group rg-security \
--name privatelink.vaultcore.azure.net
# Link the DNS zone to your VNet
az network private-dns zone vnet-link create \
--resource-group rg-security \
--zone-name privatelink.vaultcore.azure.net \
--name kv-dns-link \
--virtual-network vnet-prod \
--registration-enabled false
With private endpoints, traffic to Key Vault stays on the Azure backbone network and never traverses the public internet.
Wrapping Up
Azure Key Vault is the foundation of secret management on Azure. Use RBAC authorization over access policies, managed identities over stored credentials, and private endpoints over public access. Reference secrets from App Service with @Microsoft.KeyVault(...) syntax, mount them into AKS pods with the CSI driver, and set expiry dates with Event Grid notifications for rotation workflows. The rule is simple — if it is a credential, a key, or a certificate, it belongs in Key Vault and nowhere else.
Next up: We will compare Azure load balancing options — Load Balancer, Application Gateway, and Front Door — and help you decide which one fits your architecture.
