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

10 minute read
2

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

Short description

To encrypt a connection to a DB instance that runs MySQL, MariaDB, Microsoft SQL Server, Oracle, or PostgreSQL, use SSL or Transport Layer Security (TLS) from your application. SSL/TLS connections provide one layer of security because the connections encrypt data that's transferred between your client and the DB instance. A server certificate provides an extra layer of security because it validates 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 (CA). 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, use an intermediate certificate to connect to your AWS Region. For example, when you use SSL to connect to the AWS GovCloud (US) Regions, you must use an intermediate certificate.

You can download a certificate bundle that contains both the intermediate and root certificates for all 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 to implement SSL/TLS. To implement an SSL/TLS connection for your DB cluster, use one of the following methods based on your database engine.

Amazon RDS for Oracle

For Amazon RDS for Oracle instances, to turn on SSL mode add the SSL option in your custom option group.

RDS for Oracle supports 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 automatically set to "1.0". You can change the setting, if necessary.

You must configure the SQL*Plus client to use SSL before you connect 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 configure the SSL connection.

Example code that uses JDBC to set up the SSL connection:

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 use SSL to connect to your RDS for Oracle instance, check 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 appropriately configured 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 in only one direction. However, encryption is still possible in both directions. For more information, see Activating one-way TLS for MariaDB clients on the MariaDB website.

With server certificate verification, the client verifies that the certificate belongs to the server. For more information, see Server certificate verification on the MariaDB website.

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 based on your MariaDB version:

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

For RDS for MariaDB version 10.5 and later with the Performance Schema turned on and applications connected to a database instance, check what connections use SSL/TLS:

MariaDB> SELECT id, user, host, connection_type
FROM performance_schema.threads pst
INNER JOIN information_schema.processlist isp
ON pst.processlist_id = isp.id;

Note: For more information about Performance Schema, see Performance Schema on the MariaDB website.

Amazon RDS for MySQL

MySQL uses OpenSSL for secure connections. For more information, see SSL/TLS support for MySQL DB instances on Amazon RDS.

By default, MySQL client programs try to establish an encrypted connection when the server supports encrypted connections. For additional security, 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 use the --ssl-ca parameter for MySQL 5.7 and later to launch the client, 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 command similar to the following, based 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, run the following command:

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

For RDS for MySQL version 5.7 or 8.0 with the Performance Schema turned on and applications connected to a database instance, check what connections use SSL/TLS:

mysql> SELECT id, user, host, connection_type
FROM performance_schema.threads pst
INNER JOIN information_schema.processlist isp
ON pst.processlist_id = isp.id;

Note: For more information about Performance Schema, see Performance Schema on the MariaDB website.

Amazon RDS for Microsoft SQL Server

To use SSL to connect to your RDS for Microsoft SQL Server DB instance, you can force SSL for all connections or encrypt specific connections.

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.

To confirm that your connection is encrypted, run 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 use JDBC to connect, you might need to add the RDS SQL certificate to the Java CA Certificate (cacerts) Store. To do so, use the keytool utility.

Amazon RDS for PostgreSQL

Amazon RDS supports SSL encryption for PostgreSQL DB instances. For more information, see Using SSL with a PostgreSQL DB instance.

Before you connect to an RDS for PostgreSQL DB instance over SSL, complete the following steps:

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

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

To reference the certificate, use the sslrootcert parameter. 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"

To configure the connections to your RDS for PostgreSQL instance to use SSL, set 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. To see the summary of contents of the pg_hba.conf file, use the pg_hba_file_rules view. For more information, see pg_hba_file_rules on the PostgreSQL website.

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

Note: The type value for line_number (13) might update to hostssl after rds.force_ssl is set to 1 (on).

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

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

Related information

Using SSL/TLS to encrypt a connection to a DB instance or cluster