Spring Boot Application Secured by Let's Encrypt Certificate

14 May 2016 Spring, TLS, Tutorials

In this post, we explore how to generate a standalone certificate using Let’s Encrypt authority and how to make it work with a Spring Boot application. Let’s Encrypt made it easy and free for the whole web to obtain a valid certificate.

An extended version of this post on DZONE [here]

Introduction

In previous article, we became familiar with configuration of an Spring Boot Application with a self-signed certificate. Self-signed certificates are good for specific purposes such as test and development. But, if one needs to ship his application to production, certificates should be signed by known and eligible Certificate Authorities (CA).

These types of certificates are usually expensive. If you want to harden your application with TLS, you need to purchase one of them. The price and complex configuration of application servers made a barrier for many web applications to use secure connections.

In the post-Snowden era, no one needs to convince us that having secure connection using HTTPS is a must. There are lots of efforts to increase awareness of developers and IT administrators to employ such technologies for every single website they make. But how?

Let’s Encrypt projects aims at bringing HTTPS to World Wide Web not only for free but also with the simplest way of configuration.

How to Generate Certificates with Let’s Encrypt

Let’s Encrypt has several plugins for some application servers such as Apache and Nginx. In this section, as our target is Spring Boot Application (with an embedded Jetty/Tomcat), we just generate the certificates and later on integrate with our application.

If you’re using a firewall or any other security mechanism at your server or Cloud provider, you should relax it for a couple of minutes - specially port 80 and port 443.

Port 80 should be open and free to use as Let’s Encrypt runs a small http server behind the scene to prove whether you control your domain address (ACME protocol).

  1. You need to fetch the source code of Let’s Encrypt on your server which your domain address is pointing to. This step may take a couple minutes.
$ git clone https://github.com/certbot/certbot 
$ cd certbot
$ ./certbot-auto --help

Remark: Python 2.7.8 (or above) should be installed beforehand.

  1. By executing following command in your terminal, Let’s Encrypt generates certificates and a private key for you.
$ ./certbot-auto certonly -a standalone \
-d example.com -d www.example.com

Keys are generated in /etc/letsencrypt/live/example.com. Remark:
‘certonly’ - means that this command does not come with any special plugin like Apache or Nginx. ‘standalone’ -  means that Let’s encrypt will automatically create a simple web server on port 80 to prove you control the domain.

How to Generate PKCS12 files from PEM files

Certificates and private keys are generated in 2 steps for free which shows the simplicity of Let’s Encrypt. All of these generated materials are with PEM extension which is not supported in Spring Boot.

Spring-Boot does not support PEM files generated by Let’s Encrypt. Spring Boot supports PKCS12 extension. Using OpenSSL, we convert our certificate and private key to PKCS12.

To convert the PEM files to PKCS12 version:

  1. Go to /etc/letsencrypt/live/example.com
  2. We convert the keys to PKCS12 using OpenSSL in the terminal as follows.
$ openssl pkcs12 -export -in fullchain.pem \ 
-inkey privkey.pem \
-out keystore.p12
-name tomcat \
-CAfile chain.pem \
-caname root

The file ‘keystore.p12’ with PKCS12 is now generated in /etc/letsencrypt/live/example.com.

Configuration of your Spring Boot Application

Now we want to configure our Spring Boot application to benefit from the certificate and the private key; and eventually have the HTTPS thingy ready. At this moment, we already generated our certificate and private key. Then we converted the keys to PKCS12 extension which is ready to be used for Spring application.

  1. Open your application.properties
  2. Put this configuration there.
server.port: 8443
security.require-ssl=true
server.ssl.key-store:/etc/letsencrypt/live/example.com/keystore.p12
server.ssl.key-store-password: <your-password>
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: tomcat

Remark ‘require-ssl’ - means that your server only processes HTTPS-protected requests.

If you visit https://example.com:8443, you can see that HTTPS is successfully configured and most importantly working.

As illustrated above, the server is secured by Let’s Encrypt certificate. For privacy reasons, I hid the domain name in this picture.

Further Information

Certificate renewal. Certificates issued by Let’s Encrypt are only valid for 90 days. They believe that by using short-lived keys, damage from probable key compromise and mis-issuance is limited. It means that every 60 days you should renew your certificates. Let’s Encrypt client applications are evolving to provide automatic renewal process.

Limit on usage. Let’s Encrypt issues a limited number of certificates per week. If you plan to explore and try the configurations, you can use the ‘–test-cert’ flag in your generation command. Then you receive certificate from their staging server.

Configuration quality. Having a strong and large key is not always sufficient. Your application server should also be configured correctly. SSL Labs provides a very useful online tool to evaluate your HTTPS configuration. In addition to SSL Labs, there is a list of assessment tool in this link.

ACME Community clients. There are (evolving) list of community clients of ACME protocol. These client apps or scripts aim at assisting developers or IT administrators in order to automate the whole process with different languages and environments.

Future Work

Considering the fact that Spring applications are one of the most popular application stacks in enterprise Java world, having a module responsible for the whole process is a must. I am not sure Spring team have tendency to add a Let’s Encrypt plugin to their well-established Spring Security module.

But there are a couple of community projects trying to bring ACME protocol to Java-based projects such as Acme-Client and Acme4j. We need an extra community move towards Spring framework to benefit from a neat module integrated with Spring framewok automating everything by 2 lines of configurations. If I find time, I may give it a try to implement such module for Spring.

Ethically we should support projects like Let’s Encrypt which are clearly for good. Our basic support is to spread the news and perhaps contributing as much as we can.