Monday 18 August 2014

Enabling SSL on Tomcat with OpenSSL and Keytool on "localhost"

A Simple Step-By-Step Guide To Apache Tomcat SSL Configuration

The guide assumes that you have prior knowledge of the following concepts - 
- OpenSSL ( https://www.openssl.org/ )
- Apache Tomcat ( http://tomcat.apache.org/ )

Introduction

Configuration of all systems for SSL relies on two files, the truststore, which contains the server certificate information (the certificates it will accept from clients) , and the keystore , which manages the client certificate information (the certificates that will be provided to servers), and they are password protected. In SSL handshake, purpose of truststore is to verify credentials and purpose of keystore is to provide credentials. Hence, keystore can be used as a truststore and we will be using keystore in this tutorial.

The following certificate options are available:
  • Create your own server and client certificates
  • Create your own server certificates, get the server certificate signed by a Certificate Authority (CA), and use a corresponding signed server certificate. This certificate will be used by Tomcat.
  • Use a server and client certificate already signed by a CA. Care should be taken with these certificates, as they are associated with specific domains and/or hosts, and may cause problems in a dynamic environment.
This tutorial explains the second option.

Requirement


In our environment, we wanted to create our own "Certificate Authority" for System Testing because relying on "Trusted Certificate Authority" like Verisign, Go Dadddy etc were very expensive. So, we did the following solution approach - 
- Create your own CA
- Use Keytool to create Server ( Tomcat ) Certificates
- Sign the Server Certificates using CA
- Import the Server Certificates signed by CA into Keystore
- Configure Tomcat to use SSL
- Configure Browsers to remove some common Warnings 

Creating Your Own CA

The following websites gives you the instructions to create your CA.

Use Keytool to create Server ( Tomcat ) Certificates

The following website ( section 4.4.1.2 ) gives the instruction to create "Keystore" and "server certificate requesting to be signed by the CA" 


Create the "keystore" called "keystore.jks".
shell> keytool -genkey -alias replserver -keyalg RSA -keystore keystore.jks

Create the certificate request called "certrequest.pem". This will be signed by CA.
shell> keytool -certreq -alias replserver -file certrequest.pem \
    -keypass  password -keystore keystore.jks -storepass password

Please note the below value when prompted by "keystore" tool. 
 What is your first and last name?

Sign the server certificate using your own CA

Self Sign the certificate using your CA.
shell> openssl ca -in certrequest.pem -out certificate.pem -config "openssl config location"

Convert the certificate to a plain PEM certificate:
shell> openssl x509 -in certificate.pem -out certificate.pem -outform PEM

Finally, for a self-signed certificate, you must combine the signed certificate with the CA certificate:
shell> cat certificate.pem cacert.pem > certfull.pem

Import the Certificates signed by CA into Keystore

This imports both "CA's public certificate" along with "signed certificate of the server" ( cerfull.pem )
shell> keytool -import -alias replserver -file certfull.pem -keypass password -keystore keystore.jks

Check the contents of the keystore.jks. This should show you two entries - 

shell>keytool -list -alias rpaitomcat -keystore javakeystore\keystore.jks
Enter keystore password:password
rpaitomcat, Aug 18, 2014, PrivateKeyEntry,
Certificate fingerprint (MD5): 40:62:EB:50:1F:A1:22:B6:64:F5:59:AB:2E:E8:96:64

Configure Tomcat to use SSL

Configure the "server.xml" file of your Tomcat server to configure the SSL connector. 

<Connector port="6443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" 
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"           
               keystoreFile="E:\SSL\javakeystore\keystore.jks" 
               keystorePass="password" />

Warnings shown on browser 

On Chrome browser when you connect using the SSL port, browser will prompt you with two options - 



If you accept the option"Proceed Anyway", the SSL's "three way handshake" algorithm is initiated. However, you will see two errors -

Also, you will see that it says that "Identity not verified" for "localhost".


a) Server's Certificate does not match the URL.
The webserver in our local lab ( for testing ) runs on the URL - "localhost". However, the certificate installed on the server with the "keytool" utility has the "first name and last name" which is different from "localhost". 

E:\SSL>e:\Openssl\bin\openssl.exe x509 -in server2\certificate.pem -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=IN, ST=Karnataka, L=Bangalore, O=PaiCorporation, OU=Development, CN=RavindraPai/emailAddress=ravindra.pai@misys.com
        Validity
            Not Before: Aug 18 09:20:25 2014 GMT
            Not After : Aug 18 09:20:25 2015 GMT
        Subject: C=xx, ST=xx, O=xx, OU=xx, CN=xx
        Subject Public Key Info:

To correct this error, when using the keytool to create the certificate, mention the common name as "localhost" and get it signed by CA.

E:\SSL>e:\Openssl\bin\openssl.exe x509 -in server\certificate.pem -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=IN, ST=Karnataka, L=Bangalore, O=PaiCorporation, OU=Developme
        Validity
            Not Before: Aug 18 08:07:08 2014 GMT
            Not After : Aug 18 08:07:08 2015 GMT
        Subject: C=US, ST=California, O=Misys, OU=Manufacturing, CN=localhost

In the above case, the common name of the certificate matches the "URL". 

b) Server's certificate is not trusted
The Chrome browser comes with a set of "Trusted Certificate Authorities". However, since we have created our own private "Certificate Authority", we need to add the certificate to the Chrome browser through "Settings->HTTPS/SSL->Manage Certificates and import the certificate ( shown below ) into "Trusted Root Certification Authorities". 
Make sure that you restart Chrome.





Check if the certificate is imported into "Trusted Root Certification Authorities".




With this, the identity of "local host" is verified as seen below and errors are taken care of.