Post

Linux - Let's Encrypt for Java Apps

Intro

Install certbot as mentioned in my previous post on Linux - Install Certbot.

By default, certbot retrieves a certificate and installs it immediately on the web server by adding an extra parameter, eg. --apache for Apache HTTP Server. For the case of Docker - Demo CAS Server, it is just enough to retrieve only a certificate. This is done by adding the certonly parameter to the command as follows:

1
certbot certonly

You need to make sure that the TCP port 80 of the server is accessible from Let’s Encrypt servers and no other application is utilizing it.

This will spin up a temporary server on TCP port 80 to validate the authority of the domain to issue the required certificates. The installed Let’s Encrypt certificates in the /etc/letsencrypt/live directory on the file system.

Create Keystore file

To use a certificate in a Java application, the preferred way is to add it to a separate .keystore file. The Java Runtime Environment (JRE) ships with a tool called keytool to create certificates and manipulate key stores. Adding certificates to a keystore can be done by using OpenSSL and the keytool.

If the system doesn’t have JRE installed, you can install it by running the following command:

1
sudo apt install default-jre jq

Archive certificates to PKCS #12 file

Importing multiple public and private .pem certificates directly in a keystore is not supported by the keytool. Hence, it is necessary to add all .pem files to a PKCS 12 archive. This can be done by the OpenSSL tool with the following command:

1
2
3
4
5
6
7
8
openssl pkcs12 -export \
	 -in /etc/letsencrypt/live/cas.harryvasanth.com/cert.pem \
	 -inkey /etc/letsencrypt/live/cas.harryvasanth.com/privkey.pem \
	 -out /tmp/cas.harryvasanth.com.p12 \
	 -name cas.harryvasanth.com \
	 -CAfile /etc/letsencrypt/live/cas.harryvasanth.com/fullchain.pem \
	 -caname "Let's Encrypt Authority X3" \
	 -password pass:changeit

Change cas.harryvasanth.com with the custom FQDN of the target CAS server (or any Java application server).

Import PKCS #12 archive to the Keystore file

The next step is to import the certificates into a .keystore file.

1
2
3
4
5
6
7
8
9
keytool -importkeystore \
	-deststorepass changeit \
	-destkeypass changeit \
	-deststoretype pkcs12 \
	-srckeystore /tmp/cas.harryvasanth.com.p12 \
	-srcstoretype PKCS12 \
	-srcstorepass changeit \
	-destkeystore /tmp/cas.harryvasanth.com.keystore \
	-alias cas.harryvasanth.com

The keystore at location /tmp/cas.harryvasanth.com.keystore can now be used by the CAS server (or any Java application server).

Automate Keystore creation

Make the shell script to create keystore

Create a shell script /home/<user.name>/renew-cert-keystore.sh Here is an example:

1
2
touch /home/harry.vasanth/renew-cert-keystore.sh && \
chmod +x /home/harry.vasanth/renew-cert-keystore.sh

Add the following content to the script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/env bash

IFS='
'
cd -P "$(dirname "$0")"

# Create keystore
echo "Refreshing '$(pwd)/cas.harryvasanth.com.keystore'"

openssl pkcs12 -export \
	 -in /etc/letsencrypt/live/cas.harryvasanth.com/cert.pem \
	 -inkey /etc/letsencrypt/live/cas.harryvasanth.com/privkey.pem \
	 -out /tmp/cas.harryvasanth.com.p12 \
	 -name cas.harryvasanth.com \
	 -CAfile /etc/letsencrypt/live/cas.harryvasanth.com/fullchain.pem \
	 -caname "Let's Encrypt Authority X3" \
	 -password pass:changeit

# User Keytool to import P12 to Keystore format
keytool -importkeystore \
	-deststorepass changeit \
	-destkeypass changeit \
	-deststoretype pkcs12 \
	-srckeystore /tmp/cas.harryvasanth.com.p12 \
	-srcstoretype PKCS12 \
	-srcstorepass changeit \
	-destkeystore /tmp/cas.harryvasanth.com.keystore \
	-alias cas.harryvasanth.com

# Move certificates to the current directory
echo "Copy '/tmp/cas.harryvasanth.com.keystore' to '$(pwd)/cas.harryvasanth.com.keystore'"
cp /tmp/cas.harryvasanth.com.keystore $(pwd)/cas.harryvasanth.com.keystore

Schedule the script to run periodically

The following line in crontab makes sure our script is executed every hour.

1
0 * * * * yes | bash /home/<user.name>/renew-cert-keystore.sh >> /var/log/renew-cert-keystore.log
This post is licensed under CC BY 4.0 by the author.