This article will describe how to set up an SSL in a Spring Boot application.
Almost all articles recommend you create a Keystore file using the Java key tool, and it still could make sense, but something new came up.
Starting from Spring Boot 2.7.0, setting SSL up could be much simpler without using the key tool. That’s why we decided to create this article.
We will also describe how to generate and import self-signed certificates.
But before doing that, we’ll briefly explain why we may need an SSL on a server.
Reasons to Have an SSL on a Server
Let’s imagine you’re drinking coffee in some restaurant, your device is connected to its wifi network, and you decide to visit some web service with sensitive data. For example, you want to check your bank account.
There are some components between you and the web service, including the wifi router. Of course, we trust restaurants, but we have to be sure that no data could be captured and used against users. All requests and responses on a wifi router could be logged or even collected somewhere.
So we can not control what a wifi router does, but we can make it impossible to use captured requests and responses. This is one of the reasons why the `https` protocol could be used.
A client and a server exchange encrypted messages during the session (using a symmetric encryption key). And only a client and a server know how to decrypt these messages.
So even if some wifi router collects requests and responses between a client and a web service, it simply doesn’t know what to do with them; it cannot decrypt them and understand what exactly these messages contain.
In addition to that, a client can also verify a web service ownership using an SSL certificate.
Certificates and Private Keys
In order to use SSL on your server, you have to have the following:
- An issued certificate (or certificate chain) containing a public key and ownership data.
- A private key
The combination of these files is also called a key pair.
A key pair could be issued for a single domain by any Certificate Authority (CA). An alternative option is generating a key pair with a self-signed certificate. But in this case, no third-party site can confirm ownership of your web service, and clients could complain about such certificates.
Anyway, only a server should be aware of a private key; it’s important not to share it.
A certificate containing a public key should be exposed by a server to clients. It is impossible for a client to establish a secure connection with a server without it. Using a certificate, a client can also verify domain ownership (impossible for self-signed certificates), check certificate validity, and so on.
Even right here and right now, you can find certificate details (in most browsers, you can do it by pressing a lock button near an URL). The certificate chain is fine; Amazon verifies ownership, is still valid, contains a public key, and the `https` connection has been established successfully.
Setting Up an SSL in a Spring Boot Application
1. Setting Up a Port
Let’s start with the simplest part 🙂
By default, browsers and most of the other clients use port 80 for `http` requests and port 443 for the `https` unless you specify another port in a URL explicitly.
So, in most cases, it is better to change a server port in the application properties file to 443:
But you can choose any other port. For example, if you specify port 8443, you just have to specify it in the URL; https://127.0.0.1:8443
, and it also works.
2. Importing a Certificate and a Private Key
Basically, there’re two options for importing a key pair into a Spring Boot Application:
- Using a raw certificate and private key files.
- Using a Java Keystore.
Option 1: Direct Import of Raw Certificate and Private Key Files
This is the easiest option, and it is available since Spring Boot 2.7.0 release.
It makes sense not to use the key tool anymore if you already have a pair of a pem-certificate and a private key issued by Certificate Authority (CA), and you don’t have any intention to store several key pairs in a single keystore file.
If you develop a Spring Boot based web-application, you can just provide the application with these files and specify them in an application properties file (see Spring Boot 2.7.0 release notes)
For example, you can place pem-certificate and private key files in a resources folder. After that, you can specify the location of these files in application properties:
server:
port: 443 #this port is used for https connections in browsers by default
ssl:
certificate-private-key: classpath:keypair/privatekey.key
certificate: classpath:keypair/certificate.crt
And that’s it 🙂
If you have a chain of certificates, you can combine them into a single certificate.crt file (just place their contents there one by one).
Option 2: Import Using a Keystore File
Another option is using the Java key tool for managing keystore files. And actually, this was the only option available to use before the Spring Boot 2.7.0 release.
Using the key tool, you can create a keystore file and place any amount of key pairs into it. But, of course, every certificate in a Keystore file has to be identified by unique alias.
So you can place key pairs issued by Certificate Authority (CA), generate key pairs with self-signed certificates, and all other certificates in a single file; just use different aliases for them. Sometimes it may be useful.
It is easier to use Option 1 if you don’t need to store several key pairs in a common shared keystore file and you use Spring Boot 2.7.0 or later.
We already have an example with key pair issued by Certificate Authority (CA), so let’s consider how we can use a Keystore on the example of self-signed certificates.
You can generate such a key pair using the key tool; see the command below:
keytool -genkeypair -alias my-self-signed-cert -keystore ~/projects/myproject/src/main/resources/https/local/keystore-with-self-signed-cert.keystore -keyalg RSA -storePass PasswordForStore -storetype PKCS12 -validity 365
You will be asked about your name, organization, and some other details.
After that, the key pair with the alias my-self-signed-cert
will be generated in the keystore-with-self-signed-cert.keystore
file, the validity of the self-signed certificate is 365 days, but you can specify any other value.
Once you generated a keystore file with a self-signed certificate, you just have to set up an application to start using it:
server:
port: 8443
ssl:
key-store: classpath:https/local/keystore-with-self-signed-cert.keystore
key-store-password: PasswordForStore
key-alias: my-self-signed-cert
key-store-type: PKCS12
And that’s it; now the server supports the `https` protocol. Congratulations 🙂
But be aware most clients do not trust self-signed certificates by default because no third-party site can confirm ownership. You still can establish a secure connection, and this will work as a charm, but clients have to import certificates or disable certificate validations.
For example, if you try to request the server with a self-signed certificate using curl
you may see the following message:
$ curl https://localhost:8443/actuator/health
...
curl: (60) SSL certificate problem: self signed certificate
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
You can either import the certificate or disable validation using the appropriate argument (for curl; --insecure
). The same regard for browsers and most other clients.
Conclusion
In this article, we described two ways of setting up an SSL in a Spring Boot application; direct import of a key pair (a certificate and a private key) or using a keystore file containing one or many key pairs.
If you need to manage many key pairs in a single keystore file, you can do it using the key tool, and you can easily import a keystore to a Spring Boot application.
But if you do not intend to use some common storage for several key pairs and you use Spring Boot 2.7.0 or later, you can consider not using the key tool at all. Instead, just import a certificate and a private key to a Spring Boot application, and this could be enough.
We hope this article could be useful for somebody 🙂 Thank you for reading!