Background

We have a Spring Boot 2.6.6 application. The tomcat certificates are generated by another microservice and mounted via k8s secrets on the application filesystem. Once the new certificates land on the filesystem, we apply the following process:

  1. create keystore and trustore
  2. make sure our SslStoreProvider getKeystore/getTrustStore will return the latest certificates
  3. call reloadSslHostConfigs() on connector that was fetched via TomcatConnectorCustomizer.
  4. SslStoreProvider getters are triggered and the new certificates are delivered to tomcat

On Boot 2.6.6 this was working fine, however this behavior is broken on 2.7 due to change #30531 which removed the SslStoreProviderUrlStreamHandlerFactory: the new code is simply injecting the keystore/trustore references on configureSslStoreProvider method, so the call to reloadSslHostConfigs() is not triggering the step 4 on the process above, hence the hability to refresh tomcat certificates via SslStoreProvider has been lost on 2.7.

Is there any alternative to achieve the functionality above on 2.7 ? Is this a bug or an intentional change for 2.7 and up ?

Comment From: wilkinsona

Sorry for the change in behavior but SslStoreProviderUrlStreamHandlerFactory was only intended to enable custom SSL stores to be loaded into Tomcat and not dynamic reloading of those stores.

Rather than calling reloadSslHostConfigs, you should be able to create a new SSLHostConfig and then call org.apache.tomcat.util.net.AbstractEndpoint.addSslHostConfig(SSLHostConfig, true) to replace the old SSL configuration with the new.

Comment From: chicobento

Rather than calling reloadSslHostConfigs, you should be able to create a new SSLHostConfig and then call org.apache.tomcat.util.net.AbstractEndpoint.addSslHostConfig(SSLHostConfig, true) to replace the old SSL configuration with the new.

I was trying to go that path, but there's no way to get the endpoint reference as org.apache.coyote.http11.AbstractHttp11Protocol.getEndpoint() is protected, so Im only left with the org.apache.coyote.http11.AbstractHttp11Protocol.addSslHostConfig(SSLHostConfig) which will end up calling AbstractEndpoint.addSslHostConfig(SSLHostConfig, false) and will either duplicate the SSLHostConfig or throw an error in case of using the default name.

The other workaround that I can see so far is to fetch the current SSLHostConfig reference set by spring boot org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer and update the keystore/trustore object references via setters

Do you have any other recommendation ?

Tks

Comment From: wilkinsona

Ah, sorry. I'd missed that the access to the endpoint was protected. It looks like retrieving the SSLHostConfig via org.apache.coyote.ProtocolHandler.findSslHostConfigs() and mutating it is your best option.