I’ve bumped a couple of times into the situation where my IAM and S3 Bucket Policies were being marked as changed during the Terraform Plan phase whilst I hadn’t changed anything.
I decided to dig a bit deeper into the issue and found a Terraform pull request where this was being discussed. Notably the following:
There are a couple of situations I have encountered where a S3 bucket policy that is technically correct gets changed by AWS:
- When a policy statement has no Sid specified, it will create a Sid entry with blank data.
- When a policy statement only has one action, but is specified in an array, it will truncate the array and use a single element string action instead. (ie: “Action”: [ “s3:ListBucket” ] becomes “Action”: “s3:ListBucket”)
- Multiple actions will be sorted alphabetically.
Note that this does not only apply to S3 bucket policies but also to IAM policies.
The second situation is quite common, take this example:
When Terraform runs a refresh and compares it with the AWS state, then Terraform gets a normalised resource back. AWS tells us that there is only one element, Terraform’s state has an array with one element. If you change the above code to reflect this, then you’ll get rid of the message:
I just discovered another case where policies are being marked as changed and that’s when you’re setting up an S3 bucket policy for your Elastic Load Balancing log files. The AWS documentation on the matter tells you to create a Principal with the Elastic Load Balancer Region ID:
After normalising this Principal from an array with one element to just one element, it still got marked as changed.
After some searching, I saw an example where someone was using the full ARN for the Principal.
That did the trick.
The Terraform team is working on trying to normalise the arrays automatically during the plan/refresh phase, but till then you can follow the above recommendations to get rid of those pesky messages.