1.3.5.1. AVM 的 User Managed Key 接口
我们在前面提到过,我们会根据情况,为模块添加一个或多个标准的接口 variable
块,这样做有许多的好处。本节我们将详细叙述其中一个接口的定义,以及不同模块中对其的实现,使读者能够更直观地理解我们的意图。
在 Azure Verified Modules (AVM) 中,Customer Managed Keys(CMK)接口的定义是:
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
}
- 结构说明:
key_vault_resource_id
(必需): 指向 Azure Key Vault 或是 Azure Hardware Security Module(HSM) 的资源 ID。key_name
(必需): Key Vault 或是 HSM 中的密钥名称。key_version
(可选): 密钥的特定版本(可以为空)。user_assigned_identity
(可选): 一个对象,包含resource_id
字段,用来指定访问 Key Vault 的用户分配托管身份(UAI)。
1.3.5.1.1. 不同模块对该接口的不同实现
熟悉通用编程语言的读者应能理解接口(Interface)的概念:接口定义了一组标准的方法和属性,但具体的实现可以根据类型不同而各异。在 AVM 中,CMK 接口也遵循了类似的设计理念。
所有支持 CMK 的模块,都会暴露完全一致的 var.customer_managed_key
输入变量。用户在配置该参数时,无需关心模块内部实现细节,只需提供符合接口定义的值,模块内部便会完成 CMK 的接入。
不过,由于不同 Azure 资源在平台侧对于 Customer Managed Key 支持的实现细节各不相同,具体模块内部连接到 CMK 的方式也有所区别。
例如,在 avm-res-storage-storageaccount
模块中,CMK 是这样实现的:
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`."
}
}
}
在 Storage Account 模块中,该接口通过 azurerm_storage_account_customer_managed_key
被接入了 Storage Account 资源,而在 avm-res-cognitiveservices-account
模块中的实现则不同:
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)
}
}
...
}
可以看到,在 avm-res-cognitiveservices-account
模块中,CMK 的实现更复杂一些,需要判断 Cognitive Account 的 kind
以及 CMK 是否使用的是 HSM 中的密钥。
1.3.5.1.2. 小结
Azure Verified Modules 通过规范化的接口定义和灵活的模块内部实现,既保证了用户使用体验的一致性,又允许模块根据具体资源的差异进行合理扩展。这种模式既提高了模块间的可组合性,也降低了用户迁移不同资源时的学习和适配成本。