Accessing an SSL database from a Java app running in Cloud Foundry

Recently I had a customer with the need to deploy a Tomcat app that used a MongoDB database in Bluemix. Seems like pretty straightforward, but it isn’t.

The MongoDB offering in Bluemix is called Compose for MongoDB. Compose is a company IBM acquired a couple of years ago which does Database-as-a-Service. Through Compose you can get several different databases in Bluemix, such as MongoDB, PostgreSQL and Redis.

In the cloud world, all serious offerings use SSL for connectivity. Of course, they are exposing endpoints to the world, it better be SSL. And that’s what Compose for MongoDB does. So far so good.

In Cloud Foundry, cloud applications leverage the platform ability to bind to services. When you bind a service to an app in Cloud Foundry, the app has access to the credentials of the service and there is no need to hard code or use properties files to connect to backend services, such as a database. The developers do not need to know the credentials for the database they will be using, the values are populated in deploy time. This allows for less dependency on the environment the application will run. So when you bind a Compose for MongoDB service to an app in Bluemix, the app has access to the username, password, URL, and the ca_certificate_base64 property which contains the certificate it will need to establish a secure connection to the database. That all looks great, doesn’t it?

Then there’s the catch. Java likes its credentials on a truststore, which is a file. The certificates need to be loaded in this truststore file and the JVM needs to know where it is and have access to. But you don’t have access to the file system in Cloud Foundry. It’s the beauty of the PaaS paradigm. All you care about are your code and data. The rest is supplied by the cloud provider. In order to maintain independency of environments you can’t rely on a file system. Therefore, today, there is no way a Java runtime can read that ca_certificate_base64 environment variable, convert it to a certificate and load it to the truststore. The binding of the service in this case is useless.

In order to achieve this we’ll have to throw the cloud-native approach out the window and manually create a truststore, put it in the Java project and build a WAR file that is (unfortunately) specific for that deployment. I’ve posted my code on GitHub with some high level instructions. Feel free to reach out if you need help. I didn’t write the original app, which is in this awesome site by Amaury Valdes. I just refactored it to make it run on Cloud Foundry.

DISCLAIMER: By no means this is good example of cloud-native code, it just has the bare minimum refactoring to make it run on Bluemix.