Skip to content

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.

Minor Fixes15-30 minutes per instance

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

  1. Change the source URL in your module block to your framework subdomain
  2. Run terraform init -upgrade to download the compliance.tf module
  3. Run terraform plan to review changes. Expect a clean plan or validation errors for missing values
  4. Fix validation errors if any (see Common Issues below)
  5. Run terraform apply
  6. Verify by checking .compliancetf-manifest.json in .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 Versioncompliance.tf VersionStatusNotes
v5.xv5.xSupportedDirect 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

Rollback

To revert, change the source URL back and re-initialize:

  1. Change source back to "terraform-aws-modules/s3-bucket/aws"
  2. Run terraform init -upgrade
  3. Run terraform plan to confirm no resource changes
  4. Compliance controls are no longer enforced, but existing configurations remain in place

Migration Guide | Compatibility | S3 Bucket Module