Terraform state files often include secrets. Treat state as a sensitive artifact: secure where it’s stored, who can access it, and how it’s audited.
Do not commit Terraform state files to version control. They commonly contain secrets and other sensitive infrastructure data.
- Local state is stored on a developer workstation unencrypted unless you encrypt your disk.
- It’s easy to accidentally commit
terraform.tfstateto Git. - Sharing local state via email or chat is insecure.
- Local state provides no built-in access control, role-based permissions, or audit logging.
- Centralized storage prevents long-term state residency on developer machines.
- Backends commonly support encryption at rest (SSE-S3, SSE-KMS, Azure Storage encryption, GCS encryption).
- Access is managed via IAM/RBAC, allowing fine-grained permissions for read/write/list operations.
- Audit logging (e.g., CloudTrail) records who accessed state and when.
- State locking prevents concurrent modifications that could corrupt state.
| Feature | Local State | Remote State (recommended) |
|---|---|---|
| Encryption at rest | Depends on disk encryption | Typically supported (SSE-S3, SSE-KMS, provider-managed) |
| Access control | File system permissions only | IAM / RBAC controls via backend |
| Audit logging | None | Provider logs (e.g., CloudTrail, audit records) |
| State locking | Not available | Supported by many backends (DynamoDB, etc.) |
| Team collaboration | Risky / manual sharing | Centralized, safe collaboration |
backend.tf).
encrypt = trueenables S3 server-side encryption with AES-256 (SSE-S3).- Specifying a
kms_key_idcauses S3 to use AWS KMS (SSE-KMS). SSE-KMS is recommended because it provides additional access controls and audit trails for decryption. - Use
dynamodb_tableto enable state locking, which prevents concurrentterraform applyruns from corrupting state. - In production prefer SSE-KMS over SSE-S3 for better access control and auditing.
terraform init will prompt you to migrate the existing local state to the remote backend. This makes migration safe and non-disruptive.
Layered security for state files
Apply defense-in-depth when protecting state. Typical layers include:
- Encryption at rest (SSE-S3 or SSE-KMS).
- State locking to prevent concurrent changes.
- Fine-grained IAM/RBAC policies to restrict access.
- Audit logging (CloudTrail or provider logs) to track access and changes.
| Requirement | Why it matters | Example / Action |
|---|---|---|
| Remote state for production | Centralized control and safer collaboration | Use S3, Azure Storage, or GCS backend |
| Encryption at rest | Prevents plaintext secrets on storage | Enable SSE-KMS or SSE-S3 (encrypt = true) |
| Fine-grained access control | Limits who can read/write state | Use IAM roles, policies, or RBAC |
| State locking | Prevents concurrent writes and corruption | Configure DynamoDB (dynamodb_table) or backend locking |
| Audit logging | Trace access and detect misuse | Enable CloudTrail, provider audit logs |
