# State Encryption Configuration
## Rule
All OpenTofu projects handling sensitive data MUST enable state encryption. Use OpenTofu's native encryption feature with appropriate key providers. Never store unencrypted state containing secrets.
## Format
```hcl
terraform {
encryption {
key_provider "pbkdf2" "main" {
passphrase = var.state_encryption_passphrase
}
method "aes_gcm" "main" {
keys = key_provider.pbkdf2.main
}
state {
method = method.aes_gcm.main
}
plan {
method = method.aes_gcm.main
}
}
}
```
## Key Provider Options
| Provider | Use Case | Security Level |
|----------|----------|---------------|
| `pbkdf2` | Passphrase-based | Basic (dev/test) |
| `aws_kms` | AWS KMS managed keys | Production |
| `gcp_kms` | GCP KMS managed keys | Production |
## Good Examples
```hcl
# Production: AWS KMS encryption
terraform {
encryption {
key_provider "aws_kms" "production" {
kms_key_id = "arn:aws:kms:us-east-1:123456789:key/abcd-1234"
region = "us-east-1"
}
method "aes_gcm" "production" {
keys = key_provider.aws_kms.production
}
state {
method = method.aes_gcm.production
}
plan {
method = method.aes_gcm.production
}
}
backend "s3" {
bucket = "mycompany-tofu-state"
key = "production/main.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "tofu-locks"
}
}
```
## Bad Examples
```hcl
# BAD: No encryption — secrets visible in state
terraform {
backend "s3" {
bucket = "my-state"
key = "state.tfstate"
}
}
# Database passwords, API keys visible in plaintext state
# BAD: Hardcoded passphrase
key_provider "pbkdf2" "main" {
passphrase = "my-secret-passphrase" # In code!
}
```
## Enforcement
- Require encryption block in all OpenTofu configurations
- Use KMS key providers for production environments
- Audit state access logs for unauthorized reads
- Rotate encryption keys annually