Tomcat: How to use a self-signed SAN supported certificate via OpenSSL

The instructions below are working on OSX and should equally work on any distribution with OpenSSL. From Chrome58 onwards only the SAN (subject alternative name) extension is used to match the domain name and site-certificate (prior to Chrome58 the commonName was used).

If the certificate doesn’t have the correct subjectAlternativeName extension, users get a NET::ERR_CERT_COMMON_NAME_INVALID error letting them know that the connection isn’t private.

The instructions below create in three simple steps the key and PEM file and then white-list it in the Keystore:

Create the OpenSSL configuration

Adjust the below to your liking – especially the section “req_distinguished_name” and “alt_names”:

cat << EOL > localhost.conf
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
O=My Organisation
OU=My Organisational Unit
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
DNS.1 = localhost
DNS.2 = localhost.localdomain
DNS.3 =
DNS.4 =
DNS.5 =
DNS.6 =

Generate the key and PEM file

Generate both files via OpenSSL:

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -sha256 -keyout localhost.key -out localhost.pem  -config localhost.conf

Configure Tomcat server.xml

Copy both files to a directory relative to “${catalina.home}” on your Tomcat installation and adjust server.xml:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true" >
            <Certificate certificateKeyFile="${catalina.home}/webapps/ROOT/localhost.key"
                         type="RSA" />

Whitelist the certificate in OS X Keychain

With Tomcat running, run the following commands to add the certificate to the Keychain:

echo -n | openssl s_client -connect -servername | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | tee "/tmp/"
sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" "/tmp/"
rm -v "/tmp/"