Apache Tomcat 9 – SSL/TLS Configuration HOW-TO

In this exercise, Tomcat 9 will be installed with OpenJDK 8 using a self-signed certificate in a PKS12 keystore on a clean CentOS 7 Linux server using the Http11NioProtocol protocol.  These are the steps.

########################################################################################
# Apache Tomcat 9
########################################################################################

yum install wget vim net-tools firewalld unzip -y
yum install java-1.8.0-openjdk-devel -y
cd /opt/app
wget http://us.mirrors.quenda.co/apache/tomcat/tomcat-9/v9.0.16/bin/apache-tomcat-9.0.16.tar.gz
tar xzvf apache-tomcat-9.0.16.tar.gz
ln -s apache-tomcat-9.0.16 tomcat

########################################################################################
# Create a User
########################################################################################

[ "$(grep tomcat /etc/passwd | cut -f1 -d":")" = "tomcat" ] || useradd -s /sbin/nologin tomcat

########################################################################################
# Apply Firewall Rules
########################################################################################

systemctl enable firewalld
systemctl start firewalld
firewall-cmd --permanent --add-port=8443/tcp
firewall-cmd --reload

########################################################################################
# Apply Permissions
########################################################################################

chown -R tomcat:tomcat /opt/app/tomcat/
chown -R tomcat:tomcat /opt/app/tomcat

########################################################################################
# Create a Service
########################################################################################

cat > /usr/lib/systemd/system/tomcat.service << EOF
[Unit]
Description=Starts and stops Tomcat Server
After=syslog.target network.target
 
[Service]
User=tomcat
Group=tomcat
Type=forking
ExecStart=/opt/app/tomcat/bin/catalina.sh start
Restart=on-failure
RestartSec=10
 
[Install]
WantedBy=multi-user.target
EOF
 
systemctl daemon-reload
systemctl enable tomcat

########################################################################################
# vim conf/server.xml
# Note: Not sure if the keystoreType="PKCS12" is needed. Tested successfully without
#    it. Maybe true since PKCS12 is natively supported.
########################################################################################

<Connector SSLEnabled="true" acceptCount="100" clientAuth="false" disableUploadTimeout="true" enableLookups="false" maxThreads="25" port="8443" keystoreType="PKCS12" keystoreFile="/home/tomcat/.keystore" keystorePass="changeit" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" secure="true" sslProtocol="TLS" />

<Engine name="Catalina" defaultHost="localhost" jvmRoute="server1.example.com">

########################################################################################
# Create the PKCS12 keystore
# Note: Since Tomcat will be running as user tomcat, then the default location of the 
#    .keystore will be in the /home directory of the user whom creates the .keystore
#    so it is important to logon as tomcat to generate the cert.  This cert should be
#    located at /home/tomcat/.keystore which will match the conf/server.xml and run by
#    user tomcat/tomcat from the service tomcat created.
########################################################################################

sudo su - tomcat -s /bin/bash

echo | keytool -genkey -alias server1.example.com -keyalg RSA -storepass "changeit" -dname "CN=${pki-cn}, OU=${pki-ou}, O=${pki-o}, L=${pki-l}, S=${pki-s}, C=${pki-c}" -validity 7300 -ext SAN=dns:server1.example.com -deststoretype pkcs12

exit

########################################################################################
# Start Tomcat
########################################################################################

systemctl start tomcat

Enjoy Tomcat

Check the Cert

You can check the cert by using your browser.

http2.Http2Protocol

Alternately, you can use the http2.Http2Protocol protocol.  However, there is one prerequisite to complete the Tomcat installation.  Install tomcat-native which is available via EPEL repos.  This will provide the needed functionality to use this protocol.  A benefit of this protocol is that you will not have to create any additional certs for keystore and simply use the system and Apache certs that can just as easily be generated.  This alleviates the need to maintain additional certification types.

yum install tomcat-native

Edit the server.xml file and modify this section instead of the http11.Http11NioProtocol section.

<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
           maxThreads="150" SSLEnabled="true" >
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
    <SSLHostConfig>
        <Certificate certificateKeyFile="/etc/pki/tls/private/server1.example.com.key"
                     certificateFile="/etc/pki/tls/certs/server1.example.com.crt"
                     certificateChainFile="/etc/pki/tls/certs/server1.example.com_chain.crt"
                     type="RSA" />
    </SSLHostConfig>
</Connector>

Generate the Certificate

This should generate a self-signed certificate.  You will need to comment out the certificateChainFile directive above as it will not exist for a self-signed certificate like this one.

FQDN=server1.example.com
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout $FQDN.key -out $FQDN.crt -subj "/CN=$FQDN" \
  -extensions san \
  -config <(echo '[req]'; echo 'distinguished_name=req';
            echo '[san]'; echo "subjectAltName=DNS:$FQDN")
unset FQDN

Tests

The crt may be tested any number of ways, but this will display the Subject Alternative Name ('SAN'), the Computer Name ('CN') and the expiration date.

$ openssl x509 -in server1.example.com.crt -noout -text -subject -enddate | egrep 'DNS|subject|After'
            Not After : Jul 28 13:13:29 2029 GMT
                DNS:server1.example.com
subject= /CN=server1.example.com
notAfter=Jul 28 13:13:29 2029 GMT

Conclusion

This is a basic Tomcat install, future considerations should include log rotation and SeLinux.

Source(s)

  • https://security.stackexchange.com/questions/74345/provide-subjectaltname-to-openssl-directly-on-the-command-line