Protect Terraform State Files with an S3 Bucket Policy
When working with Terraform, the state file is one of the most sensitive assets in your infrastructure stack. It doesn't just track resources, it often contains confidential details such as resource IDs, networking configurations, and even secrets or credentials that may have been provisioned. When using an S3 backend, and S3 bucket policy can add additional protection.
While IAM user and role policies already provide access control to the bucket, it's not uncommon to find organisations granting full S3 access to anyone who needs it. Ideally, this shouldn't happen, but it unfortunately does.
The example below is a simple bucket policy that will make sure only specific users can interact with objects in the bucket.
Even if someone has allow s3:*
on their IAM policy, the bucket policy will override that.
{
"Version": "2012-10-17",
"Statement":
[
{
"Sid": "Statement",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:GetObject*",
"s3:PutObject*",
"s3:HeadObject*",
"s3:DeleteObject*"
],
"Resource":
[
"arn:aws:s3:::terraform-bucket-name",
"arn:aws:s3:::terraform-bucket-name/*"
],
"Condition":
{
"ArnNotEquals":
{
"aws:PrincipalArn":
[
"arn:aws:iam::100000000000:user/user1",
"arn:aws:iam::100000000000:user/user2"
]
}
}
}
]
}
There are many more advanced things that can be done with policies, such as limiting access by IP or connection, but this policy is a good first step. Bonus points if you Terraform the policy as well.