On Tue, Jan 19, 2021 at 5:02 AM Rob Sargent <rsarg...@xmission.com> wrote:
> > Stuck in my basement with no real domain I'm having trouble setting up > SSL/TLS on an embedded tomcat instance. And I'm very lost, having tried > more dead ends than I can remember. > > I used this to generate cert and key > openssl req -out localhost.crt -key localhost.key \ > -newkey rsa:2048 -nodes -sha256 \ > -subj '/CN=localhost' -extensions EXT -config <( \ > printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = > dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature, > nonRepudiation, keyEncipherment, > dataEncipherment\nextendedKeyUsage=serverAuth") > > and try to apply those with > > -Djavax.net.ssl.trustStore=/tmp/key/localhost.crt > -Djavax.net.ssl.trustStorePassword=changeit > -Djavax.net.ssl.trustStoreType=PKCS12 > -Djavax.net.ssl.keyStore=/tmp/key/localhost.key > -Djavax.net.ssl.keyStorePassword=changeit > -Dhttps.protocols=TLSv1.2,TLSv1.3 > -Djdk.tls.client.protocols=TLSv1.2,TLSv1.3 > > I get "toDerInputStream rejects tag type 45". > > That error rears its ugly head in several places such when adding those > same two localhost files to a pkcs12 rendition of the OS's cacerts file > using below. The crt goes in quietly. (I'm couldn't convince my self of > the openssl equivalent of this command) > root@gitanmax:/tmp/key# keytool -importkeystore -srckeystore > localhost.key -srckeypass changeit -srcstoretype pkcs12 -destkeystore > cacerts.pkcs12 -deststoretype pkcs12 -srcalias localhost -destalias > tomcatlocal > Importing keystore localhost.key to cacerts.pkcs12... > Enter destination keystore password: changeit > Enter source keystore password: changeit > keytool error: java.io.IOException: toDerInputStream rejects tag type 45 > > My actual first attempt was to just use keytool to generate a cert > interactively, filling in my own bogus values but that hit the domain > name mismatch gotcha. > > Then, there's confusion on the java side as well. > > My plan was to add a connector for my webapp > > embeddedTomcat = new Tomcat(); > logger.debug("handing in CATALINA_HOME as " + > System.getenv("CATALINA_HOME")); > embeddedTomcat.setPort(tomcatPort-1); > embeddedTomcat.enableNaming(); > Connector defaultConnector = embeddedTomcat.getConnector(); // an init, > really > defaultConnector.setSecure(true); // force https? > > Service service = embeddedTomcat.getService(); > service.addConnector(addTLSConnector(tomcatPort)); > > logger.info("tomcatd listening on port " + tomcatPort); > String contextRootPath = System.getenv("CATALINA_HOME"); > logger.debug("contextRootPath is {}", contextRootPath); > Context contextTomcat = embeddedTomcat.addContext("", new > File(contextRootPath + "/sgs").getAbsolutePath()); > logger.debug("host: {}, general context basename {}", > embeddedTomcat.getHost(), contextTomcat.getBaseName()); > //TODO: cut from here ... > java.time.LocalDateTime bootDT = java.time.LocalDateTime.now(); > Tomcat.addServlet(contextTomcat, "monitor", new HttpServlet() { > @Override > protected void doGet(HttpServletRequest req, HttpServletResponse resp) > throws ServletException, IOException { > ServletOutputStream out = resp.getOutputStream(); > out.write("SGS Agent monitor: SGS_OK\n".getBytes()); > out.write(("Up since " + bootDT.toString()).getBytes()); > out.write(("\nTime now " + > java.time.LocalDateTime.now().toString()).getBytes()); > out.flush(); > out.close(); > } > }); > contextTomcat.addServletMappingDecoded("/monitor", "monitor"); > // My webapp > Context sgsContext = embeddedTomcat.addWebapp("/sgs", contextRootPath + > "/sgs"); // /sgs.war > embeddedTomcat.start(); > embeddedTomcat.getServer().await(); > > private Connector addTLSConnector(Connector connector, int tcport) { > File keyFile = new File (System.getProperty("SGSSRVR_keystoreFile")); > if (! keyFile.exists()) throw new RuntimeException("where's the > keystore?"); > connector.setPort(tcport); > connector.setSecure(true); > connector.setScheme("https"); > connector.setProperty("protocol", "HTTP/1.1"); > connector.setProperty("sslProtocol", "TLS"); > connector.setProperty("address","127.0.0.1"); > connector.setProperty("clientAuth", "false"); > connector.setProperty("maxThreads", "200"); > connector.setProperty("protocol", > "org.apache.coyote.http11.Http11NioProtocol"); > connector.setProperty("SSLEnabled", "true"); > return connector; > } > > private Connector addTLSConnector(int tcport) { > Connector connector = new Connector(); > addTLSConnector(connector, tcport); > return connector; > } > > That "monitor" works, on a separate port, on either http or https as per > defaultConnector.setSecure(isHttps); > but possibly because I've diddle with chrome's security settings. > > I have a similar "monitor" as a servlet which I use as my > is-anybody-home call to start my analyses. And of course can also use > it via the browser at /seg/webmonitor. > > All these behave when SSL is not in play, but I'm forced, very much > against my will, to use SSL so here I am bother the good folks on this > list for more help. > Dealing with a complex configuration using the embedded API can be a bit problematic. If you're using a recent Tomcat 9 (9.0.38+), you could use the code generator that was designed for ahead of time compilation to help you out: it will produce Tomcat embedded equivalent code to the server.xml you're using. I would think server.xml is easier to get right, and there are probably tons of examples that you can use to help out. Then you can cut and paste the generated code and refine it as needed. If you want to try it out, you can add "-generateCode" to the Tomcat command line, such as "./bin/catalina.sh run -generateCode". The code will be generated in the work directory. Of course, that won't help you get the certificates right. Good luck ! Rémy