A

Terraform State Security: Protecting Your Crown Jewels

A
Amit Nepal
Security Engineer · Linux & Infrastructure · Offensive Security
·Apr 7, 2025·1 min read
Infrastructure

Terraform State Security: Protecting Your Crown Jewels

Apr 7, 2025 · 1 min read

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.