How to require SSL when connecting to MySQL on AWS RDS

With MySQL you can opt to connect to the database using an encrypted connection. This option is important to consider on AWS if you are using RDS for your MySQL database. The network between your EC2 server and the RDS server is controlled by Amazon. You don’t know who has access or what is going on in between. Enabling an SSL connection to MySQL does come with a small performance penalty. Back in 2013 I did some benchmarking on this.

First, get the CA file from AWS:

To enable an SSL connection to RDS for MySQL the first step is to download the certificate authority (CA) file from Amazon which can be found here. You may also want to read the AWS docs on the subject.

To make sure your MySQL connection is done over SSL you need to supply the CA file when connecting. It is also a very good idea to configure the MySQL user to require SSL connections. Examples of both are shown below:

When connecting via command line:

mysql -h mydb.rds.amazonaws.com
--ssl-ca=/home/myuser/rds-combined-ca-bundle.pem --ssl-mode=VERIFY_CA
You may have seen posts mentioning --ssl-verify-server-cert, but a new option --ssl-mode has been added in MySQL 5.7 which is more flexible. I'm using VERIFY_CA because it not only requires SSL, but also makes sure the CA matches.

In your .my.cnf, require SSL by setting the following:

[client]
user = myuser
password = ******
host = mydb.rds.amazonaws.com
ssl-ca = /home/myuser/rds-combined-ca-bundle.pem
ssl-mode = 'VERIFY_CA'

After you connect, to double that check SSL is being used:

Once you are connected, run the mysql status command and look for the SSL line:

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.7.19, for Linux (x86_64) using  EditLine wrapper

Connection id: 		12388
Current database:
Current user:  		myuser@myinstance
SSL:   			Cipher in use is AES256-SHA
....
--------------

In addition, FORCE your applications to connect via SSL as well:

As the AWS docs point out, it is really smart to add the REQUIRE SSL option to all your GRANT statements. That way a lazy client that isn’t setup for SSL or has a misconfigured cert will get rejected.

GRANT SELECT ON mydatabase.* TO 'myuser'@'%' IDENTIFIED BY '....' REQUIRE SSL;

For example, to configure Django 1.11 to use an encrypted connection with AWS RDS:

1) Put the rds-combined-ca-bundle.pem file in the same folder as your settings file.

2) Add the OPTIONS directive below to the DATABASES section:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydatabase',
        'HOST': 'mydb.rds.amazonaws.com',
        'USER': 'myuser',
        'PASSWORD': '....',
        'OPTIONS':  {
            'ssl': {'ca': os.path.join(os.path.dirname(os.path.dirname(__file__)), 'settings', 'rds-combined-ca-bundle.pem')}
        }
    }
}

How to decide if you should encrypt your connection to MySQL?

If you are running a database of cat memes, you probably don’t have much to gain from enabling this. If your app handles personally identifiable information (PII) or sensitive personal information (SPI) then encrypting the data in flight between the app server and db server makes more sense.

This entry was posted in Application Development, Data, Sys Admin and tagged , . Bookmark the permalink.

Comments are closed.