In an "out of the box" configuration, RDS PostgreSQL doesn't configure TLS in a safe way.
The server will allow non-TLS connections and most clients will not bother to validate the TLS certificates presented to it anyway.
But first...
Assuming that you have configured other security measures like VPC Security Groups in a sensible way then then taking advantage of these vulnerabilities is difficult, although not impossible.
Still, you care about TLS enough to be reading this document, so you probably want to implement it sensibly, right?
For the purposes of this example, I'm going to assume that there is an application built which connects to an RDS database using the PostgreSQL JDBC Driver.
The default configuration of the PostgreSQL JDBC driver is to prefer
TLS connections. This is configurable using the sslmode
option to the JDBC driver.
When the driver is configured to prefer
, it will negotiate up to a TLS connection if the server it connects to supports it. However, it will not perform any certificate validation. This exposes the application to eavesdropping and man-in-the-middle (MITM) attack (an attacker could either froce a non-TLS connection between the application and the RDS instance, or it could just sit between the application terminating TLS itself).
To mitigate against this, you can use the verify-ca
or verify-full
configurations to sslmode
.
verify-ca
asks the client to check that that the certificate presented by the RDS server is signed by a CA certificate that you specify. In the case of RDS, all servers are provisioned with certificates signed using the Amazon RDS Root CA certificates.
Even better, the PostgreSQL JDBC client doesn't require you to jump through the usual hoops with Java and importing root CA certicates into a java keystore. You can use the sslrootcert
to point to the Amazon root CA certificate on local disk, or alternatively, the default path for the sslrootcert
parameter is at ~/.postgresql/root.crt
on *nix systems (see https://jdbc.postgresql.org/documentation/head/ssl-client.html for more infomation).
verify-full
is the most secure sslmode
option, and goes one step further than verify-ca
by ensureing that the the name presented in the RDS instance's host certificate matches the name provided in the JDBC connection string.
One downside to this approach is if you use Route 53 to create a convenient alias to your RDS instance name, the alias name will not be present in the host certificate. You must use the canonical name of the RDS instance that Amazon provided you to connect with.
Now that your client's are all configured to use TLS and enforce certificate validation, you can configure the server to not accept any connections from non-TLS clients.
To do this, you need to edit a parameter in the parameter group your RDS instance uses. The one to change is rds.force_ssl
and the default value of 0
should be set to 1
. Depending on the individual circumstances of your RDS configuration, this may require a reboot.
Once you've followed this guide, your clients will only make TLS-backed connections and will perform some sort of certificate validation and your RDS instance will only allow connections that are TLS-backed.