8
votes

My Tomcat needs to connect to another web server (at https://foreign.example.com) using SSL (TLS).

foreign.example.com has a self-signed certificate, which I trust. Of course, my Tomcat does not by default - so I have to tell it. One way to do this is:

$JRE/bin/keytool -import -alias my -file ssl-cert-myselfsigned.cer -keystore 
 $JRE/lib/security/cacerts

This works: My Tomcat allows the SSL connection.

However, I don't like to do it this way: It imports the certificate into the trusted keys of my Java installation. I don't want to say: "Every application that runs Java on my machine should trust that certificate". Only Tomcat (or the user that runs Tomcat) should trust it.

So I tried importing it into the tomcat-user's keystore at ~/.keystore, and setting up Tomcat's <Connector> with these attributes:

keystoreFile="${user.home}/.keystore"
keystorePass="thePassphraseICreatedTheKeystoreWith"

However, that doesn't work at all (I believe, this is only for the server certificate of my Tomcat, not for server certificates of foreign servers, right?)

I tried the same with the truststoreFile/truststorePass attributes, but they didn't work either. (The attributes are documented at http://tomcat.apache.org/tomcat-6.0-doc/config/http.html)

Is there a way to set up Tomcat with the foreign server's server cert, or maybe to add some command line parameters to java which makes my keystore (and keystore passphrase) available to the JVM instance?

2
Can you clarify what doesn't work if you make a copy of "$JRE/lib/security/cacerts", import your specific cert into it and use the truststoreFile/truststorePass attributes? It should work. (And yes, the "keystore keystore" is for your credentials, not how you trust remote certificates.)Bruno
@Bruno: Ah, looking into the (very extensive) logs, I see that I'm getting java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must not be empty - which means, that it didn't find the truststore file... I wonder, if maybe ${user.home} doesn't work in this place?Chris Lercher
Sorry, I should have realised this earlier, but the truststore parameters only dictate the behaviour of the connector (i.e. for client-certs). When you say "My Tomcat needs to connect to another web server", I guess your webapp is the client, not the container (and definitely not the connector). The trust config will change depending on the client lib. The default SSLContext (which it's likely to use if nothing else is specified) is configured via the javax.net.ssl.trustStore system property. If you want a more local configuration, we'd need to know which client library you're using.Bruno
@Bruno: Thanks a lot! This clarified it - the trustStore can't be configured in the Connector. Using the command line parameters - together with your method of copying cacerts and adding the keys there - works.Chris Lercher

2 Answers

7
votes

JBoss (which is based on Tomcat) can be run with the following cmd arguments. The cacerts file (or however you would like to name it) must contain the cert of the endpoint.

-Djavax.net.ssl.trustStore=C:\Applications\jboss-as\server\default\conf\cacerts -Djavax.net.ssl.trustStorePassword=changeit

Therefor this should also work for Tomcat.

0
votes

An alternative approach is to add it to the SSL connector in tomcat in your tomcat server.xml file. Specifically you need to set the truststoreFile properties to enable trust of certificates from other servers.

        <Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="../../../deploy/tomcat/config/ssl/keystore.jks" keystorePass="changeit"
               truststoreFile="../../../deploy/tomcat/config/ssl/keystore.jks" truststorePass="changeit"/>