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 通过规范化的接口定义和灵活的模块内部实现,既保证了用户使用体验的一致性,又允许模块根据具体资源的差异进行合理扩展。这种模式既提高了模块间的可组合性,也降低了用户迁移不同资源时的学习和适配成本。

results matching ""

    No results matching ""