Why Terraform State Is Dangerous
Terraform state files contain every resource attribute, including secrets. RDS passwords, API keys, private key material — all in plaintext JSON. I've seen state files committed to public GitHub repos. That's an immediate full-environment compromise.
Remote State with Encryption
terraform {
backend "s3" {
bucket = "corp-terraform-state"
key = "production/main.tfstate"
region = "us-east-1"
encrypt = true
kms_key_id = "arn:aws:kms:us-east-1:123456789:key/mrk-..."
dynamodb_table = "terraform-state-lock"
}
}
The DynamoDB table provides state locking — prevents concurrent applies from corrupting state.
Bucket Policy: Enforce TLS
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::corp-terraform-state/*"],
"Condition": {
"Bool": {"aws:SecureTransport": "false"}
}
}]
}
Sensitive Outputs
output "db_password" {
value = random_password.db.result
sensitive = true
}
Marked sensitive outputs won't appear in CLI output or logs, but they're still in the state file.
Defensive Takeaways
- Never store state locally — always use remote backend with encryption
- Restrict S3 state bucket access to CI/CD role and break-glass admin only
- Enable S3 versioning on the state bucket so you can recover from
terraform destroy - Consider Vault Terraform secrets engine for dynamic credentials
Keep going
Get the next writeup in your inbox
New posts delivered when I publish. No spam.