22

I, like a lot of people, received an email saying to update my RDS instance to use the new rds-ca-2019 certificate for SSL connections (previous being rds-ca-2015 which expires March 5, 2020). Their documentation about the process is a little sparse and says things like "Update your database applications to use the new SSL/TLS certificate." and "Import the certificate into your operating system." with no further details on changes required on the client side.

When I initially set things up, I didn't install any certificates and used a vanilla Ubuntu 18.04 EC2 image. The RDS instance was set to use rds-ca-2015 and when I connected to RDS with psql it reported that it was properly using TLSv1.2. If I look at root certificates installed in the OS I find 4 "Amazon Root CA" certs numbered 1 through 4. Those don't expire until 2038 and 2040.

So, my question has 2 parts:

  1. How did the SSL/TLS properly work initially if I had never installed the RDS certs and intermediary certs provided by Amazon?
  2. If I've changed the RDS database instance to use rds-ca-2019 and it seems to "just work" is there anything more I need to do?
1
  • My best guess is that the intermediate certificates are provided by the server when a TLS connection is established. Oct 21 '19 at 14:31
14

The default sslmode for PostgreSQL is prefer which means it will encrypt the connection with the certificate provided by the server but will not verify it. If I were to change the sslmode setting to verify-ca or verify-full then I would need to install the intermediate certs in a particular directory and then it would do proper verification.

As I'm not concerned about a MITM attack on my VPC, I don't think I'll bother switching to the 'verify' modes.

1
  • If only SOC2 auditors shared your sentiment! :) Jan 13 '21 at 18:23
8

The RDS certificate in question is an intermediate certificate. You might also know it as a CA certificate. When I use MySQL Workbench, for instance, I have to specify that

  1. I want to use SSL(TLS)
  2. Use the RDS CA chain file to verify the certificate

MySQL Workbench

How did the SSL/TLS properly work initially if I had never installed the [certificate]?

Depends how your system is set up. CA certificates simply provide a trusted authority for the presented certificate. It's quite possible to set up something that will accept any certificate at all, without attempting to verify it (i.e. you use a self-signed certificate). Another option is there is something already in your CA store that trusts it implicitly. This is less likely, but not impossible.

If you're doing this locally (such as you have an EC2 instance in the same VPC as your RDS instance) you might not even need SSL.

If I've changed the RDS database instance to use rds-ca-2019 and it seems to "just work" is there anything more I need to do?

No. It's confusing, but if you're connecting and not getting any certificate errors, I wouldn't worry about it.

1
  • I hadn't thought about the possibility that it was using the cert without verifying (as I assumed that the default settings would be to reject certs not signed by a CA installed in the OS). It seems with psql it looks for certs in a certain directory and doesn't use the OS's CA certs. The default setting for sslmode is prefer which doesn't do verification but uses the server's provided cert if one exists. Oct 22 '19 at 16:06
5

In ubuntu, add the ca-cert as described here: https://askubuntu.com/questions/73287/how-do-i-install-a-root-certificate

wget https://s3.amazonaws.com/rds-downloads/rds-ca-2019-root.pem
sudo mkdir /usr/local/share/ca-certificates/aws
sudo mv rds-ca-2019-root.pem /usr/local/share/ca-certificates/aws
sudo openssl x509 \ 
    -in /usr/local/share/ca-certificates/aws/rds-ca-2019-root.pem \
    -inform PEM \
    -out /usr/local/share/ca-certificates/aws/rds-ca-2019-root.crt
sudo update-ca-certificates

: sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...

Adding debian:rds-ca-2019-root.pem
done.
done.

This link describes how to set the ssl cert location for a django application: https://www.digitalocean.com/community/questions/how-to-connect-managed-database-postgres-with-ssl-mode-varify-full-in-django-app

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': '<name>',
    'USER': '<user>',
    'PASSWORD': '<password>',
    'HOST' : '<host>',
    'PORT' : '25060',   
    'OPTIONS':{
        'sslmode':'verify-full',
        'sslrootcert': os.path.join(BASE_DIR, 'ca-certificate.crt')

}

This post in Stackoverflow https://stackoverflow.com/a/58214922/1415254 describes how to connect using commandline parameters for psql.

psql "host={hostname} sslmode=prefer sslrootcert={ca-cert.pem} \
sslcert={client-cert.pem} sslkey={client-key.pem} port={port} user={user} \
dbname={db}"

Also

psqlrc and ~/.psqlrc

Unless it is passed an -X or -c option, psql attempts to read and execute commands
from the system-wide startup file (psqlrc) and then the user's personal startup
file (~/.psqlrc), after connecting to the database but before accepting normal
commands. These files can be used to set up the client and/or the server to taste,
typically with \set and SET commands.

And more detail here (right at the end): https://info.crunchydata.com/blog/ssl-certificate-authentication-postgresql-docker-containers

# the first parameter specifies which TLS mode to use to connect
export PGSSLMODE="verify-full"
# the following two parameters point to the client key/certificate
export PGSSLCERT="`pwd`/certs/client.crt"
export PGSSLKEY="`pwd`/keys/client.key"
# this parameter points to the trusted root CA certificate
export PGSSLROOTCERT="`pwd`/certs/ca.crt"

Full list of environment variables here: https://www.postgresql.org/docs/9.2/libpq-envars.html

3

Just like the post OP answered himself, postgres has the default sslmode set to prefer, and this is the excerpt from the doc:

I don't care about encryption, but I wish to pay the overhead of encryption if the server supports it.

So by default, the pg driver will not verify the certificates unless specified; and this is exactly why to OP's original questions, it works out of the box at the beginning, and also works after the RDS is upgraded to rds-ca-2019.

One of the environment variables for connecting to postgres is via DATABASE_URL, in the form of

postgres://username:password@host/database?sslmode=verify-full&sslrootcert=config/ca/rds-combined-ca-bundle.pem

and this is where you can specify the sslmode and sslrootcert if you decide to verify the intermediate certs. The content of sslrootcert should be one of the following...

https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem
https://s3.amazonaws.com/rds-downloads/rds-ca-2019-root.pem

HTH

3

There are two sides to this certificate update:

  1. On the server side: Any RDS instances created before 2019-11-01 require a restart. This incurs an outage of ~5 minutes. This will update them to have the new certificates in place.
  2. If your clients use SSL (off/prefer by default), then you need to update the certificates (intermediate+chain) from AWS on wherever your clients run.

Postgres uses "prefer" as the default way for clients to connect, which means they will try SSL if available, but fall back if not. So existing clients with default connection configuration will continue to operate.

2

Before upgrading Certificate authority in RDS to rds-ca-2019, without connection interruption, you can upgrade certificate on client-side.

If your RDS has rds-ca-2015, you should upgrade the client-side key with this https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem.

As per AWS document https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html It says rds-combined-ca-bundle.pem file has both certs intermediate and root.

Once your applications have combined-ca file then you should proceed to upgrade your RDS to Certificate authority rds-ca-2019.

This way without the downtime you can upgrade Certificate authority in RDS to rds-ca-2019.

1

Any new RDS DB instances created after November 1, 2019, use the new certificates by default. If your RDS instance is created before the above-mentioned date, You need to update the certificate.

To change the Certificate Authority from rds-ca-2015 to rds-ca-2019 for a DB instance

  1. Sign in to the AWS Management Console and open the Amazon RDS console at https://console.aws.amazon.com/rds/.
  2. In the navigation pane, choose Databases, and then choose the DB instance that you want to modify.
  3. Choose Modify. The Modify DB Instance page appears. refer attachments
  4. In the Network & Security section, choose rds-ca-2019. refer attachments.
  5. Choose Continue and check the summary of modifications.
  6. To apply the changes immediately, choose "Apply immediately". Choosing this option causes an outage.
  7. On the confirmation page, review your changes. If they are correct, choose Modify DB Instance to save your changes.
2
  • 3
    My question is about the client side and you're explaining how to update the server side. Oct 22 '19 at 12:27
  • the emails from amazon and the links it has and all of that just leads one to believe that they need to install something on the server they are connecting from. edit: so thats wrong? just change it from the admin tool? Dec 1 '19 at 9:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.