RDS
For an engineer moving an existing RDS from terraform-aws-modules to compliance.tf. The controls cover encryption at rest, backup retention, deletion protection, IAM authentication, log exports and public access. When you finish, terraform plan passes with the compliance.tf source.
Minor to significant · 15-30 minutes per instance, or hours if the instance must be rebuilt for encryption · No state moves, unless an unencrypted instance has to be rebuilt · Upstream v7.x
Before you start
- A registry token, set up as in Registry tokens. The registry host for each framework is on Registry endpoints.
- An upstream version inside the supported range (v7.x). Older versions: upgrade upstream first, see Version compatibility.
- State: No
terraform state mv. Resource addresses stay the same, because compliance.tf modules keep the upstream resource structure. If a control adds a resource, the plan shows it as an addition. One exception: an unencrypted instance has to be rebuilt to pass the encryption control (see the fix below). - Not sure if this module should go first? The Migration kit tells you where to start. The Assessment checklist finds risks before you plan.
Change the source
The diff changes the source and adds the settings this module's controls need, so the plan passes. Replace the referenced resources (aws_...) with your own.
module "rds" {
- source = "terraform-aws-modules/rds/aws"
+ source = "soc2.compliance.tf/terraform-aws-modules/rds/aws"
version = "~> 7.0"
identifier = "my-app-db"
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t3.micro"
allocated_storage = 20
db_name = "myapp"
username = "dbadmin"
+ storage_encrypted = true
+ backup_retention_period = 7
+ deletion_protection = true
+ copy_tags_to_snapshot = true
+ iam_database_authentication_enabled = true
+ publicly_accessible = false
+ enabled_cloudwatch_logs_exports = ["audit", "error", "general", "slowquery"]
+
tags = {
Environment = "production"
}
} module "rds" {
- source = "terraform-aws-modules/rds/aws"
+ source = "pcidss.compliance.tf/terraform-aws-modules/rds/aws"
version = "~> 7.0"
identifier = "my-app-db"
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t3.micro"
allocated_storage = 20
db_name = "myapp"
username = "dbadmin"
+ storage_encrypted = true
+ backup_retention_period = 7
+ deletion_protection = true
+ iam_database_authentication_enabled = true
+ publicly_accessible = false
+ auto_minor_version_upgrade = true
+ enabled_cloudwatch_logs_exports = ["audit", "error", "general", "slowquery"]
+
tags = {
Environment = "production"
}
}Then download the new source and plan. terraform init installs a module whose source changed; -upgrade is only for fetching the same source and version again:
terraform init
terraform planAfter init, .terraform/modules/<module name>/compliancetf-manifest.json names the framework the module was built for.
Fix the plan errors
Each error names the control and links its page, which lists the frameworks that map it. These are the ones this module raises most often.
The existing instance is not encrypted
AWS cannot encrypt an existing unencrypted RDS instance in place. Setting storage_encrypted = true on it makes Terraform plan to replace the instance. Control: rds_db_instance_encryption_at_rest_enabled.
Take a snapshot, copy it with encryption, restore a new instance from the encrypted copy and move the state to it. Until then, turn the control off for this instance and record why.
storage_encrypted = trueBackup retention is 0
The control requires automated backups. Development configurations often set backup_retention_period = 0. Control: rds_db_instance_backup_enabled.
Set a retention period of at least 7 days, or longer if your retention policy says so.
backup_retention_period = 7No CloudWatch log exports
The control requires enabled_cloudwatch_logs_exports. The log types depend on the engine: audit, error, general and slowquery for MySQL; postgresql and upgrade for PostgreSQL. Control: rds_db_instance_logging_enabled.
List the log types for your engine.
enabled_cloudwatch_logs_exports = ["audit", "error", "general", "slowquery"]Deletion protection is off (SOC 2 only)
The control requires deletion_protection = true. Development instances often have it off. Control: rds_db_instance_deletion_protection_enabled.
Turn it on. AWS applies it in place, without downtime.
deletion_protection = trueAutomatic minor version upgrades are off (PCI DSS v4.0 only)
PCI DSS v4.0 maps this control; SOC 2 does not. Control: rds_db_instance_automatic_minor_version_upgrade_enabled.
Turn it on. AWS applies the next minor version in the maintenance window.
auto_minor_version_upgrade = trueA control that does not apply to this instance can be turned off on the source URL; see Turn controls on and off.
Controls this enforces
SOC 2
- RDS DB instance backup should be enabled
- RDS DB instances should be configured to copy tags to snapshots
- RDS DB instances should have deletion protection enabled
- RDS DB instance encryption at rest should be enabled
- RDS DB instances should have iam authentication enabled
- RDS DB instances should have logging enabled
- RDS DB instances should prohibit public access
PCI DSS v4.0
- RDS DB instance automatic minor version upgrade should be enabled
- RDS DB instance backup should be enabled
- RDS DB instance encryption at rest should be enabled
- RDS DB instances should have iam authentication enabled
- RDS DB instances should have logging enabled
- RDS DB instances should prohibit public access
Each framework also maps controls that this module does not enforce. Those stay with your team; the module page lists enforced and mapped-only controls apart.
Roll back
- Point the source back at
terraform-aws-modules/rds/aws, keeping the same version constraint. - Run
terraform init. - Run
terraform plan. Expect no resource changes: the values you added stay in place, but compliance.tf no longer checks them.