Рейтинг:0

Terraform: как динамически генерировать блок политики JSON?

флаг cn

У меня есть следующий ресурс:

ресурс "aws_iam_user_policy" "ses_send_policy" {
  count = var.enabled ? 1 : 0
  name_prefix = var.user_policy_name_prefix
  пользователь = aws_iam_user.ses_smtp_user[0].имя

  политика = <<EOF
{
    «Версия»: «2012-10-17»,
    "Заявление": [
        {
            «Эффект»: «Разрешить»,
            "Действие": [
                "ses:Отправить по электронной почте",
                "ses:SendRawEmail"
            ],
            "Ресурс": "*",
            "Условие": {
                "StringEquals": {
                    "ses: FromAddress": [
                        "${var.user_email_address}"
                    ]
                }
            }
        }
    ]
}
EOF
}

Я хотел бы спросить, как сделать блок «Условие» в политике необязательным и основанным на переменной типа bool? Я хочу иметь это, только если переменная.условие = истина.

Рейтинг:0
флаг ph

В документация для aws_iam_user_policy во время этого ответа основной пример использования показывает настройку политика как это:

  # Функция "jsonencode" Terraform преобразует
  # Результат выражения Terraform для корректного синтаксиса JSON.
  политика = jsonencode({
    Версия = "2012-10-17"
    Заявление = [
      {
        Действие = [
          "ec2:Описать*",
        ]
        Эффект = "Разрешить"
        Ресурс = "*"
      },
    ]
  })

Обратите внимание, что он рекомендует использовать в jsonencode функция для создания всего значения, а не пытаться создать JSON из частей с помощью конкатенации шаблонов, поскольку это гарантирует, что результат всегда будет допустимым синтаксисом JSON.

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

  политика = jsonencode({
    Версия = 2012-10-17"
    Заявление = [
      {
        Эффект = "Разрешить"
        Действие = [
          "ses:Отправить по электронной почте",
          "ses:SendRawEmail",
        ]
        Ресурс = "*"
        Условие = {
          StringEquals = {
            "ses: FromAddress" = [
              var.user_email_address,
            ]
          }
        }
      }
    ]
  })

Обратите внимание, что значение теперь записывается с использованием собственного синтаксиса выражения Terraform, а не синтаксиса JSON. Terraform самостоятельно создаст допустимый синтаксис JSON как часть оценки jsonencode вызов функции.

Ваше новое требование состоит в том, чтобы опустить Условие полностью в определенных случаях. Чтобы описать это требование как выражение Terraform, необходимо объединить объект, который описывает части, которые всегда присутствуют (Эффект, Действие, и Ресурс) с другим выражением, описывающим необязательные части.

Например:

  политика = jsonencode({
    Версия = 2012-10-17"
    Заявление = [
      объединить(
        {
          Эффект = "Разрешить"
          Действие = [
            "ses:Отправить по электронной почте",
            "ses:SendRawEmail",
          ]
          Ресурс = "*"
        },
        объединиться (вар.условие? {
          Условие = {
            StringEquals = {
              "ses: FromAddress" = [
                var.user_email_address,
              ]
            }
          }
        } : ноль, {}),
      )
    ]
  })

То, что я изменил здесь, немного тонкое и, возможно, трудно увидеть со всем остальным контентом, который не изменился, поэтому вот урезанная версия с некоторыми из предыдущих элементов, замененных комментариями, просто чтобы сделать новый контент более заметным. :

  политика = jsonencode({
    Версия = 2012-10-17"
    Заявление = [
      объединить (
        {
          # (здесь общие атрибуты)
        },
        объединиться (вар.условие? {
          # (здесь условные атрибуты)
        } : ноль, {}),
      )
    ]
  })

сливаться функция принимает несколько объектов и возвращает один объект, содержащий элементы из всех вместе взятых. В этом случае второй аргумент сливаться является более сложным выражением, которое производит либо объект с Условие атрибут или пустой объект в зависимости от значения условия. Слияние пустого объекта с объектом ничего не меняет в результате, и поэтому в этом случае условие определяет, будет ли этот второй аргумент вносить какие-либо атрибуты вообще.

Jacek avatar
флаг cn
Отличное объяснение, спасибо.
Jacek avatar
флаг cn
Один вопрос, код работает, но политика в обратном порядке, почему так?
флаг ph
Я не уверен, что вы подразумеваете под «обратным порядком», но, возможно, вы заметили, что `jsonencode` всегда сортирует атрибуты объекта по их именам, потому что объект является _неупорядоченной_ коллекцией атрибутов, и поэтому `jsonencode` самому решать какой-то порядок.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.