chocokoala
chocokoala

Reputation: 351

terraform templatefile for aws policies list

I have an example of this below from my main.tf. For some reason it forces double quotes on the template variables to wrap around on my template file while examples from other sources using below without quote wrap:

%{ for i in split(",",mylist) ~}
Here's a value: ${i}
%{ endfor }

My syntax shows no error on the file but it will error out when running it "%{ for addr in split(",",source_vpcs) ~} ${addr} %{ endfor ~}"

i am getting this error: Invalid function argument; Invalid value for "str" parameter: string required..

how can I correctly make use of the list? source_vpcs = ["vpc1212","vpc21"]

#i am trying to pass this from the main.tf to pass into aws_vpc_endpoint resource and into its policy attribute.

    policy = templatefile("../templates/access_polices.tmpl", 
                   {
                     s3env = "dev"
                     account_num = "8888888"
                     source_vpcs = local.source_vpcs
                   }
               )

here is an the tmpl file ####new content###

${jsonencode(
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "xx",
            "Effect": "Deny",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
              "*"
              ],
            "Condition": {
            "StringNotEquals": {
              "aws:SourceVpc": "${source_vpcs}",
              "s3:ResourceAccount": "${account_number}"
              }
        }
        },
        
    ]
}
)}

This is my a sample output that I want to achieve

"Condition": {
  "StringNotEquals": {
    "aws:SourceVpc": 
    [
      "vpc-888888888f",
      "vpc-999999999f"

    ]
    ,
    "s3:ResourceAccount":
    [
        888888888
     ]
  }

Upvotes: 1

Views: 5974

Answers (1)

Jordan
Jordan

Reputation: 4472

You're passing source_vpcs in as a list, then trying to split a list on ",".

Since you're already passing in a list, you don't need to do the split; it's already in different elements. So, just get rid of the split and try this:

"%{ for addr in source_vpcs ~} ${addr} %{ endfor ~}"

EDIT: This minimal example works fine for me, no errors.

template.txt

%{ for v in mylist ~}
Here's a value: ${v}
%{ endfor }

main.tf

resource "local_file" "template_test" {
  content     = templatefile("./template.txt", {
    mylist = [
      "value 1",
      "value 2"
    ]
  })
  filename = "./output.txt"
}

output.txt

Here's a value: value 1
Here's a value: value 2

EDIT 2: I don't know what you're trying to do with this JSON, and you should really consider using the aws_iam_policy_document data source for IAM policies like this, but here's how you can create the JSON string:

locals {
  source_vpcs = [
      "vpc-888888888f",
      "vpc-999999999f"
  ]
  account_number = 888888888

  jsonstring = jsonencode({
    Version = "2012-10-17",
    Statement = [
        {
            Sid = "xx",
            Effect = "Deny",
            Action = [
                "s3:GetObject"
            ],
            Resource = [
                "*"
            ],
            Condition = {
                StringNotEquals = {
                  "aws:SourceVpc" = local.source_vpcs,
                  "s3:ResourceAccount" = local.account_number
                }
            }
        }
    ]
  })
}

output "jsonstring" {
  value = local.jsonstring
}

Now you can use local.jsonstring anywhere you want to use that string (like in an IAM policy). If you really want to output it to a file, you can add:

resource "local_file" "jsonfile" {
  content     = local.jsonstring
  filename = "./policy.json"
}

And now policy.json will have your JSON content.

EDIT 3: Try this:

templatedir/policytemplate.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "xx",
            "Effect": "Deny",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
              "*"
              ],
            "Condition": {
            "StringNotEquals": {
              "aws:SourceVpc": ${jsonencode(vpc_ids)},
              "s3:ResourceAccount": "${account_number}"
              }
        }
        },
        
    ]
}

main.tf

locals {
  jsonpolicy = templatefile("./templatedir/policytemplate.json", {
    vpc_ids = [
      "vpc_1",
      "vpc_2"
    ]
    account_number = 888888
  })
}

output "jsonpolicy" {
  value = local.jsonpolicy
}

Upvotes: 1

Related Questions