Terraform Backend Implementation Summary
Overview
Complete Terraform backend infrastructure for secure, collaborative state management with S3 and DynamoDB.
What Was Implemented
1. Backend Infrastructure ✅
Location: backend/
Components:
- S3 Bucket: State storage with versioning and encryption
- S3 Bucket (Logs): Access logging bucket
- DynamoDB Table: State locking with PITR
- KMS Key: Encryption for S3 and DynamoDB
- IAM Policy: Backend access policy
- CloudWatch Alarms: Monitoring (bucket size, throttles)
- EventBridge Rules: State change tracking
Files Created:
backend/main.tf- Complete backend infrastructure (400+ lines)backend/variables.tf- Configuration variablesbackend/terraform.tfvars.example- Example configurationbackend/README.md- Comprehensive documentation
2. Configuration Files ✅
Backend Configuration:
backend.hcl.example- Backend configuration templatebackend-config.json- Generated configuration (from output)
Version Control:
.gitignore- Excludes sensitive files (backend.hcl, *.tfvars, state files)
Updated Files:
versions.tf- Updated with backend configuration instructions
3. Automation Scripts ✅
Setup Script:
scripts/setup-backend.sh- Automated backend deployment- Checks prerequisites
- Validates configuration
- Deploys infrastructure
- Generates backend.hcl
- Provides next steps
4. Documentation ✅
Comprehensive Guides:
backend/README.md- Backend infrastructure guidedocs/BACKEND.md- Complete backend configuration guide- Updated
README.md- Added backend setup steps
Features
Security
- ✅ KMS Encryption: All data encrypted at rest
- ✅ TLS Required: Encryption in transit
- ✅ Public Access Blocked: No public bucket access
- ✅ Access Logging: All access logged
- ✅ IAM Policies: Least privilege access
- ✅ State Locking: Prevents concurrent modifications
Reliability
- ✅ Versioning: Keep all state versions
- ✅ Point-in-Time Recovery: DynamoDB PITR enabled
- ✅ Lifecycle Policies: Automatic cleanup
- ✅ Monitoring: CloudWatch alarms
- ✅ Event Tracking: EventBridge rules
Cost Optimization
- ✅ Pay-per-Request: DynamoDB billing mode
- ✅ Lifecycle Transitions: Move old versions to cheaper storage
- ✅ Automatic Cleanup: Delete old versions after retention
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Terraform Backend │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ S3 Bucket (State Storage) │ │
│ │ • Versioning: Enabled │ │
│ │ • Encryption: KMS │ │
│ │ • Public Access: Blocked │ │
│ │ • Logging: Enabled │ │
│ │ • Lifecycle: 90-day retention │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ DynamoDB Table (State Locking) │ │
│ │ • Billing: Pay-per-request │ │
│ │ • PITR: Enabled │ │
│ │ • Encryption: KMS │ │
│ │ • Hash Key: LockID │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ KMS Key │ │
│ │ • Rotation: Automatic │ │
│ │ • Deletion Window: 30 days │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Monitoring │ │
│ │ • CloudWatch alarms │ │
│ │ • EventBridge rules │ │
│ │ • SNS notifications (optional) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Usage
Quick Start (Automated)
# Run automated setup
./scripts/setup-backend.sh
Manual Setup
# 1. Configure backend
cd backend
cp terraform.tfvars.example terraform.tfvars
vim terraform.tfvars
# 2. Deploy backend
terraform init
terraform apply
# 3. Save configuration
terraform output -json backend_config > ../backend-config.json
# 4. Initialize main Terraform
cd ..
terraform init -backend-config=backend.hcl
Backend Configuration
The setup script generates backend.hcl:
bucket = "your-org-control-tower-terraform-state"
key = "control-tower/terraform.tfstate"
region = "ap-southeast-2"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-2:123456789012:key/..."
dynamodb_table = "control-tower-terraform-locks"
Configuration Variables
| Variable | Description | Default | Required |
|---|---|---|---|
state_bucket_name |
S3 bucket name (globally unique) | - | Yes |
lock_table_name |
DynamoDB table name | terraform-state-locks |
No |
allowed_account_ids |
AWS account IDs for access | [] |
Yes |
region |
AWS region | ap-southeast-2 |
No |
kms_deletion_window |
KMS key deletion window (days) | 30 |
No |
state_retention_days |
State version retention (days) | 90 |
No |
logs_retention_days |
Access log retention (days) | 365 |
No |
Outputs
| Output | Description |
|---|---|
state_bucket_name |
S3 bucket name |
state_bucket_arn |
S3 bucket ARN |
lock_table_name |
DynamoDB table name |
lock_table_arn |
DynamoDB table ARN |
kms_key_id |
KMS key ID |
kms_key_arn |
KMS key ARN |
backend_policy_arn |
IAM policy ARN |
backend_config |
Complete backend configuration |
Monitoring
CloudWatch Alarms
- State Bucket Size
- Metric: BucketSizeBytes
- Threshold: 10 GB
- Action: SNS notification (if configured)
- DynamoDB Throttles
- Metric: UserErrors
- Threshold: 5 errors
- Action: SNS notification (if configured)
EventBridge Rules
- State Changes
- Events: PutObject, DeleteObject
- Target: SNS topic (if configured)
Security Best Practices
- Access Control
- Use IAM roles with least privilege
- Enable MFA for state access
- Limit
allowed_account_ids
- Encryption
- KMS encryption at rest
- TLS 1.2+ in transit
- Automatic key rotation
- Logging
- S3 access logs enabled
- CloudTrail API logging
- EventBridge state changes
- Backup
- Versioning enabled
- Regular manual backups
- Test restore procedures
- Monitoring
- CloudWatch alarms
- Review access logs
- Track state changes
Backup and Recovery
Backup State
# Download current state
aws s3 cp s3://your-bucket/control-tower/terraform.tfstate ./backup/
# List all versions
aws s3api list-object-versions \
--bucket your-bucket \
--prefix control-tower/terraform.tfstate
Restore State
# Restore specific version
aws s3api get-object \
--bucket your-bucket \
--key control-tower/terraform.tfstate \
--version-id <version-id> \
./restored-state.tfstate
# Push restored state
terraform state push ./restored-state.tfstate
Cost Estimation
Monthly Costs (Approximate)
- S3 Storage: $0.023/GB (Standard)
- S3 Requests: Minimal
- DynamoDB: Pay-per-request (~$0.50/month)
- KMS: $1/month + $0.03/10K requests
- CloudWatch: Minimal
Estimated Total: $5-10/month
Troubleshooting
State Lock Timeout
# Check locks
aws dynamodb scan --table-name control-tower-terraform-locks
# Force unlock (use with caution!)
terraform force-unlock <lock-id>
Access Denied
- Verify IAM permissions
- Check bucket policy
- Verify KMS key policy
- Ensure account ID in
allowed_account_ids
Encryption Errors
- Verify KMS key exists
- Check KMS key policy
- Ensure IAM role has KMS permissions
- Verify key is in correct region
Migration
From Local to Remote State
# Deploy backend
cd backend && terraform apply
# Migrate state
cd .. && terraform init -migrate-state -backend-config=backend.hcl
Between Backends
# Pull current state
terraform state pull > old-state.tfstate
# Reconfigure backend
terraform init -reconfigure -backend-config=new-backend.hcl
# Push state
terraform state push old-state.tfstate
Benefits
- Team Collaboration
- Multiple team members can work together
- State locking prevents conflicts
- Centralized state management
- Security
- Encryption at rest and in transit
- Access control with IAM
- Audit logging
- Reliability
- Versioning for rollback
- Point-in-time recovery
- Automated backups
- Compliance
- Audit trail
- Access logging
- Encryption requirements
Next Steps
- Deploy Backend
./scripts/setup-backend.sh - Initialize Main Terraform
terraform init -backend-config=backend.hcl - Verify Configuration
terraform state list - Deploy Control Tower
terraform plan terraform apply
References
Status: ✅ COMPLETE
Terraform backend infrastructure is production-ready with enterprise-grade security, reliability, and monitoring.