How do I successfully connect to my Amazon RDS instance using an SSL connection?

Last updated: 2021-10-25

I want to connect to my Amazon Relational Database Service (Amazon RDS) DB instance using a Secure Socket Layer (SSL) connection.

Short description

You can use SSL or Transport Layer Security (TLS) from your application to encrypt a connection to a DB instance running MySQL, MariaDB, Microsoft SQL Server, Oracle, or PostgreSQL. SSL/TLS connections provide one layer of security by encrypting data that's transferred between your client and the DB instance. A server certificate provides an extra layer of security by validating that the connection is being made to an Amazon RDS DB instance.

When you provision a DB instance, Amazon RDS creates an SSL certificate and installs the certificate on the instance. These certificates are signed by a Certificate Authority. The SSL certificate includes the DB instance endpoint as the Common Name for the SSL certificate to protect the instance against spoofing attacks. An SSL certificate created by Amazon RDS is the trusted root entity and works in most cases. However, if your application doesn't accept certificate chains, the certificate might fail. In such cases, you might need to use an intermediate certificate to connect to your AWS Region. For example, you must use an intermediate certificate to connect to the AWS GovCloud (US) Regions using SSL.

You can download a certificate bundle that contains both the intermediate and root certificates for all AWS Regions from AWS Trust Services. If your application is on Microsoft Windows and requires a PKCS7 file, then you can download the PKCS7 certificate bundle from Amazon Trust Services. This bundle contains both the intermediate and root certificates.

Resolution

Each database engine has its own process for implementing SSL/TLS. To implement SSL/TLS connection for your DB cluster, choose one of the following options based on your database engine.

Amazon RDS for Oracle

For Amazon RDS for Oracle instances, you can turn on SSL mode by adding the SSL option in your custom option group.

Amazon RDS for Oracle supports Transport Layer Security (TLS) versions 1.0 and 1.2. To use the Oracle SSL option, use the SQLNET.SSL_VERSION option setting in your option group. The following values are allowed for this option setting:

  • "1.0" - Clients can connect to the DB instance using TLS 1.0 only.
  • "1.2" - Clients can connect to the DB instance using TLS 1.2 only.
  • "1.2 or 1.0" - Clients can connect to the DB instance using either TLS 1.2 or 1.0.

For existing Oracle SSL options, SQLNET.SSL_VERSION is set to "1.0" automatically. You can change the setting, if necessary.

You must configure the SQL*Plus client to use SSL before connecting to an Oracle DB instance that uses the Oracle SSL option. To use an SSL connection over JDBC, you must create a keystore, trust the Amazon RDS root CA certificate, and then set up the SSL connection.

Example code to set up the SSL connection using JDBC:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
 
public class OracleSslConnectionTest {
    private static final String DB_SERVER_NAME = "example-dns";
    private static final Integer SSL_PORT = "example-ssl-option-port-in-option-group";
    private static final String DB_SID = "example-oracle-sid";
    private static final String DB_USER = "example-username";
    private static final String DB_PASSWORD = "example-password";
    // This key store has only the prod root ca.
    private static final String KEY_STORE_FILE_PATH = "example-file-path-to-keystore";
    private static final String KEY_STORE_PASS = "example-keystore-password";
    public static void main(String[] args) throws SQLException {
        final Properties properties = new Properties();
        final String connectionString = String.format(
                "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=%s)(PORT=%d))(CONNECT_DATA=(SID=%s)))",
                DB_SERVER_NAME, SSL_PORT, DB_SID);
        properties.put("example-username", DB_USER);
        properties.put("example-password", DB_PASSWORD);
        properties.put("oracle.jdbc.J2EE13Compliant", "true");
        properties.put("javax.net.ssl.trustStore", KEY_STORE_FILE_PATH);
        properties.put("javax.net.ssl.trustStoreType", "JKS");
        properties.put("javax.net.ssl.trustStorePassword", KEY_STORE_PASS);
        final Connection connection = DriverManager.getConnection(connectionString, properties);
        // If there is no exception, it means that an SSL connection can be opened
    }
}

Before you connect to your Amazon RDS for Oracle instance using SSL, be sure of the following:

  • The RDS root certificate is downloaded and added to a wallet file. This file is stored in a directory that's specified by the WALLET_LOCATION parameter in the sqlnet.ora file.
  • You have the correct SSL port number in your TNS entry.
  • The Amazon RDS security group is configured to allow inbound connections from your machines over the SSL port.
  • The firewall or security policies are configured appropriately to allow traffic on the SSL port from Amazon RDS.

Amazon RDS for MariaDB

Amazon RDS for MariaDB supports TLS versions 1.0, 1.1, 1.2, and 1.3. In a one-way TLS connection, TLS is used without a client certificate, and only the server can be authenticated. Therefore, authentication is possible only in one direction. However, encryption is still possible in both directions. With server certificate verification, the client verifies that the certificate belongs to the server.

To launch the MySQL 5.7 client or later with RDS certificate, run a command similar to the following:

mysql -h myinstance.123456789012.rds-us-east-1.amazonaws.com -u testuser -p --ssl-ca=[full path]global-bundle.pem --ssl-mode=VERIFY_IDENTITY

To launch the MariaDB client with RDS certificate, run a command similar to the following:

mysql -h myinstance.123456789012.rds-us-east-1.amazonaws.com -u testuser -p --ssl-ca=[full path]global-bundle.pem --ssl-verify-server-cert

To require SSL connections for specific users or accounts, run the following query depending on your MariaDB version:

ALTER USER 'test'@'%' REQUIRE SSL;

To confirm that your connection is encrypted, run either of the following queries:

MariaDB > status;
MariaDB > SHOW VARIABLES LIKE 'have_ssl';

Amazon RDS for MySQL

Amazon RDS for MySQL supports TLS versions 1.0, 1.1, and 1.2.

Amazon RDS for MySQL for MySQL uses yaSSL for secure connections in the following versions:

  • MySQL version 5.7.19 and earlier 5.7 versions
  • MySQL version 5.6.37 and earlier 5.6 versions

MySQL uses OpenSSL for secure connections in the following versions:

  • MySQL version 8.0
  • MySQL version 5.7.21 and later 5.7 versions
  • MySQL version 5.6.39 and later 5.6 versions

By default, MySQL client programs attempt to establish an encrypted connection if the server supports encrypted connections. For additional security relative to that provided by default encryption, use the --ssl-ca parameter to reference the SSL certificate that includes the DB instance endpoint as the Common Name. The SSL certificate guards the instance against spoofing attacks.

To launch the client using the --ssl-ca parameter for MySQL 5.7 and later, run a command similar to the following:

mysql -h myinstance.123456789012.rds-us-east-1.amazonaws.com -u testuser -p --ssl-ca=[full path]global-bundle.pem --ssl-mode=VERIFY_IDENTITY

To require SSL connections for specific users or accounts, run a query similar to the following depending on your MySQL version:

mysql -h myinstance.123456789012.rds-us-east-1.amazonaws.com -u testuser -p --ssl-ca=[full path]global-bundle.pem --ssl-verify-server-cert

For MySQL 5.7 and later:

ALTER USER 'testuser'@'%' REQUIRE SSL;

For MySQL 5.6 and earlier:

GRANT USAGE ON *.* TO 'testuser'@'%' REQUIRE SSL;

To confirm that your connection is encrypted, run either of the following queries:

mysql> status;
mysql> SHOW VARIABLES LIKE 'have_ssl';

Amazon RDS for Microsoft SQL Server

You can use one of the following ways to use SSL to connect to your SQL Server DB instance:

  • Force SSL for all connections: With this method, the connections happen transparently to the client, and the client doesn't have to do any work to use SSL. To use this option, set the rds.force_ssl parameter to 1 (on). By default, the rds.force_ssl parameter is set to 0 (off). The rds.force_ssl parameter is static. Therefore, after you change the value, you must reboot your DB instance for the change to take effect.
  • Encrypt specific connections: This method sets up an SSL connection from a specific client computer, and you must encrypt connections on the client.

To encrypt connections from other SQL clients, append encrypt=true to your connection string. This string might be available as an option or as a property on the connection page in the GUI tools.

Confirm that your connection is encrypted by running the following query:

SELECT ENCRYPT_OPTION FROM SYS.DM_EXEC_CONNECTIONS WHERE SESSION_ID = @@SPID;

Verify that the query returns true for encrypt_option.

Note: To activate SSL encryption for clients that connect using JDBC, you might need to add the Amazon RDS SQL certificate to the Java CA Certificate (cacerts) Store. You can do so by using the keytool utility.

Amazon RDS for PostgreSQL

Amazon RDS supports SSL encryption for PostgreSQL DB instances. Using SSL, you can encrypt a PostgreSQL connection between your applications and your PostgreSQL DB instance. You can also force all connections to your PostgreSQL DB instance to use SSL. Amazon RDS for PostgreSQL supports TLS versions 1.1 and 1.2.

Before connecting to an Amazon RDS for PostgreSQL DB instance over SSL, do the following:

  1. Download the certificate.
  2. Import the certificate into your operating system.

For more information, see Connecting to a PostgreSQL DB instance over SSL.

Use the sslrootcert parameter to reference the certificate. For example, sslrootcert=rds-ssl-ca-cert.pem.

$ psql "host=myinstance.123456789012.rds-us-east-1.amazonaws.com port=5432 user=testuser dbname=testpg sslmode=verify-full sslrootcert=global-bundle.pem"

You can also configure the connections to your RDS for PostgreSQL instance use SSL by setting rds.force_ssl to 1 (on) in your custom parameter group. By default, this value is set to 0 (off).

When you set rds.force_ssl to 1 (on), your DB instance's pg_hba.conf file is modified to support the new SSL configuration. You can use the pg_hba_file_rules view to view the summary of contents of the pg_hba.conf file.

When you set rds.force_ssl to 0 (off), the pg_hba.conf file looks similar to the following:

SELECT * FROM pg_hba_file_rules;

 line_number | type  |     database      | user_name  | address  | netmask | auth_method | options | error 
-------------+-------+-------------------+------------+----------+---------+-------------+---------+-------
           4 | local | {all}             | {all}      |          |         | md5         |         | 
          10 | host  | {all}             | {rdsadmin} | samehost |         | md5         |         | 
          11 | host  | {all}             | {rdsadmin} | all      |         | reject      |         | 
          12 | host  | {rdsadmin}        | {all}      | all      |         | reject      |         | 
          13 | host  | {all}             | {all}      | all      |         | md5         |         |
          14 | host  | {replication}     | {all}      | samehost |         | md5         |         | 
          15 | host  | {rds_replication} | {all}      | all      |         | md5         |         | 
(7 rows)

When you set rds.force_ssl to 1 (on), the pg_hba.conf file looks similar to the following:

SELECT * FROM pg_hba_file_rules;

line_number |  type   |     database      | user_name  | address  | netmask | auth_method | options | error 
-------------+---------+-------------------+------------+----------+---------+-------------+---------+-------
          4 | local   | {all}             | {all}      |          |         | md5         |         |
         10 | host    | {all}             | {rdsadmin} | samehost |         | md5         |         |
         11 | host    | {all}             | {rdsadmin} | all      |         | reject      |         |
         12 | host    | {rdsadmin}        | {all}      | all      |         | reject      |         |
         13 | hostssl | {all}             | {all}      | all      |         | md5         |         |
         14 | host    | {replication}     | {all}      | samehost |         | md5         |         |
         15 | hostssl | {rds_replication} | {all}      | all      |         | md5         |         |

You might notice that the type value for line_number (13) is updated to hostssl after rds.force_ssl is set to 1 (on).

After you activate SSL connection on your instance, you see a message similar to the following when you initiate a connection to your RDS for PostgreSQL instance:

$ psql "host=myinstance.123456789012.rds-us-east-1.amazonaws.com port=5432 user=testuser dbname=testpg"
. . .
SL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

All the non-SSL connections are rejected with the following message:

$ psql "host=myinstance.123456789012.rds-us-east-1.amazonaws.com port=5432 user=testuser dbname=testpg sslmode=disable"
psql: FATAL: no pg_hba.conf entry for host "host.ip", user "testuser", database "testpg", SSL off
$

Did this article help?


Do you need billing or technical support?