Azure Key Vault Secrets Module
This OpenTofu module provisions an Azure Key Vault with configurable purge protection/soft delete retention and RBAC authorization, a User-Assigned Managed Identity with read access to secrets, and network ACLs for secure access.
Features
- Key Vault: Both purge protection and soft delete retention are configurable, RBAC authorization enabled
- Reader Identity: User-assigned managed identity granted
Key Vault Secrets Userrole - Network ACLs: Subnet service endpoints + optional IP allowlist; Azure Services bypass enabled
- Tagging: Standard
submodule = "Secrets"tag applied
Requirements
| Name | Version |
|---|---|
| azurerm | ~> 4.0 |
| random | ~> 3.0 |
Providers
| Name | Version |
|---|---|
| azurerm | ~> 4.0 |
Modules
No modules.
Resources
| Name | Type |
|---|---|
| azurerm_key_vault.vault | resource |
| azurerm_role_assignment.reader_secrets | resource |
| azurerm_user_assigned_identity.reader | resource |
| azurerm_client_config.current | data source |
Inputs
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| allowed_ips | List of IPs to whitelist for Key Vault access | list(string) |
[] |
no |
| allowed_subnet_ids | The IDs of the subnets that can access the Key Vault (service endpoints) | list(string) |
n/a | yes |
| base_name [d] | The base name prefix used for resources | string |
n/a | yes |
| location [d] | Azure region | string |
n/a | yes |
| purge_protection_enabled | Enable purge protection (requires support ticket to purge deleted secrets) | bool |
false |
no |
| resource_group_name [d] | The name of the resource group | string |
n/a | yes |
| sku_name | The SKU of the Key Vault (standard or premium) | string |
"standard" |
no |
| soft_delete_retention_days | Days to retain soft-deleted secrets | number |
7 |
no |
| suffix [d] | A suffix to append to the keyvault name. | string |
n/a | yes |
| tags | Tags to apply to resources | map(string) |
{} |
no |
[d] Destructive: changing this input forces one or more resources to be destroyed and recreated (an OpenTofu/Terraform replacement) rather than updated in place.
Outputs
| Name | Description |
|---|---|
| identity_client_id | The client ID of the reader identity |
| identity_id | The resource ID of the user-assigned identity with read access |
| identity_principal_id | The principal ID of the reader identity, used for further RBAC assignments |
| vault_id | The resource ID of the Key Vault |
| vault_name | The name of the Key Vault |
| vault_uri | The URI of the Key Vault |
Example Usage
module "secrets" {
source = "oci://acrmerkalisdist0c66.azurecr.io/modules/azure/secrets?tag=<module-version>"
base_name = "myapp-production"
suffix = "1a2b"
resource_group_name = "rg-myapp-production"
location = "eastus"
allowed_subnet_ids = ["/subscriptions/.../subnets/my-subnet"]
allowed_ips = ["203.0.113.1/32"]
sku_name = "standard"
tags = {
Environment = "Production"
Owner = "DevOps"
}
}
Resources Created
azurerm_key_vault— Key Vault with a (default) soft-delete retention of 7 days, RBAC auth, network ACLsazurerm_user_assigned_identity— Reader identity scoped to the vaultazurerm_role_assignment—Key Vault Secrets Userrole on the vault for the identity
Network Requirements
The subnets in allowed_subnet_ids must have the Microsoft.KeyVault service endpoint enabled:
resource "azurerm_subnet" "example" {
service_endpoints = ["Microsoft.KeyVault"]
}
The vault uses default_action = "Deny" with bypass = "AzureServices" so trusted Azure platform services can still reach it.
Security Considerations
1. If purge protection is enabled it cannot be disabled after creation
2. RBAC is used instead of access policies
3. The created reader identity gets read-only access (
Key Vault Secrets User); write access requires separate role assignment4. Network ACLs deny all traffic by default; only subnets in
allowed_subnet_idsand IPs inallowed_ipscan reach the vault5. Because network isolation is enforced by denying access to all non-whitelisted IPs, Terraform/OpenTofu plans/applies will fail (in the survey phase) with
403 Forbiddenif the Terraform/OpenTofu runner's IP address is not contained inallowed_ips.
Available versions
v0.9.1