4

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

任何帮助表示赞赏。谢谢。

4

3 回答 3

6

所以我会选择的唯一合理的选择是:

创建一个包含以下内容的文件,例如 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})

希望有帮助

于 2020-04-12T20:12:09.027 回答
6

使用该语法的字符串插值${ ... }是对文字 JSON 字符串的最小更改,但如果插入的字符串包含 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 将序列理解为带引号的模板表达式而不是文字字符串,因此它会在使用 JSON 语法序列化整个结果字符串之前SOMEVAR评估结果并将结果包含在Resource值中。尽管在这种特殊情况下似乎不太可能,但如果结果是一个包含 a 的字符串,那么 JSON 编码会自动对其进行转义,以确保结果是有效的语法。SOMEVAR"\"

对于较大的数据结构,将它们分解到单独的文件中可以提高可读性,函数templatefile文档也包括一些从外部模板内部调用jsonencode的示例,结果相似。

于 2020-04-13T17:31:41.433 回答
2

更改$SOMEVAR${SOMEVAR}

请查看Terraform 字符串插值语法

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

于 2020-04-12T20:10:01.943 回答