What is this?

This is basically where I write down stuff that I work with at my job as a GIS Technical Analyst (previously system administrator). I do it because it's practical for documentation purposes (although, I remove stuff that might be a security breach) and I hope it can be of use to someone out there. I frequently search the net for help myself, and this is my way of contributing.

Saturday, June 2, 2018

Geoserver 2.12.1/Jetty - Installing a SSL certificate from a PFX keystore

I'm using a standard Windows 2016 server with Java JRE 8 update 151 and Geoserver 2.12.1 installed with pretty much default settings. This is a step-by-step description of what I had to do to extract a (wildcard) certificate/key from a IIS-type PFX (PKCS12) keystore to a JKS keystore and install it on the Jetty web server that comes bundled with Geoserver.

NOTE! When I import from the PFX keystore to my new JKS keystore I must always use the same password on both the old and new keystore. Trying to use a different password for the new keystore will just give me an error in {geoserver}/logs/wrapper.log when I start Geoserver:
FAILED org.eclipse.jetty.server.Server@104e906: java.security.UnrecoverableKeyException: Cannot recover key

Step 1:
Export data from my PFX keystore to a new JKS keystore file:
C:\Program Files (x86)\Java\jre1.8.0_151\bin>keytool.exe -importkeystore -srckeystore c:\temp\my_keystore.pfx -srcstoretype pkcs12 -destkeystore c:\temp\keystore -deststoretype JKS
Importing keystore c:\temp\my_keystore.pfx to c:\temp\keystore...
Enter destination keystore password: MyPassword
Re-enter new password: MyPassword
Enter source keystore password: MyPassword
Entry for alias le-f8a123c3-abcd-4bbb-b341-40251cf90a0b successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or cancelled

Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore c:\temp\keystore -destkeystore c:\temp\keystore -deststoretype pkcs12".

Step 2:
Verify that your new keystore is working:
C:\Program Files (x86)\Java\jre1.8.0_151\bin>keytool -list -keystore c:\temp\keystore -storepass MyPassword
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

le-f8a123c3-abcd-4bbb-b341-40251cf90a0b, 02.jun.2018, PrivateKeyEntry,
Certificate fingerprint (SHA1): A1:BF:53:7F:30:00:11:22:33:44:8D:F4:8A:20:25:FF:6B:D5:89:7C

Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore c:\temp\keystore -destkeystore c:\temp\keystore -deststoretype pkcs12".

Step 3:
Copy c:\temp\keystore to %GEOSERVER_HOME%\etc\keystore (rename the original "keystore" file for backup purposes)

Step 4:
Download the correct (see below) Jetty distribution archive (tar.gz or zip) from https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-distribution/.
Unpack ssl.mod from the archive (it's located in the modules folder) and copy it to %GEOSERVER_HOME%\modules. 7-zip is my prefered tar/gz unpacking tool when I use Windows.
NOTE: Make sure it's the correct version of ssl.mod - if your Geoserver version is different than mine (12.2.1) your Jetty version is probaably different too. You'll see which jetty version you have by checking jetty-servlet files under %GEOSERVER_HOME%/lib.

Step 5 (Optional):
for increased strength cryptography follow this link: http://docs.geoserver.org/latest/en/user/production/java.html#installing-unlimited-strength-jurisdiction-policy-files
(you can download local_policy.jar and US_export_policy.jar that you copy to %JAVA_HOME%\lib\security\policy\unlimited)

Step 6:
Configure Jetty by adding the following lines to %GEOSERVER_HOME%\start.ini:
#SSL
--module=https
jetty.secure.port=8443
jetty.keystore=etc/keystore
jetty.truststore=etc/keystore
jetty.keystore.password=MyPassword
jetty.keymanager.password=MyPassword
jetty.truststore.password=MyPassword

I added them immediately below the following section:
# --------------------------------------- 
# Module: http
--module=http

NOTE! I've seen some references to editing %GEOSERVER_HOME%\etc\jetty-ssl.xml instead of start.ini. I tried that, but I don't think Jetty read the file at all. I would always get the following errors in wrapper.log:
INFO   | jvm 1    | 2018/05/24 23:50:35 | 2018-05-24 23:50:35.874:WARN:oejuc.AbstractLifeCycle:WrapperSimpleAppMain: FAILED SslContextFactory@4b387439(C:\Program Files (x86)\GeoServer 2.13.0\./etc/keystore,C:\Program Files (x86)\GeoServer 2.13.0\./etc/keystore): java.io.IOException: Keystore was tampered with, or password was incorrect
INFO   | jvm 1    | 2018/05/24 23:50:35 | java.security.UnrecoverableKeyException: Password verification failed

Step 7:
Restart the Geoserver service.

Step 8:
Testing! Now you should be able to access your geoserver on both these addresses
http://localhost:8080/geoserver/web/
https://localhost:8443/geoserver/web/ (probably with a certificate warning due to mismatching address as expected, but I'm sure you know to proceed from here)

If Geoserver just starts and stops after a short while there is an issue with your configuration somewhere. Check %GEOSERVER_HOME%\logs\wrapper.log for details.



5 comments:

  1. Nice Information. Thank for sharing. SSL Certificates protect your customer's personal data including passwords, credit cards and identity information. Getting an SSL certificate is the easiest way to increase your customer's confidence in your online business.

    ReplyDelete
  2. You helped me A LOT. I use the same configuration as you (Windows 2016 and Geoserver on Jetty) but now on geoserver 2.15.0... that was the trick. Here is my feedback to help, I spent a lot of time, I hope it will help anyone.

    That's all!
    Geoserver 2.15.0 comes with Jetty 9.4.12 which changes the settings. What's changes?

    Step 4: from jetty distribution downloaded from https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-distribution/

    copy (add) ssl.mod from /modules to %GEOSERVER_HOME%\modules
    NEW copy (replace because inconsistent with context) jetty-ssl.xml from /etc to %GEOSERVER_HOME%\etc
    NEW copy (add) jetty-ssl-context.xml from /etc to %GEOSERVER_HOME%\etc

    Step 6: in Start.ini, add the following lines (using new namespace syntax to replace deprecated ones) after --module=http

    --module=ssl
    jetty.ssl.port=8443
    jetty.sslContext.keyStorePath=etc/keystore
    jetty.sslContext.keyStorePassword=MyPassword
    jetty.sslContext.keyManagerPassword=MyPassword
    jetty.sslContext.trustStorePath=etc/keystore
    jetty.sslContext.trustStorePassword=MyPassword
    --module=https

    ReplyDelete
  3. It's really useful information.
    Thank you for your sharing.

    ReplyDelete
  4. Trying to set up a 2nd server and, using the same configuration from a working environment, I can't seem to get the key to be recognized. The key is valid but receiving UnrecoverableKeyException: Cannot recover key". The Java version is updated so I assume there is a change there. Not sure if anyone else has encountered this.

    ReplyDelete
  5. Looks like the key was expired. Problem solved. Thanks for a great post BTW.

    ReplyDelete