tomcat + SSL

To enable SSL support for tomcat:

  1. Create a keystore using keytool from java.
  2. $ $JAVA_HOME/bin/keytool -genkey -keypass changeit -alias tomcat -keyalg RSA -keystore keystore -storepass changeit
  3. Copy the generated keystore file to where you want it to be. For my case:
  4. $ cp keystore $CATALINA_HOME/lib/keystore
  5. Edit $CATALINA_HOME/conf/server.xml, uncomment the section containing the settings for SSL.  You can try to find port number 8443.  It is the default port for SSL connection in tomcat.
  6. In the uncommented section, add in the keystoreFile and keystorePass settings.  My SSL settings look like the following:
  7. <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
    maxThreads="150" scheme="https" secure="true"
    keystoreFile="lib/keystore" keystorePass="changeit"
    clientAuth="false" sslProtocol="TLS" />
  8. Restart tomcat.  Now you can access you tomcat with https://localhost:8443/
  9. Upon entering the page, your browser will warn you about some invalid certificate.  That’s because you are using a self-sign certificate created in step 1 above.

To connect tomcat A to tomcat B via HTTPS

If you have a tomcat B that is offering some SOAP services via HTTPS but it is using self-sign certificate, you’ll get the following error when your servlet from tomcat A is trying to connect to tomcat B:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

The reason is again, the certificate is self-signed (not valid).  In browser, you have the option to accept it and continue, but you cannot do so in a servlet.  To handle this I know 2 options:

  1. Add this particular certificate to a list of accepted certificate that is applicable to the entire JRE. (easy)
  2. Accept this particular certificate only in your particular web app. (better)

For option 1:

  1. Extract the certificate from the keystore of tomcat B.
  2. $ $JAVA_HOME/bin/keytool -exportcert -alias tomcat -file keystore.cert -keystore keystore
  3. Import the certificate to the list of accepted certificates in tomcat A.
  4. $ $JAVA_HOME/bin/keytool -importcert -trustcacerts -alias tomcat -file keystore.cert -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit
  5. Restart tomcat A.  Now, servlets from tomcat A can access HTTPS SOAP services in tomcat B.

For option 2:

  1. Extract the certificate from the keystore of tomcat B.
  2. $ $JAVA_HOME/bin/keytool -exportcert -alias tomcat -file keystore.cert -keystore keystore
  3. Create a custom list of accepted certificates in tomcat A.
  4. $ $JAVA_HOME/bin/keytool -importcert -trustcacerts -alias tomcat -file keystore.cert -keystore customeCerts -storepass changeit
  5. Copy the custom list to your web app directory (or whatever place you want).
  6. $ cp customCerts MyWebApp/WEB-INF/classes
  7. Modify the servlet’s source code to use the custom list
  8. // Using self-sign certificate.
    String realPath = getServletContext().getRealPath("");
    System.setProperty("javax.net.ssl.trustStore", realPath + "/WEB-INF/classes/customCerts");
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
    
    // Continue with calls to tomcat B's SOAP services
    ...
  9. Restart tomcat A.  Now, servlets from tomcat A can access HTTPS SOAP services in tomcat B.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: