How to communicate via HTTPS between two Tomcat servers using a self-signed certificate
There is no need to pay for an SSL certificate in order to communicate two applications through a REST API over HTTPS. You just need to know a few things about Java keytool and a little bit of setup to make it work!
REST APIs have become a natural part of software development. And, as the tendency to build small, numerous and interacting applications increases overtime, so does the need of REST APIs.
These interactions most of the time will occur within a network which we may or may not have control of, and anyone with access could potentially sniff or intercept a message.
This is why we believe that encrypting those interactions using HTTPS is a good practise, and should be considered by every developer, whether the security of the information is a critical part of the system or not. Plus, it only takes some minutes of your time.
We will assume that you have some basic knowledge about HTTPS and how it works.
Consider a scenario in which we have two Java applications (
B), running over two different Tomcat servers (
B consumes a service from
A through a REST API.
Before encrypting the communication between them, we will need to learn about these two concepts:
A Java Keystore is the file where our certificate will be stored, along with its private key. This certificate will be the one used to authenticate to a remote server and encrypt the outgoing responses.
The keystore will also contain all those certificates that we're willing to trust. This is, public keys used to verify the remote certificates that we don't already know.
The Java Keytool is a key and certificate management command-line tool, bundled inside the JVM. We can use it to create self-signed ceriticates and install them in our servers, either for authentication or verification.
Creating self-signed certificate
Having said that, in order to enable our application
B to send a request to
A via HTTPS, first we should create a self-signed certificate for
A. We can do this using the Java Keytool, running the following commands in
$ cd -- $ mkdir ssl $ $JAVA_HOME/bin/keytool -genkey -alias SERVER-A -keyalg RSA -keystore ssl/SERVER-A.keystore
Then the keytool will prompt the following questions:
Enter keystore password: password What is your first and last name? [Unknown]: example.com What is the name of your organizational unit? [Unknown]: IT What is the name of your organization? [Unknown]: The Office What is the name of your City or Locality? [Unknown]: Buenos Aires What is the name of your State or Province? [Unknown]: Buenos Aires What is the two-letter country code for this unit? [Unknown]: AR Is CN=example.com, OU=IT, O=The Office, L=Buenos Aires, ST=Buenos Aires, C=AR correct? [no]: yes Enter key password for example.com (RETURN if same as keystore password): password
It's important to notice that when asked for the first and last name, we must enter the server domain or IP address.
Finally, we should see a file called
SERVER-A.keystore inside the
Export your keystore
Now we should import our new self-signed certificate into the Java Keystore of
In order to do that we will export it to a
.crt file, and then import it to the Java Keystore:
$ $JAVA_HOME/bin/keytool -exportcert -alias SERVER-A -keystore ssl/SERVER-A.keystore -file ssl/SERVER-A.crt -storepass password $ sudo $JAVA_HOME/bin/keytool -importcert -file ssl/SERVER-A.crt -alias SERVER-A -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
By the way,
changeit is the default password of the Java Keystore... in fact, we should change it :P
You will notice that we are importing our
.crt file into
$JAVA_HOME/jre/lib/security/cacerts... that's were the JVM stores our trusted certificates.
Then we should import the same
.crt file into the Java Keystore of the
SERVER-B Tomcat. We can do that running the next command line in
$ sudo $JAVA_HOME/bin/keytool -importcert -file ssl/SERVER-A.crt -alias SERVER-A -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
Finally we need to enable HTTPS for the
SERVER-A Tomcat. In order to do that, we will add a new connector to our
server.xml configuration file:
You will notice that we are using a fixed list of ciphers for our new connector, which are the more recommended and less-vulnerable ones.
We also recommend using the
1.2 version (or greater) of the TLS protocol, since lower versions are vulnerable. You can read more more information here
Setting your own self-signed certificates is not as hard as it seems, and for 5 minutes of your time, it will save you a lot of unknown future problems!