Category Recommendation
Security Never store secrets in code or configuration files
Access Control Use Azure AD service principals for application access
Cost Standard tier sufficient for most use cases (~$0.03/10K operations)
Monitoring Enable diagnostic logging for all Key Vault operations
Backup Implement automated backup strategy for critical secrets

TL;DR

  • Azure Key Vault centralizes secret management with enterprise-grade security and access controls
  • Use Azure CLI, PowerShell, or REST APIs to programmatically manage secrets instead of hardcoding credentials
  • Service principals and managed identities provide secure, passwordless authentication for applications
  • Soft delete is always on; add purge protection to prevent accidental — and malicious — data loss in production environments
  • Monitor all Key Vault operations through Azure Monitor and diagnostic logs for security compliance

Introduction

Hardcoded passwords, API keys scattered across configuration files, and database connection strings stored in plain text—these are the hallmarks of a security nightmare waiting to happen. Azure Key Vault solves these problems by providing a centralized, secure service for managing secrets, keys, and certificates.

This comprehensive azure key vault tutorial walks you through implementing proper secret management practices that eliminate security vulnerabilities while maintaining operational efficiency. You'll learn to store, retrieve, and rotate secrets programmatically, implement role-based access controls, and integrate Key Vault with your applications using industry best practices.

Whether you're migrating legacy applications to Azure or building cloud-native solutions, mastering Key Vault is essential for maintaining security compliance and protecting sensitive data. By the end of this guide, you'll have a production-ready Key Vault implementation that follows Microsoft's recommended security patterns.

Prerequisites

  • Active Azure subscription with Contributor access
  • Azure CLI 2.30+ or Azure PowerShell 6.0+ installed locally
  • Basic understanding of Azure Resource Groups and Azure Active Directory
  • Familiarity with JSON and REST API concepts
  • Text editor or IDE for code examples

Setting Up Your Azure Key Vault

1. Create a Key Vault Using Azure CLI

First, establish the foundation by creating a Resource Group and Key Vault instance:

# Set variables for consistent naming
RESOURCE_GROUP="rg-keyvault-demo"
KEY_VAULT_NAME="kv-demo-$(date +%s)"  # Unique name with timestamp
LOCATION="eastus"

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

# Create Key Vault with essential security features
az keyvault create \
  --name $KEY_VAULT_NAME \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --enable-rbac-authorization true \
  --enable-purge-protection true \
  --retention-days 90

Two details here trip up anyone copying from an older tutorial. There is no --enable-soft-delete flag any more: soft delete is on by default for every new vault and cannot be disabled once enabled, so the only knob left is --retention-days, which accepts 7 to 90 and defaults to 90. Purge protection is still opt-in — and enabling it is irreversible. The second detail is --enable-rbac-authorization, which the az keyvault create reference now describes as enabled by default; passing it explicitly just documents the intent in your scripts.

2. Grant Data Plane Access with Azure RBAC

Key Vault has two data plane authorization models, and the default has flipped. From control plane API version 2026-02-01 onward, Azure RBAC is the default for newly created vaults — access policies are the legacy model and now have to be opted into explicitly with --enable-rbac-authorization false. Both remain fully supported, but new work belongs on Azure RBAC for Key Vault data-plane authorization:

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

# Scope the assignment to the vault itself
VAULT_ID=$(az keyvault show \
  --name $KEY_VAULT_NAME \
  --resource-group $RESOURCE_GROUP \
  --query id --output tsv)

# Grant yourself secret read/write (development only)
az role assignment create \
  --role "Key Vault Secrets Officer" \
  --assignee-object-id $USER_OBJECT_ID \
  --assignee-principal-type User \
  --scope $VAULT_ID

Key Vault Secrets Officer is the read/write role; reserve it for humans and pipelines that actually create secrets, and give everything that only reads at runtime Key Vault Secrets User instead.

On a legacy vault — one created before the default flipped, or deliberately created with --enable-rbac-authorization false — the equivalent grant is an access policy. This command fails on a vault using Azure RBAC, so pick one model per vault rather than mixing them:

# Legacy access-policy model only
az keyvault set-policy \
  --name $KEY_VAULT_NAME \
  --object-id $USER_OBJECT_ID \
  --secret-permissions get list set delete backup restore recover purge

3. Alternative Setup Using PowerShell

If you prefer PowerShell, here's the equivalent setup:

# Connect to Azure
Connect-AzAccount

# Set variables
$ResourceGroup = "rg-keyvault-demo"
$KeyVaultName = "kv-demo-$(Get-Date -Format 'yyyyMMddHHmmss')"
$Location = "East US"

# Create resource group
New-AzResourceGroup -Name $ResourceGroup -Location $Location

# Create Key Vault (soft delete is implicit; RBAC data plane is the default)
New-AzKeyVault `
  -Name $KeyVaultName `
  -ResourceGroupName $ResourceGroup `
  -Location $Location `
  -EnablePurgeProtection `
  -SoftDeleteRetentionInDays 90

# Grant secret read/write to the current user via Azure RBAC
$vault = Get-AzKeyVault -VaultName $KeyVaultName -ResourceGroupName $ResourceGroup

New-AzRoleAssignment `
  -RoleDefinitionName "Key Vault Secrets Officer" `
  -SignInName (Get-AzContext).Account.Id `
  -Scope $vault.ResourceId

New-AzKeyVault dropped -EnableSoftDelete along with the CLI flag, and gained -DisableRbacAuthorization for the rare case where you genuinely need the legacy access-policy model.

Managing Secrets in Key Vault

4. Store Secrets Securely

Never store secrets in plain text. Here are the proper methods for secret creation:

# Store a database connection string
az keyvault secret set \
  --vault-name $KEY_VAULT_NAME \
  --name "DatabaseConnectionString" \
  --value "Server=myserver.database.windows.net;Database=mydb;User Id=admin;Password=SecureP@ss123;"

# Store an API key with expiration date
az keyvault secret set \
  --vault-name $KEY_VAULT_NAME \
  --name "ExternalAPIKey" \
  --value "sk-1234567890abcdef" \
  --expires "2027-06-30T23:59:59Z"

# Store a secret from file (recommended for certificates)
echo "MySecretValue123!" > temp_secret.txt
az keyvault secret set \
  --vault-name $KEY_VAULT_NAME \
  --name "ApplicationSecret" \
  --file temp_secret.txt
rm temp_secret.txt

5. Retrieve Secrets Programmatically

Applications should retrieve secrets at runtime, not during build:

# Retrieve secret value
SECRET_VALUE=$(az keyvault secret show \
  --vault-name $KEY_VAULT_NAME \
  --name "DatabaseConnectionString" \
  --query value \
  --output tsv)

echo "Retrieved secret: $SECRET_VALUE"

# List all secrets (shows names only, not values)
az keyvault secret list \
  --vault-name $KEY_VAULT_NAME \
  --output table

6. Secret Versioning and Rotation

Key Vault automatically versions secrets, enabling safe rotation:

# Update an existing secret (creates new version)
az keyvault secret set \
  --vault-name $KEY_VAULT_NAME \
  --name "ExternalAPIKey" \
  --value "sk-newkey9876543210"

# Retrieve specific version
az keyvault secret show \
  --vault-name $KEY_VAULT_NAME \
  --name "ExternalAPIKey" \
  --version "previous-version-id" \
  --query value \
  --output tsv

# List all versions of a secret
az keyvault secret list-versions \
  --vault-name $KEY_VAULT_NAME \
  --name "ExternalAPIKey" \
  --output table

Application Integration Best Practices

7. Service Principal Authentication

Create a service principal for application authentication:

# Create service principal
SP_NAME="sp-keyvault-app"
SP_CREDENTIALS=$(az ad sp create-for-rbac \
  --name $SP_NAME \
  --role Reader \
  --scopes /subscriptions/$(az account show --query id -o tsv)/resourceGroups/$RESOURCE_GROUP)

# Extract service principal details
SP_CLIENT_ID=$(echo $SP_CREDENTIALS | jq -r '.appId')
SP_CLIENT_SECRET=$(echo $SP_CREDENTIALS | jq -r '.password')
SP_OBJECT_ID=$(az ad sp show --id $SP_CLIENT_ID --query id --output tsv)

# Grant the service principal read-only secret access (Azure RBAC)
az role assignment create \
  --role "Key Vault Secrets User" \
  --assignee-object-id $SP_OBJECT_ID \
  --assignee-principal-type ServicePrincipal \
  --scope $VAULT_ID

# Legacy access-policy vaults use this instead:
# az keyvault set-policy --name $KEY_VAULT_NAME \
#   --object-id $SP_OBJECT_ID --secret-permissions get list

echo "Service Principal Client ID: $SP_CLIENT_ID"
echo "Store the client secret securely: $SP_CLIENT_SECRET"

8. Python Application Example

Here's how to integrate Key Vault into a Python application:

from azure.identity import ClientSecretCredential
from azure.keyvault.secrets import SecretClient
import os

# Configuration (environment variables in production)
TENANT_ID = "your-tenant-id"
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"
VAULT_URL = f"https://{KEY_VAULT_NAME}.vault.azure.net/"

# Authenticate using service principal
credential = ClientSecretCredential(
    tenant_id=TENANT_ID,
    client_id=CLIENT_ID,
    client_secret=CLIENT_SECRET
)

# Create Key Vault client
client = SecretClient(vault_url=VAULT_URL, credential=credential)

try:
    # Retrieve secret
    secret = client.get_secret("DatabaseConnectionString")
    print(f"Retrieved secret version: {secret.properties.version}")
    
    # Use secret value (never log it)
    connection_string = secret.value
    
    # Writing requires the Key Vault Secrets Officer role — the read-only
    # Secrets User grant above is deliberately not enough for this call:
    # client.set_secret("NewApplicationKey", "secure-value-123")
    
except Exception as e:
    print(f"Error accessing Key Vault: {e}")

Advanced Configuration and Security

9. Network Security and Firewall Rules

Restrict Key Vault access to specific networks:

# Configure firewall rules (replace with your IP)
YOUR_PUBLIC_IP=$(curl -s https://ipinfo.io/ip)

az keyvault network-rule add \
  --vault-name $KEY_VAULT_NAME \
  --ip-address $YOUR_PUBLIC_IP

# Enable private endpoint for VNet access
az keyvault update \
  --name $KEY_VAULT_NAME \
  --default-action Deny \
  --bypass AzureServices

10. Enable Monitoring and Logging

Set up comprehensive monitoring for security compliance:

# Create Log Analytics workspace
WORKSPACE_NAME="law-keyvault-logs"
az monitor log-analytics workspace create \
  --resource-group $RESOURCE_GROUP \
  --workspace-name $WORKSPACE_NAME

# Get workspace ID
WORKSPACE_ID=$(az monitor log-analytics workspace show \
  --resource-group $RESOURCE_GROUP \
  --workspace-name $WORKSPACE_NAME \
  --query id --output tsv)

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

Troubleshooting Common Issues

Access Denied Errors

Problem: The user, group or application does not have permission to perform operation

Solution:

# Which authorization model is this vault on?
az keyvault show --name $KEY_VAULT_NAME \
  --query properties.enableRbacAuthorization

# RBAC vaults: list role assignments scoped to the vault
az role assignment list --scope $VAULT_ID --output table

# Access-policy vaults: inspect the policy list instead
az keyvault show --name $KEY_VAULT_NAME --query properties.accessPolicies

# Verify your effective permissions either way
az keyvault secret list --vault-name $KEY_VAULT_NAME --output table

Network Connectivity Issues

Problem: Host not found or timeout errors

Solution:

# Test connectivity
nslookup $KEY_VAULT_NAME.vault.azure.net

# Check firewall rules
az keyvault network-rule list --vault-name $KEY_VAULT_NAME

Authentication Failures

Problem: Service principal authentication failing

Solution:

# Verify service principal exists
az ad sp show --id $SP_CLIENT_ID

# Test authentication manually
az login --service-principal \
  --username $SP_CLIENT_ID \
  --password $SP_CLIENT_SECRET \
  --tenant $TENANT_ID

Common Mistakes to Avoid

  • Storing secrets in application code: Always retrieve secrets at runtime from Key Vault
  • Granting more than the job needs: Give runtime consumers Key Vault Secrets User and reserve Key Vault Secrets Officer for the humans and pipelines that actually write secrets
  • Ignoring secret expiration: Implement automated rotation for time-sensitive credentials
  • Assuming soft delete is enough: Soft delete is on by default and can no longer be disabled, but purge protection is still opt-in — enable it in production so nobody can purge a deleted vault or secret before its 7–90 day retention window expires
  • Not monitoring access: Enable diagnostic logging to track all Key Vault operations
  • Hardcoding Key Vault names: Use environment variables or configuration files for vault URLs

Key Takeaways

  • Azure Key Vault centralizes secret management with enterprise-grade security features including encryption at rest and in transit
  • Service principals provide secure authentication for applications without exposing user credentials or requiring interactive login
  • Azure RBAC is the default data plane model for new vaults, with built-in roles such as Key Vault Secrets User and Key Vault Secrets Officer replacing hand-assembled access policy permission lists
  • Secret versioning supports safe rotation by maintaining previous versions while updating credentials in production systems
  • Monitoring and logging are essential for security compliance and should be configured from the beginning, not as an afterthought
  • Network restrictions enhance security by limiting Key Vault access to authorized IP addresses and virtual networks
  • Soft delete is automatic and purge protection is opt-in — turn purge protection on for every production vault, and set the retention window at creation time because it cannot be changed afterwards

Next Steps

Now that you've mastered basic Key Vault operations, consider these advanced topics:

  1. Implement Azure Key Vault with Azure DevOps for secure CI/CD pipeline secret management
  2. Explore Key Vault integration with Azure Kubernetes Service using the CSI Secrets Store driver
  3. Set up automated secret rotation using Azure Functions and Key Vault events

Related Articles

Thorsteinn Halldorsson Senior Cloud Engineer

Senior Cloud Engineer with 25+ years of hands-on experience across the datacenter-to-cloud stack: fiber SAN and disk storage, IBM/Lenovo blade and Dell/HP/Lenovo servers, Hyper-V and VMware clusters, and SQL and Remote Desktop Services (RDS) clusters. Deep in the Microsoft platform — Active Directory, PKI/certificate services, SQL, Power BI, Dynamics 365 Business Central (NAV) and AX (Axapta), Microsoft 365, Entra, and Intune — with a focus on Azure operations, FinOps, and applying AI tools like GitHub Copilot and Claude in real workflows. Writes practical, no-nonsense guides for IT professionals who need to ship real solutions.

Leave a Reply

Your email address will not be published. Required fields are marked *