5

I am writing a routine to access a remote server. This server I am connecting to requires mutual authentication so I have to provide a keystore, and while I'm at it I'd like to put a proper truststore in place as well.

I can find plenty of tutorials on how to create a keystore with keytool and multiple ways to get an Apache HTTP client to recognize it, but not where to store it in a Tomcat environment so that the application can find it. Somehow putting it in the application's war file seems like a bad idea to me.

Again, this is not to permit Tomcat to handle inbound https connections - I have a reverse proxy set up by our admin team for that. I'm creating outgoing https connections that require mutual authentication, i.e., both accepting a self-signed destination server certificate, and providing my server's self-signed client certificate.

Where do you store the actual keystore and truststore files in a Tomcat environment for use by a web application?

4
  • What exactly do you mean by a 'proper truststore' that isn't already met by the one supplied with Java? Commented Nov 6, 2014 at 2:17
  • That's off topic, but the service I am connecting to provides a self-signed certificate which is not acceptable to the cacert default. I currently "accept all" but they've turned on mutual and now I have to provide my own client self-signed as well, so if I have to add the plumbing for keystore then I should use the opportunity to add the truststore support as well. First I need to know where to put the darned things. Commented Nov 6, 2014 at 2:22
  • As far I know ,the keystore file can be anywhere in the directory path which the server has access to read.In server.xml of tomcat you need to specify the directory path in Connector port 8443 in the attribute Keystorefile. Commented Nov 6, 2014 at 3:26
  • @Amz The keystore used for a client TLS certificate has nothing to do with Tomcat's <Connector> configuration. This is not a Tomcat configuration problem. Commented Nov 6, 2014 at 4:09

2 Answers 2

5

You can put your keystore wherever you want, as long as you know how to tell httpclient where to load the keystore.

That, of course, is the trick.

Using Apache httpclient for https

Buried in all that mess of code in the accepted answer is the key (ha!) to using httpclient with your own custom keystore. It's unfortunate that httpclient doesn't have a simple API like "here's the path to my keystore file, now use it" or "here are the bytes for my keystore, use those" (if you wanted to load the keystore from the ClassLoader or whatever), but that seems to be the case.

The honest truth is that using keystores and truststores in Java is messy business, and there's usually no way around it. Having written a client-cert-capable HTTP client myself using nothing other than HttpsURLConnection and then also adding raw-socket components to that, I know how painful it is.

The code in the above-linked article is fairly straightforward if a bit verbose. Unfortunately, you're going to need to make it a lot messier for production-quality code because you've got to do error-checking, etc. for every step of the process to make sure your service doesn't fall-over when you are trying to set up the various stores and make your connection.

Sign up to request clarification or add additional context in comments.

1 Comment

Please see my post, which is basically a comment to your answer. +1 to your answer otherwise.
1

This is basically a comment to Christopher Schultz's answer, but since it involves some code snippets please excuse my putting it here

It's unfortunate that httpclient doesn't have a simple API like "here's the path to my keystore file, now use it" or "here are the bytes for my keystore, use those" (if you wanted to load the keystore from the ClassLoader or whatever), but that seems to be the case

This is how one can configure Apache HttpClient 4.3 to use a specific trust store for SSL context initialization.

SSLContext sslContext = SSLContexts.custom()
        .loadTrustMaterial(trustStore)
        .build();
CloseableHttpClient client = HttpClients.custom()
        .setSslcontext(sslContext)
        .build();

One can load trust material from a resource like that

URL resource = getClass().getResource("/com/mycompany/mystuff/my.truststore");
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream inputStream = resource.openStream();
try {
    trustStore.load(inputStream, null /*usually not password protected*/);
} finally {
    inputStream.close();
}

1 Comment

Thanks for the updated code snippets. If the HttpClient folks didn't hide their Javadoc, I might have been able to search for any applicable methods (or, in this case, builders) that existed. :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.