RDS database instances should use a custom administrator username
Default administrator usernames are documented in AWS guides, vendor manuals, and attack toolkits. Using them gives attackers half of the credential pair for free, reducing a brute-force attack to password guessing alone. Automated scanners specifically probe for "admin" and "postgres" against publicly or VPC-exposed endpoints.
A custom username adds obscurity that, combined with strong passwords and secrets rotation, meaningfully raises the cost of unauthorized access. It is a low-effort change at provisioning time but painful to retrofit on production databases that already have application connection strings baked in.
Retrofit consideration
Changing the master username on an existing RDS instance requires recreating the instance. All application connection strings, IAM database authentication bindings, and Secrets Manager entries referencing the old username must be updated simultaneously to avoid downtime.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "rds" {
source = "nistcsfv11.compliance.tf/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"]
}
module "rds" {
source = "pcidssv321.compliance.tf/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"]
}
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_db_instance resources, username must not be a known engine default. Failing values include "admin" (MySQL, MariaDB, Oracle, and some SQL Server configurations) and "postgres" (PostgreSQL). The list of disallowed values is engine-specific, but any non-default value passes. For Aurora clusters (aws_rds_cluster), the same logic applies to master_username. Set username or master_username to a custom string such as "app_dba", or source the value from a variable or Secrets Manager reference. There is no boolean flag to toggle; the control evaluates the literal value of the username attribute against known defaults.
Common pitfalls
Engine-specific default lists vary
The set of disallowed usernames differs by engine. "postgres" fails only for PostgreSQL instances, while "admin" fails for MySQL and MariaDB. If you standardize on a single custom username across engines, verify it does not collide with any engine's reserved words by checking engine documentation.
Terraform replace on username change
usernameonaws_db_instanceis a force-new attribute. Changing it on an existing resource triggers a destroy-and-recreate cycle, which means production data loss if you are not careful. Setlifecycle { prevent_destroy = true }on production instances and plan a blue-green migration rather than an in-place change.Aurora clusters need master_username too
With
aws_rds_clusterandaws_rds_cluster_instance, the master username is set on the cluster resource viamaster_username, not on the instance. Applying a custom username only at the instance level has no effect because Aurora instances inherit credentials from the cluster.Hardcoded usernames in Terraform state
Even custom usernames are stored in plaintext in Terraform state. The username itself can be generated with
random_stringor sourced from an external process, then passed in via a variable markedsensitive = trueto limit exposure in logs and plan output. Secrets Manager can store the final value, but username generation must be handled separately before that reference is possible.
Audit evidence
Compliance evaluation output from a custom Config rule or equivalent policy-as-code control, showing all RDS instances as COMPLIANT, is the primary artifact. Supporting evidence includes AWS CLI output from aws rds describe-db-instances showing the MasterUsername field for each instance, confirming none use default values like "admin" or "postgres".
For continuous compliance, an exported report across all accounts and regions is strongest. Screenshots of the RDS console showing the master username column are acceptable for point-in-time audits.
Framework-specific interpretation
NIST Cybersecurity Framework v1.1: PR.AC-1 covers identity and credential management for authorized users and devices. A default master username is a publicly known credential, not a managed one, which undermines the subcategory's intent. Replacing it with a custom value is one of the lowest-effort ways to satisfy the credential management expectation here.
PCI DSS v3.2.1: Requirement 2.1 is unambiguous: change all vendor-supplied defaults before putting a system on the network. An RDS instance provisioned with "admin" or "postgres" as the master username fails this requirement on first inspection.
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
rds_db_instance_no_default_admin_nameAWS Config Managed Rule:
RDS_INSTANCE_DEFAULT_ADMIN_CHECKPowerpipe Control:
aws_compliance.control.rds_db_instance_no_default_admin_nameProwler Checks:
rds_cluster_default_admin,rds_instance_default_adminAWS Security Hub Controls:
RDS.24,RDS.25
Last reviewed: 2026-03-09