using custom keystore and jsseimplementation when upgrading to tomcat 8.5

1.2k views Asked by At

We were using our own custom keystore and also provided the custom class implementation using JSSEImplementation and ServerSocketFactory and configured both in server.xml for "store" and "sslImplementation" attributes.

But now upgrading to 8.5, I started getting lot of ClassNotFoundException for JSSESocketFactory etc.
Doing little more research I found that they have removed many classes and methods like JSSESocketFactory.java, getServerSocketFactory(), getSSLUtil(AbstractEndpoint endpoint) etc.

So now, my question is:
is there any way in apache tomcat 8.5 in which I can configure my custom keystore under "store" in server.xml and use my own sslImplementation?
I was using AbstractEndpoint in the method signature to get the store name set in server.xml and then loading that keystore in MyJSSESocketFactory like this:

public class MySSLImplementation extends JSSEImplementation 
{ 
@Override
    public org.apache.tomcat.util.net.ServerSocketFactory getServerSocketFactory(
            AbstractEndpoint endpoint) {
        kStore = endpoint.getProperty("store");
        return new MyJSSESocketFactory(endpoint, kStore);
    }
}

public class MyJSSESocketFactory extends JSSESocketFactory {

    private final AbstractEndpoint _endpoint;
    private final String store;

    public MyJSSESocketFactory(AbstractEndpoint endpoint, String store) {
        super(endpoint);
        this._endpoint = endpoint;
        this.store = store;
    }
    /*
     * Gets the SSL server's keystore.
     */
    @Override
    protected KeyStore getKeystore(String type, String provider, String pass)
            throws IOException {

        if ("MYKS".equalsIgnoreCase(type)) {

            String keystoreName = store;
            KeyStore ks = null;
            try {
                if (provider == null || provider.isEmpty()) {
                    ks = KeyStore.getInstance(type);
                } else {
                    ks = KeyStore.getInstance(type, provider);
                }

                MyStoreParameter params = new MyStoreParameter(
                        keystoreName);
                ks.load(params);
            } catch (Exception ex) {
                throw new IOException(
                        "Failed to load keystore " + keystoreName, ex);
            }
            return ks;
        } else {
            return super.getKeystore(type, provider, pass);
        }
    }
}

"MYKS" is set in server.xml for "store" attribute

1

There are 1 answers

0
paulsm4 On

For whatever it's worth, this is the commit that broke it:

Remove BIo specific JSSE code

Here is some of the rationale for removing it:

https://github.com/spring-projects/spring-boot/issues/6164

@markt-asf There appears to be a number of breaking changes in 8.5.3 (upgrading from 8.0.33):

  1. Maven artifact org.apache.tomcat.embed:tomcat-embed-logging-juli no longer exists
  2. Class org.apache.tomcat.util.net.ServerSocketFactory no longer exists
  3. Class org.apache.tomcat.util.net.jsse.JSSESocketFactory no longer exists
  4. Method JSSEImplementaton.getServerSockerFactory(AbstractEndpoint) no longer exists
  5. Method JSSEImplementaton.getSSLUtil(AbstractEndpoint) no longer exists
  6. Http11NioProtocol.getEndpoint() is no longer visible
  7. Field org.apache.tomcat.util.scan.Constants.MERGED_WEB_XML no longer exists
  8. AbstractHttp11Protocol.setCompressableMimeTypes no longer exists

Reply:

1 is only required to enable container logging via log4j 1.x and that version is no longer supported by the log4j community. log4j 2.x can be used for container logging without any extra libraries.

2-6 are side effects of the connector refactoring in 8.5.x / 9.0.x. They are all low-level internal APIs that I'm a little surprised to find boot is using.

7 was part of the mechanism used to pass web.xml to Jasper for processing. It was removed as it was no longer required as of Servlet 3.0 as all the necessary information was available via the standard Servlet API.

8 That was some API clean-up. That one could be restored fairly easily for 8.5.x.

The commit was made in Nov, 2014.

As of Tomcat 8.0, the class was still there - and NOT on the *deprecated" list:

https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/tomcat/util/net/jsse/JSSESocketFactory.html

Here is the changelog that discussed "removing BIO" ("Blocking I/O"):

Migrating from Tomcat 8.0 to 8.5

Finallly, comparing these two links might help:

SSL/TLS Configuration HOW-TO Tomcat 8.0.39

SSL/TLS Configuration HOW-TO Tomcat 8.5.9