How to use SSL with Spring Boot

This is the first in a series of blog posts in which I will explain how to use SSL for a Spring Boot based web app. I will cover the basic config that is need to enable HTTPS.

A very simple Spring Boot application will serve as our example. It literally contains just a single REST endpoint.
You can find the full source code here in this public Bitbucket git repository

@RestController
public class DemoRestController {

    @GetMapping("/greet")
    String greet() {
        return "Hello World!";
    }
}

Compile, package and start the Spring Boot application

$ ./mvnw clean package
$ java -jar target/demo*.jar

During the startup, you will see the following output appear which indicates that by default Spring Boot configured your application to be served via the HTTP protocol.

Tomcat initialized with port(s): 8080 (http)

And now we can already query our fine little REST endpoint via HTTP

$ curl -s http://localhost:8080/greet
Hello World!

Let’s activate SSL

This was all very easy so far (it is not getting any more complicated). Spring Boot did all the auto-configuration for us. But obviously, this is not secure as by default HTTP is used.

Now in order to secure our endpoint with SSL, it is up to us to configure some things. No worries though, Spring Boot got us covered and will support us with its auto-configuration magic a lot.

First of all, we need an SSL certificate that can be used to encrypt the data transported to and from our application. For this demonstration I will use a self-signed certificate. Those can be easily created and are OK for local testing. For production use you want to use a certificate issued by some trusted authority though. I will cover how to use Let’s Encrypt with Spring Boot in a later blog post.

I will use Public Key Cryptography Standards #12 to store our self-signed certificate. And we can make Spring Boot directly use that keystore for SSL encryption.
The following command will create an RSA public/private key pair and store it in the PKCS#12 format in a keystone file. This is essentially our certificate. The important bits here to remember for later are the alias, the keystone filename as well as the password which you will be prompted to enter.

$ keytool -genkeypair -alias demo-alias -keyalg RSA -keysize 2048 
    -storetype PKCS12 -keystore demo-keystore.p12 -validity 365

Copy the demo-keystore.p12 file into the /src/main/resources directory (which will effectively put it onto the classpath). We can not activate SSL by adding the following properties to our application.properties file.

# The keystore format
server.ssl.key-store-type=PKCS12
# Path to the keystore file
server.ssl.key-store=classpath:demo-keystore.p12
# The password we entered when we created the certificate
server.ssl.key-store-password=PassWord123
# The alias mapped to the certificate
server.ssl.key-alias=demo-alias

And believe it or not, this is it. Spring Boot will pick up those properties and auto-configure HTTPS for our web app now.

$ ./mvnw clean package
$ java -jar target/demo*.jar

During the start-up of the application you will see that Tomcat was configured by Spring Boot to use HTTPS:

Tomcat initialized with port(s): 8080 (https)

Now we can try to access our REST endpoint again. The HTTP variant does not work anymore. But instead we can not use HTTPS to contact our Spring Boot application.

$ curl -s http://localhost:8080/greet
Bad Request
This combination of host and port requires TLS.

$ curl -s -k https://localhost:8080/greet
Hello World!

You can find the fully working sample code (including the self-signed certificate keystore file and the Spring Boot configuration) of this demonstration on the branch named step1 in the Bitbucket git repository.

Don’t package your certificate into your jar file

What I did there is not a good idea 🙂 You don’t want to bake your keystore (with your private key) into your jar file.

For production you want to store your keystore file somewhere somewhere on the server’s file system and make Spring Boot load it from there. Let’s assume your keystore file is located in the /etc/keystores/demo-keystore.p12 directory. A good practice is to configure the properties outside of your jar. E.g. in an application.properties file located in the directory from where you start your Spring Boot application. The properties from that application.properties file will be merged with those present in the jar file. Check the Spring Boot documentation for more details on how application.properties files are found and loaded. So your external application.properties should look like this:

server.ssl.key-store-type=PKCS12
server.ssl.key-store=/etc/keystores/demo-keystore.p12
server.ssl.key-store-password=PassWord123
server.ssl.key-alias=demo-alias

Leave a Reply

Your email address will not be published. Required fields are marked *

*