Terraform: Cannot create S3 bucket policy w/ Heredock notation, but can w/ file() interpolation

Created on 7 Oct 2017  ·  3Comments  ·  Source: hashicorp/terraform

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

Terraform Configuration Files

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.

Terraform Version

I am running Terraform v0.10.7

Expected Behavior

I would expect that heredock syntax works the same as putting the doc in a file and then loading the file.

Actual Behavior

it appears that some spare white space is added and the AWS API does not like this

Steps to Reproduce

  1. terraform init
  2. terraform apply - Builds the bucket, but takes ~40s to generate the policy, AWS API comes back w/ error..

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:
screen shot 2017-10-08 at 6 22 09 pm

If you un-indent the json in the config, this will apply as expected.

All 3 comments

Hi @kquinsland,

There are 2 spaces before the first { character in the policy json, because that's how is written in your config file:
screen shot 2017-10-08 at 6 22 09 pm

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.

Was this page helpful?
0 / 5 - 0 ratings