I am trying to build a cloud infrastructure in AWS using Terraform. I want to add a policy for a S3 bucket which uses attribute based authorization (ABAC) via the templatefile
function of terraform. My problem is that the variable syntax used by terraform and AWS is the same (${...}
).
Here is the policy template:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadRole1",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::${bucketName}/*",
"Effect": "Allow",
"Principal": "*",
"Condition": {
"s3:ExistingObjectTag/myid": "${aws:PrincipalTag/myid}"
}
}
]
}
The relevant part of the terrafrom file is:
resource "aws_s3_bucket_policy" "mybuckets-policy" {
bucket = aws_s3_bucket.mybuckets[count.index].bucket
policy = templatefile("${path.module}/bucket-policy.json", {
bucketName = aws_s3_bucket.mybuckets[count.index].bucket
})
count = 2
}
So what I want is that the ${bucketName}
part of the template gets replaced by terraform, while keeping the AWS expression ${aws:PrincipalTag/user-id}
in place.
But running terraform on the configuration above causes the error message
Call to function "templatefile" failed: ./bucket-policy.json:14,49-50: Extra characters after interpolation expression; Expected a closing brace to end the interpolation expression, but found extra characters..
If I put another item ${foobar}
in my template without a specifiying a value for it the error message is
Invalid value for "vars" parameter: vars map does not contain key "foobar", referenced at ./bucket-policy.json:11,30-36.
How can I make terraform do a partial evaluation of a template file while leaving all other items intact?
In the example above the syntax ${} will cause Terraform to try and evaluate the field as an interpolation function. Since u want to use this value literally and not as an interpolation function this will need to be double-escaped by using two $ symbols.
$${aws:PrincipalTag/user-id}