When connecting an application (in this case, a Rails application) to Amazon RDS using SSL, you may encounter connection issues related to self-signed certificates. RDS uses self-signed root certificates, which are not always trusted by default. Here’s how to investigate and resolve these issues.

Setting Up SSL

To enable SSL, the first step was modifying the Dockerfile to download the RDS certificate:

# Download AWS RDS Certificate
RUN mkdir -p config/certs && \
    curl -o config/certs/rds-ca-root.pem https://truststore.pki.rds.amazonaws.com/us-west-2/us-west-2-bundle.pem

Next, the database.yml was updated to enable SSL:

production:
  adapter: mysql2
  encoding: utf8mb4
  collation: utf8mb4_unicode_ci
  reconnect: true
  pool: 25
  url: <%= ENV['DATABASE_URL'] %>
  ssl: true
  ssl_ca: <%= Rails.root.join('config/certs/rds-ca-root.pem') %>
  ssl_mode: :verify_identity

Despite these updates, the connection still failed with an SSL error.

The Issue

When the connection was being attempted, this error appeared:

ActiveRecord::ConnectionNotEstablished: TLS/SSL error: self-signed certificate in certificate chain

This happens because AWS RDS uses self-signed root certificates, which aren’t always trusted by default.

Investigating the Certificate

To confirm that the issue is related to the certificate, inspect it using OpenSSL:

openssl x509 -in us-west-2-bundle.pem -text -noout

For a more targeted check, verify the subject and issuer:

openssl x509 -in ~/Downloads/us-west-2-bundle.pem -text -noout | grep "Subject:"
openssl x509 -in ~/Downloads/us-west-2-bundle.pem -text -noout | grep "Issuer:"

If the result of each of these commands have Amazon Web Services, Inc., then the certificate is self-signed, confirming the need to explicitly trust it.

Configuring SSL in Docker

The fix involves adding the RDS certificate to the Docker container’s trust store, so it can trust the self-signed certificate.

The following example is for Alpine Linux:

RUN apk add --no-cache ca-certificates
RUN cp /app/config/certs/rds-ca-root.pem /usr/local/share/ca-certificates/rds-ca-root.crt
RUN update-ca-certificates

Now that the certificate is trusted, the Rails app can connect to Amazon RDS using SSL.

Verifying the Connection

To confirm the SSL connection, run this in the Rails console:

ActiveRecord::Base.connection.execute("SHOW STATUS LIKE 'Ssl_cipher'").to_a

If successful, you’ll see output similar to:

=> [["Ssl_cipher", "TLS_AES_256_GCM_SHA384"]]

Takeaways

  • AWS RDS uses self-signed certificates that require explicit trust.
  • Containerized environments need manual certificate installation.
  • Always test and verify your SSL setup in a staging environment, if possible.

Happy Connecting! 🚀🔒

Resources