How-to: Connecting to Compose MongoDB with Java and SSL

We've heard from some Compose users that connecting to MongoDB with Java and SSL is a somewhat difficult process so we're going to illustrate the process in a stripped down example.

We'll assume that you are using the official MongoDB Java driver and you've imported it into your application. So let's recall what information we need to have to make a connection. First, the connection string for the Compose database that looks something like this in code:

   String url = "mongodb://example:example@hodor.2.dblayer.com:10287,hodor.1.dblayer.com:10302/admin?ssl=true";

This is the value from the Compose console's MongoDB overview. The username and password are for a user in the named database – in this case admin. We can use that url to connect to MongoDB like this:

   MongoClient client = new MongoClient(new MongoClientURI(url));

And, if there was no SSL in play we could run some command against the database with this client:

   MongoIterable<String> listDatabaseNames = client.listDatabaseNames();

   Block<String> printer = System.out::println;

   listDatabaseNames.forEach(printer);

This just gets a list of database names. We can do this because we're logging into the admin database and to do that we need admin level privileges.

But, notice the URL has "?ssl=true", so SSL is enabled and if we ran the code there'd be a nice big stack trace because there was no way to verify the certificate the server presented to the client.

To make this work, we need to go back to the Compose console and get the SSL certificate available on the Overview page - find it by clicking the button to reveal it and then copy it to a file. Let's call that file mongodbcert.crt for e. This is a self-signed CA certificate. There's no easy way, as there is in many other languages, to read and use that certificate. Java likes to find its credentials in a trust store file which we have to create using keytool.

keytool -import -alias compose -file ./mongodbcert.crt -keystore ./mongostore -storetype pkcs12 -storepass ilikeamiga  

This command imports the MongoDB certificate mongodbcert.crt, with an alias "compose" into a keystore called mongostore. It locks the store with the password ilikeamiga.

Now we have to tell Java that this information exists. The name of the store and the password can be set in javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword JVM variables. When your application starts running you could do something like this:

  System.setProperty("javax.net.ssl.trustStore", "/home/username/mongostore");
  System.setProperty("javax.net.ssl.trustStorePassword", "ilikeamiga");

That sets the properties, but be aware that you need to do that very early in the runtime of your application; once an SSL/TLS context is created, the property values at that point in time are locked in, so there is no changing them later on. With the properties set, you can move on to the connection code we covered earlier.

What can go wrong? Well, you may not have access to creating files in the file system to hold those credentials, or you may not be allowed or able to change the trust store. Problems like that tend to be caused by the application deployment platform and we will be looking at some approaches to solving that kind of problem in the future.