As you probably know, one of the most common ways to secure communications over a networks is the use of certificates. And although this is a great way to secure things, it can also be a pain.
In this post, I’ll share with you all a list of some of the most commons things encountered while working with certificates. I will also show you how to leverage certificates when working with Mule ESB. Finally, I’ll show you a quick hack that may save you some time when you are in a hurry.
Now what’s a keystore?
Java is shipped with the KeyTool, which is nothing more than a command line tool that allows you to create keystores. A keystore is the “secure” repository that Java uses to store the certificates. It’s basically a file that holds certificates, this file is what you’ll hock to you Java app so it knows how to encrypt and decrypt the messages.Now the “fun part”, let’s see how to create a key store:
As you can see it’s quite easy right?
So what did we do here? Basically we’ve created a new keystore and imported a certificate into it. As you can see, the command option we are using is “-import”, thus KeyTool will try to import the certificate to the existing keystore. BUT if it doesn’t exists it’ll create one.
As you probably already figured out this means that if your app is already working with a keystore and you need to add a new certificate you can just import the new certificate to the existing keystore.
KeyTool is quite a powerful tool, it allows you to do all kinds of things with a keystore. I advise you to read the documentation when in doubt.
Working with Certificates and Mule ESB
Mule ESB allows you to use certificates when you need them. The two more relevant use cases, in my own opinion, are:
- Exposing HTTPS endpoints
- Connecting to a secure JDBC instance
Exposing HTTPS endpoints
Now you can find more detailed documentation on how this works in MuleSoft documentation, but to get you up to speed – the point is to declare an HTTPS connector and define a keystore for it, like so:
As you can see, the path is kind of hardcoded, this is because Mule will try to find a resource with that name in the application class-path. Another thing to notice is that the key and the store password are placeholders. It is good practice “not to hard code password in Mule apps”.
That said this is how the HTTPS endpoint will look like:
Please notice the “connector-ref”.
Connecting to a secure JDBC instance
In Order to define a key store for your Mule JDCB connector, here is what you can do.
You could create a Java class with the sole purpose of loading that particular keystore, to make
it nicer we could create a bean that we’ll afterwards add to our Mule Application.
The bean will look like this:
And you Mule application configuration will look something like this:
As an option to this you could just set these properties sending them as a parameter to the JVM for example when starting you mule application like so: -M-Djavax.net.ssl.keyStore=you-path-to-the-key-store
Well I could give you the “in my words” explanation about what a self-signed certificate is, but I’ll let this Wikipedia article do it for me, because let’s face it, it’s better than me explaining it:
“…a self-signed certificate is an identity certificate that is signed by the same entity whose identity it certifies”
Pretty clear right? Now the ugly part, although it works, a self-signed certificate means nothing. It serves its purpose though, to encrypt a message broadcasted over a network. In real life however, it’s like you are buying a diamond and you simply take the seller’s word for it that the diamond is real. You want someone else to vouch for that diamond? Well it’s the same for Java. when you work with a self-signed certificate, Java notices it, warns you about it, and fails the execution of the application.
So why do self-signed certificates exists? As previously stated, it’s because they serve the purpose of securing communications. Usually companies use them to secure internal sites or public sandboxes, as the security requirement around them are not very tight.
Now you know the what and the why, I’ll now show you the “how to” work around the the issue with Java.
The Nasty Hack:
There are two ways to avoid Java failing when your Java application has to work with self-signed certificates:
- Import the certificate to the JDK key store
- Add code to your application to tell Java to trust the self-signed certificates
The first one is somewhat intrusive. I personally would’t like to be adding any self-signed certificate to the JDK keystore. Plus, when you are in a different environment let’s say you deploy you application to QA, good luck convincing the system’s admin to let you import that kind of certificates just because the remote system doesn’t provide a valid certificate. But it works just fine when you are in your local.
So here it is! This example shows you how to add a certificate to the JDK in a Mac:
As you can imagine, the relevant part here is the keystore path:
For those working on Windows or Linux, you just need to find the default path for this keystore.
Add code to your application to tell Java to trust the self-signed certificates
This technique relies on adding a method you have to execute before you app tries to makes use of the self-signed certificate. Just add the code below and make sure to execute it.
In short, it just tell the JVM to validate any certificate independently of its origin. Now remember this is still a hack, so I would not advise you to use this code for productive applications if you can avoid it. I came across this hack online and thought it was worth sharing! You can find a similar method in the reference below.