我可以在 Terraform 中使用 "count" 从帐户 ID 列表中创建 assume_role_policy 吗?

Can I use "count" in Terraform to create an assume_role_policy from a list of account IDs?

我正在 AWS 中设置一个可以从其他 AWS 账户访问的资源。可以访问此资源的帐户列表因部署(QA、Pre-Prod、PROD 等)而异

帐户列表如下所示。

variable "my_list" {
    default = ["123456789", "111222333"]
}

以下是我对角色信任策略的期望。

 "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789:root",
        "AWS": "arn:aws:iam::111222333:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

我尝试在 aws_iam_role 资源上使用 Terraform 中的计数,但正如预期的那样,计数正在创建多个 IAM 角色。

还有其他方法可以实现吗?

如果您使用的是 Terraform 0.12.0 或更高版本,您可以将 IAM 策略文档构造为数据结构并使用 jsonencode 将其格式化为 aws_iam_role 期望的字符串格式:

  policy = jsonencode({
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "",
        "Effect": "Allow",
        "Principal": {
          for acct in var.my_list : "AWS" => "arn:aws:iam::${acct}:root"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  })

对于 Terraform 0.11 或更早版本,没有直接的方法来实现这一点。

包含多个账户的信任策略应将 AWS 作为委托人的键,但值应为根账户的 ARN 列表。 AWS user guide 中对此进行了描述,并提供了两种指定 AWS 账户的有效方法:使用完整的 ARN 或仅使用账户 ID。他们提供的示例如下所示:

"Principal": { 
  "AWS": [
    "arn:aws:iam::123456789012:root",
    "999999999999"
  ]
}

这将是更大的信任策略文档的一部分,如下所示:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { 
        "AWS": [
          "arn:aws:iam::123456789012:root",
          "999999999999"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

要获得较短的样式输出,您只需使用 jsonencode 函数 (Terraform 0.11 or 0.12):

resource "aws_iam_role" "example_short" {
  name = "example-short"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": ${jsonencode(var.my_list)}
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

或者使用带有完整 ARN 的较长样式作为帐户的根:

resource "aws_iam_role" "example_long" {
  name = "example-long"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": ${jsonencode(formatlist("arn:aws:iam::%s:root", var.my_list))}
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}