Enabling HTTPS in Tomcat

Quick start

1. Generate key for Tomcat, password value of "changeit":

keytool -genkey -alias tomcat -keyalg RSA

This generates a RSA key with alias "Tomcat" at default keystore location (${user.home}/.keystore).

Alternatively, you can run "ant genKeys.tomcat" target, which will do the same.

Note: Tomcat uses javax.net.ssl.KeyManagerFactory and that requires same password for keystore and all contained keys - init method will try loading each key with (same) provided password.

2. Uncoment and fix the SSL Connector in tomcat/conf/server.xml:

<Connector port="8443"

maxThreads="150" minSpareThreads="25" maxSpareThreads="75"

enableLookups="false" disableUploadTimeout="true"

acceptCount="100" debug="0" scheme="https" secure="true"

clientAuth="want" sslProtocol="TLS"

truststorePass="changeit" truststoreType="jks"

truststoreFile="$OMAR_HOME/data/security/appserver-truststore.jks"/>

NOTE: you must replace $OMAR_HOME in the connector configuration. The trustore is generated by the genKeys target and its location is set by omar-setup.security.appserverTruststoreFile build-time property.

By defining clientAuth="want", you set the server to request a certificate from the client web browser. The server will provide a list of trusted CAs - which should include our RegistryOperator. If client web browser finds a match (a certificate signed by one of the CAs contained in truststoreFile), that will be sent to server.

Server will then check for a registered user corresponding to the given certificate and if, again, there is a matching certificate in the omar.security.keystore, client will be authenticated as the correponding user. Otherwise (unknownn or no certificate), the client will not be athenticated and will use RegistryGuest credentials.

For more information

Check the instructions in http://jakarta.apache.org/tomcat/tomcat-5.0-doc/ssl-howto.html (plus you might have a copy of the Tomcat documentation in $JWSDP_HOME/docs/tomcat).

The instructions lead you through making a key and editing Tomcat's server.xml file to configure HTTPS support.

Using the Correct Port for HTTPS

You need to use the correct port number for HTTPS when accessing the web service.

Your average web browser can handle a redirect from the port used for HTTP (e.g., port 80 for HTTP or port 8080 for Tomcat) to the port used for HTTPS (port 443 on Unix or port 8443 on Tomcat). Your average web service, however, can't, so use the HTTPS port number in the URL, e.g.: https://localhost:8443/omar/registry/soap

Making the Server's Certificate Known to the Client

This requires:

  1. Exporting the server's certificate
  2. Importing the server's certificate into the client's keystore
  3. Running the client with the appropriate keystore

Although these steps are not required, by following them the client will not ask if you want to trust the certificate presented by the server everytime you start a session.

Exporting the server's certificate

keytool -export -alias server -storepass server.storepass -keystore server.keystore -file server.cer

Where

server.keystore
Is the keystore containing the web server's certificate.
server.storepass
Is the 'storepass' of the keystore containing the web server's certificate

Importing the server's certificate into the client's keystore

keytool -import -v -trustcacerts -alias server -storepass ebxmlrr -keystore client.keystore -file server.cer

Where

client.keystore
Is the keystore that the client will use. It's tempting to use $jaxr-ebxml.security.keystore for this, but a separate keystore may be better since you will replace your JAXR client keystore more often than you will change the web server's certificate.

Running the client with the appropriate keystore

You need to set the javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword properties. There are at least two ways to do this:

1. In the run.browser Ant target:

Change

  <target depends="jar.browser" description="Run the Registry Browser Java UI out of jar files" name="run.browser">

<java fork="yes" jar="${build.home}/lib/${browser.name}.jar"/>

</target>

to

  <target depends="jar.browser" description="Run the Registry Browser Java UI out of jar files" name="run.browser">

<java fork="yes" jar="${build.home}/lib/${browser.name}.jar">

<sysproperty key="javax.net.ssl.trustStorePassword"

value="ebxmlrr"/>

<sysproperty key="javax.net.ssl.trustStore"

value="path/to/client.keystore"/>

</java>

</target>

2. In your Java program before the call():

System.setProperty("javax.net.ssl.trustStore", "path/to/client.keystore");

System.setProperty("javax.net.ssl.trustStorePassword", "ebxmlrr");

Where

path/to/client.keystore
Is the path ? either the absolute path or the path relative to the working directory ? to the client keystore file. path/to/client.keystore includes the name of the client keystore file, since Java isn't going to try to guess it for you.

Requiring Access to the Server to be Secure

This requires adding a <security-role> and <security-constraint> element to the servlet's deployment descriptor (i.e., in the web.xml file).

The <security-constraint> should include <transport-guarantee>CONFIDENTIAL</transport-guarantee> to force HTTPS usage.

Since the Registry Browser Java UI uses the REST interface for the "Show RegistryObject" action, you need to do the same for the REST servlet.

If you want to also allow HTTP access as well as having requiring secure access to an endpoint, then you can define a separate endpoint for the secure access, e.g.: https://localhost:8443/omar/registry/secure/soap

Excerpted example:

<web-app>

<servlet>

<servlet-name>

ebxmlrr-secure-soap-receiver-servlet

</servlet-name>

<servlet-class>

org.freebxml.omar.server.interfaces.soap.RegistrySOAPServlet

</servlet-class>

<load-on-startup>0</load-on-startup>

</servlet>

<servlet>

<servlet-name>

ebxmlrr-secure-rest-receiver-servlet

</servlet-name>

<servlet-class>

org.freebxml.omar.server.interfaces.rest.RestServlet

</servlet-class>

<load-on-startup>0</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>

ebxmlrr-secure-soap-receiver-servlet

</servlet-name>

<url-pattern>

/registry/secure/soap

</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>

ebxmlrr-secure-rest-receiver-servlet

</servlet-name>

<url-pattern>

/registry/secure/http/*

</url-pattern>

</servlet-mapping>

<security-constraint>

<web-resource-collection>

<web-resource-name>Secure servlet</web-resource-name>

<url-pattern>/registry/secure/soap/*</url-pattern>

<http-method>GET</http-method>

<http-method>POST</http-method>

</web-resource-collection>

<user-data-constraint>

<transport-guarantee>CONFIDENTIAL</transport-guarantee>

</user-data-constraint>

</security-constraint>

<security-constraint>

<web-resource-collection>

<web-resource-name>Secure REST servlet</web-resource-name>

<url-pattern>/registry/secure/http/*</url-pattern>

<http-method>GET</http-method>

<http-method>POST</http-method>

</web-resource-collection>

<user-data-constraint>

<transport-guarantee>CONFIDENTIAL</transport-guarantee>

</user-data-constraint>

</security-constraint>

</web-app>

Requiring User Authentication

The deployment descripter should include <auth-method>CLIENT-CERT</auth-method> in the <login-config> element of your servlet's deployment descriptor (i.e., in the web.xml file).

This has not been tested.

Thin client on local mode + SSL

In order to take advantage of SSL client authentication and use the provided X509 certificate to authenticate with OMAR server, Thin client must be running in localCall mode.

Set tomcat/webapps/omar/WEB-INF/classes/jaxr-ebxml.properties:

org.freebxml.omar.client.xml.registry.localCall=true