You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform重复部署时Azure Data Factory的Key Vault访问策略反复删除重建的问题咨询

解决Terraform部署Azure Key Vault与ADF访问策略循环变更问题

这个问题我之前也碰到过,根源在于Terraform管理Azure Key Vault访问策略的两种方式不能混用——嵌套在azurerm_key_vault里的access_policy块和独立的azurerm_key_vault_access_policy资源是互斥的,Terraform会把它们当成两种完全不同的管理模式,从而导致循环变更的问题:

当你在azurerm_key_vault资源里定义了access_policy块,Terraform会认为这些是Key Vault上所有应该存在的访问策略。每次部署时,Terraform对比状态和实际资源,发现独立创建的ADF策略不在嵌套列表里,就会把它移除;而下一次部署时,独立的azurerm_key_vault_access_policy.adfpolicy资源又会被重新创建,因为Terraform状态里这个资源是存在的,实际资源中却没有,最终形成循环。

下面是两种可行的解决方案:


方案一:将ADF访问策略合并到Key Vault的嵌套access_policy块中

把所有访问策略统一交给azurerm_key_vault资源管理,删除独立的ADF策略资源:

resource "azurerm_key_vault" "kv" {
  name = "${lower("${var.applicationName}-${var.environment}")}-akv"
  location = azurerm_resource_group.myresourcegroup.location
  resource_group_name = azurerm_resource_group.myresourcegroup.name
  enabled_for_disk_encryption = true
  tenant_id = data.azurerm_client_config.current.tenant_id
  sku_name = var.skuname
  purge_protection_enabled = false

  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = data.azurerm_client_config.current.object_id
    key_permissions = [ "Get","List","Create" ]
    secret_permissions = [ "Backup", "Delete", "Get", "List", "Recover", "Restore", "Set", "Purge"]
    storage_permissions = [ "Get","List","Set"]
  }

  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = var.group_object_id
    key_permissions = [ "Get","List","Create" ]
    secret_permissions = [ "Backup", "Delete", "Get", "List", "Recover", "Restore", "Set", "Purge" ]
    storage_permissions = [ "Get","List","Set" ]
  }

  # 添加ADF的访问策略到嵌套块中
  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = azurerm_data_factory.adf.identity[0].principal_id
    key_permissions = [ "Get", "Create", "List", "Restore", "Recover", "Unwrapkey", "Wrapkey", "Purge", "Encrypt", "Decrypt", "Sign", "Verify" ]
    secret_permissions = [ "Get", "List" ]
  }

  network_acls {
    bypass = "AzureServices"
    default_action = "Deny"
    ip_rules = ["198....."]
  }
}

# 删除这个独立的ADF策略资源
# resource "azurerm_key_vault_access_policy" "adfpolicy" {
#   key_vault_id = azurerm_key_vault.kv.id
#   tenant_id = data.azurerm_client_config.current.tenant_id
#   object_id = azurerm_data_factory.adf.identity[0].principal_id
#   key_permissions = [ "Get", "Create", "List", "Restore", "Recover", "Unwrapkey", "Wrapkey", "Purge", "Encrypt", "Decrypt", "Sign", "Verify" ]
#   secret_permissions = [ "Get", "List" ]
#   depends_on = [azurerm_resource_group.myresourcegroup, azurerm_virtual_network.vnet, azurerm_subnet.public_subnet, azurerm_key_vault.kv, azurerm_data_factory.adf]
# }

方案二:移除Key Vault嵌套策略,全部使用独立的azurerm_key_vault_access_policy资源

这种方式更适合动态添加策略的场景,所有访问策略都通过独立资源定义:

resource "azurerm_key_vault" "kv" {
  name = "${lower("${var.applicationName}-${var.environment}")}-akv"
  location = azurerm_resource_group.myresourcegroup.location
  resource_group_name = azurerm_resource_group.myresourcegroup.name
  enabled_for_disk_encryption = true
  tenant_id = data.azurerm_client_config.current.tenant_id
  sku_name = var.skuname
  purge_protection_enabled = false

  # 移除所有嵌套的access_policy块
  network_acls {
    bypass = "AzureServices"
    default_action = "Deny"
    ip_rules = ["198....."]
  }
}

# 原客户端的访问策略
resource "azurerm_key_vault_access_policy" "client_policy" {
  key_vault_id = azurerm_key_vault.kv.id
  tenant_id = data.azurerm_client_config.current.tenant_id
  object_id = data.azurerm_client_config.current.object_id
  key_permissions = [ "Get","List","Create" ]
  secret_permissions = [ "Backup", "Delete", "Get", "List", "Recover", "Restore", "Set", "Purge"]
  storage_permissions = [ "Get","List","Set"]
}

# 原组的访问策略
resource "azurerm_key_vault_access_policy" "group_policy" {
  key_vault_id = azurerm_key_vault.kv.id
  tenant_id = data.azurerm_client_config.current.tenant_id
  object_id = var.group_object_id
  key_permissions = [ "Get","List","Create" ]
  secret_permissions = [ "Backup", "Delete", "Get", "List", "Recover", "Restore", "Set", "Purge" ]
  storage_permissions = [ "Get","List","Set" ]
}

# 保留ADF的独立访问策略
resource "azurerm_key_vault_access_policy" "adfpolicy" {
  key_vault_id = azurerm_key_vault.kv.id
  tenant_id = data.azurerm_client_config.current.tenant_id
  object_id = azurerm_data_factory.adf.identity[0].principal_id
  key_permissions = [ "Get", "Create", "List", "Restore", "Recover", "Unwrapkey", "Wrapkey", "Purge", "Encrypt", "Decrypt", "Sign", "Verify" ]
  secret_permissions = [ "Get", "List" ]
  depends_on = [azurerm_data_factory.adf]
}

注意事项

  1. 修改代码后,先运行terraform plan确认变更符合预期,再执行terraform apply;
  2. 你的ADF同时使用了系统分配和用户分配身份,azurerm_data_factory.adf.identity[0].principal_id指向的是系统分配身份,如果要使用用户分配身份,需要改为azurerm_data_factory.adf.identity[1].principal_id或直接引用用户分配身份的principal_id;
  3. 两种方案选其一即可,不要混合使用嵌套策略和独立策略资源。

内容的提问来源于stack exchange,提问作者venkat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 01:42:38