Shibboleth for Beginners — Part 2

Installing and configuring a Shibboleth IdP on Ubuntu 16.04

John Callahan
5 min readAug 3, 2017

In Part 1, we built a simple Ruby-on-Rails (RoR) client Service Provider (SP) relies on a third-party IdP (JumpCloud) for authentication via SAML. Now, we want to run our own SAML IdP with Shibboleth — the dominant open source solution. Thanks to eduid.cz site for their insightful guide that was the basis of this article.

Install Oracle JDK

As root, in the root home directory (/root), execute the following commands to make sure your platform is up-to-date:

# apt-get update
# apt-get upgrade

Reboot if necessary. Then, install Oracle JDK:

# apt-get install software-properties-common
# add-apt-repository ppa:webupd8team/java
# apt-get update
# apt-get install oracle-java8-installer
# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
#

Then, set the JAVA_HOME environment variable and verify:

# echo "JAVA_HOME=/usr/lib/jvm/java-8-oracle/" >> /etc/environment
# source /etc/environment
# echo $JAVA_HOME
/usr/lib/jvm/java-8-oracle/
#

Install JCE US required for stronger crypto. You can find it here. Download the jce_policy-8.zip file and then:

# apt-get install unzip
# unzip jce_policy-8.zip
# cd UnlimitedJCEPolicyJDK8
# cp local_policy.jar $JAVA_HOME/jre/lib/security/
# cp US_export_policy.jar $JAVA_HOME/jre/lib/security/

Get a free SSL cert

Before we get jetty running and before we re-route ports via iptables, we need to get an SSL cert from Let’s Encrypt for your domain:

# apt-get install letsencrypt
# letsencrypt certonly -d shib.example.com
#

We’ll use this in a later step after the jetty installation. This certificate lasts 90 days and I refer you to using certbot for Let’s Encrypt renewals if you need to refresh the certificate in 3 months.

Install Jetty

It is recommended that Jetty be used in production by the Shibboleth community. First, add an idp user and group:

# groupadd idp
# useradd -m -g idp -s /bin/bash idp

Then, add port redirection (we’ll cover how to make these permanent across reboots later):

# iptables -t nat -A OUTPUT -o lo -p tcp -m tcp \
--dport 80 -j REDIRECT --to-ports 8080
# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 \
-j DNAT --to-destination :8443

These port redirections will not last between reboots, so please refer to this eduid.cz article for persistence of iptables directives. Now, install and configure jetty:

# cd /opt
# mkdir -p src jetty/tmp
# chown -R idp:idp src jetty
# su idp
$ cd /opt/src
$ wget https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.3.14.v20161028/jetty-distribution-9.3.14.v20161028.tar.gz
$ exit
# tar xzf src/jetty-distribution-9.3.14.v20161028.tar.gz
# chown -R idp:idp /opt/jetty-distribution-9.3.14.v20161028
# ln -snf /opt/jetty-distribution-9.3.14.v20161028/bin/jetty.sh \
/etc/init.d/jetty
# echo "JETTY_HOME=/opt/jetty-distribution-9.3.14.v20161028/" > \
/etc/default/jetty
# echo "JETTY_BASE=/opt/jetty" >> /etc/default/jetty
# echo "JETTY_USER=idp" >> /etc/default/jetty
# cd /opt/jetty
# su idp
$ java -jar /opt/jetty-distribution-9.3.14.v20161028/start.jar \
--add-to-startd=http,https,logging,deploy,jsp,jstl,plus,\
servlets,annotations,ext,resources,logging,requestlog
$ vi start.d/http.ini

Uncomment the jetty.http.host line to read:

## Connector host/address to bind to
jetty.http.host=0.0.0.0

Save the file, then:

$ mkdir -p /opt/jetty/webapps/root
$ vi /opt/jetty/webapps/root/index.html

And add the content:

<html>
<body>
Hello Shibboleth!
</body>
</html>

and save the file, then:

$ vi /opt/jetty/webapps/idp.xml

And add the content:

<Configure class="org.eclipse.jetty.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>
<Set name="tempDirectory">/opt/jetty/tmp</Set>
</Configure>

and save the file. Construct and install the keystore:

$ exit
# cd /root
# cp /etc/letsencrypt/live/shib.example.com/*.pem .
# openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem \
-out pkcs.p12 -name shib

Provide a password and remember it for the next steps:

# keytool -importkeystore -deststorepass PASSWORD -destkeypass \
PASSWORD -destkeystore keystore -srckeystore pkcs.p12 \
-srcstoretype PKCS12 -srcstorepass PASSWORD -alias shib
# chown idp:idp keystore
# cp keystore /opt/jetty/etc/

Provide the keystore password in the config file:

# su idp
$ vi /opt/jetty/start.d/ssl.ini

And edit the following lines:

// Configuration changes in the file 'ssl.ini'
// (these may be on different lines in the file)
jetty.sslContext.keyStorePassword=PASSWORD
jetty.sslContext.keyManagerPassword=PASSWORD
jetty.sslContext.trustStorePassword=PASSWORD

Save the file, then move the http config file out of the way (disabling access via port 8080 on an unprotected port:

$ exit
# mv /opt/jetty/start.d/http.ini .
# /etc/init.d/jetty start

You may get an error (because of the missing idp.war file if you check the /opt/jetty/logs/YYYY_MM_DD_stderrout.log file), but jetty will be running:

# /etc/init.d/jetty status
Jetty running pid=21861
START_INI = /opt/jetty/start.ini
START_D = /opt/jetty/start.d
JETTY_HOME = /opt/jetty-distribution-9.3.14.v20161028
JETTY_BASE = /opt/jetty
...
#

If you browse to https://shib.example.com/ (your domain, not this example.com of course), you should see:

See if your Jetty server is running

Install Shibboleth (finally)

Now that much of the infrastructure is in place, we can install a rudimentary Shibboleth IdP:

# mkdir -p /opt/src
# chown -R idp:idp /opt/src
# su idp
$ cd /opt/src
$ wget https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.3.14.v20161028/jetty-distribution-9.3.14.v20161028.tar.gz
$ exit
# cd /opt
# tar -xzf src/shibboleth-identity-provider-3.2.1.tar.gz
# cd shibboleth-identity-provider-3.2.1/
# ./bin/install.sh
# chown -R idp:idp /opt/shibboleth-id*
# /etc/init.d/jetty restart

Restarting the jetty server may fail, but check the status with:

# /etc/init.d/jetty status

Navigate to https://shib.example.com/idp in your browser to see:

Not very interesting, but navigate to https://shib.example.com/idp/shibboleth and you should see the IdP metadata:

Conclusions

In Part 3, I will configure the Shibboleth server with the JumpCloud LDAP-as-a-Service endpoint covered in Part 1 and test drive it with the Ruby-On-Rails Service Provider (SP) also covered in Part 1.

--

--