Terraform - 如何在单个 TF 运行 中授予 Azure API 对密钥保管库的管理访问权限?

Terraform - How to grant Azure API Management access to a key vault in a single TF run?

我有一个 PowerShell 脚本,它使用存储在 Azure 密钥保管库中的 SSL 证书创建带有自定义 HTTPS 域的 Azure API 管理服务。我正在将其转换为 Terraform,但 运行 出现了问题。

Terraform 使用“系统分配”身份创建 APIM,并且需要在密钥库中向该 ID 授予访问 SSL 证书的权限,因此可以使用以下方式创建 APIM自定义域。但是,在创建 APIM 之前,Terraform 无法授予 ID 对密钥保管库的访问权限,但是在 ID 被授予对密钥保管库的访问权限之前,无法创建 APIM。

相关片段:

resource "azurerm_api_management" "apim" {
  name                 = var.apim_name
  resource_group_name  = var.rg_name
  location             = var.location
  publisher_name       = var.publisher_name
  publisher_email      = var.publisher_email
  sku_name             = var.sku_name_capacity
  virtual_network_type = var.vnet_type

  hostname_configuration {
    dynamic "proxy" {
      for_each = var.gateway_endpoint_custom_domains
      content {
        host_name    = proxy.value
        key_vault_id = var.ssl_cert_secret_id
      }
    }
  }

  identity {
    # User assigned identities are not supported yet
    type = "SystemAssigned"
  }

  virtual_network_configuration {
      subnet_id = var.subnet_id
  }
}

resource "azurerm_key_vault_access_policy" "apim_said" {
  key_vault_id       = var.kv_id
  object_id          = var.apim_said_principal_id
  tenant_id          = data.azurerm_client_config.current.tenant_id
  secret_permissions = [
    "Get",
    "List"
  ]
}

在 PowerShell 中,这可以在一个脚本中通过三个步骤完成:

  1. 创建 APIM 及其“系统分配”标识
  2. 在 Key Vault 中授予 ID 权限,以便 APIM 可以访问 SSL 证书
  3. 修改 APIM 以添加自定义 HTTPS 域

据我了解,Terraform 无法在单个步骤中执行这三个步骤,因为 Terraform 想要将资源作为一个整体创建,而不是稍后创建和修改。

Terraform 是否可以通过使用模块来类似于PowerShell 脚本的使用?我在 Azure 门户中注意到用户分配的身份处于预览状态,但 Terraform 尚不支持此功能。

如果多次 Terraform 运行是唯一的选择,那么使用 Terraform Cloud 构建和触发后续运行的“正确”方法是什么?据我所知,唯一可行的方法是如果我有两个具有共享状态的 Terraform Cloud 工作区,但我希望有一个更优雅的解决方案。

要创建 APIM、授予对 Keyvault 的访问权限并设置域设置,您可以使用类似下面的内容来解决问题:

provider "azurerm"{
features{}
}

data "azurerm_client_config" "current" {}

resource "azurerm_api_management" "apim" {
  name                 = "ansuman-apim"
  resource_group_name  = "resourcegroup"
  location             = "West US 2"
  publisher_name       = "company"
  publisher_email      = "ansumanbal@xyx.com"
  sku_name             = "Developer_1"

  identity {
    # User assigned identities are not supported yet
    type = "SystemAssigned"
  }
}

resource "azurerm_key_vault_access_policy" "apim_said" {
  key_vault_id       = "/subscriptions/b83c1ed3-xxxx-xxxxx-xxxxx-xxxx/resourceGroups/resourcegroup/providers/Microsoft.KeyVault/vaults/testkeyvautlansuman007"
  object_id          = azurerm_api_management.apim.identity[0].principal_id
  tenant_id          = data.azurerm_client_config.current.tenant_id
  secret_permissions = [
    "Get",
    "List"
  ]
}

resource "null_resource" "previous" {}

resource "time_sleep" "wait_60_seconds" {
  depends_on = [azurerm_key_vault_access_policy.apim_said]

  create_duration = "60s"
}

resource "azurerm_api_management_custom_domain" "example" {
  api_management_id = azurerm_api_management.apim.id

  proxy {
    host_name    = "ansuman.xyz.com"
    key_vault_id = "https://testkeyvautlansuman007.vault.azure.net/secrets/test/3a6ebe74364xxxxxxxxxxx"
  }

depends_on = [
  time_sleep.wait_60_seconds
]
}

注意: 由于 azurerm_api_management 在从 Terraform 创建时无法访问 keyvault 的缺点,添加了 azurerm_api_management_custom_domain。因此,您可以创建具有身份的 APIM 并授予对 keyvault 的访问权限,然后使用自定义域块将 host_configurations 添加到您创建的 APIM。

输出: