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

and*_*era 7 json amazon-web-services amazon-iam terraform infrastructure-as-code

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

地形代码:

resource "aws_iam_policy" "example" {
  policy = "${file("policy.json")}"
}
Run Code Online (Sandbox Code Playgroud)

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": "*"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我的目标是使用存储在 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)
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏。

最好的,安德鲁

Dav*_*tia 7

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

因为您在 terraform 中定义了所有策略语句,所以它的好处是让您可以在主体数组上使用循环/过滤。

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

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}"
}
Run Code Online (Sandbox Code Playgroud)


Fra*_*ank 6

第一个选项:

如果您不想重建策略,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"]})
}
Run Code Online (Sandbox Code Playgroud)
...
%{ for account in account_number_list ~}
   {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::${account}:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
%{ endfor ~}
...
Run Code Online (Sandbox Code Playgroud)

第二个选项:

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

AWS 的 IAM 策略文档语法允许使用 ${...} 样式表示法替换语句中的策略变量,这与 Terraform 的插值语法冲突。为了将 AWS 策略变量与此数据源结合使用,请使用 &{...} 表示法来表示应该由 AWS 而不是 Terraform 处理的插值。

resource "aws_iam_policy" "example" {
  policy = templatefile("policy.json",{account_number_list = ["123","456","789"]})
}
Run Code Online (Sandbox Code Playgroud)

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