MySQL SSL/TLS connections with Oracle SQL Developer
This article covers how to setup Oracle SQL Developer to use MySQL driver and connect via SSL/TLS to a MySQL server database with a PKCS12 certificate.
Motivation
I’ve been using Oracle SQL Developer on Mac OS for a couple of years and it is my preferred tool to connect to both Oracle and MySQL databases.
Recently I had to connect to a SSL/TLS enabled MySQL server and information on setting this up happened to be from very sparse to almost non-existent. I’ve spent a few hours searching and reading through official documentation, forums, comments etc without much success. Finally I managed to combine several sources and it worked out, so I decided to put all this info together and help other people looking for the same info.
Some people will jump here and say “Why don’t you use MySQL Workbench? It has SSL/TLS support out of the box.” and my answer will be – Yes you can, but you can be used to Oracle SQL Developer interface, reports, export, graphs etc and/or use Oracle Databases at the same time and then you don’t want to switch between 2 tools all the time.
Compatibility
The commands and screenshots shown here are from Mac OS X but they should work on any Linux distro and hopefully on Windows.
The proposed method was tested with Oracle SQL Developer 17.2 and Google Cloud MySQL 5 database.
Prerequisites
You have a MySQL server with enabled SSL/TLS and you have your key and certs available:
- client-key.pem – private key of the connecting client
- client-cert.pem – client certificate corresponding to the client private key and signed by the MySQL server certificate issuer.
- server-ca.pem – server certificate
You have Oracle SQL Developer installed and working (for this article ver. 17.2 was used)
You have downloaded MySQL Connector/J and extracted archive contents in any folder – we’ll refer to that path as $CONNECTOR_J_ROOT (for this article ver. 5.1.44 was used)
Convert keys and certificates in a Java friendly format
As Oracle SQL Developer and Connector/J are written in Java the keys and certificates in PEM format will not be recognised. We need to create a Truststore for the server certificate and a Keystore for the Client key and certificate. We will use JKS but PKCS12 is also an option.
To manage keystores Java comes with a tool called “keytool”. We’ll use it to convert and import our certificates and key into JKS store.
Create a truststore
Open your terminal and execute the following changing “server-ca.pem” to the name of your server ca file
keytool -import -v -trustcacerts -alias sql-server-ca -file server-ca.pem -keystore truststore.ts
Create a keystore
Combine client details
Usually client key and client certificate come into separate files but to import them in a JKS keystore they need to be combined. For that purpose we’ll use openssl library as follows:
openssl pkcs12 -export -inkey client-key.pem -in client-cert.pem -certfile server-ca.pem -out client-keys-combined.pkcs12
Import client details into a keystore
Java supports PKCS12 keystores so you can directly use it but for consistency let’s convert it to JKS by executing the following:
keytool -v -importkeystore \ -srckeystore client-keys-combined.pkcs12 -srcstoretype PKCS12 -srcalias 1 \ -destkeystore keystore.ks -deststoretype JKS -destalias mysql-client-details
note the “-srcalias 1” which identifies that first and only entry but it is required so that we can set “-destalias”
Check store contents
To list the entries in a JKS store use the following:
keytool -list -keystore keystore.ks
Steps to set up
MySQL connection options
MySQL Connector/J documentation describes an option to send each connection configuration properties at creation . That allows us to pass SSL related properties just before the connection is made.
Here is a list of all the properties needed when SSL/TLS is enbled with client certificate authentication:
useSSL=true requireSSL=true verifyServerCertificate=true trustCertificateKeyStoreUrl=file:/path/to/truststore.ts trustCertificateKeyStoreType=JKS trustCertificateKeyStorePassword=mypass clientCertificateKeyStoreUrl=file:/path/to/keystore.ks clientCertificateKeyStoreType=JKS clientCertificateKeyStorePassword=mypass
The standard way for passing these properties is through the connection uri as key value pairs:
jdbc:mysql:server_host:port/database?enableSSL=true&requireSSL=true&verifyServerCertificate=true....
So far so good. Let’s see how we can do that in Oracle SQL Developer
Enable MySQL support in Oracle SQL Developer
Oracle SQL Developer supports loading 3rd party JDBC drivers. We’ll use that to enable MySQL support.
- Open Oracle SQL Developer
- Go to Preferences (Command+, on Mac) from window menus.
- Navigate to Database -> Third Party JDBC Drivers
- Click on Add Entry and browse to your $CONNECTOR_J_ROOT selecting the only .jar file inside.
- Click on OK to confirm and close the Preferences box
Create a new connection
Now that we have loaded the MySQL driver let’s create a new connection
- Go to File -> New and select a Database Connection
- Enter Connection name
- Enter Username
- Enter Password
- Enter Database hostname or ip address
- Enter Database port
- Leave database empty
As there is no field for connection properties and Oracle SQL Developer will construct a connection uri like $USER@//$HOST:$PORT/$DATABASE
we will leave the database field empty and abuse the port field to introduce our connection properties by filling in the following:
3306/mydatabase?enableSSL=true&requireSSL=true&verifyServerCertificate=true...the_rest_of_ssl_properties...&1=1
Note the &1=1
at the end. It is a workaround of the fact that Oracle SQL Developer puts /null
or /$database
at the end and break the value of our last parameter. If we add that string it will be ignored by the connection uri parser in Connector/J, because 1=1/null
refer to a property with name “1” which does not exist.
Test and Go
Hit the “Test” button and you should see Status: Success! Don’t forget to Save.
This works and we can stop here but the properties string is quite long for the small port field and that makes it very hard to manage especially if you have many connections with different settings i.e. connecting to microservices databases.
So what else can be done?
Connector/J documentation describes a few predefined profiles (sets of properties) which are designed to fine-tune the driver for specific databases and are passed to each connection during initialisation. They can be enabled by passing a parameter in the connection uri as described above.
jdbc:mysql:server_host:port/database?useProfiles=profile_name
This can be quite helpful as we can pack our properties into different files and load them with one property in the connection uri. The downside is these profiles are available only inside the Connector/J jar file and can be loaded from there because the classpath inside a jar defaults to its root.
So we are going to unpack the jar, put our profiles and pack it again. Then when the jar is loaded into Oracle SQL Developer profiles can be used as a value in the port field i.e. 3306/mydatabase?useProfiles=myprofile1&1=1
which is much more clear but hides the configuration a bit.
Packing profiles in the jar
Create a profile file
The file must be named with extension .properties and must be following the Java properties file rules
Open your favourite text editor and enter the following changing the paths and passwords accordingly:
useSSL=true requireSSL=true verifyServerCertificate=true trustCertificateKeyStoreUrl=file:/path/to/truststore.ts trustCertificateKeyStoreType=JKS trustCertificateKeyStorePassword=mypass clientCertificateKeyStoreUrl=file:/path/to/keystore.ks clientCertificateKeyStoreType=JKS clientCertificateKeyStorePassword=mypass
Save as e.g. myprofile1.properties
Repack the Connector/J jar
- Open a Terminal window and navigate to $CONNECTOR_J_ROOT
- Create a new folder named unpacked and go inside
mkdir unpacked; cd unpacked
- Unpack the jar
jar -xf ../mysql-connector-java-5.1.44-bin.jar
- Copy myprofile1 (or as many profiles you need) to configs folder
cp /path/to/myprofile1.propertis com/mysql/jdbc/configs
- Make a new jar
jar -cf ../mysql-connector-java-5.1.44-bin-with-myprofiles.jar *
Setup Oracle SQL Developer
Now go to Oracle SQL Developer and replace the original Connector/J jar file with your new jar.
Edit your connection and change the Port value to look like
3306/mydatabase?useProfiles=myprofile1&1=1
Test, Save and Enjoy!
Notes
If you upgrade Connector/J to a new version, you will have to repeat only the repacking steps and reload the driver in Oracle SQL Developer.
I hope I managed to save someone a few hours of searching and reading partial information.
The underlying connections.xml file looks like this:
jdbc:mysql://gdnd1.cwimgnvqntri.us-east-1.rds.amazonaws.com:3306/gdndb?trustCertificateKeyStoreUrl=file:C:\temp\truststore.ts&trustCertificateKeyStoreType=JKS&trustCertificateKeyStorePassword=rds-db-ca
gdnd1.cwimgnvqntri.us-east-1.rds.amazonaws.com
com.mysql.jdbc.Driver
3306
MYSQL
false
convertToNull
MySQL
testme2
awsrdsdb1
Port config is not correct as in your connection XML i can see 3306 on a separate line, while mine has both URL and port &1=1/dbname at the end
false
MySQL
-16743292
jdbc:mysql://XXX.XXX.XXX.XXX:3306/dbname?useConfigs=klstage&1=1/dbname
XXX.XXX.XXX.XXX
com.mysql.jdbc.Driver
3306/dbname?useConfigs=klstage&1=1
MYSQL
convertToNull
user
Stage Core
Profiles are just a shorthand for providing all parameters so it shouldn’t make any difference if you use them or not.
I did take care of spaces and provided absolute paths with little luck yet. I still have the same problem connecting to the database. SQL Developer does NOT even complain if the path is wrong and/or if the file does NOT exist.
I first tried with no profile, it looked for the truststore file in the path specified. However, it did NOT connect to the database when ‘require SQL’ is configured for the given user on the database.
3306/mydb?useSSL=true&requireSSL=true& verifyServerCertificate=true&trustCertificateKeyStoreUrl=file:somepath_truststore.ts &trustCertificateKeyStoreType=JKS &trustCertificateKeyStorePassword=somepassword &1=1
Hi Krishna,
There are a few spaces in the query string which i suspect are copy&paste mistakes, so please make sure they are not present in your SQL Developer setup.
Also when giving paths to trust and keystore files please use absolute paths.
Desislav, i wonder if you are able to help me.
I am working for Vodafone Group, we are struggling to connect SQL developer via SSL in AWS. Please reach out if you think you could help 🙂
Sure, will drop you an email for further communication.