Managing Azure Key Vault with Terraform
Learn how to set up and manage Azure Key Vault for secure secrets, keys, and certificates management using Terraform
Managing Azure Key Vault with Terraform
Azure Key Vault is a cloud service for securely storing and accessing secrets, keys, and certificates. This guide demonstrates how to manage Azure Key Vault using Terraform.
Video Tutorial
Learn more about managing Azure Key Vault with Terraform in this comprehensive video tutorial:
Prerequisites
- Azure CLI configured with appropriate permissions
- Terraform installed (version 1.0.0 or later)
- Azure subscription with Key Vault access
- Resource group created
Project Structure
terraform-azure-keyvault/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── keyvault/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── policies/
└── key_vault_policy.json
Key Vault Configuration
Create modules/keyvault/main.tf
:
# Key Vault
resource "azurerm_key_vault" "main" {
name = "${var.project_name}-kv"
location = var.location
resource_group_name = var.resource_group_name
enabled_for_disk_encryption = true
tenant_id = data.azurerm_client_config.current.tenant_id
soft_delete_retention_days = 7
purge_protection_enabled = true
sku_name = "standard"
network_acls {
default_action = "Deny"
bypass = "AzureServices"
ip_rules = var.allowed_ip_ranges
virtual_network_subnet_ids = var.subnet_ids
}
tags = var.tags
}
# Access Policy
resource "azurerm_key_vault_access_policy" "example" {
key_vault_id = azurerm_key_vault.main.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
key_permissions = [
"Get",
"List",
"Create",
"Delete",
"Update",
"Import",
"Backup",
"Restore",
"Recover"
]
secret_permissions = [
"Get",
"List",
"Set",
"Delete",
"Backup",
"Restore",
"Recover"
]
certificate_permissions = [
"Get",
"List",
"Create",
"Import",
"Update",
"Delete",
"Backup",
"Restore",
"Recover"
]
}
# Secrets
resource "azurerm_key_vault_secret" "example" {
name = "example-secret"
value = var.secret_value
key_vault_id = azurerm_key_vault.main.id
tags = var.tags
depends_on = [
azurerm_key_vault_access_policy.example
]
}
# Keys
resource "azurerm_key_vault_key" "example" {
name = "example-key"
key_vault_id = azurerm_key_vault.main.id
key_type = "RSA"
key_size = 2048
key_opts = [
"decrypt",
"encrypt",
"sign",
"unwrapKey",
"verify",
"wrapKey",
]
depends_on = [
azurerm_key_vault_access_policy.example
]
}
# Certificates
resource "azurerm_key_vault_certificate" "example" {
name = "example-cert"
key_vault_id = azurerm_key_vault.main.id
certificate_policy {
issuer_parameters {
name = "Self"
}
key_properties {
exportable = true
key_size = 2048
key_type = "RSA"
reuse_key = true
}
lifetime_action {
action {
action_type = "AutoRenew"
}
trigger {
days_before_expiry = 30
}
}
secret_properties {
content_type = "application/x-pkcs12"
}
x509_certificate_properties {
# Server Authentication = 1.3.6.1.5.5.7.3.1
# Client Authentication = 1.3.6.1.5.5.7.3.2
extended_key_usage = ["1.3.6.1.5.5.7.3.1"]
key_usage = [
"cRLSign",
"dataEncipherment",
"digitalSignature",
"keyAgreement",
"keyCertSign",
"keyEncipherment",
]
subject_alternative_names {
dns_names = ["example.com", "www.example.com"]
}
subject = "CN=example.com"
validity_in_months = 12
}
}
depends_on = [
azurerm_key_vault_access_policy.example
]
}
## Private Endpoint Configuration
1. **Private Endpoint Setup**
```hcl
resource "azurerm_private_endpoint" "keyvault" {
name = "${var.project_name}-pe"
location = var.location
resource_group_name = var.resource_group_name
subnet_id = var.subnet_id
private_service_connection {
name = "${var.project_name}-psc"
private_connection_resource_id = azurerm_key_vault.main.id
is_manual_connection = false
subresource_names = ["vault"]
}
private_dns_zone_group {
name = "default"
private_dns_zone_ids = [azurerm_private_dns_zone.keyvault.id]
}
}
resource "azurerm_private_dns_zone" "keyvault" {
name = "privatelink.vaultcore.azure.net"
resource_group_name = var.resource_group_name
}
resource "azurerm_private_dns_zone_virtual_network_link" "keyvault" {
name = "${var.project_name}-vnet-link"
resource_group_name = var.resource_group_name
private_dns_zone_name = azurerm_private_dns_zone.keyvault.name
virtual_network_id = var.vnet_id
}
Monitoring Configuration
- Diagnostic Settings
resource "azurerm_monitor_diagnostic_setting" "keyvault" {
name = "${var.project_name}-diag"
target_resource_id = azurerm_key_vault.main.id
log_analytics_workspace_id = var.log_analytics_workspace_id
log {
category = "AuditEvent"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
metric {
category = "AllMetrics"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
}
- Alert Rules
resource "azurerm_monitor_metric_alert" "keyvault" {
name = "${var.project_name}-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_key_vault.main.id]
description = "Alert when total API hits exceeds threshold"
criteria {
metric_namespace = "Microsoft.KeyVault/vaults"
metric_name = "ServiceApiHit"
aggregation = "Total"
operator = "GreaterThan"
threshold = 1000
}
action {
action_group_id = var.action_group_id
}
}
Backup Configuration
- Automated Backup
resource "azurerm_key_vault_backup" "example" {
key_vault_id = azurerm_key_vault.main.id
storage_account_id = var.backup_storage_account_id
backup_container_name = "keyvault-backups"
backup_folder_path = "backups"
}
resource "azurerm_automation_schedule" "backup" {
name = "${var.project_name}-backup-schedule"
resource_group_name = var.resource_group_name
automation_account_name = var.automation_account_name
frequency = "Day"
interval = 1
timezone = "UTC"
start_time = "2025-01-01T00:00:00Z"
description = "Schedule for Key Vault backup"
}
Best Practices
-
Security
- Use Private Endpoints
- Enable Soft Delete
- Enable Purge Protection
- Regular access reviews
-
Access Control
- Use Managed Identities
- Implement least privilege
- Regular rotation
- Monitor access
-
Monitoring
- Enable diagnostics
- Configure alerts
- Regular audits
- Monitor performance
-
Backup and Recovery
- Regular backups
- Test recovery
- Document procedures
- Maintain compliance
Advanced Features
- Managed HSM
resource "azurerm_key_vault_managed_hardware_security_module" "example" {
name = "${var.project_name}-hsm"
resource_group_name = var.resource_group_name
location = var.location
sku_name = "Standard_B1"
purge_protection_enabled = true
tenant_id = data.azurerm_client_config.current.tenant_id
admin_object_ids = [
data.azurerm_client_config.current.object_id
]
network_acls {
bypass = "AzureServices"
default_action = "Deny"
ip_rules = var.allowed_ip_ranges
}
}
- Role-Based Access Control
resource "azurerm_role_assignment" "keyvault" {
scope = azurerm_key_vault.main.id
role_definition_name = "Key Vault Administrator"
principal_id = var.admin_group_id
}
Conclusion
You’ve learned how to manage Azure Key Vault using Terraform. This setup provides:
- Secure secret management
- Access control
- Monitoring and alerts
- Backup and recovery
Remember to:
- Monitor access
- Rotate secrets regularly
- Maintain backups
- Review security settings