RDS databases and clusters should not use a database engine default port
Default database ports are the first thing automated scanners and attackers probe. Running MySQL on 3306 or PostgreSQL on 5432 means every bot on the internet already knows where to knock. Changing the port does not replace proper network controls, but it drops your database from bulk scans and cuts noise in security logs.
Security-in-depth means removing easy signals. A non-default port combined with security group restrictions and private subnets makes unauthorized discovery meaningfully harder.
Retrofit consideration
Changing the port on a running RDS instance or Aurora cluster forces a reboot and requires updating every application connection string, security group rule, and DNS-based service discovery entry. Plan a maintenance window and coordinate with all consumers.
Implementation
Choose the approach that matches how you manage Terraform.
If you use terraform-aws-modules/rds/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
Use AWS provider resources directly. See docs for the resources involved: aws_db_instance.
resource "aws_db_instance" "this" {
allocated_storage = 20
enabled_cloudwatch_logs_exports = ["general", "slowquery"]
engine = "mysql"
identifier = "pofix-abc123"
instance_class = "db.t3.micro"
monitoring_interval = 60
monitoring_role_arn = "arn:aws:iam::123456789012:role/example-role"
password = "ChangeMe123!"
skip_final_snapshot = true
username = "dbadmin"
}
What this control checks
For aws_rds_cluster, port must not match the engine default: 3306 for aurora-mysql/aurora, 5432 for aurora-postgresql. For aws_db_instance, the same applies: 3306 for mysql and mariadb, 5432 for postgres, 1433 for sqlserver-*, 1521 for oracle-*. Omitting port fails the control because Terraform and AWS assign the engine default. An explicit value that matches the default also fails. To pass, set port to a custom value (3307 for MySQL and 5433 for PostgreSQL are common choices) and update security group rules to match.
Common pitfalls
Omitting the port argument defaults to engine port
Terraform passes no port value to AWS unless you set it explicitly, so AWS assigns the engine default. The control flags this as non-compliant regardless of intent. Always set
porton bothaws_db_instanceandaws_rds_cluster.Read replicas inherit the source port
Read replicas created via
replicate_source_dbinherit the source instance's port. If the primary is still on the default, the replica will be too. Fix the source first, or setportexplicitly on the replica (which forces recreation).Security group rules must match the new port
Connectivity breaks immediately if
portchanges without matching updates tofrom_portandto_portinaws_security_group_ruleoraws_vpc_security_group_ingress_rule. Update both in the same apply.Aurora cluster vs. instance port mismatch
Aurora port is a cluster-level setting. Set it on
aws_rds_cluster, not onaws_rds_cluster_instance. Settingporton individual instance resources has no effect; the cluster value propagates to all instances automatically.Snapshot restores can carry forward prior port settings
Set
portexplicitly on any resource restored from a snapshot. Terraform will otherwise carry forward whatever port the snapshot captured, which is likely the engine default if the source was never remediated.
Audit evidence
Config rule evaluation results showing all RDS instances and Aurora clusters as COMPLIANT are the primary artifact. The RDS console port field on each instance or cluster detail page works as direct visual confirmation. Prowler output listing each resource and its configured port is a clean, exportable alternative. Organizations using Security Hub can pull the finding status across accounts and regions as consolidated proof.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
rds_db_instance_and_cluster_no_default_portPowerpipe Control:
aws_compliance.control.rds_db_instance_and_cluster_no_default_portProwler Checks:
rds_cluster_non_default_port,rds_instance_non_default_portAWS Security Hub Control:
RDS.23KICS Query:
bca7cc4d-b3a4-4345-9461-eb69c68fcd26
Last reviewed: 2026-03-09