Skip to content

Instantly share code, notes, and snippets.

@beezly
Last active January 28, 2020 16:57
Show Gist options
  • Save beezly/72a07266a4364863ce965cdfb98c6c2f to your computer and use it in GitHub Desktop.
Save beezly/72a07266a4364863ce965cdfb98c6c2f to your computer and use it in GitHub Desktop.
Correctly configuring TLS on RDS PostgreSQL instances

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...

Don't Panic

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?

First Steps... Client-side

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

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

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.

Next up... server-side

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.

That's all!

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment