There appears to be something broken in the heredock functionality.
I am using terraform to create a simple s3 bucket.
I am then attempting to attach a bucket policy to that bucket.
I would _like_ to use terraform's variable interpolation to insert the ARN of the bucket dynamically as shown in this documentation:
https://www.terraform.io/docs/providers/aws/r/s3_bucket.html
Here's my code
resource "aws_s3_bucket" "storage" {
bucket = "bucket.com-takeout-storage"
acl = "private"
}
resource "aws_s3_bucket_policy" "storage" {
bucket = "${aws_s3_bucket.storage.id}"
# This works!
#policy = "${file("working_policy.json")}"
# SAME content as the JSON file, not working
policy = <<POLICY
{
"Version": "2008-10-17",
"Statement": [{
"Sid": "DenyIncorrectEncryptionHeader",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::bucket.com-takeout-storage/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
},
{
"Sid": "DenyUnEncryptedObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::bucket.com-takeout-storage/*",
"Condition": {
"Null": {
"s3:x-amz-server-side-encryption": "true"
}
}
}
]
}
POLICY
}
When I hard code the ARN into the json, and then load that json file as the policy:
policy = "${file("working_policy.json")}"
the correct policy is applied to the bucket.
However, when attempt to use the here dock format, I get this error in my terraform output:
MalformedPolicy: Policies must be valid JSON and the first byte must be '{'
status code: 400, request id: <SNIP>, host id: <SNIP>
I see this in the console as terraform is running:
policy: "" => " {\n \"Version\": \"2008-10-17\",\n \"Statement\": [{\n \"Sid\": \"DenyIncorrectEncryptionHeader\",\n \"Effect\": \"Deny\",\n \"Principal\": \"*\",\n \"Action\": \"s3:PutObject\",\n \"Resource\": \"arn:aws:s3:::bucket.com-takeout-storage/*\",\n \"Condition\": {\n \"StringNotEquals\": {\n \"s3:x-amz-server-side-encryption\": \"AES256\"\n }\n }\n },\n {\n \"Sid\": \"DenyUnEncryptedObjectUploads\",\n \"Effect\": \"Deny\",\n \"Principal\": \"*\",\n \"Action\": \"s3:PutObject\",\n \"Resource\": \"arn:aws:s3:::bucket.com-takeout-storage/*\",\n \"Condition\": {\n \"Null\": {\n \"s3:x-amz-server-side-encryption\": \"true\"\n }\n }\n }\n ]\n }\n\n"
You can clearly see that the policy is going from "" to " {\n<snip>". Note that there is a gap () between the open quote and the beginning of the JSON string. It looks like there's a spare byte or two of whitespace being added to the beginning of the string when using here dock form. This spare byte is not added when using the file method.
I am running Terraform v0.10.7
I would expect that heredock syntax works the same as putting the doc in a file and then loading the file.
it appears that some spare white space is added and the AWS API does not like this
terraform initterraform apply - Builds the bucket, but takes ~40s to generate the policy, AWS API comes back w/ error..Hi @kquinsland,
There are 2 spaces before the first { character in the policy json, because that's how is written in your config file:

If you un-indent the json in the config, this will apply as expected.
@jbardin Doh. Good catch! 😨
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
Hi @kquinsland,
There are 2 spaces before the first

{character in the policy json, because that's how is written in your config file:If you un-indent the json in the config, this will apply as expected.