您如何使用 Terraform 动态创建具有可变数量资源块的 AWS IAM 策略文档?

How do you dynamically create an AWS IAM policy document with a variable number of resource blocks using terraform?

在我当前的 Terraform 配置中,我使用静态 JSON 文件并使用文件功能导入到 Terraform 中以创建 AWS IAM 策略。

地形代码:

resource "aws_iam_policy" "example" {
  policy = "${file("policy.json")}"
}

JSON 文件 (policy.json) 中的 AWS IAM 策略定义:

{
    "Version": "2012-10-17",
    "Id": "key-consolepolicy-2",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::777788889999:root"
                ]
            },
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::444455556666:root"
                ]
            },
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "*"
        }
    ]
}

我的目标是使用存储在 terraform 变量中的帐号列表,并使用它在 terraform 中动态构建 aws_iam_policy 资源。我的第一个想法是尝试使用 terraform jsonencode 函数。但是,看起来可能有一种方法可以使用新的 terraform 动态表达式 foreach 循环来实现这一点。

症结似乎在于在 IAM 策略中附加了可变数量的资源块。

伪代码如下:

var account_number_list = ["123","456","789"]
policy = {"Statement":[]}
for each account_number in account_number_list:
    policy["Statement"].append(policy block with account_number var reference)

感谢任何帮助。

最好的, 安德鲁

aws 的 aws_iam_policy_document 数据源为您提供了一种创建 json 策略的方法,无需从文件或多行字符串导入原始 json。

因为您全部在 terraform 中定义策略语句,所以它的好处是让您可以在主体数组上使用 looping/filtering。

在您的示例中,您可以执行以下操作:

data "aws_iam_policy_document" "example_doc" {
  statement {
    sid = "Enable IAM User Permissions"
    effect = "Allow"

    actions = [
      "kms:*"
    ]

    resources = [
      "*"
    ]

    principals {
      type = "AWS"
      identifiers = [
        for account_id in account_number_list:
        account_id
      ]
    }
  }

  statement {
    ...other statements...
  }
}

resource "aws_iam_policy" "example" {
  // For terraform >=0.12
  policy = data.aws_iam_policy_document.example_doc.json

  // For terraform <0.12
  policy = "${data.aws_iam_policy_document.example_doc.json}"
}

这很棒,是一个可以坚持下去的好模式。不幸的是,我 运行 遇到了一个问题,它违反了配额限制:

担任角色策略:LimitExceeded:不能超过 ACLSizePerRole 的配额:2048

您可以请求增加此配额大小,但据说最大值为 4098。我们拥有的每个 AWS 帐户都需要我尝试创建的代入角色策略,因此我们最终也会达到该限制。

不幸的是,您可以在代入角色策略的 arn 中使用通配符,但您可以使用“*”,我认为这样做风险更大。

第一个选项:

如果您不想在 aws_iam_policy_document 中重建策略,您可以使用 templatefile 请参阅 https://www.terraform.io/docs/language/functions/templatefile.html

resource "aws_iam_policy" "example" {
  policy = templatefile("policy.json",{account_number_list = ["123","456","789"]})
}
...
%{ for account in account_number_list ~}
   {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::${account}:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
%{ endfor ~}
...

第二个选项:

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html#policy-vars-infotouse

AWS's IAM policy document syntax allows for replacement of policy variables within a statement using ${...}-style notation, which conflicts with Terraform's interpolation syntax. In order to use AWS policy variables with this data source, use &{...} notation for interpolations that should be processed by AWS rather than by Terraform.

...
       {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::&{aws:userid}:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },

点赞:https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document