RDSSecurityDatabase

AWS RDS Security: Hardening Managed Databases Against Common Threats

Vigilare Engineering

Platform Team · January 8, 2026 · 9 min read

RDS security has improved significantly over the years, but the default configurations for new RDS instances still leave room for hardening. A database provisioned without careful attention to network access, authentication settings, and logging can be reachable from the internet, authenticating with weak credentials, and producing no audit trail of who queries what data. Each of these gaps represents both a security risk and a compliance gap for any framework that cares about data protection.

This guide covers the layered security configuration that a production RDS instance should have, from network isolation to query-level audit logging.

Network Isolation: Private Subnets Only

The first and most important RDS security configuration: databases should be in private subnets with no public internet access. A database with a publicly accessible endpoint is reachable for attacks from the internet regardless of what your security groups say — the network path exists and brute-force attempts will arrive.

Check whether your RDS instance is publicly accessible with:

aws rds describe-db-instances   --query 'DBInstances[?PubliclyAccessible==`true`].[DBInstanceIdentifier,DBInstanceClass,Endpoint.Address]'   --output table

For instances showing as publicly accessible, modify the instance to disable public access if the workload allows it. Removing public access might break connectivity for tools that connect from outside your VPC (BI tools, developer local connections). For these use cases, use a bastion host, an AWS Client VPN connection, or AWS Session Manager port forwarding to access the database through your VPC without making the database publicly accessible.

AWS Config rule rds-instance-public-access-check continuously monitors for publicly accessible RDS instances and can trigger automatic remediation. Enable this rule as part of your Config baseline.

Security Groups for Database Access

After removing public access, security groups control which resources within your VPC can reach the database. Follow the principle from the security groups best practices guide: reference security group IDs rather than CIDR ranges for allowing application access to databases.

Create a security group for your database (e.g., rds-postgres-production) with inbound rules that allow PostgreSQL (5432) or MySQL (3306) only from the application server security group. No access from 0.0.0.0/0, no access from office IP ranges, no access from "all VPC traffic" CIDR. If a developer needs direct database access for a debugging session, they use a bastion host that establishes a session through the bastion security group (which is explicitly allowed), not by opening the database to all sources.

Encryption at Rest and in Transit

Enable storage encryption for all RDS instances. Encryption must be configured at instance creation — you cannot enable encryption on an existing unencrypted instance without creating an encrypted snapshot and restoring to a new encrypted instance. Set your account's default encryption preference to enabled so all new RDS instances are encrypted automatically.

For encryption key management, use customer-managed KMS keys (CMK) rather than AWS-managed keys for production databases. CMKs provide audit logging of all key usage through CloudTrail, granular control over who can use and manage the key, and the ability to revoke access to encrypted data by disabling the key. The operational overhead is minimal compared to the visibility and control benefits.

Require SSL/TLS for all database connections. For PostgreSQL, set the rds.force_ssl parameter to 1 in the parameter group. For MySQL, set require_secure_transport to ON. Download the RDS CA bundle and configure your application's database client to verify the certificate — this prevents man-in-the-middle attacks even within your VPC.

Authentication and Credentials

Database master credentials should be stored in AWS Secrets Manager, not in environment variables or application configuration files. Secrets Manager handles automatic credential rotation for RDS databases — when rotation runs, it creates a new password, updates the RDS instance, and updates the secret, all without application downtime if your application uses the Secrets Manager API to retrieve credentials.

IAM database authentication is an alternative to password-based authentication for MySQL and PostgreSQL. With IAM authentication, database connections use short-lived tokens generated from AWS credentials rather than long-lived passwords. There's no credential to leak, and access is controlled through IAM policies. The limitation is a maximum of 200 connections per second for IAM-authenticated connections, which makes it unsuitable for high-connection-rate applications. Evaluate IAM authentication for lower-connection workloads where the security benefit outweighs the connection rate constraint.

Audit Logging

RDS audit logging capabilities depend on the database engine. For MySQL/MariaDB, enable the MYSQL_AUDIT or the general query log. For PostgreSQL, use the pgaudit extension for comprehensive query-level audit logging (log all reads, writes, DDL, function calls). For Aurora MySQL, AWS provides native audit logging through the aws_cloudwatch_logs_exports parameter.

Ship database audit logs to CloudWatch Logs for centralized analysis and long-term retention. Enable the relevant log exports in the RDS instance configuration. For compliance frameworks (PCI DSS, HIPAA), database audit logs are a specific evidence requirement — configure retention in CloudWatch Logs to match your compliance requirement (typically 1-7 years).

Enhanced Monitoring and Performance Insights

Enhanced Monitoring provides OS-level metrics for your RDS instances (CPU, memory, disk I/O at the process level). Performance Insights provides query-level performance data showing which queries are consuming database resources. Both are useful for capacity management, but Performance Insights is also valuable for security: unusual query patterns (high-volume data exports, access to tables that shouldn't be accessed during normal operations) appear in the Performance Insights dashboard.

Related Reading

FAQ

Can I enable encryption on an existing unencrypted RDS instance?

Not directly. You must create an encrypted snapshot of the unencrypted instance and then restore from the encrypted snapshot to a new instance. The new instance has the same data but is encrypted. Plan for downtime or coordinate with a blue-green deployment strategy to minimize impact. Establish a policy that all new RDS instances must be created with encryption enabled to prevent this migration burden accumulating over time.

How do I handle RDS credential rotation without application downtime?

AWS Secrets Manager's rotation function for RDS uses a two-phase rotation approach: the rotation function creates a new password in the database, updates the secret to the new password, then verifies the new password works before marking rotation complete. Your application must retrieve credentials from Secrets Manager on each connection rather than caching credentials at startup. Most modern database client libraries support credential refresh; configure your connection pool to retrieve fresh credentials from Secrets Manager when connections are established.

What RDS engines support IAM database authentication?

IAM database authentication is supported for MySQL 5.6.34+, MySQL 5.7.16+, MySQL 8.0, PostgreSQL 9.5.15+, PostgreSQL 9.6.11+, PostgreSQL 10.6+, and later versions, plus Aurora MySQL and Aurora PostgreSQL. SQL Server, Oracle, and MariaDB do not support IAM authentication. Check the current AWS documentation for the latest supported versions and any version-specific limitations.

Protect your AWS accounts before it's too late

Vigilare monitors your AWS accounts for suspension risks — billing anomalies, IAM issues, GuardDuty findings, and more — and alerts you before AWS takes action.

Written by Vigilare Engineering

Platform Team