Jetty12
Using Jetty 12.0 or 12.1
Based on testing it appears the examples here work for both 12.0 and 12.1, so we have not created a separate page for 12.1 at this time.
These pages are examples and do not reflect any normative requirements or assumptions on the part of the IdP software and may be a mix of suggestions from both the project team and deployers. You should take any of this advice with a grain of local salt and consider general security/deployment considerations appropriate to the use of web software in your local environment.
The official information about containers and versions we support is solely maintained on the SystemRequirements page. If you wish to operate without complete responsibility for your Java servlet container, you may consider the Windows package we provide that installs a version of Jetty with very limited configurability.
The following conventions are used this document:
/opt/shibboleth-idp is used to indicate that an absolute path to the IdP installation directory is required
idp.homerefers to the IdP installation directory (as specified during the installation process)JETTY_HOMErefers to the location of the Jetty installation (jetty-home-$VERSION)JETTY_BASErefers to the directory containing your deployment-specific Jetty configuration filesAll paths are relative to
JETTY_BASEunless otherwise noted
We strongly recommend placing all IdP-specific Jetty configuration under JETTY_BASE to facilitate Jetty upgrades. Do not place that directory inside the IdP installation directory; they can be siblings as desired.
Note that Jetty 12 requires the recommended home/base split; the distribution itself is always considered read-only.
Do NOT skip the Getting Started section. All of the example material depends on the use of files that have to be downloaded and installed to create an initial jetty-base directory tree.
Version Notes
The latest stable version of Jetty 12.0 or 12.1 should be used.
Migrating from Jetty 11 (or 10 if making the jump) is a “mostly lateral” process except that the version of logback will be different because of the Servlet API changes in this version. If you use the “recommended” approach of using logback with Jetty, you’ll get a different set of jars appropriate to that version’s logging module(s) when adding that module.
The most significant difference from a Shibboleth perspective is that we do not have a supported mechanism to convince Jetty to accept client TLS certificate authentication on a secondary port from arbitrary certificates. This is the so-called “back-channel” support that, while very much historical at this point, dates to the very early days of the project. The Shibboleth software (both IdP and SP) are fully capable of operating all profiles over port 443, with so-called “back-channel” use cases generally relying on message signing as a substitute for mutual TLS, which is generally not as easy to deploy nowadays due to proxying and load balancers.
(Notably, any back-channel use with OpenID and OAuth do not rely on any meaningful security (only the highly questionable value of a commercially acceptable TLS certificate), so there is no limitation there.)
If you still rely on a secondary port for some use cases, you will need to migrate off of that approach prior to upgrading Jetty to 12.x.
Getting Started
The examples on this page are based on the use of a number of files that are not included in the Jetty distribution but are part of the java-idp-jetty-base project we store in our Git repository. The examples won't work as is without starting from that complete set of example files. The 12 branch contains the files used in this material.
The following commands (Linux-style) will get you to the starting point assumed from the examples in this page:
$ git clone https://git.shibboleth.net/git/java-idp-jetty-base
$ cd java-idp-jetty-base
$ git checkout 12
# or 12.1 as you prefer
$ cp -r src/main/resources/net/shibboleth/idp/module/jetty/jetty-base /my/desired/location/Required Configuration
The bulk of the configuration is established by setting properties in "ini" files that are combined in the start.d directory. Some of the properties are defined by Jetty and configure built-in modules and others are specific to the IdP and configure the custom module we created.
The start.d/idp.ini file that configures the “idp” module contains not only the bulk of the basic settings needed but is also a place you can add your own settings to control JVM startup, change which logging module is used, etc. Or you can continue to use a separate start.ini file as shown next.
Configure Jetty Modules and JVM Settings
File(s): start.d/start.ini
start.ini
# Any other required Jetty modules...
# Allows setting Java system properties (-Dname=value)
# and JVM flags (-X, -XX) in this file
# NOTE: spawns child Java process
--exec
# Uncomment if IdP is installed somewhere other than /opt/shibboleth-idp
#-Didp.home=/path/to/shibboleth-idp
# Maximum amount of memory that Jetty may use, at least 1.5G is recommended
# for handling larger (> 25M) metadata files but you will need to test on
# your particular metadata configuration. If MDQ metadata on demand is used,
# requirements may be much lower.
-Xmx1500m
# Prevent blocking for entropy.
-Djava.security.egd=file:/dev/urandom
# Set Java tmp location
-Djava.io.tmpdir=tmp
# May be needed in certain cases depending on content of TLS certificate.
#jetty.ssl.sniHostCheck=falseConfigure HTTP/HTTPS Connectors
File(s): credentials/idp-userfacing.p12, start.d/idp.ini
The basic HTTP/HTTPS port, address, etc. configuration can be handled within the custom "idp" module and the idp.ini property file.
The example below shows some of the basic properties you can use to configure networking and TLS credentials.
One challenge remains that if you want to use standard ports on Linux, you would need to pick one of these options to avoid running as root:
(Best option) Use POSIX capabilities to allow use of priviledged ports by an unpriviledged process, e.g., when using systemd by setting
AmbientCapabilities=CAP_NET_BIND_SERVICEin the unit file.Use Jetty’s setuid module to support listening on the privileged ports as a non-root user. This extension is now JNA-based and seems to be undocumented at this point, but works fine. You can enable this module via
java -jar /opt/jetty-home-12.0.0/start.jar --add-module=setuidUse a port forwarding approach (load balancer, iptables rules, etc).
Adjust the range of ports considered privileged if supported by your Linux kernel (most newer distributions can do this).
Example idp.ini
The TLS credential example relies on a PKCS12 file containing the X.509 certificate and private key used to secure the HTTPS channel that users access during authentication and other browser-based message exchanges involving the IdP. This is generally the one you get from a browser-compatible CA, and the example shows it being loaded from a directory inside the JETTY_BASE tree.
A variety of other networking properties can be set based on the built-in Jetty http and https modules; refer to their documentation.
Configure IdP Context Descriptor
File(s): webapps/idp.xml
In order to deploy the IdP, Jetty must be informed of the location of the IdP war file. This file is called a context descriptor and the recommended content is provided below.
Note this file assumes the location of the IdP installation is explicitly set in the file, and controls the context path to which the application is deployed, which is /idp in the following configuration block.
idp.xml
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.ee9.webapp.WebAppContext">
<Set name="war">/opt/shibboleth-idp/war/idp.war</Set>
<Set name="contextPath">/idp</Set>
<Set name="extractWAR">false</Set>
<Set name="copyWebDir">false</Set>
<Set name="copyWebInf">true</Set>
</Configure>Managing Startup
Non-Windows
The two main service startup/shutdown mechanisms on non-Windows platforms are the newer “systemd” framework, which relies on declarative “unit” files, and the legacy “init.d” mechanism that relies on shell scripts with certain conventions. Since “systemd” is now the standard mechanism, we will use it in this example.
In either scenario, there a couple of approaches you can use to actually start the service:
Run the Jetty start command directly.
Run a shell script that runs the Jetty start command.
The main difference is that in the first case, you usually need to manage the version of Jetty and the location of other directories in “root-owned” files, while in the second case you can manage that in the shell script that’s run by the root-owned files. The main disadvantage of the latter is that if you run Jetty as root to handle binding to privileged ports, a shell script will be running as root and likely be under the control of a non-root account, creating an exposure. In practice, this exposure is meaningless on a single-purpose host but this issue should be considered.
In this example, we’ll use the simpler approach of directly running Jetty via a systemd unit file:
/etc/systemd/system/jetty.service
[Unit]
Documentation=https://www.eclipse.org/jetty/documentation/
Description=Jetty Server
After=network-online.target
Wants=network-online.target
[Service]
# To use a shell script to run Jetty, change to "forking"...
Type=exec
# Set as desired to limit privileges.
User=jetty
Group=shibboleth
# Allow use of port80/443.
AmbientCapabilities=CAP_NET_BIND_SERVICE
Restart=no
TimeoutSec=45
KillMode=process
WorkingDirectory=/opt/jetty
# Change every time you upgrade Jetty or you could use a symlink, etc...
Environment="JETTY_HOME=/opt/jetty-home-12.0.0"
Environment="JETTY_BASE=/opt/jetty"
# Checks that start configuration exists ad we're not trying to start jetty without having that configured
ExecStartPre=/usr/bin/test -d ${JETTY_BASE}/start.d -a -f ${JETTY_BASE}/start.d/start.ini
ExecStart=/etc/alternatives/jre/bin/java -Djetty.home=$JETTY_HOME -Djetty.base=$JETTY_BASE -jar $JETTY_HOME/start.jar --exec &
ExecStop=/bin/kill ${MAINPID}
SuccessExitStatus=130 143Whether run directly or via a script, using the “--exec” option will cause Jetty to fork off a child process with the full command line, so you will end up with two Java processes, one the parent of the other.
Windows
Startup on Windows is best managed by running jetty as a system service. The Apache Procrun project provides a suitable framework.
Configuring using PrunMgr
Java Tab
Java Claspath:
\Windows\Path\To\Start.jarJavaOptions
-Didp.home=C:/unix/path/to/idp.home -Djdk.tls.ephemeralDHKeySize=2048 -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.Slf4jLog -Djava.io.tmpdir=C:\Windows\Path\to\jetty-tmp -Dlogback.configurationFile=C:\Windows\Path\to\jetty-base\resources\logback.xml -XX:+UseG1GC
Startup Tab
Class
org.eclipse.jetty.start.MainArugments
STOP_PORT=8963 STOP.KEY=<KEY< jetty.base=C:\Windows\Path\to\jetty-base\ jetty.logging.dir=C:\Windows\Path\to\idphome\logs
Shutdown Tab
Class
org.eclipse.jetty.start.MainArugments
--stop STOP_PORT=8963 STOP.KEY=<KEY< jetty.base=C:\Windows\Path\to\jetty-base\ jetty.logging.dir=C:\Windows\Path\to\idphome\logs
Configuring from the command line
You can do something like the following. You should consult the documentation and not do this blindly
SET PORTPASS=<whatever>
SET PR_DISPLAYNAME=Shibboleth IdP Daemon
SET PR_DESCRIPTION=Runs the Jetty Container
SET PR_CLASSPATH=c:\windows\path\to\jetty-home\start.jar
SET PR_JVMOPTIONS=-Didp.home=c:/unix/path/to/idphome;-Djdk.tls.ephemeralDHKeySize=2048;-Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.Slf4jLog;-Djava.io.tmpdir=c:\windows\path\to\jetty\tmp;-Dlogback.configurationFile=c:\windows\path\to\jettybase\resources\logback.xml;-XX:+UseG1GC
SET PR_JVMMX=2048
SET PR_JVM=auto
SET PR_JAVAHOME=c:\windows\path\to\java\home
SET PR_LOGPATH=c:\windows\path\to\idphome\logs
SET PR_STDOUTPUT=auto
SET PR_STDERROR=auto
SET PR_STARTMODE=JVM
SET PR_STARTCLASS=org.eclipse.jetty.start.Main
SET PR_STARTPARAMS=STOP_PORT=8963;STOP.KEY=%PORTPASS%;jetty.base=c:\windows\path\to\jettybase\;jetty.logging.dir=c:\windows\path\to\idphome\logs
SET PR_STOPMODE=JVM
SET PR_STOPCLASS=org.eclipse.jetty.start.Main
SET PR_STOPPARAMS=--stop;%PR_STARTPARAMS%
PRUNSRV.exe //IS --Startup=autoRunning Jetty as a captive user
Procun allows you to specify an unprivileged user to run the IdP. If you do this you will need:
To set the appropriate ACLs on idpHome. The SetACLCommand does this. Additionally
You need to give read access to jetty-base and jetty-home
You need to give write access to the logging directory (if different from the IdP logging) and to the Jetty temporary directory.
Recommended Configuration
Jetty Logging
File(s): start.d/idp.ini, resources/logback.xml
The recommended approach is to use logback for all Jetty logging. Note that this isn’t required, and the version of logback (or slf4j) used does not depend on the version used by the IdP. They are separately configured and can vary independently.
To enable the logback support in Jetty, first add this to idp.ini:
--module=logging-logbackThen ask Jetty to download the necessary logging libraries by running the --add-module command:
java -jar /opt/jetty-home-12.0.0/start.jar --add-module=logging-logbackJetty will populate a lib/logging folder with the 2 logback libraries it requires. If there are older versions left behind by earlier Jetty versions, you will need to remove them.
Of course, this is completely insecure. If you want to be appropriately careful, you can compare the 2 jars it downloads to the signed copies available from Maven Central and check their signatures.
If you find that Jetty isn’t producing the logging output expected, you may wish to try adding this to your startup sequence:
-Dlogback.configurationFile=resources/logback.xmlThe next step is to instruct Jetty to produce its access/request log using the same logging APIs it uses for everything else. This is not a Jetty module at this point, so requires the etc/jetty-requestlog.xml file we provide:
A sample logback configuration for both debug and request logging is provided in resources/logback.xml.
Disable Directory Indexing
Jetty has had vulnerabilities related to directory indexing (sigh) so we suggest disabling that feature at this point. There are a few different ways this can be done, but one method that's fairly self-contained within the IdP footprint is to modify web.xml (i.e. copy the original version from idp.home/dist/webapp/WEB-INF/web.xml to idp.home/edit-webapp/WEB-INF/web.xml) and then rebuild the war file.
web.xml addition
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.eclipse.jetty.ee9.servlet.DefaultServlet</servlet-class>
<init-param>
<param-name>dirAllowed</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>You can place it above the existing <servlet> elements in the file.
TLS Ciphers
As with all web servers, it's a challenge to stay on top of all the best practices related to TLS/SSL versions, ciphers, etc. Jetty has been good of late in shipping reasonable defaults, but they frequently get bad advice pressuring them to be "more interoperable", so it's hard to count on things staying good. It's usually best to be in a position to make adjustments to this quickly, and test after upgrades.
Jetty documents a way to adjust this sort of thing here. The basic procedure is to create a file at etc/tls-config.xml to adjust the settings. You should do some testing against SSL Labs or some other source of information to evaluate what the defaults look like and make any adjustments you think are warranted.
Optional Configuration
Supporting SOAP Endpoints
As noted above, this is no longer something we support via a separate port. You should publish support for SOAP, if you need it, on port 443 in your metadata. The IdP will automatically reject any requests it cannot authenticate using message signatures.
Other Modules
Jetty has a ton of advanced and optional functionality available in the form of modules that can be enabled selectively. They don't function in the way Apache modules do, but they're basically packaged "example" configuration files that will get copied from JETTY_HOME into JETTY_BASE when you need them and you get "just" the minimum files needed to support the feature but keep future upgrades simple.
To enable a module, you run the Jetty start file from within JETTY_BASE:
$ cd jetty-base
$ java -jar /opt/jetty-home-12.0.0/start.jar --add-module=modulenameSupporting X-Forwarded-For Natively
If you are running the Jetty engine behind a proxy or load balancer Jetty has built-in support for forwarding the client address and other details via headers using its “http-forwarded” module, and after adding it with the --add-module command (see previous section) you can edit the https-forwarded.ini file it will create to configure it.
Note that this example applies the forwarding rule to all ports, so if you also operate the server on other ports, those must also be proxied/protected or this will lead to exposures due to clients having the ability to smuggle in a false client address.
Local Proxying via Apache
If your IdP is behind Apache rather than proxied via a load balancer, you might only need it to listen for HTTP traffic locally. This is not applicable in general to load balancing via an applicance like an F5 or NetScaler.
At present, this involves commenting out or removing two lines from the [depend] section of idp.mod: the lines containing https and ssl.
The http-forwarded module mentioned above is also required so that requests coming to the IdP aren't seen as coming from localhost.
Finally, make sure the jetty.http.host and jetty.http.port properties are set apropriately in idp.ini, or remove them from there and add them to http.ini.
jetty.http.host=127.0.0.1
jetty.http.port=8080Since 8080 is the default http port for Jetty, It's also okay to leave this unset. That change will confine Jetty to listen locally only rather than over a network.