Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to put keystore for Tomcat web app using Apache HTTP client

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?

like image 407
Matt Thompson Avatar asked Nov 06 '14 02:11

Matt Thompson


People also ask

Where are certificates stored in Tomcat?

By default Tomcat looks for your Keystore with the file name . keystore in the home directory with the default password "changeit". The home directory is generally /home/user_name/ on Unix and Linux systems, and C:\Documents and Settings\user_name\ on Microsoft Windows systems.

Where is the keystore located?

The default location is /Users/<username>/. android/debug. keystore.

Where does Keytool saved keystore?

On a Windows system, the location of the Java cacerts keystore is: install_dir \jre\lib\security\, and the location of the keytool is install_dir \jre\bin\.

What is Tomcat JKS file?

Tomcat currently operates only on JKS , PKCS11 or PKCS12 format keystores. The JKS format is Java's standard "Java KeyStore" format, and is the format created by the keytool command-line utility. This tool is included in the JDK.


2 Answers

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.

like image 198
Christopher Schultz Avatar answered Oct 29 '22 18:10

Christopher Schultz


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();
}
like image 25
ok2c Avatar answered Oct 29 '22 18:10

ok2c