Azure Key Vault
Azure Key Vault is a managed service for storing and controlling access to sensitive material, so secrets don't end up in source code, config files, or CI variables. It handles three kinds of objects:
- Secrets: arbitrary small values such as connection strings, API keys, and passwords.
- Keys: cryptographic keys (RSA, EC) used for signing, encryption, and wrapping. Operations run inside the vault, so private key material never leaves it (with HSM-backed keys, never leaves the HSM).
- Certificates: TLS/SSL certificates with lifecycle management, including auto-renewal with supported CAs.
Tiers: Standard (software-protected keys), Premium (HSM-backed keys), and Managed HSM (a dedicated, single-tenant HSM pool for the strictest compliance needs).
Key features
- Access control: Azure RBAC is the recommended model (access policies are the legacy model). Common roles are Key Vault Secrets User (read secrets), Key Vault Secrets Officer (manage them), Key Vault Crypto User, and Key Vault Administrator.
- Soft delete and purge protection: deleted items can be recovered during a retention period, and purge protection prevents permanent deletion until it ends.
- Versioning: every secret update creates a new version, so you can roll back or rotate gracefully.
- Auditing: logs go to Azure Monitor / Log Analytics.
- Network security: firewall rules and private endpoints.
- Events: Event Grid notifications for things like a secret nearing expiry.
The best practice: no credentials to reach the vault
Your app authenticates to Key Vault with a managed identity, so you don't need a secret to get your secrets. DefaultAzureCredential uses the managed identity when running in Azure, and falls back to your az login or Visual Studio sign-in locally.
1. Create the vault and grant access
az keyvault create --name my-unique-vault --resource-group my-rg \
--location centralindia --enable-rbac-authorization true
az keyvault secret set --vault-name my-unique-vault \
--name "ConnectionStrings--Default" --value "Server=...;Password=..."
# Enable a system-assigned identity on your App Service
az webapp identity assign --name my-unique-app-name --resource-group my-rg
# Let that identity read secrets
az role assignment create \
--role "Key Vault Secrets User" \
--assignee <principalId-from-previous-command> \
--scope $(az keyvault show --name my-unique-vault --query id -o tsv)
For local development, give your own user the same role on the vault, and make sure you're signed in with az login or Visual Studio.
2. Option A: load secrets into IConfiguration (most common)
Install the packages:
dotnet add package Azure.Identity
dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
using Azure.Identity;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddAzureKeyVault(
new Uri("https://my-unique-vault.vault.azure.net/"),
new DefaultAzureCredential());
var app = builder.Build();
// Reads the Key Vault secret "ConnectionStrings--Default"
var cs = builder.Configuration.GetConnectionString("Default");
Key Vault secret names can't contain :, so use -- instead. ConnectionStrings--Default maps to ConnectionStrings:Default. Secrets are loaded at startup, and the provider can refresh periodically if you set a ReloadInterval in AzureKeyVaultConfigurationOptions.
3. Option B: call Key Vault directly with the SDK
dotnet add package Azure.Security.KeyVault.Secrets
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
var client = new SecretClient(
new Uri("https://my-unique-vault.vault.azure.net/"),
new DefaultAzureCredential());
KeyVaultSecret secret = await client.GetSecretAsync("StripeApiKey");
string apiKey = secret.Value;
For keys and certificates, use Azure.Security.KeyVault.Keys (KeyClient and CryptographyClient for encrypt/sign operations) and Azure.Security.KeyVault.Certificates (CertificateClient).
Register the client once via dependency injection rather than creating it per request:
builder.Services.AddSingleton(_ => new SecretClient(
new Uri("https://my-unique-vault.vault.azure.net/"),
new DefaultAzureCredential()));
4. Option C: Key Vault references (no code changes)
In App Service or Azure Functions, set an app setting whose value is a reference:
@Microsoft.KeyVault(SecretUri=https://my-unique-vault.vault.azure.net/secrets/StripeApiKey/)
or
@Microsoft.KeyVault(VaultName=my-unique-vault;SecretName=StripeApiKey)
The platform resolves it using the app's managed identity and injects the value as an ordinary environment variable. Your .NET code just reads IConfiguration as usual. It's the simplest approach when you're already on App Service or Functions, and leaving the version off means the app picks up newer secret versions automatically.
Practical tips
- Cache secrets instead of fetching them on every request. Key Vault has per-vault throttling limits, and each call adds latency.
- Prefer RBAC and least privilege: Secrets User for apps, with write roles reserved for pipelines or admins.
- Use one vault per app and environment (dev/test/prod) so access can be scoped tightly.
- Rotate secrets: set expiry dates, subscribe to the
SecretNearExpiryevent, and have your app tolerate version changes. - Don't log secret values, and avoid putting the vault URI in places where it matters if exposed (the URI isn't secret, but access control should be what protects it).
- Related uses: ASP.NET Core Data Protection keys can be protected with a Key Vault key, and Entra ID app credentials can be certificate-based using Key Vault certificates.
No comments:
Post a Comment
Note: only a member of this blog may post a comment.