Terraform Plan阶段Key Vault证书访问权限错误解决方案咨询
问题
部署应用网关时遇到循环依赖:需要引用Key Vault中的证书,但运行Terraform的服务主体要等apply完成后才能获得Key Vault的访问权限,导致plan阶段因无权限读取证书而失败,无法生成Plan文件进而无法执行apply。已确认访问策略包含证书的Get权限,求除UI手动配置权限外的解决办法。
Key Vault 配置
resource "azurerm_key_vault" "web" { name = lower(format("az-kv-web-%s-%s-%s", var.instance.environment, var.instance.az-region, var.instance.serial)) location = azurerm_resource_group.web.location resource_group_name = azurerm_resource_group.web.name sku_name = var.instance.key-vault.sku-name # Azure AD tenant tenant_id = var.instance.aad-tenant-id dynamic "access_policy" { for_each = var.instance.key-vault.access content { tenant_id = var.instance.aad-tenant-id object_id = access_policy.value.object-id certificate_permissions = access_policy.value.cert-permissions key_permissions = access_policy.value.key-permissions secret_permissions = access_policy.value.secret-permissions storage_permissions = access_policy.value.storage-permissions } } }
证书数据源配置
data "azurerm_key_vault_certificate" "gateway" { name = var.gateway.certificate-name key_vault_id = var.key-vault.id }
错误信息
╷ │ Error: reading Key Vault Certificate: keyvault.BaseClient#GetCertificate: Failure responding to request: StatusCode=403 -- Original Error: autorest/azure: Service returned an error. Status=403 Code="Forbidden" Message="The user, group or application 'appid=***;oid=***;numgroups=3;iss=https://sts.windows.net/***/' does not have certificates get permission on key vault 'az-kv-web-dev-eastus-001;location=eastus'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287" InnerError={"code":"ForbiddenByPolicy"} │ │ with module.web["001"].module.app-gateway.data.azurerm_key_vault_certificate.gateway, │ on modules\app-gateway\main.tf line 123, in data "azurerm_key_vault_certificate" "gateway": │ 123: data "azurerm_key_vault_certificate" "gateway" { │ ╵
解决办法
拆分Terraform执行阶段
将部署拆分为两个独立步骤:- 第一步仅部署Key Vault及对应的访问策略,执行
terraform plan -target=azurerm_key_vault.web和terraform apply -target=azurerm_key_vault.web,确保服务主体获得证书Get权限。 - 第二步执行完整的
terraform plan和terraform apply,此时服务主体已有权限读取证书,数据源能正常加载。
- 第一步仅部署Key Vault及对应的访问策略,执行
使用远程状态分离资源
将Key Vault和应用网关的代码拆分为两个独立的Terraform工作区:- 第一个工作区专门管理Key Vault及访问策略,部署完成后通过远程状态(如Azure Storage存储状态文件)共享Key Vault的ID。
- 第二个工作区引用远程状态中的Key Vault ID,配置应用网关和证书数据源。由于Key Vault已提前部署,服务主体权限已生效,
plan阶段可正常读取证书。
通过null_resource触发权限同步
在代码中添加null_resource,通过本地执行Azure CLI命令,在Key Vault创建后立即为服务主体添加权限,再依赖此资源加载证书数据源:resource "null_resource" "grant_kv_permission" { depends_on = [azurerm_key_vault.web] provisioner "local-exec" { command = <<EOT az keyvault set-policy --name ${azurerm_key_vault.web.name} --resource-group ${azurerm_resource_group.web.name} --spn ${var.service_principal_app_id} --certificate-permissions get EOT } } data "azurerm_key_vault_certificate" "gateway" { name = var.gateway.certificate-name key_vault_id = var.key-vault.id depends_on = [null_resource.grant_kv_permission] }注意:运行Terraform的环境需已安装Azure CLI并完成身份验证,且服务主体本身具备修改Key Vault访问策略的权限。
内容的提问来源于stack exchange,提问作者Jonathon Anderson
相关产品推荐
相关产品推荐

