Migrate S3 Bucket
S3 bucket module with compliance controls for encryption, logging, versioning, public access blocking, replication, and object lock. S3 has the highest control count of any module, making it a good first migration to understand the compliance.tf enforcement model.
Before and After
The migration is a source URL change. Your arguments, outputs, and Terraform state remain the same.
Before (terraform-aws-modules):
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "~> 5.0"
bucket = "my-app-logs"
tags = {
Environment = "production"
}
}
After (compliance.tf / PCI DSS v4.0):
module "s3_bucket" {
source = "pcidss.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = "~> 5.0"
bucket = "my-app-logs"
tags = {
Environment = "production"
}
}
Before (terraform-aws-modules):
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "~> 5.0"
bucket = "my-app-logs"
tags = {
Environment = "production"
}
}
After (compliance.tf / SOC 2):
module "s3_bucket" {
source = "soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = "~> 5.0"
bucket = "my-app-logs"
tags = {
Environment = "production"
}
}
What Changes
- Source URL points to compliance.tf registry
- Compliance controls are enforced via validation rules
- terraform plan will fail if required controls are not satisfied
What Stays the Same
- All input variables (same interface as upstream terraform-aws-modules)
- All output values
- Resource addresses in Terraform state
- Provider configuration
- Version constraints
Step-by-Step Migration
- Change the source URL in your module block to your framework subdomain
- Run
terraform init -upgradeto download the compliance.tf module - Run
terraform planto review changes. Expect a clean plan or validation errors for missing values - Fix validation errors if any (see Common Issues below)
- Run
terraform apply - Verify by checking
.compliancetf-manifest.jsonin.terraform/modules/
Common Issues and Fixes
Object lock on existing buckets requires additional steps
Cause: While AWS now supports enabling Object Lock on existing versioned buckets, applying retention to existing objects requires S3 Batch Operations. New objects get the default retention automatically.
Fix: Enable Object Lock on the existing bucket (requires versioning), then use S3 Batch Operations for existing objects. Or disable the control with ?disable=s3_bucket_object_lock_enabled if not needed.
Missing logging configuration
Cause: The s3_bucket_logging_enabled control requires a logging block with target_bucket set. Most upstream configurations omit this.
Fix: Add a logging block: logging = { target_bucket = "my-log-bucket", target_prefix = "logs/" }
Missing KMS encryption configuration
Cause: The s3_bucket_default_encryption_enabled_kms control requires KMS encryption (not just AES-256). The server_side_encryption_configuration block must specify sse_algorithm = "aws:kms" with a kms_master_key_id.
Fix: Add server_side_encryption_configuration with sse_algorithm = "aws:kms" and provide a KMS key ARN.
Missing cross-region replication
Cause: The s3_bucket_cross_region_replication_enabled control requires a replication_configuration block with an IAM role and destination bucket in another region.
Fix: Add a replication_configuration block with a replication IAM role and destination bucket. Versioning must also be enabled on both buckets.
MFA delete required (PCI DSS only)
Cause: The s3_bucket_mfa_delete_enabled control requires versioning.mfa_delete = "Enabled". This is a PCI DSS v4.0 requirement not present in SOC 2.
Fix: Add mfa_delete = "Enabled" to the versioning block. Note: enabling MFA delete requires the root account credentials.
Version Compatibility
| Upstream Version | compliance.tf Version | Status | Notes |
|---|---|---|---|
| v5.x | v5.x | Supported | Direct swap. Adapter version constraint: >=5.0.0 |
State Impact
No terraform state mv needed in typical cases. Resource addresses are unchanged because compliance.tf modules use the same internal resource structure as upstream. If a compliance control adds a new resource (rare), terraform plan will show the addition.
Controls Enforced
- S3 buckets should not use ACLs for user access control
- S3 buckets should have cross-region replication enabled
- S3 buckets should have default encryption enabled
- S3 buckets should have default encryption enabled using KMS
- S3 buckets should have event notifications enabled
- S3 buckets should have lifecycle policies configured
- S3 buckets should have logging enabled
- S3 buckets should have MFA delete enabled
- S3 buckets should not be accessible to all authenticated users
- S3 buckets should have object lock enabled
- S3 buckets should have object logging enabled
- S3 buckets should have policies that prohibit public access
- S3 buckets should restrict cross-account permissions
- S3 buckets should prohibit public read access
- S3 buckets should prohibit public write access
- S3 buckets with versioning enabled should have lifecycle policies configured
- S3 buckets should have versioning enabled
- S3 buckets should have cross-region replication enabled
- S3 buckets should have default encryption enabled
- S3 buckets should have default encryption enabled using KMS
- S3 buckets should have event notifications enabled
- S3 buckets should have lifecycle policies configured
- S3 buckets should have logging enabled
- S3 buckets should not be accessible to all authenticated users
- S3 buckets should have object lock enabled
- S3 buckets should have object logging enabled
- S3 buckets should have policies that prohibit public access
- S3 buckets should prohibit public read access
- S3 buckets should prohibit public write access
- S3 buckets with versioning enabled should have lifecycle policies configured
- S3 buckets should have versioning enabled
Rollback
To revert, change the source URL back and re-initialize:
- Change source back to "terraform-aws-modules/s3-bucket/aws"
- Run terraform init -upgrade
- Run terraform plan to confirm no resource changes
- Compliance controls are no longer enforced, but existing configurations remain in place