迭代列表以创建具有多个主体的单个存储桶策略

时间:2017-12-15 14:21:38

标签: amazon-s3 terraform

我正在创建一个存储桶,然后创建一个存储桶策略,以允许所有列出的帐户访问。似乎传递了terraform plan / apply,但是看着控制台,只列出了一个帐户,似乎是践踏了之前的政策补充。

我有一个变量列表和代码来生成存储桶/策略:

variable "accounts" {
    type = "list"
    default = [
         "111111111111",
         "222222222222",
         "333333333333",
         "444444444444",
         "555555555555",
         "666666666666",
         "777777777777"
    ]
}


resource "aws_s3_bucket" "my_bucket" {
  bucket = "${var.bucket_name}"
}
resource "aws_s3_bucket_policy" "my_bucket_policy" {
  bucket = "${aws_s3_bucket.my_bucket.id}"
  count = "${length(var.accounts)}"
  policy =<<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::${element(var.accounts, count.index)}:root"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::${var.bucket_name}/CloudTrail/AWSLogs/${element(var.accounts, count.index)}/*"
        }
    ]
}
EOF
}

有没有办法只在Resource或Principal部分迭代变量列表?目标是生成一个包含变量所有arns的存储桶策略。

1 个答案:

答案 0 :(得分:0)

每个存储桶仅支持一个存储桶策略,因此您无法创建多个存储桶策略。

相反,您可以在单个策略中创建多个语句,每个帐户一个。 Terraform不支持​​迭代,但使用formatlist()join()函数可以获得更多相同的效果。

resource "aws_s3_bucket_policy" "my_bucket_policy" {
  bucket = "${aws_s3_bucket.my_bucket.id}"
  policy =<<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        ${join(",\n",formatlist("
        {
            \"Effect\": \"Allow\",
            \"Principal\": {
                \"AWS\": \"arn:aws:iam::%s:root\"
            },
            \"Action\": \"s3:PutObject\",
            \"Resource\": \"arn:aws:s3:::%s/CloudTrail/AWSLogs/%s/*\"
         }
         ", var.accounts, var.bucket_name, var.accounts))}
    ]
}
EOF
}

在这种情况下,我将整个语句内容作为formatlist()函数的第一个参数。有必要避开双引号,但Terraform不需要转义换行符。它包含您要放置替换的%s。其他formatlist()参数是替换。

formatlist()的输出是一个列表,因此我必须使用join()函数将列表加入到单个输出字符串中。 join()函数还允许我在每个语句之间添加逗号分隔符。