【问题标题】:Prevent KeyVault from updating secrets using Terraform防止 KeyVault 使用 Terraform 更新机密
【发布时间】:2021-06-02 18:41:52
【问题描述】:

我正在构建一个 terraform 模板来创建 Azure 资源,包括 Keyvault Secrets。客户订阅政策不允许任何人更新/删除/查看 keyvault 机密。

如果我第一次运行terraform apply,它将完美运行。但是,再次运行相同的模板会出现以下错误:错误:

Error updating Key Vault "####" (Resource Group "####"): keyvault.VaultsClient#Update: Failure responding to request: StatusCode=403 --
Original Error: autorest/azure: Service returned an error. Status=403 Code="RequestDisallowedByPolicy" Message="Resource '###' was disallowed by policy. Policy identifiers: '[{\"policyAssignment\":{\"name\":\"###nis-deny-keyvault-acl\", ...

on ..\..\modules\azure\keyvault\main.tf line 15, in resource "azurerm_key_vault" "keyvault": 
15: resource "azurerm_key_vault" "keyvault" { 
  • 如何让我的 CI/CD 正常工作,而这意味着 terraform apply 将持续运行?
  • 有没有办法在 terraform 中通过此策略?
  • 有没有办法阻止 terraform 在 KV 创建后更新 KV(锁定资源除外)?

这里是 Keyvault 模块:

variable "keyvault_id" { 
  type        = string
} 
variable "secrets" { 
  type        = map(string) 
} 


locals { 
  secret_names = keys(var.secrets) 
} 

resource "azurerm_key_vault_secret" "secret" { 
  count        = length(var.secrets) 
  name         = local.secret_names[count.index] 
  value        = var.secrets[local.secret_names[count.index]] 
  key_vault_id = var.keyvault_id 
} 

data "azurerm_key_vault_secret" "secrets" { 
  count        = length(var.secrets) 
  depends_on   = [azurerm_key_vault_secret.secret] 
  name         = local.secret_names[count.index] 
  key_vault_id = var.keyvault_id 
} 

output "keyvault_secret_attributes" { 
  value = [for i in range(length(azurerm_key_vault_secret.secret.*.id)) : data.azurerm_key_vault_secret.secrets[i]] 
} 

这是我模板中的模块:

locals { 
  secrets_map = { 
    appinsights-key     = module.app_insights.app_insights_instrumentation_key 
    storage-account-key  = module.storage_account.primary_access_key 
  }
  output_secret_map = { 
    for secret in module.keyvault_secrets.keyvault_secret_attributes : 
    secret.name => secret.id 
  } 
} 

module "keyvault" { 
  source              = "../../modules/azure/keyvault" 
  keyvault_name       = local.kv_name 
  resource_group_name = azurerm_resource_group.app_rg.name 
} 


module "keyvault_secrets" { 
  source      = "../../modules/azure/keyvault-secret" 
  keyvault_id = module.keyvault.keyvault_id 
  secrets     = local.secrets_map 
} 

module "app_service_keyvault_access_policy" { 
  source                  = "../../modules/azure/keyvault-policy" 
  vault_id                = module.keyvault.keyvault_id 
  tenant_id               = module.app_service.app_service_identity_tenant_id 
  object_ids              = module.app_service.app_service_identity_object_ids 
  key_permissions         = ["get", "list"] 
  secret_permissions      = ["get", "list"] 
  certificate_permissions = ["get", "list"] 
} 

【问题讨论】:

  • 您需要提供整个 Terraform 模板代码,以便我们找出问题所在。
  • @CharlesXu 添加的 KV 秘密模块的代码以及模板中的模块调用。
  • 我认为您的问题并未表明 Terraform 代码的真正目的是什么。该错误表示您的密钥保管库未设置访问策略。

标签: continuous-integration terraform continuous-deployment terraform-provider-azure


【解决方案1】:

使用 Terraform 来配置和管理具有这种限制的密钥库听起来是个坏主意。 Terraforms 的主要思想是监视资源的状态 - 如果不允许读取资源,它就会变得毫无用处。您的问题甚至不是 Terraform 正在尝试更新某些内容,它失败了,因为它想要检查您的资源的当前状态并且失败了。

如果您的目标只是在密钥库中创建机密,我将只使用 az keyvault 这样的命令:

az login
az keyvault secret set --name mySecret --vault-name myKeyvault --value mySecretValue

最佳解决方案当然是您用于执行 Terrafom 命令的服务主体具有足够的权限来执行它为之创建的操作。

【讨论】:

    【解决方案2】:

    我知道这是一个迟到的答案,但对于未来的访客:

    运行 Terraform 计划和应用的管道将需要对密钥保管库具有适当的访问权限。

    因此,如果您从 Azure Pipelines 运行 CI/CD,您通常会有一个服务连接,您的管道将使用该服务连接进行身份验证。 您用于 Terraform 的服务连接很可能基于一个服务主体,该服务主体具有贡献者权限(至少在资源组级别),可以提供任何东西。

    如果是这种情况,那么您必须添加一个策略,以赋予相同的服务主体(使用服务主体企业对象 ID)以至少具有列出、获取和设置机密的权限。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-31
      • 2021-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 2020-10-01
      相关资源
      最近更新 更多