Shibboleth for Beginners — Part 2
Installing and configuring a Shibboleth IdP on Ubuntu 16.04
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=21861START_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:
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.