SSL Certificate Installation on Tomcat

SSL Certificate Installation on Tomcat

This guide is aimed at individuals who have Apache Tomcat set up their website running on either the default port 8080 or port 80 via the HTTP protocol. Once this condition is satisfied, SSL installation can be initiated.

Tomcat offers a flexible approach to SSL installation compared to most other servers. SSL certificates can be installed using either APR (Apache Portable Runtime) or JSSE (Java Secure Socket Extension) connectors. The JSSE method, which involves interaction with Java keystores created via keytool, is the most commonly used connector. APR streamlines SSL installation to follow the typical Apache-like process.

Prerequisites

Make sure that you have issued and active SSL certificate files prepared before proceeding with SSL installation. You can download the active certificate from your 1Byte account directly.

If the CSR was generated using the keytool on your server, you can stick to the PKCS7 installation steps. If you generated the CSR elsewhere and have the matching Private key, use the PKCS12 or APR-based installation.

Important: If you have separate Private key and certificate files, you will need to convert them into a PKCS#12 file first, unless there is an APR configured along with your Tomcat. Once the files are converted, you can proceed with the respective PKCS#12 installation steps.

Java keystores

After you have created a keystore containing the Private key along with the corresponding CSR, you will need to import your issued SSL certificate into the keystore under the main keystore alias. Each time you interact with a keystore file, you will need to enter its password. Below is an overview of all the possible ways of adding a certificate to your keystore.

PKCS#7

The most time-efficient way to install your SSL on Tomcat from a keystore is to use a PKCS#7 formatted certificate (a file with the .p7b or .cer extension).

Step 1: Upload SSL files

Upload the PKCS#7 certificate file on the server. Then, import it using the following command:

keytool -import -trustcacerts -alias tomcat -file certificate.p7b -keystore yourkeystore.jks

Where:

  • tomcat is the actual alias of your keystore
  • certificate.p7b is the actual name/path to your certificate file
  • yourkeystore.jks is the actual name/path to the keystore file

Make sure the certificate file has the same alias used for creating the keystore. Otherwise, the “Input not an X.509 certificate” error may take place.

After you have imported successfully, you should receive the following output:

Certificate reply was installed in keystore

Step 2: Edit SSL Configuration

In the next step, you will need to modify the connector for the default port 8443 or 443.

The modification should be done in the ‘Tomcat installation directory’/conf/server.xml file. You can find the location of the directory containing the server.xml configuration file by issuing this command:

sudo find / -ipath '*tomcat*server.xml'

It will most likely be in /opt/tomcat/conf/server.xml or /etc/tomcat/server.xml

Here is an example of a JSSE connector for port 443 using the HTTP/1.1 protocol with TLS up to 1.3 enabled:

<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="443"
maxThreads="200"
scheme="https"
secure="true"
SSLEnabled="true"
keystoreFile="/opt/tomcat/ssl/yourkeystore.jks"
keystorePass="keystore_password"
clientAuth="false"
sslProtocol="TLS"/>

Where:

  • /opt/tomcat/ssl/yourkeystore.jks is the absolute path and actual name of the keystore file
  • keystore_password is the actual password for your keystore

Step 3: Apply changes

Once done, please restart Tomcat to apply the changes. If you are not quite sure about the steps to reproduce, feel free to jump to the section Apply the changes to apply the changes and verify SSL installation.

PEM

The most challenging, yet still common, way of installing an SSL certificate on Tomcat is by using separate PEM-formatted SSL certificates.

Step 1: Prepare the files

This method requires you to have each of the certificates saved in separate files:

  1. CA root certificate.
  2. CA second intermediate certificate (optional and can be omitted if your CA bundle contains only 1 intermediate certificate).
  3. CA intermediate certificate.
  4. End-entity certificate for your domain.

The order of the certificate will be as follows for the most frequently used PositiveSSL certificate:

keytool -import AAA Certificate Services
keytool -import USERTrust RSA Certification Authority
keytool -import Sectigo RSA Domain Validation Secure Server CA
keytool -import example.com.crt

Note: The “AAA Certificate Services” is only installed if you chose the CA Bundle containing the cross-signed certificate.

The above list is composed in reverse order on purpose as this is the exact order in which the certificates should be imported to the keystore. You can download the certificate files from your 1Byte account along with the CA bundle. It may come in handy if you encounter the “keytool error: java.langException: Failed to establish chain from reply” error.

Step 2: Import the files

Follow the below steps in the given order to import the files properly.

Import the root certificate by running:

keytool -import -trustcacerts -alias root -file root.crt -keystore yourkeystore.jks

Where:

  • root is the alias of the imported CA root certificate
  • root.crt is the actual name/path of your CA root certificate
  • yourkeystore.jks is the actual name/path of the keystore file

Note: During import of the CA root certificate, you may be prompted with the following message.

Certificate already exists in system-wide CA keystore under alias <aliasname>
Do you still want to add it to your own keystore? [no]:

Disregard the warning and confirm certificate import with submitting y.

Import the second intermediate certificate:

keytool -import -trustcacerts -alias intermediate2 -file intermediate_2.crt -keystore yourkeystore.jks

Where:

  • intermediate2 is the alias of the imported second intermediate CA certificate
  • intermediate_2.crt is the actual name/path of your second intermediate CA certificate

Import the first intermediate certificate:

keytool -import -trustcacerts -alias intermediate1 -file intermediate_1.crt -keystore yourkeystore.jks

Where:

  • intermediate1 is the alias of the imported first intermediate CA certificate
  • intermediate_1.crt is the actual actual name/path of your first intermediate CA certificate

After the successful import of each of the above certificates, you should receive the following output:

Certificate was added to keystore

Import the end-entity certificate for your domain:

keytool -import -trustcacerts -alias tomcat -file certificate.crt -keystore yourkeystore.jks

Where:

  • tomcat is the actual alias of your keystore. The alias for your end-entity certificate should be the same as the one you used when creating the keystore with the Private key. If you did not specify the alias during the keystore creation, the default value will be mykey.
  • certificate.crt is the actual actual name/path of your end-entity certificate file.

After import of the end-entity certificate, the below message will be prompted:

Certificate reply was installed in keystore

Step 3: Edit the connector

In the next step, you will need to modify the connector for the default port 8443 or 443.

The modification should be done in the ‘Tomcat installation directory’/conf/server.xml file. You can find the location of the directory containing the server.xml configuration file by issuing the below command:

sudo find / -ipath '*tomcat*server.xml'

Most likely, it will be in /opt/tomcat/conf/server.xml or /etc/tomcat/server.xml

Here is an example of the JSSE connector for port 443 using HTTP/1.1 protocol along with TLS up to 1.3 protocol versions:

<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="443"
maxThreads="200"
scheme="https"
secure="true"
SSLEnabled="true"
keystoreFile="/opt/tomcat/ssl/yourkeystore.jks"
keystorePass="keystore_password"
clientAuth="false"
sslProtocol="TLS"/>

Where:

  • /opt/tomcat/ssl/yourkeystore.jks is the absolute path and actual name of the keystore file
  • keystore_password is the actual password for your keystore

Step 4: Enforce the changes

Once done, please restart Tomcat in order to apply changes.If you are not quite sure about the steps to reproduce, you can go to the heading Apply the changes in this article to apply the changes and verify SSL installation.

PKCS#12

If you have no APR enabled on Apache Tomcat, this method of SSL installation is the optimal balance between the PKCS#7 and PEM import methods. PKCS#12 is a certificate standard when all the required parts (end-entity certificate for the hostname, CA bundle, and the Private key) are stored in the same file.

Step 1: Prepare the SSL files

Feel free to jump right to the next part if you already have a PKCS#12 (.pfx/.p12) certificate. If you do not have one, convert the corresponding files first.

Step 2: Modify the keystore

PKCS#12 file is considered as a keystore in itself. Thus, you will just need to specify the path to the PKCS#12 file in the keystoreFile directive. The process is pretty much the same as for the PKCS7 and PEM standards.

The modification should be done in the ‘Tomcat installation directory’/conf/server.xml file. You can find the location of the directory containing the server.xml configuration file by issuing the below command:

sudo find / -ipath '*tomcat*server.xml'

It will most likely be in /opt/tomcat/conf/server.xml or /etc/tomcat/server.xml.

Here is an example of PKCS#12 JSSE connector for port 443 using HTTP/1.1 protocol along with TLS up to 1.3 protocol versions:

<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="443"
maxThreads="200"
scheme="https"
secure="true"
SSLEnabled="true"
keystoreFile="/opt/tomcat/ssl/somefile.pfx"
keystorePass="password_from_your_pfx"
keystoreType="PKCS12"
clientAuth="false"
sslProtocol="TLS"/>

Where:

  • /opt/tomcat/ssl/somefile.pfx is the absolute path and actual name for the PKCS#12 certificate
  • password_from_your_pfx is the actual password for the PKCS#12 file

Note: In all cases when you use PKCS12 file, the "keystoreType" directive should be specified in the SSL configuration to define that the keystore format is PKCS#12 for the server to read the file properly.

Step 3: Complete the SSL installation

Once done, please restart Tomcat to apply changes. If you are not quite sure about the steps to reproduce, skip to this section to apply the changes and verify SSL installation.

APR-based installation

Most Linux distributions ship packages for APR out-of-the-box. Still, additional libtcnative, libapr1-dev and libssl-dev packages are required for APR to function properly with Tomcat (if you do not have installed them yet). Tomcat Native libraries also need to be compiled. We do not address this topic in this guide; it’s assumed you already have APR set up with Tomcat. If no APR is set up on your Apache Tomcat, check out this at the heading Prerequisites at the beginning of this article.

Step 1: Upload files

First, upload the certificate, the Private key, and the CA bundle (if the Certificate Signing Request was generated elsewhere) to the server.

Step 2: Configure the connector

Next, modify the existing connector for the default port 8443 or 443. The modification should be done in the ‘Tomcat installation directory’/conf/server.xml file.

You can find the location of the directory containing the server.xml configuration file by issuing below command:

sudo find / -ipath '*tomcat*server.xml'

It will most likely be in /opt/tomcat/conf/server.xml or /etc/tomcat/server.xml

Here is an example of the APR connector for the port 443 using HTTP/1.1 protocol along with TLS1.1 & TLS1.2 enabled:

<Connector
protocol="org.apache.coyote.http11.Http11AprProtocol"
port="443"
maxThreads="200"
scheme="https"
secure="true"
SSLEnabled="true"
SSLCertificateFile="/opt/tomcat/ssl/cert.crt"
SSLCertificateChainFile="/opt/tomcat/ssl/bundle.ca-bundle"
SSLCertificateKeyFile="/opt/tomcat/ssl/private.key"
SSLVerifyClient="optional"
SSLProtocol="TLSv1.1+TLSv1.2"/>

Where:

  • /opt/tomcat/ssl/cert.crt is the absolute path and actual name of the PEM-formatted certificate
  • /opt/tomcat/ssl/bundle.ca-bundle is the absolute path and actual name of the CA bundle file
  • /opt/tomcat/ssl/private.key is the absolute path and actual name of the Private key file

Important Note: The APR connector requires you to set the SSLCertificateChainFile directive explicitly. It isn’t possible to install the certificate properly with a single file containing both the end-entity certificate and CA bundle chain, like it is usually done on Apache 2.4.8 and above. If only the SSLCertificateFile is set in the connector, the first certificate from the file will be retrieved during handshake, which could possibly trigger the ERR_CERT_AUTHORITY_INVALID error.

Important: Access permissions settings
When installing a certificate for the APR connector, you may encounter the following error message:

WARNING [main] org.apache.tomcat.util.net.openssl.OpenSSLContext.init Error initializing SSL context java.lang.Exception: Unable to load certificate key /opt/tomcat/ssl/private.key (error:0200100D:system library:fopen:Permission denied)

It is caused by improper access permissions set for the certificate and Private key files. You need to make your tomcat user the owner of the certificate and Private key files. Use the following commands to accomplish this:

sudo chown tomcat /etc/ssl/private.key /etc/ssl/cert.crt

Where /opt/tomcat/ssl is the directory containing the respective certificate and Private key files, and tomcat is your tomcat user.

Be aware that Tomcat is permission-sensitive, thus it will not be possible to use certificate & Private key or keystore files saved in the /root or similar access-restricted directories.

Step 3: Apply the changes

Once done, please restart Tomcat to apply changes. If you are not quite sure about the steps to reproduce, feel free to jump to the heading Apply the changes below in this article to apply the changes and verify SSL installation.

Apply the changes

Save the changes and restart Tomcat either via the systemd service if there is any available, like so:

sudo systemctl restart tomcat

Or by using binaries. These will most likely be found in the following location:

/opt/tomcat/bin/shutdown.sh
/opt/tomcat/bin/startup.sh

However, the location of Tomcat binaries may vary between installations. You can find the location of both the startup and shutdown binary files by executing the below command:

sudo find / -ipath '*tomcat*\/s[h t]*.sh'

You will have 2 files in the output. They should be used for restarting Tomcat. Run the below commands in the following order to restart the server:

sudo sh /opt/tomcat/bin/shutdown.sh
sudo sh /opt/tomcat/bin/startup.sh

Where:

  • /opt/tomcat/bin/shutdown.sh is the absolute path to the shutdown.sh file from the previous output
  • /opt/tomcat/bin/startup.sh is the absolute path to the startup.sh file from the previous output

Once restarted, feel free to check the SSL installation using this online tool.

Troubleshooting

View keystore content

Use this command to check the imported decoded certificates in the keystore. For each correctly-imported certificate, you will see its details in a keystore entry. The Private key entry is displayed in the list as well:

keytool -list -keystore yourkeystore.jks -v

The output should be similar to the below listing:

$ keytool -list -keystore yourkeystore.jks -v
Enter keystore password:
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 4 entries

Alias name: tomcat
Creation date: Mar 13, 2020
Entry type: PrivateKeyEntry
Certificate chain length: 4
Certificate[1]:
Owner: CN=example.com
Issuer: CN=Sectigo RSA Domain Validation Secure Server CA, O=Sectigo Limited, L=Salford, ST=Greater Manchester, C=GB
Serial number: 45<...>76
Valid from: Fri Mar 13 00:00:00 UTC 2020 until: Tue Mar 09 23:59:59 UTC 2021
Certificate fingerprints:
SHA1: 4A:BA<...>67:BE
SHA256: D8:9D<...>3D:D3
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

To view the keystore content with respective encoded certificates in plain text (RFC-style), use the below command:

keytool -list -rfc -keystore yourkeystore.jks

The output should be similar to the below listing:

$ keytool -list -rfc -keystore yourkeystore.jks
Enter keystore password:
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 4 entries

Alias name: tomcat
Creation date: Mar 13, 2020
Entry type: PrivateKeyEntry
Certificate chain length: 4
Certificate[1]:
-----BEGIN CERTIFICATE-----
MIIFvTCCBKWgAwIBAgIQRQgwqjjPDLDCtR8R7NN1djANBgkqhkiG9w0BAQsFADCB
...
6NB/mQXfhuiyeBSe4jTmr4nja6JXvjQU1GUOgrv08KuU
-----END CERTIFICATE-----

Extract Private key from keystore

It is not possible to extract the Private key from a keystore directly, but there is a workaround with OpenSSL. You will need to:

  1. Convert the Java keystore file into the PKCS#12 standard file;
  2. Get the PKCS#12 file converted into a separate PEM encoded Private key file, i.e. export the Private key;
  3. View the content of the newly created Private key file.

Follow the below commands to start the process:

  1. keytool -importkeystore -srckeystore yourkeystore.jks -destkeystore somefile.pfx -srcstoretype JKS -deststoretype PKCS12 -deststorepass password_from_your_pfx
Note:
Some Java versions running Tomcat (or another servlet container using keytool as a Private/Public keys management shell) have different prefered file extensions for PKCS#12 (e.g. older versions like JDK 1.6 and earlier can generate .p12 files). The current stable versions usually generate .pfx files. The file content of .p12 and .pfx files are essentially the same.
  1. openssl pkcs12 -in somefile.pfx -out private.key -nocerts -nodes
  2. cat private.key

Be aware that the exported Private key may contain additional attributes (such as Bag Attributes or Key Attributes) along with the key code itself. In the output file, feel free to remove the first ~4 lines standing before the -----BEGIN PRIVATE KEY----- tag.

Proprietary keystore format warning

If you have a JDK version older than version 9 installed, the keystore will be generated in the JKS format (which should not be confused with the .jks file extension). The current up-to-date openjdk environment will give the following warning for such a keystore:

The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format ..."

You can probably disregard the warning and install the certificate as usual. Still, to stay on the safe side, you should probably convert the JKS keystore into the PKCS#12 format for the sake of compatibility. You can use the below command to convert this keystore type:

keytool -importkeystore -srckeystore yourkeystore.jks -destkeystore yourkeystore.jks -deststoretype pkcs12

Where yourkeystore.jks is the actual name/path to your keystore file.

Once done, you can check the keystore type by listing the keystore contents at the heading View keystore content in this article.

The successful output will give a warning stating that the previous keystore in the JKS format was backed up in a separate file:

Migrated "yourkeystore.jks" to PKCS12. The JKS keystore is backed up as "yourkeystore.jks.old".