Hardening database access: the basics
What does "access hardening" actually mean across AWS data stores?
Database access hardening is not one setting. It is a family of properties that show up in different shapes across every data store AWS runs: an RDS instance that authenticates with a long-lived password instead of an IAM-issued token, an Aurora cluster created with the default master username, a Neptune or DMS endpoint that has never had IAM authorization switched on, an OpenSearch domain with no fine-grained access control, a DocumentDB cluster with no audit log export, a Redshift cluster still answering to the public default awsuser, or an RDS instance parked in a public subnet that routes straight to an internet gateway. Each service expresses the gap in its own field, but the risk is the same: who can reach the database, how they prove who they are, and whether anyone would notice.
AWS Security Hub turns each of these into its own control, which is why a single estate can fail a dozen database-access checks at once. RDS.10 and RDS.12 cover IAM database authentication on instances and clusters; RDS.24 and RDS.25 cover custom administrator usernames; Redshift.8 covers the default Redshift admin name; Neptune.7 and DMS.10 cover IAM authorization on graph and migration workloads; Opensearch.7 covers fine-grained access control; DocumentDB.4, Neptune.2, RDS.34 and RDS.37 cover audit log exports; RDS.46 covers databases sitting in public subnets. They look like separate findings on the report, but they are one capability: make database access deliberate, identity-based, observable and private.
The good news is that most of these are configuration drift rather than considered decisions. A password baked into a Terraform module, a console wizard that filled in postgres for you, an audit log export nobody enabled, a subnet group that inherited an internet route from the default VPC. The job is to inventory how every data store authenticates and where it lives, move authentication onto IAM where the engine supports it, replace default admin names, turn on the audit exports, and pull databases off any subnet with a public route.
In this lesson you will learn how AWS expresses database access across authentication, admin identity, audit logging and network placement, how to find every data store that relies on a static password, a default name, a missing log export or a public subnet, and how to close those gaps without breaking the workloads that depend on them. The Controls this lesson covers section lists every Security Hub control in this capability, each linking to a deep page with the exact check and a copy-and-paste fix.
Half the credentials, published for free
Honeypot researchers running fake database endpoints on the public internet report that the overwhelming majority of authentication attempts target the well-known default usernames: postgres and admin for PostgreSQL, root and mysql for MySQL, sa for SQL Server, and awsuser for Redshift. Botnet credential lists ship with these pre-filled, so the attacker is not guessing the username, only the password. AWS wrote Security Hub controls (RDS.24, RDS.25, Redshift.8) whose entire job is to check for those exact strings, because the username is half the credential pair and the default hands it over before anyone tries the door.
Finding weak database access across an estate
Priya is the security lead at a scale-up preparing for its first SOC 2 audit. Security Hub shows database-access failures spread across RDS, Aurora, Neptune and Redshift in three accounts that pre-date the team's current guardrails: static-password instances, default admin usernames, and one production database in a public subnet.
Rather than work the findings one by one, she starts with the highest-leverage signal: which production databases still authenticate with a long-lived password instead of an IAM-issued token, because that is the credential that stays valid for months if it leaks.
Audit every RDS instance for IAM database authentication. The flag that matters is IAMDatabaseAuthenticationEnabled; false means the only way in is a static password.
Static-password databases are the highest-value finding in this group. The default admin name on the same row stacks a second control on top.
How AWS evaluates database accessdeep dive
Most controls in this group resolve to one of four mechanisms. The first is authentication mode: a boolean such as IAMDatabaseAuthenticationEnabled on RDS instances and clusters (RDS.10, RDS.12), enableIAMDatabaseAuthentication on Neptune (Neptune.7), or the IAM authorization flag on DMS endpoints (DMS.10), where IAM-issued, Signature Version 4-signed tokens replace a static password. The second is admin identity: the MasterUsername field checked against a deny list of public defaults for RDS and Aurora (RDS.24, RDS.25) and against the literal awsuser for Redshift (Redshift.8). The third is the audit trail: whether engine audit and slow-query logs are exported to CloudWatch (DocumentDB.4, Neptune.2, RDS.34, RDS.37). The fourth is network placement and in-cluster authorization: a subnet that routes 0.0.0.0/0 to an internet gateway (RDS.46), and OpenSearch fine-grained access control (Opensearch.7).
Two of these are immutable and so cannot be fixed with a flag. The MasterUsername is set once at creation and there is no rename API on RDS, Aurora or Redshift, so the only path to a non-default admin name is snapshot-and-restore (or DMS/logical replication) into a new resource whose name is set explicitly. Subnet placement is structural too: a database is moved off a public subnet by building a new DB subnet group from private subnets across at least two Availability Zones and modifying the instance onto it. The IAM-auth and audit-export flags, by contrast, apply dynamically with no reboot.
Security Hub evaluates these through AWS Config, some on a change-triggered schedule and some periodically, so a fix does not always flip the finding to PASSED instantly. The control plane change is immediate, but the report catches up on the next evaluation. The strongest of these controls move authentication off the database entirely: when IAM auth is on, there is no long-lived secret to leak, rotate or commit, and a captured token expires within 15 minutes.
What is the impact of weak database access?
The direct impact is credential and data exposure. A static database password copied into config, a CI secret or a developer laptop stays valid until somebody rotates it, often weeks. An IAM token in the same place is dead in 15 minutes. A default admin username hands an attacker half the credential pair for free. A database in a public subnet is one over-broad security group rule away from being reachable by the whole internet. An OpenSearch domain without fine-grained access control gives every admitted caller every index. Each gap is a different way the same data leaks.
The second-order impact is blast radius and detection. IAM-based access ties a connection to a current role, so removing the role removes access instantly, with no shared-password rotation. Audit log exports turn "someone with the password connected" into a record of who did what, which is the difference between noticing an intrusion and discovering it in a post-mortem. Private subnet placement shrinks the attack surface to the front doors you actually operate. These controls compound: hardened auth limits who gets in, audit logging records what they do, and network isolation limits where they can reach from.
On the compliance side, every modern framework (SOC 2, ISO 27001, HIPAA, PCI DSS, NIST 800-53) expects database access to be identity-based, least-privilege, logged and network-segmented. A passing set of these controls across every account is among the cheapest and most defensible artefacts you can hand an auditor, and a clean answer on the enterprise security questionnaire that asks whether all production databases use centralised, identity-based access can be the difference between a deal that closes and one that stalls in legal review.
How do you harden database access safely?
Work the capability as one loop rather than chasing individual findings. The order matters: the free, reversible toggles first, then the migrations that cannot be undone with a flag, and a guardrail so new databases are born hardened.
1. Inventory how every data store authenticates and where it lives
Across services, list each database's authentication mode (IAM or static password), its master username, whether audit logs are exported, and whether its subnet routes to an internet gateway. Treat this inventory as the source of truth rather than the Security Hub finding count, because one database can trigger several controls at once (a static-password instance with a default name in a public subnet fails three).
2. Move authentication onto IAM and turn on audit exports
These are the free, reversible wins. Enable IAM database authentication on RDS and Aurora (RDS.10, RDS.12), Neptune (Neptune.7) and DMS endpoints (DMS.10), then grant the connect permission and update callers to fetch a signed token per connection before retiring the old password. Enable audit and slow-query log export to CloudWatch on DocumentDB, Neptune and Aurora (DocumentDB.4, Neptune.2, RDS.34, RDS.37). Enable OpenSearch fine-grained access control and scope roles to actual need (Opensearch.7). None of these need a reboot.
3. Migrate the immutable cases: default admin names and public subnets
A default master username (RDS.24, RDS.25, Redshift.8) cannot be renamed in place, so snapshot-and-restore (or use DMS / logical replication) into a new cluster created with a non-default name, cut traffic over, then retire the old one. A database in a public subnet (RDS.46) is moved by building a new DB subnet group from private subnets across at least two AZs and modifying the instance onto it during a maintenance window. Sequence non-production first to validate the playbook.
4. Make the hardened state the default for new databases
Bake the safe defaults into your IaC modules: IAM auth enabled, a non-default master username (reject the deny-list values in code review), audit log exports on, and private subnet groups only. Layer AWS Config rules and, for the strongest enforcement, Service Control Policies so a new database physically cannot land with a default name or in a public subnet. Enforcing it at creation is the only thing that stops these findings reappearing on the next cluster someone spins up.
# Move the highest-impact databases onto IAM authentication first (free, no reboot).
for db in $(aws rds describe-db-instances \
--query 'DBInstances[?IAMDatabaseAuthenticationEnabled==`false`].DBInstanceIdentifier' \
--output text); do
aws rds modify-db-instance --db-instance-identifier "$db" \
--enable-iam-database-authentication --apply-immediately
echo "$db: IAM database authentication enabled"
done
# Find every instance still using a default admin username (immutable; needs migration).
aws rds describe-db-instances \
--query "DBInstances[?contains(['admin','postgres','root','sa','master','mysql','dbadmin'], MasterUsername)].[DBInstanceIdentifier,MasterUsername]" \
--output table
# Recreate one of those with a non-default master username set explicitly at creation.
aws rds restore-db-cluster-from-snapshot \
--db-cluster-identifier prod-orders-db-v2 \
--snapshot-identifier prod-orders-db-pre-rename \
--engine aurora-postgresql Quick quiz
Question 1 of 5Security Hub shows database-access failures across RDS, Aurora, Neptune and Redshift. What is the most efficient way to think about them?
You scored
0 / 5
Keep learning
Go deeper on how authentication, admin identity and network placement work across the services in this capability.
- IAM database authentication for MySQL and PostgreSQL How short-lived IAM tokens replace static passwords on RDS and Aurora, with per-engine database-user setup.
- Fine-grained access control in Amazon OpenSearch Service Master users, roles and role mapping that restrict access inside an OpenSearch domain, not just at the front door.
- Working with a DB instance in a VPC How DB subnet groups and public versus private subnets work, the reference for moving a database off a public subnet.
You can now treat database access as one capability rather than a scatter of findings: inventory how every data store authenticates and where it lives, do the free wins first (move authentication onto IAM, turn on audit log exports, scope OpenSearch roles), then plan the migrations for the cases a flag cannot fix (default admin usernames and public subnet placement), and make the hardened state the default for new databases. The Controls this lesson covers section below links every control in this group to its deep page and fix.
Back to the library