根据 Terraform 中某个资源是否存在,有条件地设置 IAM 策略

问题描述

我正在尝试根据 IAM 角色是否存在来设置 KMS 密钥策略。 yaml 文件看起来像这样。

app.yaml

此 terraform 脚本的问题在于,如果我的帐户中不存在 data "aws_iam_policy_document" "key_policy" { statement { sid = "Give Access to the my Role" actions = [ "kms:GenerateDateKey","kms:Decrypt" ] resources = ["*"] principals { type = "AWS" identifiers = ["arn:aws:iam::${var.account_id}:role/myrole"] } } } ,它就会失败。我们有多个 AWS 账户,其中只有一部分拥有此 myrole。我们的 CI 将为所有帐户运行相同的脚本。有没有办法仅在 myrole 存在时应用此语句?

解决方法

terraform (TF) 的设计原则规定当前的 TF 配置文件应该明确定义您的基础设施。这意味着定义您的解决方案的资源仅由给定的配置文件和当前的 TF 状态管理。如果某些资源不处于 TF 状态,则仅将其视为超出 TF 的范围并且不存在。

因此,TF不直接支持检查任何资源的存在,也不支持基于此类条件的conditional creation of resources。这会导致问题,因为您的 TF 无法完全代表您的架构。

因此,TF docs 建议:

与其尝试编写一个模块,该模块本身尝试检测某物是否存在并在不存在时创建它,我们建议应用依赖倒置方法:让模块接受它需要的对象作为参数,通过输入变量

基于上述内容,您应该致力于开发您的 aws_iam_policy_document.key_policy,以便它根据输入变量创建有问题的 statement。这意味着您的 CICD 管道必须检查角色是否存在,并将此信息作为输入变量传递给您的 CF 文件,例如my_role_exists 带有 truefalse 值。

然后,您可以使用 dynamic blocks 使 statement 有条件:

data "aws_iam_policy_document" "key_policy" {

  dynamic "statement" {

    for_each = var.my_role_exists == true ? [1] : [] 

    content {
      sid = "Give Access to the my Role"

      actions = [
        "kms:GenerateDateKey","kms:Decrypt"
      ]

      resources = ["*"]

      principals {
        type        = "AWS"
        identifiers = ["arn:aws:iam::${var.account_id}:role/myrole"]
      }
    }
   } 
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...