Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: versions++

...

Note
iconfalse
titleThis Guide assumes
  • A fresh, minimal (e.g. netinst.iso) install of Debian 1112 ("BullseyeBookworm") with no "tasks" except openssh-server
    • Ubuntu 1822.04 LTS ("xenialJammy Jellyfish") Server works the same as Debian 11 12 for the purpose of this guide
  • Accessed via SSH or the console (no GUI/X11/wayland required nor and certainly not recommended),
  • Correct server time configuration using NTP (e.g. using systemd-timesyncd or ntpd)
  • Packet filters or firewall rules in place, e.g.:
    • With outgoing(ports TCP/80 and TCP/443) network access:
      • Port 80 for Debian APT updates, i.e., for downloading signed software packages
      • Port 80 and 443 for downloading cryptographically signed eduID.at Metadata documents.
      • Port 443 is also needed for downloads of the Shibboleth IDP software or additional modules
      • The With local authentication the IDP will likely also need to connect to your LDAP Directory Servers for authentication and attribute lookup,
        • either on the standard port TCP/389 for LDAP(+STARTTLS),
        • or on port TCP/636 for LDAPS (which which no formal specification exists),
        • or maybe on the "global catalog" port of your Microsoft Active Directory (only if it's necessary you need to access that).
      • For access to NTP services you also need outgoing connectivity to the configured NTP servers (e.g. ACOnet's)
    • And incoming HTTPS access on port TCP/443 only. Noone needs to access your IDP by manually by entering its URL, so no need to be even have the IDP listening on TCP/80 and therefore also no need for a redirect from TCP/80 to TCP/443.
      • Also incoming , if the server is managed via SSH you'll need to allow access to port TCP/22 for access though only from a management network, if the server is managed via SSH.
  • All commands in this guide are to be issued by user user root (uid=0) so sudo -s first as needed.
  • The shell to use is used is /bin/bash (you can get fancy with fish/zsh/etc. after finishing the install/configuration if you want)
  • Use of systemd for service management, using the amended service unit as described in this documentation

...

Install required (and used, throughout this documentation) packages, possibly replacing vim with your $EDITOR of choice (e.g. emacs-nox or nano micro, both of which also support syntax highlighting, which helps when editing XML files) and stop the automatically started tomcat until we've completed more configuration performed further below:

No Format
apt install --no-install-recommends default-jdk-headless tomcat9tomcat10 \
  vim less openssl curl expat multitail gnupg net-tools

systemctl stop tomcat9tomcat10

Post-install fix-ups

Redirect requests to Tomcat's web root ("/") to a URL of your choice, e.g. your institution's home page, replacing "www.example.edu" in the command  belowThe Shibboleth IDP application by default will run at /idp, allowing you to easily add and update other content outside of /idp, e.g. logos or CSS stylesheets without having them to integrate them with the "idp" context/application. The document root for that is in /var/lib/tomcat9tomcat10/webapps/ROOT/ and nothing in the Shibboleth IDP software (or during use of SAML) by default links to / of the server, so you can use that for locally hosted content without interfering with the IDP application. For example, you will want to add a robots.txt file to avoid unnecessary scanning by well-behaved search bots.

No Format
rm /var/lib/tomcat9tomcat10/webapps/ROOT/index.html
echo '<% response.sendRedirect("https://www.example.edu/"); %>' > /var/lib/tomcat9tomcat10/webapps/ROOT/index.jsp
echo -e "User-agent: *\nDisallow: /" > /var/lib/tomcat9tomcat10/webapps/ROOT/robots.txt

Set JAVA_HOME for the current (and future) shell(s):

...

Note

Do not use an existing wildcard certificate (if one is available that would also cover your IDP webserver) – just do the work as described below and create another certificate for your IDP. Under ACOnet's TCS agreement you can get unlimited globally valid commercial certificates at no cost to you. (Alternatively, though not recommended for your eduID.at IDP, there's always letsencrypt.)
So there should be no excuse to promiscuously share an existing TLS key pair across unrelated servers and services.

...

Tip
titleRenewing an existing TLS certificate?

In case you're replacing an expiring TLS certificate where the matching private key is still considered to be secure and of sufficient strength (in 2021 2023 for RSA keys that means a key size of at least 2048 bits) you may 'll want to keep using the existing private key (and PKCS#12 keystore passphrase) and generate the CSR any CSRs from that key.
To do that first extract the private key from your keystore (instead of generating a new one):

No Format
openssl pkcs12 -in /etc/tomcat9tomcat10/webserver.p12 -nocerts | tail +5 > webserver.key

When asked to "Enter Import Password" supply the existing keystorePass for the  port="443" Connector from your /etc/tomcat9tomcat10/server.xml configuration file.
When asked to "Enter PEM pass phrase" simply enter/paste that same passphrase again.
And yet again, when asked to "Verifying - Enter PEM pass phrase".

Then generate a CSR from the extracted private key, either by supplying the necessary data (at least the subject) on the command line or by entering any data interactively when being prompted for it (when not adding -subj to the command):

No Format
openssl req -new -key webserver.key -out webserver.csr -subj "/CN=WEBSERVER-FQDN"

When asked to "Enter pass phrase for webserver.key" again provide the passphrase from the previous steps.

The content of webserver.csr is what you provide to your CA then, e.g. via cat webserver.csr and pasting the result into the CA's web interface.

Equipped with the CSR you can now request a TLS certificate based from your CA, e.g. using the ACOnet TCS supplier. Once the certificate has been issued copy it to the IDP server as webserver.crt.
You'll also need to copy any intermediate intermediary Certificate Authority (CA) certificates to the IDP server.

...

No Format
openssl pkcs12 -export -in webserver.crt -inkey webserver.key -certfile GEANT-OV-RSA-CA-4.crt -name "webserver" -out webserver.p12

When asked to "Enter pass phrase for webserver.key" provide the passphrase generated earlier.
Again when asked to "Enter Export Password".
And yet again, when asked to "Verifying - Enter Export Password".

Move the newly created keystore to its final location (we're chosing Tomcat's config directory) and set strict file system permissions on it:

No Format
[[ -f /etc/tomcat9tomcat10/webserver.p12 ]] && cp -a /etc/tomcat9tomcat10/webserver.p12 /etc/tomcat9tomcat10/webserver.p12.`date -u +%Y%m%d`
mv webserver.p12 /etc/tomcat9tomcat10/
chown root:tomcat /etc/tomcat9tomcat10/webserver.p12
chmod 640 /etc/tomcat9tomcat10/webserver.p12

Configure Tomcat Connector

Remove or comment out all other Connectors in /etc/tomcat9tomcat10/server.xml, then add the two Connectors as per below, replacing keystorePass with the password generated earlier:

...

Code Block
languagehtml/xml
<!-- Localhost-only connector for IDP command line tools -->
<Connector address="127.0.0.1" port="80" />
 
<!-- https://tomcat.apache.org/tomcat-910.01-doc/ssl-howto.html -->
<Connector
  port="443"
  protocol="org.apache.coyote.http11.Http11NioProtocol"
  maxThreads="150"
  maxPostSize="100000"
  SSLEnabled="true"
  scheme="https"
  secure="true"
  clientAuth="false"
  sslProtocol="TLS"
  sslEnabledProtocols="TLSv1.2,TLSv1.3"
  keystoreType="pkcs12"
  keystoreFile="/etc/tomcat9tomcat10/webserver.p12"
  keystorePass="see above">
  <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
</Connector>

...

No Format
systemctl restart tomcat9tomcat10
netstat -lntp | fgrep java  # should show 443, and 80 only on the loopback interface

...

In case of errors check the output of "journalctl -u tomcat9 tomcat10 -ef".

If everything works fine and the certificate chain looks as expected you can remove the private key and certificate again (as both can be extracted from the PKCS#12 keystore if needed), keeping the CSR in file webserver.csr around for next time you need to renew that certificate (as long as you still consider the matching private key secure):

...

By default Tomcat logs everything multiple times, including to /var/log/tomcat9tomcat10/catalina.out and /var/log/tomcat9tomcat10/localhost.*, which we don't care for. So create a backup copy of Tomcat's logging.properties and replace its content with the minumum needed to getTomcat's stdout/stderr to the console (which ends up in the systemd journal in our configuration). To prevent catalina.out from being created we deacticate it further below (in our "Systemd service" override) by setting the CATALINA_OUT=/dev/null environment variable for the java process.

No Format
systemctl stop tomcat9tomcat10
cp -a /etc/tomcat9tomcat10/logging.properties /etc/tomcat9tomcat10/logging.properties.`date -u +%Y%m%d`
 
echo -n 'handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = org.apache.juli.SystemdFormatter
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = java.util.logging.ConsoleHandler
' > /etc/tomcat9tomcat10/logging.properties

Then comment out or delete the whole Valve element at the end of your /etc/tomcat9tomcat10/server.xml, and replace it with the following one:

...

After deleting all Tomcat logs (only) access.log should be generated in Tomcat's log directory going forward:

No Format
rm -f /var/log/tomcat9tomcat10/*
systemctl restart tomcat9tomcat10
ls -l /var/log/tomcat9tomcat10/
multitail /var/log/tomcat9tomcat10/* -l 'journalctl -u tomcat9tomcat10.service -f'  # exit with 'q'
systemctl stop tomcat9tomcat10

If you're certain there's no catalina.log file being generated anymore you can also disable the default logrotate config snippet for it:

No Format
sed -i 's/^/#/' /etc/logrotate.d/tomcat9tomcat10

Systemd service

Debian's Tomcat comes with an almost-usable systemd service that needs to be amended in order to

...

Code Block
languagebash
install -o root -g root -m 0755 -d /etc/systemd/system/tomcat9tomcat10.service.d

cat <<'EOF' > /etc/systemd/system/tomcat9tomcat10.service.d/override.conf
[Service]
Environment="CATALINA_OUT=/dev/null"
Environment="JAVA_OPTS=-Djava.security.egd=file:/dev/urandom -Djava.awt.headless=true -Xmx3g"
Environment="JSSE_OPTS=-Djdk.tls.ephemeralDHKeySize=2048"
ExecStart=
ExecStart=/usr/bin/java \
  $JAVA_OPTS $JSSE_OPTS \
  -classpath ${CATALINA_HOME}/bin/bootstrap.jar:${CATALINA_HOME}/bin/tomcat-juli.jar \
  -Dcatalina.base=${CATALINA_BASE} \
  -Dcatalina.home=${CATALINA_HOME} \
  -Djava.util.logging.config.file=${CATALINA_BASE}/conf/logging.properties \
  -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager \
  -Djava.io.tmpdir=${CATALINA_TMPDIR} \
  org.apache.catalina.startup.Bootstrap
ReadWritePaths=/var/log/shibboleth/
ReadWritePaths=/opt/shibboleth-idp/logs/
ReadWritePaths=/opt/shibboleth-idp/metadata/
EOF

...