- tested with Jetty 9.3.6 on Raspbian JESSIE, configuration is suitable for any current Debian based Linux system, of course including Ubuntu.
I am using Jetty as a platform to develop and test web services, as well as to operate web services productively for private purpose. In this context it is neccessary to secure the web server, at least in a basic manner. However this task has prooved to be time consuming and somewhat annoying, as it never works from scratch. Jetty changes the way it is configured significantly with nearly every update, while documentation is never up-to-date. So this guide will most likely be suitable for Jetty 9.3.6 only (as a consequence I probably won't upgrade to newer Jetty within the next 2 - 3 years).
In this guide, we're using just one password in all places where a password is needed, and we're creating a self-signed certificate instead of a purchased one. For my own purpose that is good enough, even in productive configurations. But it's of course up to you to use more than one password for keys and to purchase some "official" trusted certificate.
Jetty 9.3.6 and Oracle Java 8 installed, JAVA_HOME pointing to the Java 8 installation,
Jetty placed in /opt/jetty.
Login as root or use all commands in sudo context. Let's begin in the /opt/jetty/lib folder:
java -cp ./jetty-util-9.3.6.v20151106.jar org.eclipse.jetty.util.security.Password top08secret15this will give us an output like
OBF:1mm61ku51y7v1ikq1mpx1vgv1t331vfz1mt51ino1y831kqp1mio MD5:02057101e96453c5e3e3ebcef5169625This is our example password: top08secret15. It's obfuscated representation is OBF:1mm61ku51y7v1ikq1mpx1vgv1t331vfz1mt51ino1y831kqp1mio.
mkdir /opt/certificate cd /opt/certificateIn the new folder, first create a private key:
openssl genrsa -des3 -out jetty.key
Generating RSA private key, 2048 bit long modulus .........................................................................+++ .....................................................................................................................+++ e is 65537 (0x10001) Enter pass phrase for jetty.key: top08secret15 Verifying - Enter pass phrase for jetty.key: top08secret15Now, create a certificate, which - in our example - is to expire after 5500 days (15 years). You need some name and address data, which may be fictional if the certificate is self signed:
openssl req -new -x509 -days 5500 -key jetty.key -out jetty.crt
Enter pass phrase for jetty.key: top08secret15 You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:UK State or Province Name (full name) [Some-State]: Yorkshire Locality Name (eg, city) : Middleton-in-Teesdale Organization Name (eg, company) [Internet Widgits Pty Ltd]: Teesside People Organizational Unit Name (eg, section) : IT Common Name (e.g. server FQDN or YOUR name) : highforce.teesvalley.info Email Address : email@example.comImport the certificate - as "trusted" - into the local keystore:
keytool -keystore keystore -import -alias jetty -file jetty.crt -trustcacerts
Enter keystore password: top08secret15 Re-enter keystore password: top08secret15 . . . a lot of output . . . Trust this certificate? [no]: yes Certificate added to keystoreNot sure about the next step, which creates another certificate (maybe obsolete):
openssl req -new -key jetty.key -out jetty.csr
Enter pass phrase for jetty.key: top08secret15 You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. . . . enter the same date as for jetty.crt above . . . Please enter the following 'extra' attributes to be sent with your certificate request A challenge password : top08secret15 An optional company name : Teesside PeopleThe certificate needs to be formatted to be suitable for Jetty:
openssl pkcs12 -inkey jetty.key -in jetty.crt -export -out jetty.pkcs12
Enter pass phrase for jetty.key: top08secret15 Enter Export Password: top08secret15 Verifying - Enter Export Password: top08secret15Now, import the formatted certificate into the keystore:
keytool -importkeystore -srckeystore jetty.pkcs12 -srcstoretype PKCS12 -destkeystore keystore
Enter target keystore password: top08secret15 Enter source keystore password: top08secret15 Entry for alias 1 imported successfully. Import completed: 1 entry imported successfully, 0 entries failed or cancelled.
Until this point, this (not really comfortable) procedure is quite stable. The next step is to bring the certificate and passwords into the Jetty configuration. This, as mentioned above, seems to vary with every Jetty update. With Jetty 9.3.6 proceed as follows:
There is a default key store - /opt/jetty/etc/keystore - delivered with Jetty and placed within the installation. This keystore is adapted to Jetty's default configuration, so when it's replaced by another one, Jetty is no more executable unless the configuration is adapted. Therefore it might be a good decision to backup the existing /opt/jetty/etc/keystore before proceeding with the next step.
Having done the backup, copy the new keystore, containing the certificate created obove, into place, thus overwriting the existing default keystore:
cp -f /opt/certificate/keystore /opt/jetty/etcAlso copy the key and certificate files into /opt/jetty/etc:
cp -f /opt/certificate/jetty.* /opt/jetty/etcNow edit opt/jetty/start.ini and add the following two lines at the end of the file:
vi /opt/jetty/start.ini . . . # --------------------------------------- # Module: websocket --module=websocket # --------------------------------------- # Module: jstl --module=jstl --module=ssl --module=httpsIn opt/jetty/modules/ssl.mod make sure that the Connector port to listen on line is commented in and set to port 8443 (or the local SSL port of your choice). Additionally, comment in the Keystore password, KeyManager password and Truststore password lines and replace the obfuscated password entries by the respective obfuscated password created in the very first step above:
vi /opt/jetty/modules/ssl.mod . . . ## Connector port to listen on jetty.ssl.port=8443 . . . ## Keystore password jetty.sslContext.keyStorePassword=OBF:1mm61ku51y7v1ikq1mpx1vgv1t331vfz1mt51ino1y831kqp1mio . . . ## KeyManager password jetty.sslContext.keyManagerPassword=OBF:1mm61ku51y7v1ikq1mpx1vgv1t331vfz1mt51ino1y831kqp1mio ## Truststore password jetty.sslContext.trustStorePassword=OBF:1mm61ku51y7v1ikq1mpx1vgv1t331vfz1mt51ino1y831kqp1mio . . .Now, as the last step, modify /opt/jetty/start.d/ssl.ini the same way, i.e. comment in the Connector port to listen on line, setting the correct SSL port, and also comment in the Keystore password, KeyManager password and Truststore password lines and also replace the obfuscated password entries by the one created in the first step:
vi /opt/jetty/start.d/ssl.ini . . . ## Connector port to listen on jetty.ssl.port=8443 . . . ## Keystore password jetty.sslContext.keyStorePassword=OBF:1mm61ku51y7v1ikq1mpx1vgv1t331vfz1mt51ino1y831kqp1mio . . . ## KeyManager password jetty.sslContext.keyManagerPassword=OBF:1mm61ku51y7v1ikq1mpx1vgv1t331vfz1mt51ino1y831kqp1mio ## Truststore password jetty.sslContext.trustStorePassword=OBF:1mm61ku51y7v1ikq1mpx1vgv1t331vfz1mt51ino1y831kqp1mio . . .That's it. Having worked carefully, avoiding mistakes - in particular when typing the password - Jetty will support SSL after re-starting the service. To test the configuration, place an example HTML file named index.html into /opt/jetty/webapps/root and browse https://localhost:8443 . The browser should require you to confirm the certificate before granting access to the page.