Skip to content


Multiple Keystores in Apache Camel/HttpClient

Update 2020: a kind contributor has transformed the original blog post into an sslcontext library. He also shows how to configure SSL in the top dozen HTTP clients in Java.

Now that we know how to use multiple SSL keystores in Java, how do we configure Apache HttpClient (embedded in Apache Camel) to use them? This is useful if you want to load additional keystores in addition to the “factory” installed ones, for example. There’s no obvious way to do this using HttpClient or Camel. If you look at any of the documentation online, you’ll either see configuration via the JSSE configuration utility, like so:

KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("/users/home/server/keystore.jks");
ksp.setPassword("keystorePassword");
 
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("keyPassword");
 
SSLContextParameters scp = new SSLContextParameters();
scp.setKeyManagers(kmp);
 
ProtocolSocketFactory factory =
    new SSLContextParametersSecureProtocolSocketFactory(scp);
 
Protocol.registerProtocol("https", new Protocol("https", factory, 443));

Or you’ll see direct configuration of Apache HttpClient using HttpClientConfigurer or something like this:

Protocol authhttps = new Protocol("https", new AuthSSLProtocolSocketFactory(
  new URL("file:my.keystore"), "mypassword",
  new URL("file:my.truststore"), "mypassword"), 443);
 
Protocol.registerProtocol("https", authhttps);

However, we’re not reading from the keystore from a file, nor do we only want to use a single keystore. So all of these convenient wrappers that Apache Camel and Apache HttpClient are actually becoming an inconvenience to us.

This becomes even more frustrating when you realize you can’t even find many classes used in the examples, including the AuthSSLProtocolSocketFactory, on your classpath (because of Camel bundling older versions of HttpClient). Fortunately, if you hunt through the javadocs and sources long enough, you’ll learn as I did that it always boils down to an SSLContext or, more specifically, an SSLSocketFactory.

The protocol must be registered using Protocol.registerProtocol, so we need an instance of a ProtocolSocketFactory. Digging through the source shows that the promising-sounding SSLProtocolSocketFactory always uses the default SSLSocketFactory.  However, it turns out that the Camel-provided SSLContextParametersSecureProtocolSocketFactory can accept a SSLSocketFactory as a constructor argument instead of the SSLContextParameters shown in all the examples. That’s the key!

  @Provides @Singleton
  ProtocolSocketFactory provideSslProtocolSocketFactory(SSLContext sslContext) {
    return new SSLContextParametersSecureProtocolSocketFactory(sslContext.getSocketFactory());
  }

Now we just need to register this factory for use by the HTTPS protocol as in the examples.

  Protocol.registerProtocol("https",
      new Protocol("https", factory, 443));

Its simple once we know what we need, but time-consuming to hunt and peck through all the docs and sources to find it. Hopefully this has helped you save some time!

We can now make HTTPS requests through Camel using multiple (custom) keystores.

As a sidenote, compare this with Ning’s AsyncHttpClient, which exposes a setSSLContext method directly in the AsyncHttpClientConfig.Builder(). That’s almost too easy by comparison. 😉

Posted in Tutorials.


0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.



Some HTML is OK

or, reply to this post via trackback.

 



Log in here!