Как динамически создать документ политики AWS IAM с переменным количеством блоков ресурсов с помощью terraform?

В моей текущей конфигурации terraform я использую статический файл JSON и импортирую в terraform с помощью функции файла для создания политики AWS IAM.

Код Terraform:

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

Определение политики AWS IAM в файле JSON (policy.json):

{
    "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, и использовать его для динамического создания ресурса aws_iam_policy в terraform. Моей первой идеей было попробовать использовать функцию jsonencode terraform. Однако похоже, что есть способ реализовать это, используя новые динамические выражения 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)

Любая помощь приветствуется.

Бест, Андрей

3 ответа

Решение

В aws_iam_policy_document источник данных из aws дает вам возможность создавать политики json в терраформе, без необходимости импортировать необработанный json из файла или из многострочной строки.

Поскольку вы определяете все свои политики в терраформе, это дает возможность использовать цикл / фильтрацию в массиве принципалов.

В вашем примере вы можете сделать что-то вроде:

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}"
}

1-й вариант:

если вы не хотите перестраивать политику в 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 ~}
...

2 вариант:

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

Синтаксис документа политики AWSIAM позволяет заменять переменные политики в операторе с использованием нотации в стиле $ {...}, что противоречит синтаксису интерполяции Terraform. Чтобы использовать переменные политики AWS с этим источником данных, используйте нотацию & {...} для интерполяций, которые должны обрабатываться AWS, а не 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

Это было здорово, и это хороший образец, за который можно держаться. К сожалению, у меня возникла проблема с превышением лимита квоты:

Предположительная политика ролей: LimitExceeded: не может превышать квоту для ACLSizePerRole: 2048

Вы можете запросить увеличение этого размера квоты, но предположительно максимальный размер составляет 4098. Политика предполагаемых ролей, которую я пытаюсь создать, необходима для каждой учетной записи AWS, которая у нас есть, поэтому мы в конечном итоге также достигнем этого предела.

К сожалению, вы можете использовать подстановочные знаки в arns политики предполагаемых ролей, но вы можете использовать «*», что, как я считаю, гораздо более рискованно.

Другие вопросы по тегам