Hi,
New to the forum, thanks first of all.
I am struggling to render a template with templatefile by passing a list of resources as variable.
Given the below json template:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket*",
"s3:GetObject*",
"s3:PutObject*"
],
"Resource": "${bucket_arns}",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": [
"true"
]
}
}
}
]
}
And having the following policy document:
data "aws_iam_policy_document" "analyst_s3_list_get_put_to_archive" {
source_json = templatefile("${path.module}/rendering/generic/s3_list_get_put_to_bucket.json", {
bucket_arns = [
"arn:aws:s3:::${var.bucket_prefix}-${var.environment}-archive",
"arn:aws:s3:::${var.bucket_prefix}-${var.environment}-archive/*"
]
})
}
The rendering fails as follows in the plan phase:
Call to function "templatefile" failed:
../../modules/policy_definitions/rendering/generic/s3_list_get_put_to_bucket.json:10,28-39:
Invalid template interpolation value; Cannot include the given value in a
string template: string required..
What am I missing and how could I make this to work?
Thanks!
Alberto.
The surface problem here is that you are passing an HCL collection value into your template and rendering it directly into what looks like a JSON string value.
However, the AWS provider supports defining your policy statements using Terraform code, which is then rendered as JSON for you. For example, I think your policy document could be written as (untested):
data "aws_iam_policy_document" "analyst_s3_list_get_put_to_archive" {
statement {
actions = [
"s3:ListBucket*",
"s3:GetObject*",
"s3:PutObject*"
]
resources = [
"arn:aws:s3:::${var.bucket_prefix}-${var.environment}-archive",
"arn:aws:s3:::${var.bucket_prefix}-${var.environment}-archive/*"
]
condition {
test = "Bool"
variable = "aws:MultiFactorAuthPresent"
values = [ true ]
}
}
}
Would that work for your use case?
1 Like
Thanks for your reply @alisdair!!
That definitely works and was my previous iteration, however I’m trying to achieve reusability of common s3 json policies without the need to repeat statements blocks in aws_iam_policy_document. For example, to list and to get from a bucket, depending on a list of buckets, I can give one role access to some buckets while giving another role access to a different bucket without filling the code with aws_iam_policy_document (which is fine, they’re human readable)
In that case, you might want to use the override functionality, pointing to a generated policy’s source JSON and adding rules to override. See this example from the provider docs.
If you’ve already evaluated that idea and rejected it, then I think the solution to your original problem is likely to call jsonencode(…)
on your bucket_arns
collection value when you pass it to templatefile
, then remove the "
quotes in your template.
1 Like
Thanks again @alisdair!
Removing the quotes from the json template did the trick. Thank you very much!
Alberto.