在策略中使用模板

Posted

技术标签:

【中文标题】在策略中使用模板【英文标题】:Using template in a policy 【发布时间】:2020-10-27 00:32:17 【问题描述】:

我正在努力将 kms 密钥导入 terraform,不幸的是,每个 sid 都有大量的 Principal 资源,每个 sid 的这个 principal 都是相同的。所以我正在尝试使用模板来制定政策。

我试过了:

policy.json.tpl


    "Version": "2012-10-17",
    "Id": "key-policy-1",
    "Statement": [
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": 
                "AWS": $allowed_resources
            ,
            "Action": "kms:*",
            "Resource": "*"
        ,
        
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": 
                "AWS": $allowed_resources
            ,
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        
    ]

main.tf

data "template_file" "key_policy" 
  template = file("$path.module/policy.json.tpl")
  vars = 
    allowed_resources = var.allowed_resources
  


resource "aws_kms_key" "key" 
  description = ""
  tags        = local.common_tags
  policy      = data.template_file.amp_key_policy.rendered

变量.tf

variable "allowed_resources" 
  description = "list of all principal resources"
  type        = list(string)
  default = [
    "arn:aws:iam::xxxxxxxxxxxx:user/a",
    "arn:aws:iam::xxxxxxxxxxxxx:user/b",
    "arn:aws:iam::xxxxxxxxxx:user/c",
    "arn:aws:iam::xxxxxxxxxx:role/abc,
  ]

错误:

在 main.tf 第 11 行,数据“template_file”“key_policy”:11: vars = 12: allowed_resources = var.allowed_resources 13:

属性“vars”的值不合适:元素“allowed_resources”: 需要字符串。

使用 Terraform 0.12.20

我尝试将我的 arn 传递给 vars = 仍然出现错误。有人可以指出我错在哪里。

【问题讨论】:

我用的 Terraform 不多,但是看看AWS::Include Transform 你能完全扩展第二个语句吗?目前尚不清楚您在该部分做什么。 @ydaetskcoR 我已经更新了代码,当我尝试使用模板时出现错误 【参考方案1】:

您使用的是 Terraform 0.12,因此您应该使用 the templatefile function 而不是 template_file 数据源。 templatefile 函数的一个显着好处是它不受 Terraform 0.11 提供程序协议的限制(因为它内置于 Terraform 语言中),因此它没有您设置的变量必须始终是字符串的限制。

resource "aws_kms_key" "key" 
  description = ""
  tags        = local.common_tags
  policy      = templatefile("$path.module/policy.json.tpl", 
    allowed_resources = var.allowed_resources
  )

但这不足以使用您现有的模板,因为您现有的模板被编写为直接插入allowed_resources,但这不起作用,因为该变量有一个列表值,所以它需要先编码成字符串。

幸运的是,因为您正在生成 JSON,所以您可以遵循 templatefile 文档页面上关于 Generating JSON or YAML from a template 的建议,使用 jsonencode 函数让 Terraform 担心生成有效的 JSON 语法,这样您就可以担心编写使用 Terraform 的表达式语法所需的数据结构:

$jsonencode(
  "Version": "2012-10-17",
  "Id": "key-policy-1",
  "Statement": [
    
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": 
        "AWS": allowed_resources
      ,
      "Action": "kms:*",
      "Resource": "*"
    ,
    
      "Sid": "Allow use of the key",
      "Effect": "Allow",
      "Principal": 
        "AWS": allowed_resources
      ,
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    
  ]
)

The jsonencode function 知道如何将 Terraform 的所有值类型序列化为 JSON,因此它会看到这里的 allowed_resources 引用生成列表并自动生成 JSON 数组语法。

【讨论】:

也只是想知道导入后为什么会这样显示,无论如何要避免它? ~ 校长 = ~ AWS = [ - "arn:aws:iam::xxxxxxx:user/a", + "arn:aws:iam::xxxxxxxx:user/b", + "arn:aws:iam::xxxxxxxx :user/c", 我不确定,但 AWS IAM 可能正在重新排序该数组中的项目,因为在 IAM 语法中排序并不重要。如果是这样,您可能需要确保配置中给出的列表与 AWS API 返回的顺序相同,以免 Terraform 将其显示为“漂移”。如果这没有帮助,我建议您提出一个新的 Stack Overflow 问题,以便您可以分享完整的输出和更新的配置。

以上是关于在策略中使用模板的主要内容,如果未能解决你的问题,请参考以下文章

为什么喜欢模板方法而非依赖注入?

用于 aws 策略列表的 terraform 模板文件

在基于策略的设计中多次使用策略

设计模式之模板方法模式和策略模式

Ajax 跨域和同源策略的解释和使用,使用jQuery跨域,模板引擎artTemplate的使用详细解释+案例

模板方法和策略模式有啥区别?