USEPA / emf

Emissions Modeling Framework (EMF)
6 stars 3 forks source link

run Tomcat with SSL for EMF server #130

Open cseppan opened 1 year ago

cseppan commented 1 year ago

Need to look at how to configure Tomcat to using SSL/TLS, or possibly add nginx proxy on server. Confirm that EMF Client works with HTTPS connection, including local file upload and download.

ddelvecchio commented 1 year ago

I did find a useful article on the that should help when get to this task. I will add a link to this in the ticket.

Using SSL with Axis: https://www.informit.com/articles/article.aspx?p=24604

cseppan commented 1 year ago

I was able to successfully set up SSL in my Tomcat installation (9.0) and connect with the EMF client.

https://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html#Configuration

Generate a keystore file - for development, this is a self-signed certificate. On the production server, we'll need to get a real SSL certificate from an authority.

keytool -genkey -alias tomcat -keyalg RSA -keystore /usr/local/tomcat/conf/localhost-rsa.jks

password: changeit (this is the Java default so it's not a secret) first and last name: localhost

Update the Tomcat conf file server.xml. Uncomment the section

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>

Restart Tomcat and confirm that https://localhost:8443/ loads in a browser - the browser will complain about the certificate.

With a real certificate, the EMF Client should just work at this point by setting the URL to https://server:8443/emf/services. For development, the self-signed certificate needs to get added to Java's keystore.

I opted to make a local copy of the default keystore to modify

cp /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/lib/security/cacerts .

Download the self-signed certificate

echo -n | openssl s_client -connect localhost:8443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > self_cert.crt

Add the self-signed certificate to the keystore

keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias mycert -file self_cert.crt

When running the EMF Client, add the system property javax.net.ssl.trustStore

java -Djavax.net.ssl.trustStore=/path/to/custom/cacerts -classpath … gov.epa.emissions.framework.client.EMFClient https://localhost:8443/emf/services

cseppan commented 1 year ago

Based on my testing, I think we can go ahead and get an SSL certificate for the production server - not sure how that's handled for epa.gov domains. Once we have the certificate, we can turn on SSL alongside the existing HTTP connection and confirm there are no issues.

cseppan commented 1 year ago

Successfully ran the EMF Client using port 8443 on the EPA server. Two changes are needed to the EMFClient.bat file:

1) Change the URL from http://server:8080/emf/services to https://server:8443/emf/services 2) Add the flag "-Djavax.net.ssl.trustStore=WINDOWS-ROOT"

Current

java -Xmx1024M ... http://server:8080/emf/services

New

java -Xmx1024M -Djavax.net.ssl.trustStore=WINDOWS-ROOT ... https://server:8443/emf/services

Will need to update the EMF Client Installer program which automatically writes the EMFClient.bat file

cseppan commented 1 year ago

Looking through the emf.properties table, there's a property named DOWNLOAD_EXPORT_ROOT_URL which references port 8080. Once non-SSL access is turned off, this should get updated to 'https://server:8443/exports/'.

aeythepa commented 11 months ago

I tried setting the last of of bat file to this, but I could not get on:

java -Xmx1024M -DUSER_PREFERENCES="%userprofile%\EMFPrefs.txt" -DEMF_HOME="%EMF_HOME%" -DR_HOME="%R_HOME%" -Djavax.net.ssl.trustStore=WINDOWS-ROOT -classpath %CLASSPATH% gov.epa.emissions.framework.client.EMFClient https://sage.hesc.epa.gov:8443/emf/services

The error was: Nov 03, 2023 10:45:32 AM org.apache.axis.utils.JavaUtils isAttachmentSupported WARNING: Unable to find required classes (javax.activation.DataHandler and javax.mail.internet.MimeMultipart). Attachment support is disabled. Verifying server version is v4.2 - 03/06/2023 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException faultSubcode: faultString: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target faultActor: faultNode: faultDetail: {http://xml.apache.org/axis/}stackTrace:javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alert.createSSLException(Unknown Source) at sun.security.ssl.TransportContext.fatal(Unknown Source) ... Verifying server version is v4.2 - 03/06/2023 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException faultSubcode: faultString: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target faultActor: faultNode: faultDetail: {http://xml.apache.org/axis/}stackTrace:javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alert.createSSLException(Unknown Source) at sun.security.ssl.TransportContext.fatal(Unknown Source) ... Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source) at java.security.cert.CertPathBuilder.build(Unknown Source) ... 51 more sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target gov.epa.emissions.framework.services.EmfException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at gov.epa.emissions.framework.client.login.LoginPresenter.checkEmfVersion(LoginPresenter.java:88) at gov.epa.emissions.framework.client.login.LoginWindow.display(LoginWindow.java:85) at gov.epa.emissions.framework.client.login.LoginPresenter.display(LoginPresenter.java:113) at gov.epa.emissions.framework.client.EMFClient$1.run(EMFClient.java:59)

cseppan commented 9 months ago

It looks like the Java property to set should be javax.net.ssl.trustStoreType rather than trustStore

java -Xmx1024M -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT ... https://server:8443/emf/services

I've attached a small Java program to help with testing the SSL connection (I needed to add the .txt extension to make GitHub happy):

SSLTest.java.txt

javac SSLTest.java java SSLTest

null null Response Code : 200 Cipher Suite : TLS_AES_256_GCM_SHA384

Cert Type : X.509 Cert Hash Code : -1325636615 Cert Public Key Algorithm : EC Cert Public Key Format : X.509

Cert Type : X.509 Cert Hash Code : 266225904 Cert Public Key Algorithm : RSA Cert Public Key Format : X.509

Cert Type : X.509 Cert Hash Code : 1081005260 Cert Public Key Algorithm : RSA Cert Public Key Format : X.509

By default, the program contacts google.com and prints some info about the certificate chain. Because Google uses a standard certificate issuer, nothing special needs to happen with the trustStoreType setting. The first two lines in the output (null, null) are the values of the trustStoreType and trustStore properties.

If you give the trustStoreType as a command-line parameter:

java -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT SSLTest

You should see the first line in the output be WINDOWS-ROOT instead of null. This is a quick check to make sure the command-line parameter is correct. The connection to google.com should still work fine; the program is just using Window's certificate trust information instead of what's built into the JVM.

To try connecting to the EPA EMF server, edit the Java program and change the line

String site = "https://google.com/";

to

String site = "https://sage.hesc.epa.gov:8443/";

If you run the modified program without any parameters, you should get the same "PKIX path building failed" error we've been seeing. But with -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT hopefully things will work.

As a test, I tried connecting to a military website that uses a custom certificate authority managed by DoD. I used the Windows program certmgr.msc to add the certificate authority to the list of Trusted Root Certification Authorities. At that point, I could load the site through a browser without any security warnings, and setting trustStoreType allowed the SSLTest program to connect. I'm hoping this is analogous to how the EPA Enterprise certificate authority has already been set up on the EPA Windows machines.