如何在Terraform中的AWS策略内插入变量

时间:2020-04-12 19:44:24

标签: amazon-web-services terraform aws-policies

我在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

我希望其中的Resource部分是一个变量,像这样(伪代码)

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 个答案:

答案 0 :(得分:2)

$SOMEVAR更改为${SOMEVAR}

请查看Terraform string interpolation syntax

此外,我强烈建议使用数据源aws_iam_policy_document定义IAM策略,而不是使用此处的文档。

答案 1 :(得分:2)

因此,我唯一可行的选择是:

创建文件,例如具有以下内容的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})

希望有帮助

答案 2 :(得分:1)

使用${ ... }语法的字符串内插是从文字JSON字符串起的最小变化,但是如果例如使用插入的字符串包含JSON解析器可能会误解的反斜杠和引号。

Terraform的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编码将自动将其转义为\"以确保结果是有效的语法。

对于更大的数据结构,它可以提高可读性以将其分解到一个单独的文件中,the templatefile function文档还包括了calling jsonencode from inside an external template的一些示例,结果相似。