====== Shibboleth IdP ====== This section is split in two parts -- installation and configuration. Installation itself is trivial, takes minimum time and differences are very simple, for example, entering entity ID, etc. Configuration is, on the other hand, quite complex depending on particular needs such as whether using LDAP or Active Directory, etc. ===== IdP installation ===== Shibboleth IdP is installed by downloading [[https://shibboleth.net/downloads/identity-provider/3.2.1/|source code]], extracting it and running a shell script ''install.sh'' from within the extracted directory. Checking SHA256 fingerprints is highly recommended. # Downloading Shibboleth IdP mkdir -p /opt/src chown -R idp:idp /opt/src su idp cd /opt/src wget https://shibboleth.net/downloads/identity-provider/3.2.1/shibboleth-identity-provider-3.2.1.tar.gz \ https://shibboleth.net/downloads/identity-provider/3.2.1/shibboleth-identity-provider-3.2.1.tar.gz.asc \ https://shibboleth.net/downloads/identity-provider/3.2.1/shibboleth-identity-provider-3.2.1.tar.gz.sha256 # Checking SHA256 fingerprints sha256sum shibboleth-identity-provider-3.2.1.tar.gz && cat shibboleth-identity-provider-3.2.1.tar.gz.sha256 # Checking GPG signature # Importing key 07CEEB8B gpg --keyserver hkp://keys.gnupg.net --search-keys 07CEEB8B # Checking the signature gpg --verify shibboleth-identity-provider-3.2.1.tar.gz.asc # # Run EXIT command to become 'root' user back again # exit Now, with source code downloaded and checked, installation might proceed. # Installing Shibboleth (as user root) cd /opt tar -xzf src/shibboleth-identity-provider-3.2.1.tar.gz cd shibboleth-identity-provider-3.2.1/ ./bin/install.sh After running the installation script: - accept source installation directory - fill in server hostname (might be set correctly by default) - accept entityID (or choosing a different one, for example, the one already existing [never change entityID after choosing one]) - enter organization scope - enter two passwords asked for (''pwgen'' might help) The output of the installation script ''install.sh'' might look like this: $ ./bin/install.sh Source (Distribution) Directory: [/opt/shibboleth-identity-provider-3.2.1] Installation Directory: [/opt/shibboleth-idp] Hostname: [localhost.localdomain] whoami-dev.cesnet.cz SAML EntityID: [https://whoami-dev.cesnet.cz/idp/shibboleth] Attribute Scope: [localdomain] cesnet.cz TLS Private Key Password: Re-enter password: Cookie Encryption Key Password: Re-enter password: Warning: /opt/shibboleth-idp/bin does not exist. Warning: /opt/shibboleth-idp/dist does not exist. Warning: /opt/shibboleth-idp/doc does not exist. Warning: /opt/shibboleth-idp/system does not exist. Warning: /opt/shibboleth-idp/webapp does not exist. Generating Signing Key, CN = whoami-dev.cesnet.cz URI = https://whoami-dev.cesnet.cz/idp/shibboleth ... ...done Creating Encryption Key, CN = whoami-dev.cesnet.cz URI = https://whoami-dev.cesnet.cz/idp/shibboleth ... ...done Creating TLS keystore, CN = whoami-dev.cesnet.cz URI = https://whoami-dev.cesnet.cz/idp/shibboleth ... ...done Creating cookie encryption key files... ...done Rebuilding /opt/shibboleth-idp/war/idp.war ... ...done BUILD SUCCESSFUL Total time: 1 minute 0 seconds It is required to change the ownership of ''/opt/shibboleth-idp/'' and ''/opt/shibboleth-identity-provider-3.*/'' directories to the user ''idp'' belonging to the group ''idp''. # Changing the ownership (as root user) chown -R idp:idp /opt/shibboleth-id* Restart Jetty to load Shibboleth IdP into the web server: # Restarting Jetty /etc/init.d/jetty restart It is time to check Shibboleth IdP. The following test requires Jetty to listen on HTTP, i.e. port 80. Otherwise ''-u'' parameter is mandatory since default value is ''http://localhost/idp''. # Shibboleth IdP status cd /opt/shibboleth-idp/ ./bin/status.sh If everything is set correctly, the following output shall be seen: ### Operating Environment Information operating_system: Linux operating_system_version: 3.16.0-4-amd64 operating_system_architecture: amd64 jdk_version: 1.8.0_91 available_cores: 1 used_memory: 311 MB maximum_memory: 958 MB ### Identity Provider Information idp_version: 3.2.1 start_time: 2016-05-09T15:04:57+02:00 current_time: 2016-05-10T16:53:33+02:00 uptime: 92916009 ms service: shibboleth.LoggingService last successful reload attempt: 2016-05-09T13:03:48Z last reload attempt: 2016-05-09T13:03:48Z service: shibboleth.ReloadableAccessControlService last successful reload attempt: 2016-05-09T13:03:55Z last reload attempt: 2016-05-09T13:03:55Z service: shibboleth.MetadataResolverService last successful reload attempt: 2016-05-09T13:03:53Z last reload attempt: 2016-05-09T13:03:53Z metadata source: ShibbolethMetadata last refresh attempt: 2016-05-10T14:48:57Z last update: 2016-05-10T14:48:57Z service: shibboleth.RelyingPartyResolverService last successful reload attempt: 2016-05-09T13:03:53Z last reload attempt: 2016-05-09T13:03:53Z service: shibboleth.NameIdentifierGenerationService last successful reload attempt: 2016-05-09T13:03:52Z last reload attempt: 2016-05-09T13:03:52Z service: shibboleth.AttributeResolverService last successful reload attempt: 2016-05-09T13:03:50Z last reload attempt: 2016-05-09T13:03:50Z DataConnector myStoredId: has never failed DataConnector myLDAPgroups: has never failed DataConnector staticAttributes: has never failed DataConnector myLDAP: has never failed service: shibboleth.AttributeFilterService last successful reload attempt: 2016-05-09T13:03:50Z last reload attempt: 2016-05-09T13:03:50Z Accessing ''https://HOSTNAME/idp'' is also possible, however, no useful information is displayed compared to ''status.sh'' script. {{:cs:tech:idp:shib-no_service.png|}} ===== IdP configuration ===== Shibboleth IdP configuration might be very complex depending on particular needs and requirements of an organization. Here, just basic configuration is presented, but anyone should be able to modify it to meet any requirements. //The guide is written in a step by step manner. Skipping parts of this guide might easily lead to misconfiguration.// ==== conf/access-control.xml ==== In this configuration file, IP ranges (or better just IP addresses) allowed to access the diagnostic page (''https://HOSTNAME/idp/status'') and other administrative features such as reloading particular configuration (metadata feeds, etc.) are defined. //I recommend to allow just necessary IP addresses such as admin's workstation IP.// # Edit access-control.xml vi /opt/shibboleth-idp/conf/access-control.xml In this example, ''1.2.3.4/32'' IPv4 address and ''2001:1:2:3::4/128'' IPv6 address are chosen. The addresses must be specified with the address mask. p:allowedRanges="#{ {'127.0.0.1/32', '::1/128', '1.2.3.4/32', '2001:1:2:3::4:5/128'} }" Shibboleth IdP configuration (Access Control List) should be reloaded in order to allow access from defined IP addresses. # Reloading ACLs cd /opt/shibboleth-idp ./bin/reload-service.sh -id shibboleth.ReloadableAccessControlService Accessing the diagnostic page (''https://HOSTNAME/idp/status'') from the above defined IP addresses will display status information simlarly to ''status.sh'' shell script run from console earlier. ==== conf/ldap.properties ==== All the information related to LDAP connection are set in ''conf/ldap.properties'' configuration file. # Edit ldap.properties vi /opt/shibboleth-idp/conf/ldap.properties The following options are the most important ones: idp.authn.LDAP.authenticator = bindSearchAuthenticator idp.authn.LDAP.ldapURL = ldaps://ldap1.example.org:636 \ ldaps://ldap2.example.org:636 idp.authn.LDAP.useStartTLS = false idp.authn.LDAP.useSSL = true idp.authn.LDAP.sslConfig = certificateTrust idp.authn.LDAP.trustCertificates = %{idp.home}/credentials/ldap-server.crt idp.authn.LDAP.baseDN = ou=people,dc=example,dc=org idp.authn.LDAP.subtreeSearch = true idp.authn.LDAP.bindDN = uid=shibboleth,ou=users,dc=example,dc=org idp.authn.LDAP.bindDNCredential = nejakeheslo idp.attribute.resolver.LDAP.returnAttributes = givenName,sn,cn,o,schacHomeOrg,eduPersonPrincipalName,uid,mail The first variable ''idp.authn.LDAP.authenticator'' specifies authentication strategy. If set to //bindSearchAuthenticator// Shibboleth will bind to LDAP. Default value is //anonSearchAuthenticator// for anonymous searching. Option ''idp.authn.LDAP.ldapURL'' specifies LDAP server(s) to connect to. In the example above, IdP is set to connect to server ''ldap1.example.org'' and ''ldap2.example.org''. Connection is secured by SSL on the standard port ''636''. //ldapURL comment:// There must not be a slash (/) at the end of the ldapURL such as ''[[ldaps://ldap1.example.org:636/]]''! In that case, Shibboleth will not start and output an error ''java.lang.NumberFormatException: For input string: "636/".'' to its log file. Configuration options ''idp.authn.LDAP.useStartTLS'' and ''idp.authn.LDAP.useSSL'' define SSL usage instead of TLS. The following option ''idp.authn.LDAP.trustCertificates'' contains path to a certificate. Finally, ''idp.authn.LDAP.baseDN'' sets so called "base DN" in an LDAP directory, ''idp.authn.LDAP.bindDN'' and ''idp.authn.LDAP.bindDNCredential'' define username and password used for accessing LDAP directory when asking for users' attributes. ==== conf/metadata-providers.xml ==== Metadata sources are defined in ''conf/metadata-providers.xml'' configuration file. In the following example, a production federation eduID.cz is used. Metadata is downloaded and saved locally. # Editing metadata-providers.xml vi /opt/shibboleth-idp/conf/metadata-providers.xml //Code block stated above (element ) has to be put inside the element in ''metadata-providers.xml'' configuration file otherwise it will not work. A valid XML file has to contain only ONE root element.// Description of individual [[https://wiki.shibboleth.net/confluence/display/IDP30/HTTPMetadataProviders|]] element's attributes follows: * id -- metadata provider identifier (used for logging, etc.) * xsi:type -- defines the type of the plugin used for metadata reading * backingFile -- specifies the file for local metadata cache * metadataURL -- source URL address * [[https://wiki.shibboleth.net/confluence/display/IDP30/MetadataConfiguration#MetadataConfiguration-AttributesAttributes|maxRefreshDelay]] -- upper bound on the next refresh Metadata is valid only for specific time and then it is invalid, which means untrustworthy and not usable. The default reaload interval is set to 4 hours. You can tweak it using [[https://wiki.shibboleth.net/confluence/display/IDP30/MetadataConfiguration#MetadataConfiguration-AttributesAttributes|maxRefreshDelay]] element of [[https://wiki.shibboleth.net/confluence/display/IDP30/MetadataConfiguration|]] as shown above. If federation metadata is not digitally signed '''' is meaningless. However, production federation should definitelly sign metadata and entities within the federation should definitelly validate the signature. To reload federation metadata manually, just run these commands: # Reloading federation metadata cd /opt/shibboleth-idp ./bin/reload-service.sh -id shibboleth.MetadataResolverService In the metadata directory (''/opt/shibboleth-idp/metadata/'') a cached federation metadata should be available: # Listing downloaded metadata ls -1 metadata/ # Downloaded metadata eduidcz.xml idp-metadata.xml ==== conf/attribute-resolver.xml ==== Users' attributes will be obtained from an LDAP server. As a basic for such configuration it is wise to take an take advantage of the prepared configuration file ''attribute-resolver-ldap.xml'' which contains an LDAP connector. The original file ''attribute-resolver.xml'' can be safely overwritten as it will not be needed anymore. # Preparing attribute-resolver.xml cd /opt/shibboleth-idp/conf cp attribute-resolver-ldap.xml attribute-resolver.xml vi attribute-resolver.xml Following attributes are user-specific and are to be obtained from an LDAP server. There is no need to specify "scope" for ''eduPersonPrincipalName'' since it is loaded from ''idp.properties'' configuration file. The scope is defined during Shibboleth IdP installation ''o'' (organization name) and ''schacHomeOrg'' attributes are so called static. That means they are the same for every single user. It does not make sense to store them in an LDAP, but to have it defined statically. Attributes received from an LDAP server employs ''myLDAP'' connector. All the information for the LDAP have been already set in the configuration file ''conf/ldap.properties''. Static attributes are obtained from static data connector: EXAMPLE, Ltd. example.org ==== conf/attribute-filter.xml ==== After defining attributes it is needed to specify which ones will be released to service providers. This is defined in ''conf/attribute-filter.xml'' configuration file. # Editing attribute-filter.xml vi /opt/shibboleth-idp/conf/attribute-filter.xml There are three different policies. One can release attributes to: * any service * a group of services (''groupID'', for example to a federation) * a specific service (''entityID'') The following code releases ''givenName'', ''sn'', ''cn'' and ''o'' attributes for any service available in the federation. The following example releases ''givenName'', ''sn'', ''cn'', ''o'' and ''schacHomeOrg'' to a group of services identified as ''https://example.org/metadata''. The last example releases attributes to a specific service identified by ''https://www.myservice.org'' entitiyID. The code releases ''givenName'', ''sn'', ''cn'', ''o'', ''schacHomeOrg'', ''eduPersonPrincipalName'', ''uid'' and ''mail'', so every single attribute we have defined earlier. ==== metadata/idp-metadata.xml ==== Identity Provider's metadata (''metadata/idp-metadata.xml'') contains information about "endpoints" (where to connect for authentization, etc.), however, it should always also include some non-technical/administration information such as '''' element inside '''' element as follows: # Editing idp-metadata.xml vi /opt/shibboleth-idp/metadata/idp-metadata.xml example.org ORGANIZATION ORGANIZACE Identity Provider for ORGANIZATION employees. Identity Provider pro zaměstnance ORGANIZACE. http://www.example.org/en/ http://www.example.org/cs/ https://img.example.org/logo-200.gif https://img.example.org/logo-400.gif https://img.example.org/logo-800.gif There should also be specified the organization's name in '''' element within '''' element: Organization Organizace ORGANIZATION ORGANIZACE http://www.example.org/en/ http://www.example.org/cs/ The last thing is a technical contact person, including e-mail address, specified within '''' element. It might put right after '''' element: GivenName Surname mailto:firtname.lastname@example.org Complete metadata of CESNET's IdP is available at https://whoami.cesnet.cz/idp/shibboleth address. ==== Login page customisation ==== The default login page looks similarly to the following screenshot. {{:cs:tech:idp:shib-loginpage-default.png|Default login page appearance.}} It is possible to tweak the appearance. All the modifications are made in ''/opt/shibboleth-idp/edit-webapp/'' directory. This directory is not overwritten after upgrading Shibboleth IdP installation, so there is no need to be affraid of loosing modifications. When done with tweaking the web appearance, a new ''idp.war'' file has to be build and Jetty restarted using the following commands: # Rebuilding idp.war cd /opt/shibboleth-idp ./bin/build.sh # Restarting Jetty service jetty restart # Rebuilding idp.war and restarting Jetty terminal output Installation Directory: [/opt/shibboleth-idp] Rebuilding /opt/shibboleth-idp/war/idp.war ... ...done BUILD SUCCESSFUL Total time: 3 seconds Stopping Jetty: OK Starting Jetty: . . . . . . . . . . . . OK Tue Aug 11 13:15:19 CEST 2015 ===== Adding metadata to a federation ===== To be a part of a federation, IdP's metadata has to be added into a federation metadata. Depending on the federation, metadata is registered using web-based management system or sent to the federation operator via email. ===== Startup and testing ===== Now, everything should be set properly and ready to test. If Jetty is not started yet, now it is the right time to run it: # Starting Jetty service jetty start If Jetty is already running, but any configuration changes have been made like customizing login web page, restart should take place now. Restarting Jetty also verifies that everything works correctly and starts as expected after operating system reboot: # Restarting Jetty service jetty restart Everything should be set correctly and run smoothly, thus it is time to test it out using any service within the federation the IdP is now a part of.