Azure Key Vault Tutorial

Step-by-step tutorial for creating Azure Key Vault, storing secrets and keys, configuring access policies with RBAC, and integrating with Azure services for secure secret management.

12 min readUpdated 2026-01-13

Azure Key Vault provides secure storage and management for secrets, encryption keys, and certificates. This tutorial walks you through creating a Key Vault, storing secrets, configuring access with RBAC, and integrating with Azure services for production-ready secret management.

This article is part of our comprehensive guide on Cloud Security Tips for 2026, which covers essential security practices across all major cloud platforms.

Overview

Azure Key Vault supports three types of objects:

  • Secrets: General-purpose key-value storage for passwords, API keys, connection strings
  • Keys: Cryptographic keys for encryption, signing, and wrapping operations
  • Certificates: X.509 certificates for TLS/SSL and authentication

Key Vault provides centralized secret management, eliminating the need to store credentials in code, configuration files, or environment variables.

Prerequisites

Before creating a Key Vault, ensure you have:

  • Azure subscription with Contributor role
  • Azure CLI installed (version 2.50 or later)
  • Understanding of identity types (managed identity, service principal)
  • Basic familiarity with Azure RBAC

Step 1: Create a Key Vault

Create Key Vault via Azure Portal

  1. Sign in to the Azure Portal
  2. Search for Key vaults and select it
  3. Click + Create
  4. Configure the basics:
    • Subscription: Select your subscription
    • Resource group: Create or select existing
    • Key vault name: Enter a globally unique name (e.g., kv-myapp-prod-001)
    • Region: Select a region close to your applications
    • Pricing tier: Standard (or Premium for HSM-backed keys)
  5. Click Next: Access configuration
  6. Configure access:
    • Permission model: Select Azure role-based access control (recommended)
    • Soft-delete: Enabled (default, cannot be disabled)
    • Purge protection: Enable for production (recommended)
  7. Click Review + create, then Create

Create Key Vault via Azure CLI

# Set variables
RESOURCE_GROUP="rg-app-production"
KEYVAULT_NAME="kv-myapp-prod-001"
LOCATION="eastus"

# Create resource group
az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

# Create Key Vault with RBAC and purge protection
az keyvault create \
  --resource-group $RESOURCE_GROUP \
  --name $KEYVAULT_NAME \
  --location $LOCATION \
  --sku standard \
  --enable-rbac-authorization true \
  --enable-purge-protection true \
  --retention-days 90

# Verify creation
az keyvault show \
  --resource-group $RESOURCE_GROUP \
  --name $KEYVAULT_NAME \
  --query "{Name:name, Location:location, RBAC:properties.enableRbacAuthorization}" \
  -o table

Key Vault Naming Requirements

  • Globally unique across Azure
  • 3-24 characters
  • Alphanumeric and hyphens only
  • Must start with a letter
  • Cannot end with a hyphen

Step 2: Store Secrets

Add Secrets via Azure Portal

  1. Navigate to your Key Vault
  2. Click Secrets under Objects
  3. Click + Generate/Import
  4. Configure the secret:
    • Upload options: Manual
    • Name: database-connection-string
    • Value: Your secret value
    • Content type: (optional) text/plain
    • Set activation/expiration date: (optional) Configure validity period
  5. Click Create

Add Secrets via Azure CLI

# Store a simple secret
az keyvault secret set \
  --vault-name $KEYVAULT_NAME \
  --name "api-key" \
  --value "sk-live-abc123xyz"

# Store secret with expiration (1 year from now)
EXPIRY=$(date -u -d "+1 year" +"%Y-%m-%dT%H:%M:%SZ")
az keyvault secret set \
  --vault-name $KEYVAULT_NAME \
  --name "database-password" \
  --value "SuperSecretP@ssw0rd!" \
  --expires "$EXPIRY" \
  --content-type "text/plain"

# Store a connection string
az keyvault secret set \
  --vault-name $KEYVAULT_NAME \
  --name "connection-string" \
  --value "Server=sql.database.windows.net;Database=mydb;User Id=admin;Password=secret"

# List all secrets
az keyvault secret list \
  --vault-name $KEYVAULT_NAME \
  --query "[].{Name:name, Enabled:attributes.enabled}" \
  -o table

Retrieve Secrets

# Get secret value
az keyvault secret show \
  --vault-name $KEYVAULT_NAME \
  --name "api-key" \
  --query value -o tsv

# Get specific version
az keyvault secret show \
  --vault-name $KEYVAULT_NAME \
  --name "api-key" \
  --version "abc123"

# List secret versions
az keyvault secret list-versions \
  --vault-name $KEYVAULT_NAME \
  --name "api-key" \
  --query "[].{Version:id, Created:attributes.created}" \
  -o table

Step 3: Configure Access with RBAC

Azure RBAC provides fine-grained access control to Key Vault objects.

Built-in Key Vault Roles

RoleSecretsKeysCertificates
Key Vault AdministratorFullFullFull
Key Vault Secrets OfficerFull--
Key Vault Secrets UserRead--
Key Vault Crypto Officer-Full-
Key Vault Crypto User-Use-
Key Vault Certificates Officer--Full
Key Vault ReaderListListList

Assign RBAC Roles via Azure CLI

# Get current user's object ID
USER_OBJECT_ID=$(az ad signed-in-user show --query id -o tsv)

# Assign Key Vault Administrator to yourself
az role assignment create \
  --role "Key Vault Administrator" \
  --assignee $USER_OBJECT_ID \
  --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME"

# Grant secrets read access to an application (managed identity)
APP_IDENTITY_ID="00000000-0000-0000-0000-000000000000"
az role assignment create \
  --role "Key Vault Secrets User" \
  --assignee $APP_IDENTITY_ID \
  --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME"

# Grant access to an Entra ID group
GROUP_ID="00000000-0000-0000-0000-000000000000"
az role assignment create \
  --role "Key Vault Secrets Officer" \
  --assignee $GROUP_ID \
  --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME"

# List role assignments
az role assignment list \
  --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME" \
  --query "[].{Principal:principalName, Role:roleDefinitionName}" \
  -o table

Configure Access via Portal

  1. Navigate to your Key Vault
  2. Click Access control (IAM)
  3. Click + Add > Add role assignment
  4. Select a role (e.g., Key Vault Secrets User)
  5. Click Members and select users, groups, or managed identities
  6. Click Review + assign

Step 4: Integrate with Azure Services

Azure App Service Integration

Reference Key Vault secrets in App Service app settings:

# Enable system-assigned managed identity on App Service
az webapp identity assign \
  --resource-group $RESOURCE_GROUP \
  --name "my-webapp"

# Get managed identity ID
IDENTITY_ID=$(az webapp identity show \
  --resource-group $RESOURCE_GROUP \
  --name "my-webapp" \
  --query principalId -o tsv)

# Grant secrets access to App Service
az role assignment create \
  --role "Key Vault Secrets User" \
  --assignee $IDENTITY_ID \
  --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME"

# Configure app setting to reference Key Vault
az webapp config appsettings set \
  --resource-group $RESOURCE_GROUP \
  --name "my-webapp" \
  --settings "[email protected](VaultName=$KEYVAULT_NAME;SecretName=database-password)"

Azure Functions Integration

# Enable managed identity on Function App
az functionapp identity assign \
  --resource-group $RESOURCE_GROUP \
  --name "my-function"

# Reference secret in function app settings
az functionapp config appsettings set \
  --resource-group $RESOURCE_GROUP \
  --name "my-function" \
  --settings "[email protected](SecretUri=https://$KEYVAULT_NAME.vault.azure.net/secrets/api-key/)"

Access from Application Code

Python example:

from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient

# Use DefaultAzureCredential for automatic authentication
credential = DefaultAzureCredential()
vault_url = "https://kv-myapp-prod-001.vault.azure.net"
client = SecretClient(vault_url=vault_url, credential=credential)

# Retrieve secret
secret = client.get_secret("api-key")
print(f"Secret value: {secret.value}")

C# example:

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;

var vaultUri = new Uri("https://kv-myapp-prod-001.vault.azure.net");
var client = new SecretClient(vaultUri, new DefaultAzureCredential());

KeyVaultSecret secret = await client.GetSecretAsync("api-key");
Console.WriteLine($"Secret value: {secret.Value}");

Step 5: Enable Monitoring and Auditing

Enable Diagnostic Logging

# Get Log Analytics workspace ID
WORKSPACE_ID=$(az monitor log-analytics workspace show \
  --resource-group "rg-security" \
  --workspace-name "law-security" \
  --query id -o tsv)

# Enable diagnostic settings
az monitor diagnostic-settings create \
  --resource "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME" \
  --name "keyvault-diagnostics" \
  --workspace $WORKSPACE_ID \
  --logs '[{"category": "AuditEvent", "enabled": true}]' \
  --metrics '[{"category": "AllMetrics", "enabled": true}]'

Query Audit Logs

// View all Key Vault operations
AzureDiagnostics
| where ResourceType == "VAULTS"
| project TimeGenerated, OperationName, CallerIPAddress, ResultSignature, identity_claim_upn_s
| order by TimeGenerated desc

// Find failed access attempts
AzureDiagnostics
| where ResourceType == "VAULTS"
| where ResultSignature contains "Forbidden" or ResultSignature contains "Unauthorized"
| project TimeGenerated, OperationName, CallerIPAddress, identity_claim_upn_s

// Track secret access
AzureDiagnostics
| where ResourceType == "VAULTS"
| where OperationName == "SecretGet"
| summarize AccessCount=count() by id_s, bin(TimeGenerated, 1h)

Best Practices

  1. Use RBAC over Access Policies: Modern, granular, PIM-compatible
  2. Enable soft-delete and purge protection: Prevent accidental data loss
  3. Use managed identities: Avoid storing credentials to access Key Vault
  4. Set secret expiration: Enforce regular rotation
  5. Enable diagnostic logging: Audit all access and operations
  6. Use Private Endpoints: Restrict network access for production vaults
  7. Separate vaults by environment: Dev, staging, and production vaults

Troubleshooting

Access denied when retrieving secrets:

  • Verify RBAC role assignment exists
  • Check role scope (vault-level, not subscription-level)
  • Allow 5-10 minutes for RBAC propagation

Managed identity not working:

  • Confirm identity is enabled on the resource
  • Verify RBAC assignment uses correct principal ID
  • Check application is using DefaultAzureCredential

Secret reference not resolving in App Service:

  • Ensure managed identity is assigned
  • Verify Key Vault Secrets User role is assigned
  • Check secret URI format is correct

Next Steps

After setting up Key Vault, enhance your secret management:

  • Implement secret rotation with Azure Functions
  • Configure Private Endpoints for network isolation
  • Enable Event Grid notifications for secret expiration
  • Review Cloud Security Tips for 2026 for comprehensive cloud security guidance

Frequently Asked Questions

Find answers to common questions

Access Policies are the legacy permission model where you grant permissions at the vault level to specific principals. Azure RBAC is the modern approach where you assign built-in or custom roles at the vault, resource group, or subscription level. RBAC offers more granular control, integration with Azure Privileged Identity Management, and consistent permissions management across Azure services. Microsoft recommends RBAC for new Key Vaults.

Azure Infrastructure Experts

Comprehensive Azure management including architecture, migration, security, and 24/7 operations.