Installation of Shibboleth relies on the installation of several packages, applications and proper firewall configuration. While none of the steps are difficult in themselves, the combination of so many steps can be quite daunting. Hopefully the guide below will break down the installation process and ease the job of installing Shibboleth.
Unless otherwise stated, do not build and install the
components in this guide under a remote branch of the file
system. All the examples here are installed under
/usr/local
. If /usr/local
is part of a network-mounted
or shared file system, replace this with something local,
e.g. /opt
.
Many of the following stages require obtaining files from the World Wide Web. If necessary, configure your environment so that tools such as wget are able to access the web:
$ export http_proxy=http://webproxy.example.edu:8080
Where webproxy.example.edu is the host and 8080 the port of your web proxy.
It is generally regarded as good practice to have a firewall installed on servers. Redhat AS3.0 comes with the "iptables" firewall solution. If you have your own firewall solution or policy then you may wish to ignore this section.
It is probably a good idea to get the firewall setting sorted out as early as possible, as it is the kind of thing you can forget later on in an install. Since it drops connections silently it is difficult to identify as the source of a later problem.
In order to use Pubcookie you will need to allow:
network time protocol, this usually occurs via UDP communication to port 123;
HTTP and HTTPS web serving, the default ports are TCP 80 and TCP 443;
an additional port of 8443 is also required (more later), communication is via TCP;
for testing the Tomcat install opening up port 8080 to TCP is a good idea though in a live deployment you may wish to shut this down.
It is possible to check what is listening on an open
port using lsof -i:<port
number>
There are lots of ways to setup firewalls and lots of
situations which require different firewall settings. If you
don't know how to setup a firewall in your institution now is
the time to consult someone who does. However, if you are
just experimenting, the following rules would form the basis
of a reasonable setup. Redhat keeps the iptables firewall
rules in /etc/sysconfig/iptables
. The syntax of this
file is that generated by the tool iptables-save
.
# iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT # iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT # iptables -A INPUT -p udp -m udp --dport 123 -j ACCEPT # iptables -A INPUT -p udp -m udp --dport 22 -j ACCEPT # iptables -A INPUT -p tcp -m tcp --dport 8443 -j ACCEPT # iptables -A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT
The following commands ensure that local and existing connections are uninhibited:
# iptables -A INPUT -m state --state RELATED -j ACCEPT # iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT # iptables -A INPUT -i lo -m state --state NEW -j ACCEPT
The following commands ensure that any traffic not already dealt with by the above commands will be dropped:
# iptables -P FORWARD DROP # iptables -P INPUT DROP
If you are remotely manipulating the machine, you may want to allow through the traffic that lets you do so. The secure shell protocol ssh operates on TCP port 22 and a rule is included above for it. Make sure you include this rule or one suitable for your setup before changing the default policy to 'DROP', especially if the machine is not physically close to you!
There is some excellent documentation on iptables and its parent project netfilter at http://www.netfilter.org/. Go there for help writing more complex iptable recipes, including how to restrict access to individual addresses or subnets.
Both Shibboleth and Pubcookie requires accurate network time. They both use time stamps on cookies, forms, and SOAP messages to try and avoid "replay" attacks. In order to get accurate network time running it is a good idea to us xntpd to keep track of accurate time. Xntpd is a daemon that talks to a variety of time sources (as configured in ntp.conf) which can include specialised hardware clocks but in most case are just NTP servers which are in turn synchronised to accurate clocks. Running xntpd gives a much more stable and accurate time as it learns how inaccurate the local machine's clock is and can keep it reasonably well adjusted even if it loses contact with the remote servers.
It may be possible to use a publicly accessible network time protocol server if you don't have access to one. The web site at http://www.eecis.udel.edu/~mills/ntp/clock2a.html may provide information about this, though use at you own risk.
To configure edit /etc/ntp.conf
to tell it which NTP server
to use. You can put in multiple NTP server entries for
redundancy.
# # Standard NTP configuration for systems # server ntpA.example.edu server ntpB.example.edu server ntpC.example.edu # # Drift file. Put this in a directory which the daemon can write to. # No symbolic links allowed, either, since the daemon updates the file # by creating a temporary in the same directory and then rename()'ing # it to the file. # driftfile /etc/ntp/drift
Then to get xntpd to run and survive server reboots you need to:
# chkconfig ntpd on # service ntpd start
To check it is running properly run:
$ ntpq -p
You should see output something like:
remote refid st t when poll reach delay offset jitter ============================================================================== +ntp1.example.edu ntp1.ja.net 2 u 605 1024 377 0.771 -0.796 0.170 101.101.101.101 0.0.0.0 16 u - 1024 0 0.000 0.000 4000.00 *ntp2.example.edu ntp1.ja.net 2 u 298 1024 377 3.608 -2.041 1.324 LOCAL(0) LOCAL(0) 10 l 28 64 377 0.000 0.000 0.008
The above shows a working connection to the first and third ntp servers the second server is unreachable. A jitter of 4000.0 means the server is unreachable as does a reach of 0. You only need to be able to contact one server in order to sycronise, contacting more just makes it more resilient. It is also worth nothing that on some (possibly all) configs your clock needs to be reasonably close to accurate time in order to initially syncronise. Use the "date" utility to set the machine clock to something close to accurate time before setting up ntpd.
In order to install Pubcookie you will require the httpd-devel version of Apache httpd as supplied by Redhat. The "devel" version is required as the apxs script is needed for the Pubcookie install. Obviously openssl and mod_ssl are required to provide secure serving necessary for logins.
To install the required packages simply run up2date:
# up2date httpd # up2date httpd-devel # up2date openssl # up2date openssl-devel # up2date mod_ssl
This will get you Apache 2, Apache development files including the module installer (apxs), openssl for secure SSL and mod_ssl to enable SSL in Apache.
It is a good idea to de-activate Apache modules that are not being used, to limit the amount of code that is being executed. The less code executed, the fewer potential security holes that are open to crackers.
If you are using the server for another purpose then you
may need additional modules. De-activate other modules by
editing /etc/httpd/conf/httpd.conf
. We also suggest
removing files (or renaming to remove the .conf
extension) in /etc/httpd/conf.d
which are unnecessary:
e.g. php.conf
, perl.conf
, python.conf
.
This step can probably be ignored if you are just testing the setup or think this is overly paranoid.
The following list of LoadModule directives will provide the required modules:
LoadModule access_module modules/mod_access.so LoadModule auth_module modules/mod_auth.so LoadModule log_config_module modules/mod_log_config.so LoadModule env_module modules/mod_env.so LoadModule setenvif_module modules/mod_setenvif.so LoadModule mime_module modules/mod_mime.so LoadModule autoindex_module modules/mod_autoindex.so LoadModule negotiation_module modules/mod_negotiation.so LoadModule dir_module modules/mod_dir.so LoadModule alias_module modules/mod_alias.so LoadModule cgi_module modules/mod_cgi.so
The modules mod_ssi.so
mod_jk2.so
and mod_pubcookie.so
are also required, but
they are inserted into /etc/httpd/conf.d/ssl.conf
in the later
stages of this guide.
Start the Apache httpd server as a service (for details of service script see /etc/init.d/httpd):
# service httpd start
Now browse to the server via http (visit http://weblogin.example.edu/) and https (visit https://weblogin.example.edu/). In both cases you should see the "Redhat Enterprise Linux test page".
Optionally you can use run levels to make httpd fire up after reboot using chkconfig (for full details use "man chkconfig" and Redhat documentation). In this case the server runs at run level 2,3 so httpd will start once the server reaches those run levels. Those running graphical (non headless) systems may wish to set it so httpd also runs at the run level required by these systems.
# chkconfig --level 23 httpd on # chkconfig --list
You may wish to decide on a log rotation and retention policy. The default Redhat install will result in log file that are rotated weekly and kept for a month. This might not be ideal if you want to later looks at stats. In version 1.3 Shibboleth tries as much as possible to use it's own log files however the web server logs may be useful especially for looking at errors due to probelms with ssl connections.
It is necessary to generate proper signed certificate and key pair in order to work with Pubcookie. This needs to be signed by a trusted Certificate Authority as, in the secure negotiation when generating a key pair, Pubcookie checks the signing chain to make sure that the requesting server is valid.
$ openssl genrsa -out shib.example.edu.key 1024 $ openssl req -new -key shib.example.edu.key -out shib.example.edu.key.csr
You should then send the csr file to your Certificate Authority (Thawte, Verisign or similar) so that they can give you a fully signed certificate for use.
For testing you can generate a temporary self signed certificate until you get the fully signed one back from your Certificate Authority:
$ openssl x509 -req -days 30 -in shib.example.edu.csr -signkey shib.example.edu.key -out shib.example.edu.crt
This certificate should be good enough for some light testing but you will have to wait until you get the signed one back in order to be able to use Pubcookie.
There is a Makefile at /etc/httpd/conf which will allow you to generate certificates and key pairs however I prefer to do it by hand as at least then I know what I have done.
As mentioned previously this guide assumes you have already setup a Pubcookie login server elsewhere. If not look at the companion guide 'Installing Pubcookie on Redhat AS 3.0 and authenticating against Windows Active Directory', accessible at http://iamsect.ncl.ac.uk/. It is not strictly necessary to use Pubcookie, however it is this guide's preferred choice of login provider. It is possible to use other techniques to allow people to login, mod_auth_ldap, Yale's CAS or even simple htpasswd files will all work. The important thing is that you have a mechanism for getting someones username into the REMOTE_USER server variable in the Apache httpd server. This is the recommended way of propagating authentication in Apache, so most of the modules should do this.
In order to get login you must install the Pubcookie authentication module. This is easily done using the steps below:
$ mkdir /usr/local/pubcookie $ cd /usr/local/pubcookie $ wget http://www.pubcookie.org/downloads/pubcookie-3.1.1.tar.gz $ tar -xzvf pubcookie-3.1.1.tar.gz $ cd pubcookie-3.1.1/ $ ./configure --prefix=/usr/local/pubcookie \ --enable-apache \ --with-apxs=/usr/sbin/apxs $ make # make install
To confirm the module has installed:
ls -l /etc/httpd/modules
it should list mod_pubcookie.so as having been recently created. You will need to edit your /etc/httpd/conf.d/ssl.conf and /etc/httpd/conf/httpd.conf so that the module is loaded and configured properly.
Firstly edit /etc/httpd/conf.d/ssl.conf and where it says LoadModule ssl_module modules/mod_ssl.so append LoadModule pubcookie_module modules/mod_pubcookie.so so that it should read:
LoadModule ssl_module modules/mod_ssl.so LoadModule pubcookie_module modules/mod_pubcookie.so
You will also need to configure a virtual host block to serve secure pages:
<VirtualHost _default_:443> DocumentRoot "/var/www/html" ServerAdmin webmaster@example.edu ServerName shib.example.edu:443 # Use separate log files: ErrorLog logs/ssl_error_log TransferLog logs/ssl_access_log # SSL Engine Switch: # Enable/Disable SSL for this virtual host. SSLEngine on PubcookieAuthTypeNames EGNetID PubcookieGrantingCertFile /usr/local/pubcookie/keys/pubcookie_granting.cert PubcookieSessionKeyFile /etc/httpd/conf/ssl.key/shib.example.edu.key PubcookieSessionCertFile /etc/httpd/conf/ssl.crt/shib.example.edu.crt.signed PubcookieLogin https://shib.example.edu/cgi-bin/index.cgi PubcookieDomain .example.edu PubcookieKeyDir /usr/local/pubcookie/keys/ ## Disable inactivity timeout by default to not timeout <Directory "/var/www/html"> PubcookieInactiveExpire -1 </Directory> <Directory "/var/www/html/test"> AuthType EGNetID require valid-user </Directory> </VirtualHost>
It is also necessary to edit /etc/httpd/conf/httpd.conf so that it contains the lines below. I add them just before the virtual hosts block. I'm not sure why it is necessary to duplicate these line in the httpd.conf, I would have thought them being in ssl.conf would be enough, however if PubcookieAuthTypeNames is not set here the server will fail to start, issuing a complaint that PubcookieAuthTypeNames is not set:
PubcookieAuthTypeNames EGNetID PubcookieGrantingCertFile /usr/local/pubcookie/keys/pubcookie_granting.cert PubcookieSessionKeyFile /etc/httpd/conf/ssl.key/shib.example.edu.key PubcookieSessionCertFile /etc/httpd/conf/ssl.crt/shib.example.edu.signed PubcookieLogin https://weblogin.example.edu/cgi-bin/index.cgi PubcookieDomain .example.edu PubcookieKeyDir /usr/local/pubcookie/keys/
If you now make a directory called test at /var/www/html/test
$ mkdir /var/www/html/test
and place a suitable index.html file into it (one saying "hello" will do). This can be used later for testing that the Pubcookie module is working.
To recap, the installation involves installation of Apache and the Pubcookie module, allowing communication over required ports (see firewall section above), setup of NTP and editing the Pubcookie config file. Make changes to the Apache config as described above. This should result in a working Pubcookie application server. The only difference is that you need to transfer the pubcookie_granting.cert file to the application server (default location is /usr/local/pubcookie/keys/pubcookie_granting.cert) vi sftp or whatever mechanism you are comfortable with. Then tell the keyserver on the login server to accept connections from this application server . On the login server:
$ cd/usr/local/pubcookie $ ./keyclient -P shib.example.edu
You may also need to add shib.example.edu to the appropriate section of the hosts.allow file as detailed in the previous document. To briefly recap here it would be something like:
keyserver: shib.example.edu
Then request a key from the application server:
$ cd/usr/local/pubcookie $ ./keyclient make_crypt_keyfile: hello make_crypt_keyfile: goodbye Set crypt key for shib.example.edu
If this fails look through the logs in /var/log/secure
and /var/log/messages
on both machines to get
error messages. If successful this should result in a fully
working application server.
It should be possible to set up the appserver and login server to distribute the pubcookie_granting cert automatically however attempts to do this failed. Similarly it should not be necessary to use the permit (-P) option on the login server as the keyserver_client_list should inform it which server can request keys. However in practice this step proved to be necessary
As described above in 'Remote File Systems (e.g. NFS)', Pubcookie directories should not be mounted on NFS. This is due to the security model built into the Pubcookie design: if a cracker takes control of an application server, they haven't automatically compromised the other application servers, or the authentication server. However if they all shared all the keys and certificates compromising one application server would lead to communication with all being untrustworthy.
Restart the server to make sure that changes are recognised:
# service httpd restart
then browse to the test directory using a web browser e.g. go to https://shib.example.edu/test/index.html
You should be redirected to the login server you setup previously where you can login, on successful login you should be redirected back to the index.html page e.g. https://shib.example.edu/test/index.html. If there are problems check the Apache error and access logs and check in /var/log/secure and /var/log/messages for potential causes. It may be necessary to do this both on the application server and the login server. If you were successful you now have a means of getting a user's login name into the REMOTE_USER server variable and can start thinking about getting Shibboleth working.
Download from http://java.sun.com/products/archive/ the Java2 SDK version 1.4.2_04 (j2sdk-1_4_2_04):
there where bugs reported in shibboleth 1.2 and j2sdk-1_4_2_05, i'm unsure if this has been rectified in shibboleth 1.3. It should be possible to use more modern versions of the Java JDK with shibboleth 1.3 as no serious problems have been reported on the mailing lists however the author can't confirm this as we haven't tested.
$ sh ./j2sdk-1_4_2_04-linux-i586-rpm.bin $ rm ./j2sdk-1_4_2_04-linux-i586-rpm.bin # rpm -i j2sdk-1_4_2_04-linux-i586.rpm
This should have installed Java at /usr/java/j2sdk1.4.2_04. You now need to setup the JAVA_HOME environment variable so that it points to Java and Java based applications know where to find the Java commands. You will probably have your own favourite way of doing this, for those new to this the two scripts below would make sure bash and c shell have JAVA_HOME set to the jdk you installed. If you later decide to upgrade the jdk you should change the script to reflect the new location.
Edit /etc/profile.d/java.csh so it contains:
if ( "${path}" !~ */usr/java/j2sdk1.4.2_04/bin* ) then set path = ( /usr/java/j2sdk1.4.2_04 $path ) endif setenv JAVA_HOME /usr/java/j2sdk1.4.2_04
Edit /etc/profile.d/java.sh so it contains:
if ! echo ${PATH} | grep -q /usr/java/j2sdk1.4.2_04/bin ; then PATH=/usr/java/j2sdk1.4.2_04/bin:${PATH} fi JAVA_HOME="/usr/java/j2sdk1.4.2_04" export JAVA_HOME
To test whether this has worked logoff and log back in (so that your shell picks up the changes) and then use the 'which' command:
$ which java /usr/java/j2dsk1.4.2_04/bin/java $ which javac /usr/java/j2dsk1.4.2_04/bin/javac
If this hasn't worked, either the scripts that set Java into your path and environment variables have failed or the Java install has failed. You should check your installation.
You need to grab a version of Apache Tomcat. This is available from Apache software mirrors, a list of which is available at http://www.apache.org/dyn/closer.cgi.
We used http://apache.mirror.positive-internet.com/, but the URL above will suggest one to you. Substitute your particular mirror in the commands below.
Tomcat is kept within the directory jakarta/tomcat-5/. At the time of writing version 5.0.27 was available and so we used that. However Apache do not keep older versions of software available for long so you may not be able to find this version. 5.0.28 is reported to work too. Substitute the version number below for one that is available:
$ mkdir /usr/local/tomcat $ cd /usr/local/tomcat $ wget http://apache.mirror.positive-internet.com/jakarta/tomcat-5/v5.0.27/bin/jakarta-tomcat-5.0.27.tar.gz $ tar -zxf jakarta-tomcat-5.0.27.tar.gz $ tar -zxf Fedora-Core-1-i386.tar.gz
In order to make upgrading easy I create a symlink from /usr/local/tomcat/current to the version of Tomcat I am running. This makes upgrading easier and more importantly makes backing out of a bad upgrade easier.
$ ln -s jakarta-tomcat-5.0.27 current $ cd current/bin
For the sake of tidiness and so files are easy to see I remove some of the Windows specific control files (if you envisage moving to Windows then you may wish to leave them)
$ rm *.bat
You should now test that Tomcat can run:
$ cd /usr/local/tomcat/current/bin $ ./startup.sh
To verify it is running, you can browse to http://shib.example.edu:8080/. You should get a Tomcat page that tells you it has installed and lists a couple of test servlets and JSPs.
Alternatively you could execute the command:
$ ps -ef | grep tomcat
Which should list a process with a command containing '/usr/java/j2sdk1.4.2_04/bin/java -Djava.endorsed.dirs=/opt/tomcat/current/common/endorsed ...'
If this doesn't occur look through the Tomcat logs at /usr/local/tomcat/current/logs to find possible reasons.
If the test is successful shutdown the server using the command:
$ ./shutdown.sh
you can install on tomcat 5.5 but you will probably use java 1.5 ( branded as 5.0 i think) as tomcat 5.5 is designed for that platform
Now that you have a working Tomcat and Apache install you need to install the mod_jk2 connector so that Apache can pass the authenticated user name from Pubcookie over to Tomcat so that is can be used by Shibboleth later on. To do this you must download the appropriate mod_jk2 connector binary and install it. Good sources are rpmfind.net or http://www.jpackage.org/, jpackage will probabably have redhat AS specific rpms, select which one you are confortable with and ddownload and install the rpm e.g. :
$ wget \ ftp://fr2.rpmfind.net/linux/fedora/core/2/i386/os/Fedora/RPMS/mod_jk2-4.1.27-13.i386.rpm # rpm -i mod_jk2-4.1.27-13.i386.rpm
If you do not trust rpmfind.net or jpackage to provide safe binaries, you can obtain the source code to mod_jk2 from http://jakarta.apache.org/site/sourceindex.cgi#tomcat-connectors , verify the source and build it yourself.
To confirm it has installed you should use rpm's ability to query a package, which should print out the location of files from the RPM on the filesystem:
$ rpm -ql mod_jk2 /etc/httpd/conf.d/jk2.conf /etc/httpd/conf/workers2.properties /usr/lib/httpd/modules/mod_jk2.so /usr/share/doc/mod_jk2-4.1.27 /usr/share/doc/mod_jk2-4.1.27/CHANGES.html /usr/share/doc/mod_jk2-4.1.27/CHANGES.txt /usr/share/doc/mod_jk2-4.1.27/README.txt /usr/share/doc/mod_jk2-4.1.27/STATUS.txt
Because the jk2.conf file is in the conf.d directory it will now be included by Apache upon restart, this will load the mod_jk2.so module into Apache. Since jk2.conf also references the workers2.properties file it to will also be recognised by Apache after a restart.
It is now a good idea to test the mod_jk connector is working.
Replace the file /etc/httpd/conf/workers2.properties by one containing the following text:
[shm] info=Scoreboard. Required for reconfiguration and status with multiprocess servers. file=anon # Defines a load balancer named lb. Use even if you only have one machine. [lb:lb] # Example socket channel, override port and host. [channel.socket:localhost:8009] port=8009 host=127.0.0.1 # define the worker [ajp13:localhost:8009] channel=channel.socket:localhost:8009 group=lb # Map the Tomcat examples webapp to the Web server uri space [uri:/jsp-examples/*] group=lb [uri:/shibboleth/*] worker=ajp13:localhost:8009 group=lb [status:] info=Status worker, displays runtime information [uri:/jkstatus/*] info=The Tomcat /jkstatus handler group=status:
To summarise this rather dense configuration: this file tells the mod_jk2 connector to create a socket that listens on port 8009 on local host, it then assigns that socket to a mod_jk worker and adds that worker to a group called lb (in this case it is a group of 1 but in other configs you can have multiple workers in a group). The group lb will then be used take any requests to /jsp-examples or /shibboleth and redirect them to Tomcat.
Make sure that both Tomcat and httpd have been restarted, you should then try browsing to http://shib.example.edu/jsp-examples/, this should get you the same page as browsing directly to Tomcat http://shib.example.edu:8080/jsp-examples/. If this works then you have successfully used the mod_jk2 connector to mount Tomcat served webapps in Apache httpd. The entry in the workers2.properties file for Shibboleth will do nothing at this point, however it will be used later on in this install guide.
Stop Tomcat and edit the /usr/local/tomcat/current/conf/jk2.properties file so that it contains the line:
request.tomcatAuthentication=false
This will force Tomcat to take its authentication from httpd and will allow you to pass the username Pubcookie stores in REMOTE_USER into Shibboleth when it is configured.
Now that you have a working httpd server which can authenticate users and you can pass that authentication to Tomcat you are now in a position to deploy Shibboleth.
First it is necessary to download the Shibboleth origin (identity provider) install:
$ cd /opt $ wget http://shibboleth.internet2.edu/downloads/shibboleth-idp-1.3c.tar.gz $ tar -zxvf shibboleth-idp-1.3c.tar.gz
next you need to build and compile shibboleth using the java tool ant. Ant is a java program a bit like make, it's not really important to know what it is or how it works just that in installs shibboleth. Ant relies on having your JAVA_HOME environment variable set properly so it may complain if you havne't done that properly (this gude has already told you how)
cd shibboleth-idp-1.3c-install/ ./ant
The build script will ask a series of questions about what and where to install The screen input blow will get you a working install
Do you want to install the Shibboleth Identity Provider? [Y,n] Y What name do you want to use for the Identity Provider web application? [default: shibboleth-idp] shibboleth-idp Deploying the java web application. Do you want to install it directly onto the filesystem or use the tomcat manager application? 1) filesystem (default) 2) manager 1 Select a home directory for the Shibboleth Identity Provider [default: /usr/local/shibboleth-idp] /usr/local/shibboleth-idp Enter the tomcat home directory [default: /usr/local/tomcat] /usr/local/tomcat/current/
It is also necessary to copy several jar files into an endorsed directory. The reason for this is that the Java you installed earlier comes with XML tools that are too old to work with Shibboleth so you have to override them by placing newer ones in Tomcat's endorsed directory:
$ rm /usr/local/tomcat/current/common/endorsed/xercesImpl.jar $ rm /usr/local/tomcat/current/common/endorsed/xml-apis.jar $ cp /opt/shibboleth-idp-1.3c-install/endorsed/*.jar /usr/local/tomcat/current/common/endorsed
Restart Tomcat and it should automatically expand the shibboleth.war file deployed by the install script above to /usr/local/tomcat/current/webapps/shibboleth/:
$ cd /usr/local/tomcat/current/bin $ ./shutdown.sh $ ./startup.sh
In order to overcome a bug in Apache httpd 2.0 it is necessary to mount the Attribute Authority on a separate virtual host from the rest of the Shibboleth install. Edit your /etc/httpd/conf.d/ssl.conf file so that it has entries something like the one below. The important thing is to make sure that the <Location "/shibboleth/HS"> is there and protected by Pubcookie so that people have to login to access the handle service. It is also important that the <Location "/shibboleth/AA"> is in a separate virtual host to overcome the Apache bug. The easiest way of doing this is to stick a virtual host on the port 8443, that way you can use the same certificates (SSL certs just verify the server name e.g. shib.example.edu, they don't "care" about which port is being used) to do this you can edit the /etc/httpd/conf.d/ssl.conf file so it looks something like this:
<VirtualHost _default_:443> DocumentRoot "/var/www/html" ServerAdmin webmaster@example.edu ServerName shib.example.edu:443 ErrorLog logs/ssl_error_log TransferLog logs/ssl_access_log SSLEngine on PubcookieAuthTypeNames EGNetID PubcookieGrantingCertFile /usr/local/pubcookie/keys/pubcookie_granting.cert PubcookieSessionKeyFile /etc/httpd/conf/ssl.key/shib.example.edu.key PubcookieSessionCertFile /etc/httpd/conf/ssl.crt/shib.example.edu.crt.signed PubcookieLogin https://shib.example.edu/cgi-bin/index.cgi PubcookieDomain .example.edu PubcookieKeyDir /usr/local/pubcookie/keys <Directory "/var/www/html"> PubcookieInactiveExpire -1 </Directory> <Directory "/var/www/html/test/"> AuthType EGNetID require valid-user </Directory> <Location "/shibboleth/HS"> AuthType EGNetID require valid-user </Location> SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP SSLCertificateFile /etc/httpd/conf/ssl.crt/shib.example.edu.crt.signed SSLCertificateKeyFile /etc/httpd/conf/ssl.key/shib.example.edu.key SSLCACertificateFile /usr/share/ssl/certs/ca-bundle.crt SetEnvIf User-Agent ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 CustomLog logs/ssl_request_log \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" </VirtualHost> <VirtualHost _default_:8443> LogLevel info ErrorLog /usr/local/shibboleth-idp/logs/AAssl_error_log TransferLog /usr/local/shibboleth-idp/logs/AAssl_access_log SSLEngine on SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP # Server Certificate: SSLCertificateFile /etc/httpd/conf/ssl.crt/shib.example.edu.signed SSLCertificateKeyFile /etc/httpd/conf/ssl.key/shib.example.edu.key SSLCACertificateFile /usr/share/ssl/certs/ca-bundle.crt SSLVerifyClient optional SSLOptions +OptRenegotiate SSLOptions +StdEnvVars +ExportCertData <Location /shibboleth/AA> SSLVerifyClient optional SSLOptions +OptRenegotiate SSLOptions +StdEnvVars +ExportCertData </Location> SetEnvIf User-Agent ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 CustomLog logs/AAssl_request_log \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" </VirtualHost>
After the line:
Listen 0.0.0.0:443
Insert the line:
Listen 0.0.0.0:8443
To summarise, the above file configures httpd so that Pubcookie is configured and then protects the Shibboleth handle service "/shibboleth/HS" by making sure users have to be logged in via Pubcookie to access it. It then creates a separate virtual host on port 8443 and places the Shibboleth attribute authority on it. The virtual hosting of this on a separate virtual host is solely there to work around a known Apache httpd SSL bug.
Shibboleth 1.3 has made some changes to the default location of configuration files. In 1.2 most of the files resided in a directory structure in the WEB-INF directory of the shibboleth webapplication. In 1.3 config files logs and some tools now reside in the default location of /usr/local/shibboleth-idp the main config file has changed names from origin.xml to idp.xml and is located at /usr/local/shibboleth-idp/etc
It is necessary to edit the /usr/local/tomcat/current/webapps/shibboleth/WEB-INF/classes/conf/origin.xml file to configure Shibboleth to suitable values for your origin. Below is an example configuration file:
<?xml version="1.0" encoding="UTF-8"?> <ShibbolethOriginConfig xmlns="urn:mace:shibboleth:origin:1.0" xmlns:cred="urn:mace:shibboleth:credentials:1.0" xmlns:name="urn:mace:shibboleth:namemapper:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mace:shibboleth:origin:1.0 origin.xsd" AAUrl="https://shib.example.edu:8443/shibboleth/AA" resolverConfig="file:/usr/local/shibboleth-idp/etc/resolver.xml" defaultRelyingParty="urn:mace:inqueue" providerId="urn:mace:inqueue:example.edu"> <!-- You'll need to get a test credential from an InQueue CA --> <RelyingParty name="urn:mace:inqueue" signingCredential="inqueue_cred"> <HSNameFormat nameMapping="shm"/> </RelyingParty> <ReleasePolicyEngine> <ArpRepository implementation="edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository"> <Path>/conf/arps/</Path> </ArpRepository> </ReleasePolicyEngine> <Logging> <ErrorLog level="DEBUG" location="file:///tmp/shib-error.log" /> <TransactionLog location="file:///tmp/shib-access.log" /> </Logging> <NameMapping xmlns="urn:mace:shibboleth:namemapper:1.0" id="shm" format="urn:mace:shibboleth:1.0:nameIdentifier" type="SharedMemoryShibHandle" handleTTL="1800"/> <Credentials xmlns="urn:mace:shibboleth:credentials:1.0"> <FileResolver Id="foo"> <Key format="PEM"> <Path>file:///etc/httpd/conf/ssl.key/shib.example.edu.key</Path> </Key> <Certificate format="PEM"> <Path>file:///etc/httpd/conf/ssl.crt/shib.example.edu.crt.signed</Path> </Certificate> </FileResolver> <FileResolver Id="inqueue_cred"> <Key format="PEM"> <Path>file:///etc/httpd/conf/ssl.key/shib.example.edu.key</Path> </Key> <Certificate format="PEM"> <Path>file:///etc/httpd/conf/ssl.crt/shib.example.edu.crt.signed</Path> </Certificate> </FileResolver> </Credentials> <FederationProvider type="edu.internet2.middleware.shibboleth.metadata.provider.XMLMetadataLoadWrapper" uri="/conf/sites.xml"/> </ShibbolethOriginConfig>
It is important to get AAUrl to point at the AA on your server remembering that it is on port 8443 e.g. AAUrl="https://shib.example.edu:8443/shibboleth/AA. Also make the providerId reflect what is required for your setup e.g. providerId="urn:mace:inqueue:example.edu". It is important that the File resolver element is set for the inqueue_cred as since it is referenced by the signingCredentials attribute of the RelyParty element shibboleth won't start without it. Also set the defaultRelyingParty to the InQueue federation. The Logging element has been configured to debug and will log to the /tmp directory so check there when things don't work.
It is also necessary to edit the resolver.xml file /usr/local/shibboleth-idp/etc/resolver.xml so that your AA knows how to pickup attributes from their stores, in this case we are going to add the simplest form where the AA will just echo no attributes. This is enough to get working with the test page for InQueue. At a later time it will be necessary to edit this so that actual attributes are fetched by the AA. The smart scope of the attributes should also be set as the domain name of the institute e.g. example.edu
<AttributeResolver xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mace:shibboleth:resolver:1.0" xsi:schemaLocation="urn:mace:shibboleth:resolver:1.0 shibboleth-resolver-1.0.xsd"> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonEntitlement"> <DataConnectorDependency requires="echo"/> </SimpleAttributeDefinition> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonAffiliation"> <DataConnectorDependency requires="echo"/> </SimpleAttributeDefinition> <!-- To use these attributes, you should change the smartScope value to match your site's domain name. --> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" smartScope="example.edu"> <AttributeDependency requires="urn:mace:dir:attribute-def:eduPersonAffiliation"/> </SimpleAttributeDefinition> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonPrincipalName" smartScope="example.edu"> <DataConnectorDependency requires="echo"/> </SimpleAttributeDefinition> <CustomDataConnector id="echo" class="edu.internet2.middleware.shibboleth.aa.attrresolv.provider.SampleConnector"/> </AttributeResolver>
Normally you would now edit the attribute release policy files in the arps.site.xml in the directory /usr/local/tomcat/current/webapps/shibboleth/WEB-INF/classes/conf/arps/ in a real live install. However the attribute release policy that comes with Shibboleth are good enough for a test install. In our current case there are no attributes to release. In a real deployment you would need to edit this file to get a sensible policy for you institution.
It is also necessary to setup you attribute release policy (ARP) to release the attribute you have just configured to service providers. It is impossible to write a comprehensive guide to this as it is very much dependant on an institutes policies and what attribute are going to be useful. For testing it is possible to write a configuration that releases your attributes to any service provider. However you should decide on your own policy and read the documentataion on the shibboleth site as to how to implement it. A specimen overly permissive release policy is listed below, it's alright for testing but should not be used on a live system.
<?xml version="1.0" encoding="UTF-8"?> <AttributeReleasePolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" x mlns="urn:mace:shibboleth:arp:1.0" xsi:schemaLocation="urn:mace:shibboleth:arp: 1.0 shibboleth-arp-1.0.xsd" > <Description>Simplest possible ARP.</Description> <Rule> <Target> <AnyTarget/> </Target> <Attribute name="urn:mace:dir:attribute-def:eduPersonAffiliation"> <AnyValue release="permit"/> </Attribute> <Attribute name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation"> <AnyValue release="permit"/> </Attribute> <Attribute name="urn:mace:dir:attribute-def:eduPersonTargetedID"> <AnyValue release="permit"/> </Attribute> <Attribute name="urn:mace:dir:attribute-def:eduPersonPrincipalName"> <AnyValue release="permit"/> </Attribute> <Attribute name="urn:mace:dir:attribute-def:eduPersonScopedEntitlement"> <AnyValue release="permit"/> </Attribute> <Attribute name="urn:mace:dir:attribute-def:eduPersonEntitlement"> <AnyValue release="permit"/> </Attribute> </Rule> </AttributeReleasePolicy>
A guide to the format of arps can be found at http://shibboleth.internet2.edu/guides/idp/infoarps.html and a tool called SHARPE is being developed to allow user control of attribute release see http://mams.melcoe.mq.edu.au/wiki/display/MAMS/Shibboleth+Attribute+Request+Policy+Editor+(ShARPE) for details.
Now you have a technically working Shibboleth install you need to join a federation in order to test it. The American InQueue federation http://inqueue.internet2.edu/ is a good candidate at present. Fill in the form at http://inqueue.internet2.edu/join.html. You should sign up as an Identity Provider.
When filling in the form you will need to know:
The domain name of the Identity Provider site, this will be something like example.edu;
The complete URL for the handle service is e.g. https://shib.example.edu/shibboleth/HS;
The complete URL for the attribute authority , remember this is going to be virtual hosted onto port 8443 e.g.https://shib.example.edu:8443/shibboleth/AA;
The CN or the full subject of the HS's certificate, this should be the name of the server e.g. shib.example.edu;
The short name(s) the WAYF should display for this identity provider is basically this is what users are going to select in a drop down list when the tell the where are you from (WAYF) service which institute they are from so maker it recognisable and in keeping with your brand e..g "The University of Example".
Once you have joined a federation you will have to download the sites.xml. file that they provide, this file tells your Shibboleth install who else is in the federation so that Shibboleth can decide whether to trust them. It may be necessary to wait a day until the federation has updated your details into the file. Fortunately Shibboleth has provided a tool that can be automated by a cron job so that you don't have to manually download every time a new member joins the federation. In order to run the tool use the command below:
cd /usr/local/shibboleth-idp/ ./bin/metadatatool -i http://wayf.internet2.edu/InQueue/IQ-sites.xml \ -k conf/internet2.jks -p shib123 -a sitesigner \ -o /usr/local/tomcat/current/webapps/shibboleth/WEB-INF/classes/conf/sites.xml
This should save the latest federation sites into /usr/local/tomcat/jakarta-tomcat-5.0.27/webapps/shibboleth/WEB-INF/classes/conf/sites.xml. It may be informative to have a look through the file.
Now that you have successfully joined go to https://wayf.internet2.edu/inQueue/sample.jsp since you aren't yet authenticated you should be redirected to a page showing a drop down menu of institutes select you own and you should be redirected to your home pubcookie login, on successful login you should be redirected back to the original https://wayf.internet2.edu/InQueue/sample.jsp page. If you manage to get to the page without it reporting errors then you have a working test install
Shibboleth is a realtively complex system with interoperating component parts. Often it is necessary to look in log files to work out configuration errors. Logging of the shibboleth processes is configure using the idp.xml file in /usr/local/shibboleth-idp/etc the lines below being the configuration.
<Logging> <ErrorLog level="DEBUG" location="file:/usr/local/shibboleth-idp/logs/shiberror.log" /> <TransactionLog level="DEBUG" location="file:/usr/local/shibboleth-idp/logs/shibaccess.log" /> </Logging>
There is more to a working shibboleth configuration than just the shibboleth process however, sometimes things appear in the apache logs that may be relevant. The section in the apache ssl config file at /etc/httpd/conf.d/ssl.conf
<VirtualHost _default_:8443> LogLevel info ErrorLog /usr/local/shibboleth-idp/logs/AA_ssl_error_log TransferLog /usr/local/shibboleth-idp/logs/AA_ssl_access_log
This will tell the virtual server that handle requests to the attribute authority section of shibboleth to log any errors to the smae directory as your shibboleth software. In this way most of the relevant log entires will be contained in one directory. The AA_ssl_error_log can be particularly infomative if you are having problems and nothing is appearing in the shibboleth logs. Wrong configuration of your ssl can lead to apache ssl dropping the connections before shibboleth ever gets a chance to deal with it. In a production deployment you may wish to alter logging locations and behavior to suit what your institution does, however in an initial install having the log files in one place can help.
The configuration described aboove using the detault simple file whose use is configured by the line resolverConfig="file:/usr/local/shibboleth-idp/etc/resolver.xml" in idp.xml is reasonable for testing and in many cases may be suitable for your production deployment, if you just don't need to exchange complicated attributes. However many institute will need to use complicated attributes which riside in ldap directories or databases. Shibboleth Attribute Authority does support pulling attributes out of these stores in a basic way. It also supports custom connectors which can be written in java to enable institutes to obtain attributes in bespoke tailored ways using complex logic. Shibboleth comes bundeled with two connector configurations /usr/local/shibboleth-idp/etc/resolver.jdbc.xml and /usr/local/shibboleth-idp/etc/resolver.ldap.xml. The database connector proved to be the best choce for our institute.
in order to use the jdbc connector to connect to databases you need to alter the idp.xml so that the resolver configt line now reads as resolverConfig="file:/usr/local/shibboleth-idp/etc/resolver.jdbc.xml" you can then edit the specimen /usr/local/shibboleth-idp/etc/resolver.jdbc.xml to connect to your databse and get the attribute you need. Below is an example file with example configs illustrating the main features available:
<AttributeResolver xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mace:shibboleth:resolver:1.0" xsi:schemaLocation="urn:mace:shibboleth:resolv er:1.0 shibboleth-resolver-1.0.xsd"> <!-- example of a simple attribute eduPersonPrincipalName which is pulled from a data base notw by default the returned value pair has to have the right name so i have to rename the username AS eduPerson principla name so the resolver knows to use it as this attribute The ? is replaced by what was passed to shibboleth from the REMOTE_USER apache variable populated by whatever login programme you are using, in this case pubcookie. --> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonPrincipalName" smartScope="ncl.ac.uk"> <DataConnectorDependency requires="db1"/> </SimpleAttributeDefinition> <JDBCDataConnector id="db1" dbURL="jdbc:mysql://database.example.edu/attributedatabase?user=someuser&password=somepassword" dbDriver="com.mysql.jdbc.Driver" maxActive="10" maxIdle="5"> <Query>SELECT username AS eduPersonPrincipalName FROM usertable WHERE userid=?</Query> </JDBCDataConnector> <!--end example of a simple attribute eduPersonPrincipalName --> <!-- example of a complex attribute eduPersonTargetedID which is pulled from a data base and then hashed so it appears as a randomised but consistent user identifier that service providers can use to personalise a site, save search terms etc without ever actually knowing who the user is. There is some controversy around eduPersonTargetID and people may not use it --> <PersistentIDAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonTargetedID" scope="ncl.ac.uk" sourceName="eduPersonTargetedID"> <DataConnectorDependency requires="db2"/> <Salt>put some random stuff here</Salt> </PersistentIDAttributeDefinition> <JDBCDataConnector id="db2" dbURL="jdbc:mysql://database.example.edu/attributedatabase?user=someuser&password=somepassword" dbDriver="com.mysql.jdbc.Driver" maxActive="10" maxIdle="5"> <Query>SELECT username AS eduPersonTargetedID FROM usertable WHERE userid=?</Query> </JDBCDataConnector> <!--end example of a complex attribute eduPersonTargetedID --> <!-- example of a complex attribute eduPersonEntitlement which is pulled from a data base with complex logic This shows it is poosible to encapsulate quite complex logic in the SQL query. However it should be noted that this can get ugly and it may be that you need to contamplate coding a custom connector which will enable you to use the logic offerred by java rather than relying on your sql query to do it Note sourceName="sdssentitlement" in the Definition blow means the resolver will look for the result with sdssentitlment as it's column name so you don't have to name the column as the attribute name This is similar to a query we use to identify if a student is a on a medical courses and can therefore access restricted medical content from EMOL (autopsy videos and the like) --> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonEntitlement" sourceName="sdssentitlement"> <DataConnectorDependency requires="db3"/> </SimpleAttributeDefinition <JDBCDataConnector id="db3" dbURL="jdbc:mysql://database.example.edu/attributedatabase?user=someuser&password=somepassword" dbDriver="com.mysql.jdbc.Driver" maxActive="10" maxIdle="5"> <Query>SELECT course_code, CASE course_code WHEN 'A101' THEN 'urn:mace:ac.uk:sdss.ac.uk:entitlement:emol.sdss.ac.uk:restricted' WHEN 'A106' THEN 'urn:mace:ac.uk:sdss.ac.uk:entitlement:emol.sdss.ac.uk:restricted' WHEN 'O106' THEN 'urn:mace:ac.uk:sdss.ac.uk:entitlement:emol.sdss.ac.uk:restricted' WHEN '3019P' THEN 'urn:mace:ac.uk:sdss.ac.uk:entitlement:emol.sdss.ac.uk:restricted' WHEN '3384P' THEN 'urn:mace:ac.uk:sdss.ac.uk:entitlement:emol.sdss.ac.uk:restricted' WHEN '5826P' THEN 'urn:mace:ac.uk:sdss.ac.uk:entitlement:emol.sdss.ac.uk:restricted' ELSE 'none' END AS sdssentitlement FROM coursetable WHERE userid = ? </Query> </JDBCDataConnector> <!--end example of a complex attribute eduPersonEntitlement --> <!-- example of a dual query pulling back several attribute from a data base note these are fake attribute for a fake example which i don't use I don't have a need for this kind of query so i have not tested it. the urn value are made up to and you should look up guides on how to make a proper urn --> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:role" > <DataConnectorDependency requires="db4"/> </SimpleAttributeDefinition> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:group" > <DataConnectorDependency requires="db4"/> </SimpleAttributeDefinition> <JDBCDataConnector id="db4" dbURL="jdbc:mysql://database.example.edu/attributedatabase?user=someuser&password=somepassword" dbDriver="com.mysql.jdbc.Driver" maxActive="10" maxIdle="5"> <Query>SELECT role, groupFROM usertable WHERE userid=?</Query> </JDBCDataConnector> <!--end example of a simple attributes role and group --> <!-- example of an attribute that depends on the value of another. Also demonstarates that some attributes can simply be echoed because they are availabl in shibboleth without querying . --> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" smartScope="ncl.ac.uk"> <AttributeDependency requires="urn:mace:dir:attribute-def:eduPersonAffiliation"/> </SimpleAttributeDefinition> <SimpleAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonAffiliation"> <DataConnectorDependency requires="echo"/> </SimpleAttributeDefinition> <CustomDataConnector id="echo" class="edu.internet2.middleware.shibboleth.aa.attrresolv.provider.SampleConnector"/> </AttributeResolver>
Pubcookie login pages (mainly the login template) in the web app
IdP.jsp IdPError.jsp accessError.html
error pages and explanation on iss site