2

I have a web app running in Tomcat that is making a web service call to another system. I need to secure this call with SSL and client authentication. The Tomcat I'm hosted in is already properly configured with a truststore and keystore specific to the environment, so I need to use those stores to secure my own call. This is where I'm stuck.

How can I locate the keystore and truststore that Tomcat is configured with to make my own SSL call? Or better, generate a properly configured SSLContext or SSLSocketFactory with those values?

Things I've tried:

  1. I tried relying on the SSLContext.getDefault(). That doesn't appear to be set.

  2. I tried relying on System properties:

    System.getProperty("javax.net.ssl.trustStore");
    System.getProperty("javax.net.ssl.trustStorePassword");
    System.getProperty("javax.net.ssl.trustStoreType");
    System.getProperty( "javax.net.ssl.keyStore");
    System.getProperty( "javax.net.ssl.keyStorePassword");
    System.getProperty("javax.net.ssl.keyStoreType");
    

But this appears to be a brittle solution as Tomcat doesn't have to be configured with system properties. In one of the test environments, the trust store information is set, but the keystore variables aren't. They're defined in Tomcat's server.xml.

Is there some simple way to do this that I'm overlooking?

Updated:

This question is similar and one of the answers points out that SSL could be handled by OpenSSL\APR, so any solution here will depend heavily on the way Tomcat is configured. Assuming JSSE, the solutions appear to be:

  • Ensure Tomcat is configured through system properties.
  • Have the stores live at a predefined location on the server.
  • Package your own copies of the stores in your war.

For the first two above, you'd have to ensure the security policy allows access to those files.

Are these really the best practices for what I'm trying to do?

Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100
Don
  • 29
  • 1
  • 3
  • possible duplicate of [Accessing SSL Private Key From a Servlet](http://stackoverflow.com/questions/4048892/accessing-ssl-private-key-from-a-servlet) – Bruno Mar 19 '12 at 16:13
  • Note that, in general, not being able to access the container's SSL settings (in particular its private key) is a security feature, since the webapp might not be fully trusted. You may also be interested in this: http://stackoverflow.com/q/5162279/372643 – Bruno Mar 19 '12 at 16:23
  • I suspected it might be a security feature, but it's odd since those stores are actually pretty easy to access depending on how Tomcat is configured. I hoped there was a way to mark the servlet as trusted or something. – Don Mar 19 '12 at 18:14
  • If you configure the system properties in the script that launches Tomcat (e.g. `catalina.sh` or its Windows equivalent, see 2nd link above), you should be able to access the system properties (assuming you're not using a security manager or it's configured to allow it). – Bruno Mar 19 '12 at 18:16
  • I don't think this is a duplicate of [Accessing SSL Private Key From a Servlet](http://stackoverflow.com/questions/4048892/accessing-ssl-private-key-from-a-servlet). While related, this is a much more general question about how to manage key/truststores. This post helped me a lot more (with my particular issue) than the other did. I think this questions should stay. – Hawkeye Parker Sep 13 '12 at 19:34

1 Answers1

1

I think amongst other things you're confusing inbound and outbound SSL connectivity. Server.xml contains inbound SSL settings.

When using outbound SSL in Java, javax.net.ssl.trustStore* and javax.net.ssl.keyStore* should be explicitly set in Tomcat's startup. Remember, by default the keystore can only contain one private key unless you code your own keymanager.

Most well known webservice libraries use standard HTTP libraries which use HTTPConnection/HTTPSConnection or Jakatta HTTPClient and will present a client cert from the keystore if requested by the server. You shouldn't need to create your own SSLContext.

If you're terminating inbound Webservice calls then I would use Apache HTTP Server with SSL and client auth if required.

Edit for clarity: The keystore specified by javax.net.ssl.keyStore can contain more that one private key/cert pair, but you will not be able to use the additional private keys/cert UNLESS you write your own KeyManager. This can be a problem when you're terminating inbound SSL connections in Tomcat - you will need a private key/cert for external inbound connections and another private key/cert for outbound connections.

Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100
  • If I remember correctly you can have multiple private keys in a KeyStore if you specify the aliases. – Pith Sep 09 '15 at 15:44
  • You can have as many private keys and personal certificates as you like. The client specifies who it will trust in the `ClientHello` message, and it is up to the server, via the default or installed `KeyManager`, to find a personal certificate that the client will accept. @Pith – user207421 Feb 25 '19 at 11:08
  • @user207421 I'm not sure what spec. you're reading, but a TLS client certainly does **not** specify what certificates it'll trust in the `ClientHello` message - The client (running in the Tomcat server in this instance) will specify what ciphers and protocol versions it will use but **not who may signed the certificates**. It sounds like you've mixed up server and client - The server MAY inform the client what personal certificates it will accept via the `certificate_authorities` field of the `Certificate Request` (https://tools.ietf.org/html/rfc5246#page-53). – Alastair McCormack Feb 25 '19 at 14:14
  • My point, which is still valid, was that if you're making outbound SSL requests AND the server requires client-authentication, then you can have only one private key UNLESS you implement a `KeyManager`. Otherwise, the SSL client will select the first one in the configured `KeyStore` for ALL connections. – Alastair McCormack Feb 25 '19 at 14:17
  • @pith Indeed, you can have multiple private and public key/certs. Aliases help you (nothing/no one else), to select a certificate in your code. – Alastair McCormack Feb 25 '19 at 14:29