Description
Spring Boot version: 2.3.4.RELEASE
Context: I have an REST API that depending on the environment (local, dev, int, ...) runs either via http or https. Furthermore, that API needs to initiate TLS connections. For that (at least) the truststore and truststore password need to be specified (if not relying on JDK cacerts truststore) in order to validate the peers certificate. Those properties are set via system properties (javax.net.ssl.trustStore/javax.net.ssl.trustStorePassword) and are subsequently taken into account by JSSE.
Problem: When switching from http --> https (one-way TLS) I need to specify the location and password of a keystore holding the private key and associated certificate. Location and password can be passed via properties (server.ssl.key-store/server.ssl.key-store-password) and do totally fine. The problem occurs with the truststore here. Ultimately that one is not needed at all as I don't need to validate client certificates. When the embedded Tomcat server initiates the SSLContext settings are obtained from SSLHostConfig which initially obtains values from system properties as specified by JSSE. Afterwards Spring modifies that object by settings retrieved from the environment. The problematic part is in SslConnectorCustomizer (line 147). In my case I haven't set a trustedPassword so that in the SSLHostConfig the trustedPassword is overwritten with a null value. Note that truststoreFile is still set (obtained from JSSE system property). In the end an exception is thrown as we have a trustStoreFile without a password.
Enhancement:
Change:
protocol.setTruststorePass(ssl.getTrustStorePassword());
To:
if (ssl.getTrustStorePassword() != null) {
protocol.setTruststorePass(ssl.getTrustStorePassword());
}
This is already done for other properties such as trustStoreType or trustStoreProvider.
Benefit: If not specified otherwise default settings as provided by the embedded Tomcat are used (here default values from JSSE system properties). In this case this would allow me to 1) set JSSE system properties as default values for TLS connections in general, and 2) overwrite with Spring properties where necessary for the Tomcat TLS server part. With the current solution I need to specify the truststore password for Tomcat TLS (in order not have it set to null) although I don't even need a truststore for Tomcat.