Skip to main content

Azure Key Vault

Short Introduction

Azure Key Vault is a cloud service for securely storing and accessing secrets, keys, and certificates. It provides centralized storage for application secrets with hardware security module (HSM) protection and fine-grained access control.

Official Definition

"Azure Key Vault is a tool for securely storing and accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, or cryptographic keys."

Setup and Deployment Steps

Azure CLI Setup

# Create Key Vault
az keyvault create --name mykeyvault --resource-group myResourceGroup --location eastus --enabled-for-template-deployment

# Add secrets
az keyvault secret set --vault-name mykeyvault --name "ConnectionString" --value "Server=myserver;Database=mydb;User Id=myuser;Password=mypass;"

# Add certificate
az keyvault certificate import --vault-name mykeyvault --name "ssl-cert" --file certificate.pfx

# Create managed identity for app
az webapp identity assign --name mywebapp --resource-group myResourceGroup

# Grant access to Key Vault
az keyvault set-policy --name mykeyvault --object-id <managed-identity-object-id> --secret-permissions get list

Bicep Template

resource keyVault 'Microsoft.KeyVault/vaults@2023-02-01' = {
name: 'mykeyvault'
location: resourceGroup().location
properties: {
tenantId: subscription().tenantId
sku: {
family: 'A'
name: 'standard'
}
accessPolicies: []
enabledForTemplateDeployment: true
enabledForDiskEncryption: true
enabledForDeployment: true
}
}

resource secret 'Microsoft.KeyVault/vaults/secrets@2023-02-01' = {
parent: keyVault
name: 'ConnectionString'
properties: {
value: 'Server=myserver;Database=mydb;Integrated Security=true;'
}
}

Typical Usage and Integration with .NET Apps

NuGet Packages

<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.0" />
<PackageReference Include="Azure.Identity" Version="1.10.3" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.5.0" />

Configuration Integration

// Program.cs
using Azure.Identity;
using Azure.Extensions.AspNetCore.Configuration.Secrets;

var builder = WebApplication.CreateBuilder(args);

// Add Key Vault configuration
if (!builder.Environment.IsDevelopment())
{
var keyVaultUri = builder.Configuration["KeyVaultUri"];
builder.Configuration.AddAzureKeyVault(
new Uri(keyVaultUri),
new DefaultAzureCredential());
}

// Alternative: Specific credential
// builder.Configuration.AddAzureKeyVault(
// new Uri(keyVaultUri),
// new ManagedIdentityCredential());

var app = builder.Build();

Direct Key Vault Access Service

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

public interface IKeyVaultService
{
Task<string> GetSecretAsync(string secretName);
Task SetSecretAsync(string secretName, string secretValue);
Task<IEnumerable<string>> ListSecretsAsync();
Task DeleteSecretAsync(string secretName);
}

public class KeyVaultService : IKeyVaultService
{
private readonly SecretClient _secretClient;
private readonly ILogger<KeyVaultService> _logger;

public KeyVaultService(IConfiguration configuration, ILogger<KeyVaultService> logger)
{
var keyVaultUri = configuration["KeyVaultUri"];
_secretClient = new SecretClient(new Uri(keyVaultUri), new DefaultAzureCredential());
_logger = logger;
}

public async Task<string> GetSecretAsync(string secretName)
{
try
{
var secret = await _secretClient.GetSecretAsync(secretName);
return secret.Value.Value;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Failed to retrieve secret: {secretName}");
throw;
}
}

public async Task SetSecretAsync(string secretName, string secretValue)
{
try
{
await _secretClient.SetSecretAsync(secretName, secretValue);
_logger.LogInformation($"Secret {secretName} updated successfully");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Failed to set secret: {secretName}");
throw;
}
}

public async Task<IEnumerable<string>> ListSecretsAsync()
{
var secretNames = new List<string>();
await foreach (var secret in _secretClient.GetPropertiesOfSecretsAsync())
{
secretNames.Add(secret.Name);
}
return secretNames;
}

public async Task DeleteSecretAsync(string secretName)
{
await _secretClient.StartDeleteSecretAsync(secretName);
_logger.LogInformation($"Secret {secretName} deleted");
}
}

Using Secrets in Controllers

[ApiController]
[Route("api/[controller]")]
public class ConfigController : ControllerBase
{
private readonly IConfiguration _configuration;
private readonly IKeyVaultService _keyVaultService;

public ConfigController(IConfiguration configuration, IKeyVaultService keyVaultService)
{
_configuration = configuration;
_keyVaultService = keyVaultService;
}

[HttpGet("database-connection")]
public async Task<IActionResult> GetDatabaseConnection()
{
// This automatically comes from Key Vault if configured
var connectionString = _configuration.GetConnectionString("DefaultConnection");

// Or get directly from Key Vault service
var directSecret = await _keyVaultService.GetSecretAsync("ConnectionString");

return Ok(new { HasConnection = !string.IsNullOrEmpty(connectionString) });
}
}

Certificate Management

using Azure.Security.KeyVault.Certificates;

public class CertificateService
{
private readonly CertificateClient _certificateClient;

public CertificateService(string keyVaultUri)
{
_certificateClient = new CertificateClient(new Uri(keyVaultUri), new DefaultAzureCredential());
}

public async Task<X509Certificate2> GetCertificateAsync(string certificateName)
{
var certificate = await _certificateClient.DownloadCertificateAsync(certificateName);
return certificate.Value;
}
}

Use Cases

  • Secure storage of connection strings and API keys
  • Certificate management for SSL/TLS
  • Encryption key management
  • Database passwords and service credentials
  • OAuth client secrets
  • Configuration secrets for different environments

When to Use vs Alternatives

Use Azure Key Vault when

  • Centralized secret management across multiple applications
  • Compliance requirements for secret storage
  • Integration with Azure services and managed identities
  • Hardware security module (HSM) protection needed
  • Audit logging of secret access required

Don't use when

  • Simple applications with few secrets
  • Cost optimization is critical for small projects
  • Secrets don't need centralized management
  • Non-Azure environments primarily

Alternatives

  • Azure: App Configuration (for non-secret config), Azure Managed HSM
  • AWS: AWS Secrets Manager, AWS Systems Manager Parameter Store
  • GCP: Secret Manager
  • Open Source: HashiCorp Vault, Kubernetes Secrets

Market Pros/Cons and Cost Considerations

Pros

  • Hardware security module (HSM) backing
  • Integration with Azure Active Directory
  • Automatic secret rotation capabilities
  • Comprehensive audit logging
  • Managed identities eliminate credential management

Cons

  • Additional complexity for simple scenarios
  • Network dependency for secret retrieval
  • Cost for high-volume secret operations
  • Learning curve for proper implementation

Cost Considerations

  • Standard tier: ~$0.03 per 10,000 transactions
  • Premium tier (HSM): ~$1.00 per 10,000 transactions + $5/hour per HSM
  • Certificate operations: ~$3.00 per certificate request
  • No charge for storage of secrets, keys, and certificates