This document introduces how to configure SSL/TLS on Jetty in a practical way - from creating key and certificate.


Installation of Jetty

Prerequisites

Jetty is a web server and servlet engine running on JVM.
Therefore, the assumption is that you already installed JDK on your machine.
I tested w/ Oracle JDK 1.8 on Mac and CentOS. (The results are the same.)

$ java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
cs

Download

You can download tarball (or zip file) of every version of Jetty distribution from the following link.

Here is the list of versions I tested.
jetty-distribution-9.2.11.v20150529
jetty-distribution-9.3.15.v20161220
jetty-distribution-9.4.8.v20171121

The installation is untar (or unzip) the file into a certain directory.
I put the 3 different version of Jetty in ~/Work/apps/jetty and make a symlink of "current" as changing the versions.

Simple Test

Before applying SSL/TLS, you can test Jetty up and running as following.

$ cd $JETTY_HOME
$ java -jar ./start.jar
2018-03-06 11:52:26.186:INFO::main: Logging initialized @355ms
2018-03-06 11:52:26.242:WARN:oejs.HomeBaseWarning:main: This instance of Jetty is not running from a separate {jetty.base} directory, this is not recommended.  See documentation at http://www.eclipse.org/jetty/documentation/current/startup.html
2018-03-06 11:52:26.391:INFO:oejs.Server:main: jetty-9.3.15.v20161220
2018-03-06 11:52:26.410:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/webapps/] at interval 1
2018-03-06 11:52:26.431:INFO:oejs.AbstractConnector:main: Started ServerConnector@210c9d62{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2018-03-06 11:52:26.650:INFO:oejs.Server:main: Started @820ms
cs


Then, you can access the Jetty web server on your browser w/ "http://localhost:8080".

Error 404 is not an error actually - You have not deployed any webapps, that's why.


You can run and stop by using a script Jetty provides as following.

This enables Jetty running as a daemon as keeping the logs in a directory.

$ cd $JETTY_HOME
$ ./bin/jetty.sh start
Starting Jetty: 2018-03-06 11:59:20.067:INFO::main: Logging initialized @636ms
2018-03-06 11:59:20.124:WARN:oejs.HomeBaseWarning:main: This instance of Jetty is not running from a separate {jetty.base} directory, this is not recommended.  See documentation at http://www.eclipse.org/jetty/documentation/current/startup.html
2018-03-06 11:59:20.332:INFO::main: Redirecting stderr/stdout to /Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/logs/2018_03_06.stderrout.log
OK Tue Mar  6 11:59:23 MST 2018
 
$ ./bin/jetty.sh stop
Stopping Jetty: OK
cs


Creating Certificate

Note that this step introduces how to create a self signed certificate.
If you have an official certificate, you can bypass this section.

There are a few ways to create SSL key and certificates.
In general, OpenSSL and keytool are most popular tools for it.
It does not matter which way you choose. In this document, most procedures are based on openssl, except for creating keystore file.

SSL Key

Note that the pass phrase is "jetty123456".
$ openssl genrsa -des3 -out jetty.key
Generating RSA private key, 2048 bit long modulus
....................................................................................................................................................+++
..................................................................................................+++
e is 65537 (0x10001)
Enter pass phrase for jetty.key:
Verifying - Enter pass phrase for jetty.key:
 
$ cat jetty.key
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,15CAAF41EEF60FD3
 
L9eEDkoogWBXdQ3WPZqfY2vxZHWS5nTY1ow853Hpcf+1mhmyxEzb2uxJAuWhRnCI
JHMyyZHjnrtzDBLMUEwVZQ4u63yKFs1hidlPgOP5Xr5Rm118Dzpwbka3VOz0nQ86
Oa+7axV3Zg1qH82+Uda11SYrtRDbizSDW3F3ZQvz3AOyu05AuO9Nibdkc9UQ/zWA
lMLe2yjbzBLr1NmOIxrsrb7RCcxwtuIGGKeE8o2KalmehJfvNePcAbjnAn+35+7h
1fh5MuDMeUs5POviGzNUYH8e3U/3rhqWH+0Wj7pFvFvBVV9TjrFecdvmXx7MCtBr
GP99SpChF94FBPDAu2Nn/o2jBPlHiVeMLyDsD+KJgSAlb42QDVfJYjHcaBcVsOa4
3vugAkg06AYH2MeOIX0SGKSF4ZYktmV48mtyuC1WcKdAnf8Vp18JaynVY/0wczkz
5KwZUGs2Xa3cQ+XYAR4CY8fY7HPjBXJBNxowdVIVi7UqvVz9nhXeFJeFrld0Tmpx
TweitNzEx6Ie8W4PFRGAMx4xhfn5UKhmS/hzqrlPDRxMOXOs2XaPTcmwU8+Asy6E
QjGJMQmSWWl1IyXikcavHfmAg5eezFv3ZFl67FpObivzTsS3ABh55DAb1Z1fT8GF
iYpaq0dyVmQ16Jzi9FAz40IBrh7AeDRE/mBVnjZtH6XnWgrO7nA8QjXlw9863QDF
J136UJaqTcVcjM3GwoclNlTLKpZL7/erUL0UIkeySoQnKU+GF7g4UVnPyp0zkEGU
aF5sXSWzxwchGapYHefUkUXhF15pGObZ+cIj9ck/sd2OGhOZwAzcJaBvzN+xGzQX
+dO5JMUNQpqjnPgCItslqL84NE/vLVJr6bSfPNBzeNaxl4LBXLQGPF1tGdjroZJo
JB8lz+fP/9EQiYzzr2ek/UbYKOoMdm1JmcvBAnOCgsUcMzP1mwV6xdcBO00dojwR
dJTCKnez4wYLl6kXbkQ3W8fQNT9yliPUG653hrDZWt5pvA1uDEQ61c7W9IXqV+ZN
Sa+VmGiosKW1jvKqdCkmUU272RIy119Un9zxW2yQm5OpC5/bPDVbGYZ1wMJPWqga
3HDe54AwKzS9IU50RhK8HVkQcwUwt5Zx3W2t/eukDfnNWa01jRQe3P+VyXbcRvXC
PDXR2p9h5j0iubM+9jqTXAmCA8j2PoqqE1UIHXUXlN3FCZb14QN5/NY9KpdY7Oap
k3I2kVf35iq4oo5NjrqbKo3ieN0NBWgKeee/GTYaFXBKSbwf1mqCLZf/xxsx7u+G
JjVuDRNbrQFqTOkrY4ihenLMFwsVbbjRaQbXVuLXPPjALdEE17dcROx5wiII271o
JXNPZjOfPuGkNZeCgUAte5PDyz9rU0A4bJfaJCbuzy34Ksug2qxhnvoZkQ4wh4jE
c9uzumP4zMzyw/MtUKfpbneuaxRp9STL8pyX9D22iepCCk7OjsJhgAZRlYgVr17V
z4EDH1W7Kh4i17uhBDNWqVex/caNQJWb5AeWs3X043WwSW3TxD9HZwxnOg9mxhXc
u2N9opFZ5xBgj1qe0/h1Z4J72BvnEc0864ryWm00mpyUa5YmrVYysQ==
-----END RSA PRIVATE KEY-----
cs

Certificate

$ openssl req -new -x509 -key jetty.key -out jetty.crt
 
Enter pass phrase for jetty.key:
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) []:US
State or Province Name (full name) []:Colorado
Locality Name (eg, city) []:Englewood
Organization Name (eg, company) []:Comcast
Organizational Unit Name (eg, section) []:MELD
Common Name (eg, fully qualified host name) []:kafka-gw
Email Address []:bumjoon_kim@comcast.com
 
$ cat jetty.crt
-----BEGIN CERTIFICATE-----
MIIDnjCCAoYCCQDo//zRFi9XizANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMC
VVMxETAPBgNVBAgMCENvbG9yYWRvMRIwEAYDVQQHDAlFbmdsZXdvb2QxEDAOBgNV
BAoMB0NvbWNhc3QxDTALBgNVBAsMBE1FTEQxETAPBgNVBAMMCGthZmthLWd3MSYw
JAYJKoZIhvcNAQkBFhdidW1qb29uX2tpbUBjb21jYXN0LmNvbTAeFw0xODAzMDYx
NzI3MzlaFw0xODA0MDUxNzI3MzlaMIGQMQswCQYDVQQGEwJVUzERMA8GA1UECAwI
Q29sb3JhZG8xEjAQBgNVBAcMCUVuZ2xld29vZDEQMA4GA1UECgwHQ29tY2FzdDEN
MAsGA1UECwwETUVMRDERMA8GA1UEAwwIa2Fma2EtZ3cxJjAkBgkqhkiG9w0BCQEW
F2J1bWpvb25fa2ltQGNvbWNhc3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAwAxkNLhram/mDSPbd4bOyKItSStM2GB4tG1YF+I1N+bvgCoyY+c5
PP1m9GxvhKPCk8upfeTbvgLl/xN2rd101ABS0pIO8tMLU2MNkZXf8AC+QXZm1uAn
ThiILLkk41PyLlYw0wulklrqTmnrrJ+0l0pZ8wJus48rdDJ1lIlT7GFgiT1J2fHr
wxkwDdfYy5QrES8SK0bH85i1hc4xLBrDrgah2dMTAyxj20H7KnyTgy5m1V5Xs4VC
KtKFV+WBaY1Htwzq5RUjD4Rmrw0N2o0K9mRUxi/s8isbn5TB9Q0mjNoxB9ZwQzh+
NTn6IV8NnmSAStQWkDrGTp4xtcKtIY2Z3wIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
AQA3bVYBvo82PgQXX/VenktSCa0TycT8aZTk2un9upJl1Db9zq4ZbZqmS8yadxwM
lsMSwexFZJ0OHvXK9CLDUzQ11lOxwJng4ejsreeZua4d5o3suI2S+DZ8u9ySGasj
zSBLkjh6Cj7G4D8lOPNZhurSLg4Ysl1J+XKcdUnx8Sf6S+RG009iQ8H0Nq1/x9v0
CI8rHvQD+e5heUR0q/z2MuawCK7zP3KOr1BxwAZPBCqzII5mgYB6AwJ6bRNClsD8
5sd/a3Y/Iap+59lRMjvYYFugcNiNAECdIGo5VX1rsJp4DA+WhToVyOO4FaTBQ4ZD
Is4y5bUsZh/Gjr+ONK2YfrjF
-----END CERTIFICATE-----
cs


Convert to PKCS12 Format

Note that the export password is the same - "jetty123456".
$ openssl pkcs12 -inkey jetty.key -in jetty.crt -export -out jetty.p12
Enter pass phrase for jetty.key:
Enter Export Password:
Verifying - Enter Export Password:
cs


Then, you will get "jetty.p12".

Create keystore

Note that the destination password is also the same - "jetty123456".
$ keytool -importkeystore -srckeystore jetty.p12 -srcstoretype PKCS12 -destkeystore keystore
Importing keystore jetty.p12 to keystore...
Enter destination keystore password:
Re-enter new password:
Enter source keystore password:
Entry for alias 1 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 keystore -destkeystore keystore -deststoretype pkcs12".
cs


Then, you will have "keystore" file, which will be used for Jetty configuration.

SSL/TLS Configuration on Jetty

Locate keystore

The keystore file generated in previous step should be located to $JETTY_HOME/etc.
(Actually, it can be placed in other locations but $JETTY_HOME/etc/keystore is the default configuration.)

Password Encryption

As mentioned above, "jetty123456" is the only password I used.
It needs to be encrypted before being applied to the configuration.
Here is the example of encrypting the password. Note that "OBF:" will be used for the configuration later.
$ java -cp $JETTY_HOME/lib/jetty-util-9.2.11.v20150529.jar org.eclipse.jetty.util.security.Password jetty123456
2018-03-06 10:33:03.217:INFO::main: Logging initialized @139ms
jetty123456
OBF:1ktv1jn31mf31m801n0m18jj1mwo1m4e1mbj1jkf1kqz
MD5:09919a53fefcbe804d1cb7b807dc4c19
cs

Configuration

First, you need to create a directory "start.d" in $JETTY_HOME.
Then, 2 files should be created as following.
$ cd $JETTY_HOME/start.d
 
$ cat https.ini
--module=https
 
$ cat ssl.ini
jetty.ssl.host=0.0.0.0
jetty.ssl.port=8443
jetty.sslContext.keyStorePath=etc/keystore
jetty.sslContext.keyStorePassword=OBF:1ktv1jn31mf31m801n0m18jj1mwo1m4e1mbj1jkf1kqz
jetty.sslContext.keyManagerPassword=OBF:1ktv1jn31mf31m801n0m18jj1mwo1m4e1mbj1jkf1kqz
jetty.sslContext.trustStorePassword=OBF:1ktv1jn31mf31m801n0m18jj1mwo1m4e1mbj1jkf1kqz
cs


As you see above, the encrypted password is used.

You can change the port number of SSL and keystore location.


Test

If you run Jetty with the same command - "java -jar $JETTY_HOME/start.jar", you will see 2 servers running - plain HTTP and HTTPS.
$ java -jar start.jar
2018-03-06 12:27:10.854:INFO::main: Logging initialized @701ms
2018-03-06 12:27:10.917:WARN:oejs.HomeBaseWarning:main: This instance of Jetty is not running from a separate {jetty.base} directory, this is not recommended.  See documentation at http://www.eclipse.org/jetty/documentation/current/startup.html
2018-03-06 12:27:11.104:INFO:oejs.Server:main: jetty-9.3.15.v20161220
2018-03-06 12:27:11.125:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/webapps/] at interval 1
2018-03-06 12:27:11.147:INFO:oejs.AbstractConnector:main: Started ServerConnector@4909b8da{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2018-03-06 12:27:11.164:INFO:oejus.SslContextFactory:main: x509=X509@6537cf78(1,h=[],w=[]) for SslContextFactory@67b6d4ae(file:///Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/etc/keystore,file:///Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/etc/keystore)
2018-03-06 12:27:11.343:INFO:oejs.AbstractConnector:main: Started ServerConnector@55d56113{SSL,[ssl, http/1.1]}{0.0.0.0:8443}
2018-03-06 12:27:11.343:INFO:oejs.Server:main: Started @1190ms
cs


Let's check it on a web browser.

"http://localhost:8080" will give you the same result as preivous.

"https://localhost:8443" will be the same but it's definitely based on HTTPS now.



References


+ Recent posts