Как вставить переменную в политику AWS в terraform

У меня есть политика, определенная в terraform для ресурсов AWS, например:


device-status-policy = <<EOF
{"Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:Connect", "Resource": "arn:aws:iot:us-west-2:foobaraccountid:client/device-status-qa*" }, { "Effect": "Allow", "Action": [ "iot:Publish", "iot:Receive", "iot:Subscribe" ] }
   EOF

Я бы хотел, чтобы его ресурсная часть была переменной, например (псевдокод)

device-status-policy = <<EOF
{"Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:Connect", "Resource": "$SOMEVAR/device-status-qa*" }, { "Effect": "Allow", "Action": [ "iot:Publish", "iot:Receive", "iot:Subscribe" ] }
   EOF

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

3 ответа

Решение

Строковая интерполяция с использованием ${ ... } синтаксис - это наименьшее изменение по сравнению с буквальной строкой JSON, но возникает риск проблем с созданием правильного синтаксиса JSON, если, например, вставляемые строки содержат обратную косую черту и кавычки, которые синтаксический анализатор JSON может неправильно интерпретировать.

Terraform's jsonencode Функция может быть хорошим компромиссом, потому что Terraform имеет синтаксис объекта, который очень похож на JSON, и, таким образом, возможность быстро понять, какая структура JSON, которую он создает, сохраняется, в то же время позволяя произвольные выражения Terraform, результаты которых будут автоматически закодированы с использованием правильный синтаксис JSON:

  device-status-policy = jsonencode({
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": "iot:Connect",
        "Resource": "${SOMEVAR}/device-status-qa*"
      },
      {
        "Effect": "Allow",
        "Action": [ "iot:Publish", "iot:Receive", "iot:Subscribe" ]
      }
    ]
  })

Обратите внимание, что выше используется вариантная форма синтаксиса объекта языка Terraform, в которой используются двоеточия вместо знаков равенства; оба действительны, и использование двоеточий здесь помогает входным данным напоминать JSON и, следовательно, упрощает адаптацию JSON, который вы уже написали (как я сделал здесь), без большого переписывания.

Тем не менее "${SOMEVAR}/device-status-qa*" Последовательность понимается Terraform как цитируемое выражение шаблона, а не как буквальная строка, поэтому она будет оценивать SOMEVAR и включите результат в Resourceзначение перед сериализацией всей результирующей строки с использованием синтаксиса JSON. Хотя в данном конкретном случае это кажется маловероятным, еслиSOMEVAR результатом была строка, содержащая " тогда кодировка JSON автоматически экранирует его как \" чтобы убедиться в правильности синтаксиса результата.

Для более крупных структур данных, где он улучшает читаемость фактора их в отдельный файл, templatefile документация по функциям включает несколько примеров вызоваjsonencodeизнутри внешнего шаблона тоже с аналогичными результатами.

Итак, единственный разумный вариант, который я бы выбрал, - это следующий:

Создайте файл, например policy.tpl, со следующим содержанием:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "${SOMEVAR}/device-status-qa*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Receive",
        "iot:Subscribe"
      ]
    }
  ]
}

В этом файле политики есть нужная вам переменная.

Затем вы просто ссылаетесь на него и передаете переменную следующим образом:

device-status-policy = templatefile("file.tpl", { SOMEVAR = var.your_terraform_variable})

надеюсь, это поможет

+ Изменить $SOMEVAR к ${SOMEVAR}.

Пожалуйста, ознакомьтесь с синтаксисом Terraform строка интерполяции.

Кроме того, я настоятельно рекомендую использовать источник данных aws_iam_policy_document для определения политик IAM, а не здесь docs.

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