Terraform部署Azure Key Vault时403权限错误问题排查
Azure Key Vault Terraform 403权限错误排查
问题描述
我作为DevOps人员,计划通过Terraform创建Azure Key Vault,为开发者配置Get权限,自身拥有该Vault的完整管理权限。执行terraform validate命令未报错,但执行terraform apply时出现403权限错误,错误信息如下:
│ Error: checking for presence of existing Secret "ConnectionStrings--DBContext" (Key Vault "https://deneme-beta.vault.azure.net/"): keyvault.BaseClient#GetSecret: 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=04b071-811ddb-461a-bbee-02f9e1bf7b46;oid=b78911-511d7b-4968-a654-4389ef10196d;numgroups=1;iss=https://sts.windows.net/d07101-51110d-4151-abf2-d14d0729ada3/' does not have secrets get permission on key vault 'deneme-beta;location=germanywestcentral'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287" InnerError={"code":"AccessDenied"} │ │ with azurerm_key_vault_secret.vault_secrets["deneme-beta-ConnectionStrings--DBContext"], │ on main.tf line 59, in resource "azurerm_key_vault_secret" "vault_secrets": │ 59: resource "azurerm_key_vault_secret" "vault_secrets" {
配置文件
locals.tf
locals { contexts = [ { "name" : "deneme-beta", "vars" : [ { "variable" : "ConnectionStrings--DBContext", "value" : "data source=192.168.10.1:1521/beta;password=deneme-test;user id=PRJ" }, { "variable" : "MinioSettings--SecretKey", "value" : "flkjdwfkljdkfjdjkfjdkfjkdjf" }, { "variable" : "RabbitMQConfiguration--Password", "value" : "94j9j9j9j" } ] }, { "name" : "deneme-stage", "vars" : [ { "variable" : "ConnectionStrings--DBContext", "value" : "data source=192.168.10.1:1521/stage;password=deneme-stage;user id=PRJ" }, { "variable" : "MinioSettings--SecretKey", "value" : "dkmkdemmdcmdkmckmdkcmddcdcdcdc" }, { "variable" : "RabbitMQConfiguration--Password", "value" : "223232323" } ] } ] variables = merge([for context in local.contexts : { for vars in context.vars : "${context.name}-${vars.variable}" => { name = context.name variable = vars.variable value = vars.value } }]...) }
provider.tf
terraform { required_version = ">=1.0" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>3.0" } azuread = { source = "hashicorp/azuread" version = "~>2.48" } } } provider "azurerm" { features {} }
main.tf
resource "azurerm_resource_group" "rg" { name = "rg_vault_deneme" location = "germanywestcentral" } data "azurerm_client_config" "current" {} resource "azurerm_key_vault" "ygm_vaults" { for_each = toset([for context in local.contexts : context.name]) name = each.key location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name tenant_id = data.azurerm_client_config.current.tenant_id sku_name = "standard" soft_delete_retention_days = 7 purge_protection_enabled = false } resource "azurerm_key_vault_access_policy" "ygm_vault_access_policy-devops" { for_each = azurerm_key_vault.ygm_vaults key_vault_id = azurerm_key_vault.ygm_vaults[each.value.name].id tenant_id = data.azurerm_client_config.current.tenant_id object_id = data.azurerm_client_config.current.object_id key_permissions = [ "Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", ] secret_permissions = [ "Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", ] } data "azuread_client_config" "current" {} data "azuread_user" "developer" { user_principal_name = "deneme@live.com" } resource "azurerm_key_vault_access_policy" "ygm_vault_access_policy-developer" { for_each = azurerm_key_vault.ygm_vaults key_vault_id = azurerm_key_vault.ygm_vaults[each.value.name].id tenant_id = data.azuread_client_config.current.tenant_id object_id = data.azuread_user.developer.object_id key_permissions = [ "Get", "List" ] secret_permissions = [ "Get", "List" ] } resource "azurerm_key_vault_secret" "vault_secrets" { for_each = local.variables key_vault_id = azurerm_key_vault.ygm_vaults[each.value.name].id name = each.value.variable value = each.value.value }
问题排查与修复
问题根源
- 资源并行创建导致权限未生效:Terraform默认并行执行资源创建,
azurerm_key_vault_secret可能在azurerm_key_vault_access_policy(给DevOps用户配置权限)完全生效前就尝试访问Key Vault,触发403错误。 - 访问策略引用冗余:
azurerm_key_vault_access_policy中key_vault_id使用azurerm_key_vault.ygm_vaults[each.value.name].id的写法冗余,且未明确依赖关系,可能导致策略应用延迟。
修复步骤
1. 添加资源依赖关系
在azurerm_key_vault_secret资源中添加depends_on,确保访问策略完全应用后再创建密钥:
resource "azurerm_key_vault_secret" "vault_secrets" { for_each = local.variables key_vault_id = azurerm_key_vault.ygm_vaults[each.value.name].id name = each.value.variable value = each.value.value # 明确依赖两个访问策略,确保权限生效后再创建密钥 depends_on = [ azurerm_key_vault_access_policy.ygm_vault_access_policy-devops, azurerm_key_vault_access_policy.ygm_vault_access_policy-developer ] }
2. 简化访问策略的Key Vault引用
azurerm_key_vault_access_policy的for_each已遍历azurerm_key_vault.ygm_vaults,直接用each.value.id引用Key Vault ID即可:
# DevOps访问策略 resource "azurerm_key_vault_access_policy" "ygm_vault_access_policy-devops" { for_each = azurerm_key_vault.ygm_vaults key_vault_id = each.value.id tenant_id = data.azurerm_client_config.current.tenant_id object_id = data.azurerm_client_config.current.object_id key_permissions = [ "Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", ] secret_permissions = [ "Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", ] } # 开发者访问策略 resource "azurerm_key_vault_access_policy" "ygm_vault_access_policy-developer" { for_each = azurerm_key_vault.ygm_vaults key_vault_id = each.value.id tenant_id = data.azuread_client_config.current.tenant_id object_id = data.azuread_user.developer.object_id key_permissions = [ "Get", "List" ] secret_permissions = [ "Get", "List" ] }
3. 验证订阅级权限(可选)
确认执行Terraform的用户在Azure订阅中拥有Key Vault Contributor或更高权限,避免因订阅级权限不足导致访问策略无法正常应用。
内容的提问来源于stack exchange,提问作者Serkan 2
相关产品推荐
相关产品推荐

