1.3.5.1. User Managed Key Interface in AVM
As mentioned in the previous section, we add one or more standard variable blocks to modules depending on the situation, which offers many benefits. In this section, we will detail the definition of one such interface and its implementation across different modules, allowing readers to intuitively understand our intent.
In Azure Verified Modules (AVM), the Customer Managed Keys (CMK) interface is defined as follows:
variable "customer_managed_key" {
type = object({
key_vault_resource_id = string
key_name = string
key_version = optional(string, null)
user_assigned_identity = optional(object({
resource_id = string
}), null)
})
default = null
}
- Structure Description:
key_vault_resource_id(Required): The Resource ID pointing to the Azure Key Vault or Azure Hardware Security Module (HSM).key_name(Required): The name of the key within the Key Vault or HSM.key_version(Optional): The specific version of the key (can be null).user_assigned_identity(Optional): An object containing aresource_idfield, used to specify the User Assigned Identity (UAI) for accessing the Key Vault.
1.3.5.1.1. Different Implementations of the Interface Across Modules
Readers familiar with general-purpose programming languages should understand the concept of an Interface: an interface defines a set of standard methods and properties, but the concrete implementation can vary by type. In AVM, the CMK interface follows a similar design philosophy.
All modules supporting CMK expose an identical var.customer_managed_key input variable. When configuring this parameter, users do not need to worry about the internal implementation details of the module; they simply provide values conforming to the interface definition, and the module handles the CMK integration internally.
However, since the implementation details for Customer Managed Key support vary across different Azure resources on the platform side, the specific way modules connect to the CMK differs internally.
For example, in the avm-res-storage-storageaccount module, CMK is implemented as follows:
resource "azurerm_storage_account_customer_managed_key" "this" {
count = var.customer_managed_key != null ? 1 : 0
key_name = var.customer_managed_key.key_name
storage_account_id = azurerm_storage_account.this.id
key_vault_id = var.customer_managed_key.key_vault_resource_id
key_version = var.customer_managed_key.key_version
user_assigned_identity_id = try(var.customer_managed_key.user_assigned_identity.resource_id, null)
lifecycle {
precondition {
condition = (var.account_kind == "StorageV2" || var.account_tier == "Premium")
error_message = "`var.customer_managed_key` can only be set when the `account_kind` is set to `StorageV2` or `account_tier` set to `Premium`, and the identity type is `UserAssigned`."
}
}
}
In the Storage Account module, this interface connects to the Storage Account resource via azurerm_storage_account_customer_managed_key, whereas the implementation in the avm-res-cognitiveservices-account module is different:
resource "azurerm_cognitive_account_customer_managed_key" "this" {
count = var.customer_managed_key != null && !var.is_hsm_key ? 1 : 0
cognitive_account_id = local.resource_block.id
key_vault_key_id = data.azurerm_key_vault_key.this[0].id
identity_client_id = local.managed_key_identity_client_id
dynamic "timeouts" {
for_each = var.timeouts == null ? [] : [var.timeouts]
content {
create = timeouts.value.create
delete = timeouts.value.delete
read = timeouts.value.read
update = timeouts.value.update
}
}
}
resource "azurerm_ai_services" "this" {
count = var.kind == "AIServices" ? 1 : 0
...
dynamic "customer_managed_key" {
for_each = var.is_hsm_key && var.customer_managed_key != null ? [1] : []
content {
identity_client_id = local.managed_key_identity_client_id
# we'll leave the regular key to `azurerm_cognitive_account_customer_managed_key` resource
managed_hsm_key_id = try(data.azurerm_key_vault_managed_hardware_security_module_key.this[0].versioned_id, null)
}
}
...
}
As shown, the CMK implementation in the avm-res-cognitiveservices-account module is slightly more complex, requiring logic to check the kind of the Cognitive Account and whether the CMK uses a key from an HSM.
1.3.5.1.2. Summary
Through standardized interface definitions and flexible internal implementations, Azure Verified Modules ensure a consistent user experience while allowing reasonable extensions based on specific resource differences. This pattern not only improves composability between modules but also reduces the learning curve and adaptation costs for users when migrating between different resources.