I am trying to automate the certificate updating in Tomcat, requiring the SSL Protocol to be reloaded. This question is similar to my requirement How do I force tomcat to reload trusted certificates? and Programmatically update certificates in tomcat 8 without server restart . Essentially, I am wanting to issue the reloadSslHostConfigs jmx command. This can be accomplished via
https://localhost/manager/jmxproxy?invoke=Catalina:type=ProtocolHandler,port=8443,address="127.0.0.1"&op=reloadSslHostConfigs
The "manager" webapp provides a handy set of actions that I can utilise, and with the "ant" definitions loaded into groovy i can quite easily reload a web. Here is a snippet of groovy to do this:
def ant = new AntBuilder()
ant.import (file:new File(catalina_home, "bin/catalina-tasks.xml"))
switch (action) {
case 'd':
ant.deploy (url:web_base, username:username, password:pass
, path:"/" + webs[0], update:"true", war:war_path )
break
case 's':
webs.each {webapp ->
ant.start (url:web_base, username:username, password:pass, path:"/" + webapp)
}
break
The documentation here https://tomcat.apache.org/tomcat-9.0-doc/manager-howto.html also shows that it supports JXMquery/get/set - but I am not sure how to apply/use it. I also see a second group of jmx and definitions that includes start/stop/invoke. I think i need the invoke type. But if or how can this be used to issue the reloadSsl command. I think I am getting closer:
ant.jmxManagerQuery (url:jmx_base, query:"Catalina:type=Environment,resourcetype=Global,name=*", username:username, password:pass)
currently returns
Trying to override old definition of datatype resources
[jmxManagerQuery] Query string is ?qry=Catalina%3Atype%3DEnvironment%2Cresourcetype%3DGlobal%2Cname%3D*
Error: : java.io.IOException: Server returned HTTP response code: 403 for URL: http://localhost:8080/manager/jmxproxy/?qry=Catalina%3Atype%3DEnvironment%2Cresourcetype%3DGlobal%2Cname%3D*
I have also enabled remote jmx, just to see if this works: https://groovy-lang.org/jmx.html#_monitoring_tomcat And indeed following these instructions I can get the documented sample working - but I would rather not enable direct jmx, but use the manager app instead. And also I cannot see how this form of jmx access would be used to provoke the ssl reload.
I see a useful example here: https://github.com/rmannibucau/letsencrypt-manager/blob/master/src/main/java/com/github/rmannibucau/letsencrypt/manager/LetsEncryptManager.java Which pulls together much of the requirements in this excellent presentation: http://tomcat.apache.org/presentations.html#latest-lets-encrypt
Its all rather confusing to an infrequent developer that just wants a simple bash or groovy script to rattle off the certificate fetch and reload without restarting Tomcat.
PS. The connector config looks like this:
<Connector SSLEnabled="true" maxThreads="150" port="443" protocol="org.apache.coyote.http11.Http11Nio2Protocol">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"></UpgradeProtocol>
<SSLHostConfig certificateVerification="false" ciphers="HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!kRSA" honorCipherOrder="true" protocols="TLSv1.1,TLSv1.2">
<Certificate certificateKeystoreFile="blaa" certificateKeystorePassword="blaa" certificateKeystoreType="JKS"></Certificate>
</SSLHostConfig>
</Connector>