This is because the SSL is enforced at the user level and not at the server port level. Typically when you disable insecure traffic to a particular server you will disable the port that it is listening on for insecure traffic - such as port 80 for the apache web server.
MySQL is different, you still connect through the default port (3306), or whatever port you have configured it to run, but the difference is the way you connect. In order to ensure secure communication you must first create a user which requires SSL to connect:
First connect to the RDS instance as the root user:
mysql -h myinstance.123456789012.us-east-1.rds.amazonaws.com -P 3306 -u root -pYou can then create users in the specific way:
GRANT SELECT, INSERT, UPDATE, DELETE on db_name.* to 'encrypted_user'@'%' IDENTIFIED BY 'suprsecret' REQUIRE SSL;FLUSH PRIVILEGES;You can now test this with the mysql client that you used earlier to connect to the database earlier:
mysql -h myinstance.123456789012.us-east-1.rds.amazonaws.com -u encrypted_user -p --ssl_ca=mysql-ssl-ca-cert.pem --ssl-verify-server-certThe above should prompt you for the password that you set up above, and allow you to connect to the database securely.
This is the database server end complete. The next part is to configure your application to use SSL to connect to the database securely. There are a number of ways in which you can complete this, for this example I'm going to configure a java application.
For this example we're going to configure the JDK to allow the secure connection. There are a number of options here, including application container specific configurations but this way has the advantage that all java applications (container or otherwise) will be able to connect.
First get the RDS MySQL server certificate from AWS:
wget https://rds.amazonaws.com/doc/mysql-ssl-ca-cert.pemNow import this into the java trust store (replace $JAVA_HOME as necessary):
$JAVA_HOME/bin/keytool -importcert -alias rds -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeme -file ./auspost-root-ca.cer -nopromptConnecting to the MySQL database is the same as before however you now specify three new options in your connection string which connect using SSL:
jdbc:mysql://myinstance.123456789012.us-east-1.rds.amazonaws.com:3306?useSSL=true&verifyServerCertificate=true&requireSSL=trueFor brevity I will not include the rest of the code that you use in java in order to connect.
This comment has been removed by the author.
ReplyDeleteI am able to connect using the mySQL client but using the jdbc driver I get the following error
ReplyDeleteCould you please help with this this error:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.
On seeing the SSL logs, I found this error as well:
***
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_256_CBC_SHA]
main, SEND TLSv1 ALERT: fatal, description = certificate_unknown
main, WRITE: TLSv1 Alert, length = 2
Hey Ravi,
DeleteSounds like you don't have the RDS SSL certificate in your java truststore. My above example assumes this, probably incorrectly. You can get the ssl root certificate from amazon here:
https://s3.amazonaws.com/rds-downloads/rds-ca-2015-root.pem
Which you can then import into your truststore. The above example uses the default java trust store which is in $JAVA_HOME/jre/lib/security/cacerts
Hope this helps.
This comment has been removed by the author.
ReplyDelete