Child pages
  • Installing a Shibboleth 3.x IdP

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • On RHEL/CentOS 7 with firewalld (and with a single default zone) run:

    Code Block
    languagebash
    firewall-cmd --add-service=https
    firewall-cmd --add-port=8443/tcp
    firewall-cmd --permanent --add-service=https
    firewall-cmd --permanent --add-port=8443/tcp


  • On systems using plain iptables (more likely on RHEL/CentOS 6), edit /etc/sysconfig/iptables and add rules to permit incoming traffic to ports 443 and 8443; add the following just below the rule for port 22:

    No Format
    -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
    -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8443 -j ACCEPT
    

     


    • And restart iptables:

      No Format
      service iptables restart
      


Note

Please remember that besides the incoming connections discussed here, the IdP also needs outgoing connections to TCP ports 80 and 443, and also to UDP port 514 for Centralized logging (more details below)

Outgoing connections are open in the default configuration of a local RHEL/CentOS firewall, but please make sure the perimeter firewall permits these connections too.

 


Bootstrapping the VM

We assume a standard install of either CentOS or RHEL, version 7. The IdP web application (as of version 3) needs Tomcat at least at version 7 (or the upstream instructions recommend Jetty). Also, the IdP java binaries are compiled in class format 51.0 and need Java7.  However, given that Java7 is being phased out, the IdP works well with Java8, and the compatibility issues (see the Scripted Attributes section below) are easy to resolve, we recommend installing Java8 on platforms where it's available (which does include CentOS/RHEL 7).

...

Note
titleSELinux

RHEL/CentOS distributions (both 6 and 7) come with SELinux.

SELinux improves the security of the system and we recommend leaving SELinux turned on.

Up until late 2017, Tomcat was running in the unconfined context and the IdP web application did not directly benefit from SELinux, but even so, at least Apache interactions were controlled by SELinux.  And the only SELinux-specific step this manual had to cover was permitting the Apache to LDAP communication needed for ECP.

As of late 2017 (RHEL/CentOS 7.4), Tomcat runs in a confined domain.  This has serious impact on operating an IdP - as the IdP web application running inside Tomcat now runs under SELinux restrictions, it now needs all actions explicitly permitted.

We still recommend running with SELinux in enforcing mode.  A new section (Configuring SELinux for Tomcat) further below details the steps needed.  Please follow the instructions carefully - otherwise, the IdP would fail to start.

 


Securing the MySQL server

...

  • Invoke installer

    No Format
    sh ./bin/install.sh
    
    • Answer the following questions:
      • Source (Distribution) Directory: confirm the current directory
      • Installation directory: accept the proposed value of /opt/shibboleth-idp if suitable.
      • Hostname: enter the user-facing hostname of the IdP, typically idp.institution.domain.ac.nz
      • SAML Entity ID: accept the value derived from the hostname, https://idp.institution.domain.ac.nz/idp/shibboleth
      • Attribute Scope: set this to the domain name of your institution ( institution.domain.ac.nz in the above example). The value offered based on the hostname should be already correct, but please check and adjust as needed.
      • Enter the passphrase to protect the generated keystores (back-channel and cookie encryption). It is acceptable to use the phrase "changeit" (as the files are protected by filesystem permissions and the phrase itself is also stored in files on the same filesystem).
        • Note that the installer generates three separate certificates+keypairs for back-channel, signing, and encryption, respectively - and also an encryption key for cookie. Only the back-channel private key is encrypted, the other two private keys will be stored on disk unencrypted.  The passphrase for the cookie encryption key is stored in the generated idp.properties file.  Therefore, there is no need to choose a secure keystore password and instead, it is important to secure access to the system...

         


    • This installs the Shibboleth IdP web application into /opt/shibboleth-idp/war/idp.war
Note
iconfalse
titleAbout re-running the installer

In general, it should not be necessary to re-run the installer.

  • Re-running the installer would overwrite system files under $IDP_HOME/system, but would preserve configuration files under $IDP_HOME/conf
  • But the installer would only be re-run to perform an upgrade - running the installer from a newer version distribution directory would overwrite system files in the installation directory $IDP_HOME, but would preserve the (assuming compatible) configuration files in $IDP_HOME/conf.

To just rebuild the WAR file, run $IDP_HOME/bin/build.sh instead.

 


  • The installer has generated three separate certificates+keypairs for back-channel, signing, and encryption.  The back-channel private key was only stored in a Java keystore, but for Apache, we need it converted to the PEM format.  Run the following command (and when prompted for the keystore passphrase, enter the default passphrase "changeit"):

    Code Block
    openssl pkcs12 -in $IDP_HOME/credentials/idp-backchannel.p12 -out $IDP_HOME/credentials/idp-backchannel.key -nocerts -nodes


...

Note
iconfalse

Historically, the installation process involved deploying XML parser libraries as endorsed libraries in Tomcat. Since IdP 2.4.3, this is no longer needed and the step has been removed.

 


  • Connectors: in /etc/tomcat/server.xml, define a new AJP connector at port 8009.

    Note
    titleNote

    Tomcat7 already has this connector defined, but in an insecure way that would be opening the connector to outside connections as well. Comment the original definition out and instead put this definition in.


    No Format
       <Connector port="8009" address="127.0.0.1"
                  enableLookups="false" redirectPort="443" protocol="AJP/1.3"
                  tomcatAuthentication="false" />
    


  • And comment out the existing http connector defined for port 8080:

    No Format
        <!--
        <Connector port="8080" maxHttpHeaderSize="8192"
                   maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
                   enableLookups="false" redirectPort="8443" acceptCount="100"
                   connectionTimeout="20000" disableUploadTimeout="true" />
        -->
    


...

Note

Note: historically, this guide used to recommend to disable SSL session cache to work around a bug - while the bug was never fully tracked, the current version of OpenSSL/ShibbolethSP/httpd/mod_ssl no longer demonstrate this bug, so for performance reasons, we recommend keep SSL session caching turned on. Also, as the bug was in the back-channel communication which is rarely used with SAML2, even the impact in the unlikely case the bug reoccurs should be quite minimal.

 


  • To make Apache listen at ports 443 and 8443, create /etc/httpd/conf.d/ports.conf (or install from ports.conf)  with

    No Format
    Listen 443
    Listen 8443 https
    


...

Note
iconfalse

Earlier documentation was instructing to modify the generated metadata and fix the scope. This is no longer necessary because:

  • The installer now specifically asks for scope (instead of just guessing it from the hostname), so the generated metadata should contain the correct scope
  • The generated local IdP metadata is no longer used by the IdP directly.

However, the contents of $IDP_HOME/metadata/idp-metadata.xml is served by the IdP at the URL corresponding to the default IdP entityID - https://idp.institution.ac.nz/idp/shibboleth

If this URL is used anywhere to obtain the IdP metadata (we recommend against this practice, as it is insecure and fragile, but this gets used in some bilateral setups), this file will have to be kept up-to-date with the actual IdP metadata.  However, the installer should initially create it with the correct contents.

Multiexcerpt include
nopaneltrue
MultiExcerptNameidp3-load-metadata
nopaneltrue
PageWithExcerptConfiguring a Shibboleth Identity Provider to join the Tuakiri Federation

 

 



Note
iconfalse

Please note that historically (in IdP 2.x), the IdP was  also loading its own metadata.  This is no longer needed and the $IDP_HOME/metadata/idp-metadata.xml file now exists only for informative purposes.

 


Configure the IdP to use secure cookies: by default Shibboleth IdP 3.x uses session cookies not marked as secure - which means the browser would also send them over a plain unencrypted HTTP connection.

...

No Format
idp.cookie.secure = true

 

 



Configure LDAP Authentication

...

Note

IdP 3.4.0 replaces Dependencies of Attribute Definitions and Data Connectors on other Attribute Definitions and Data Connectors with instead declaring them as inputs - and also shifts the sourceAttributeID from the attribute definition into the input specification.  This has strong implications only for very specific edge cases (where multiple dependencies produced attributes of the same name) - and otherwise is a syntactic change only.

The syntactic change is trivial: as per the upstream instructions:

  • replace a Dependency referencing an attributes with an InputAttributeDefinition referencing the same attribute.
  • replace a Dependency referencing a data connector in a definition with a sourceAttributeID with an InputDataConnector referencing the same connector and selecting the attribute from the sourceAttributeID definition:

    • e.g., turn

      Code Block
          <AttributeDefinition id="commonName" xsi:type="Simple" sourceAttributeID="cn">
              <Dependency ref="myLDAP" />


    • into

      Code Block
          <AttributeDefinition id="commonName" xsi:type="Simple">
              <InputDataConnector ref="myLDAP" attributeNames="cn" />


  • replace a Dependency referencing a data connector in a definition with no sourceAttributeID with an InputDataConnector referencing the same connector and selecting all attributes:

    Code Block
    <InputDataConnector ref="myLDAP" allAttributes="true" />


This documentation has already been updated to this new syntax - but existing attribute resolver configuration files will need to be transformed accordingly.  Version 3.4 will work with legacy configuration, but would produce deprecation warnings.  And support for legacy configuration will be removed in V4.

 


Delete existing definitions

...

Note

The arcs-shib-ext module versions 1.5.x and older are only compatible with IdP v2.x - and are not compatible with IdP V3.

The most recent version is 1.9.0 (as of October 2018) and this version is compatible only with IdP 3.4.0.

For IdP 3.2.x and 3.3.x, use version 1.8.4.

Please note that earlier versions (up to and including 1.8.2) break with Tomcat 7.0.66+, so to avoid issues with Tomcat updates (as they appear in the RHEL7 update stream as of January 2017), please update the plugin to the latest version suitable for your IdP version).

Older versions compatible with older 3.x releases are 1.7.x for IdP 3.1.x+ and 1.6.x for IdP 3.0.x

Please see https://github.com/REANNZ/arcs-shibext/releases for up-to-date information.

 


...

  • Add connector definition to attribute-resolver.xml(sharedToken) with the following customizations:
    • idPIdentifier - your IdP entityId
    • sourceAttributeID: combination of attributes that is unique, non-reassignable and if possible persistent - if usernames are not reused at your institution, username is perfectly fine - so the "cn" or "uid" attribute would do
      • Make sure the source attribute is also included as inputs (formerly dependencies).
      • The below example uses sAMAccountName from the myLDAP DataConnector - but it is also possible to use InputAttributeDefinition to reference other existing attribute definitions.
    • If using a MySQL server, enter the database connection details, with the IDP_ADMIN_PASSWORD as defined just above
    • If storing sharedToken in an LDAP server:
      • Omit the DatabaseConnection element from the below snippet

      • Change the values to storeLdap="true" and storeDatabase="false" and

      • Make sure the LDAP connector is listed as an InputDataConnector (formerly Dependency)
      • If storing the sharedToken value in an attribute other than auEduPersonSharedToken, set this name in storedAttributeName.
      • Set the ldapConnectorId attribute to the ID of the connector (this is required to identify it among the dependencies).

        Note

        Please note that when storing the sharedToken values in LDAP, the sharedToken module would be accessing the LDAP server from the connector specified in the dependency - so the same LDAP server as used for retrieving all other attributes, with the same credentials. Therefore, in order for this module to succeed in storing the generated sharedToken values, the account specified in the LDAP connector needs to have the permissions to write into the auEduPersonSharedToken attribute (or the attribute set in storedAttributeName).


    • The connector definition is:

      Code Block
      xml
      xml
          <!-- ==================== auEduPersonSharedToken data connector ================== -->
      
          <DataConnector xsi:type="st:SharedToken" xmlns:st="urn:mace:arcs.org.au:shibboleth:2.0:resolver:dc"
                              id="sharedToken"
                              idpIdentifier="https://idp.institution.domain.ac.nz/idp/shibboleth"
                              sourceAttributeID="sAMAccountName"
                              storeLdap="false"
                              ldapConnectorId="myLDAP"
                              storedAttributeName="auEduPersonSharedToken"
                              storeDatabase="true"
                              salt="SALT-GOES-HERE">
              <InputDataConnector ref="myLDAP" attributeNames="auEduPersonSharedToken sAMAccountName"/>
      
              <st:DatabaseConnection jdbcDriver="com.mysql.jdbc.Driver"
                                  jdbcURL="jdbc:mysql://localhost/idp_db"
                                  jdbcUserName="idp_admin"
                                  jdbcPassword="IDP_ADMIN_PASSWORD"
                                  preferredTestQuery="/* ping */ SELECT 1;"
                                  testConnectionOnCheckout="true"
                                  primaryKeyName="uid"/>
      
          </DataConnector>
      

       

       




  • Note: on the first install, generate a suitable salt value with:

    No Format
     openssl rand -base64 36 
    • On subsequent installs, reuse the same value (stored somewhere carefully)
  • Note also that the SharedToken value depends on the IdP entityID - which could be picked up from the environment, but is better set in the configuration.
  • Database reconnection

    Note

    Earlier versions of this documentation were instructing to adjust the JdbcURL to set the "autoReconnect=true" option and the wait_timeout session variable.

    Version 1.8.2 of arcs-shib-ext, released on August 1st, 2016, introduces settings for configuring connection testing on checkout in the DataSource.  These are now included in the example above - and with these settings in place, it is no longer necessary to set the increased wait_timeout OR the autoReconnect option.


...

Note

Earlier versions of this manual were instructing when performing an upgrade from a 2.x IdP that was using ComputedIdConnector for eduPersonTargetedID (i.e., not storing the values in a database), to first follow the instructions at Configuring an 2.x IdP to use StoredID Connector.

While it is still strongly recommended to store the values in a database, it is no longer deemed necessary to change the configuration of the version 2 IdP, as the version 3 IdP would be producing the same values.

However, if the existing persistent ID values are not stored in a database, it is crucial to use the identical salt value on the old 2.x and the new 3.x IdP.

 


To configure SAML2 Persistent NameID (based on https://wiki.shibboleth.net/confluence/display/IDP30/NameIDGenerationConfiguration):

  • Edit conf/saml-nameid.properties  and set the following properties:
    • idp.persistentId.sourceAttribute: set this to a local attribute that is unique, persistent, and non-reassignable. Typically, the username attribute (cn, uid or sAMAccountName) would be a good choice.  However, if usernames are reused at your institution, you must choose a different attribute (e.g., objectGUID on AD servers works well for this purpose)
    • idp.persistentId.salt: at the first install generate a salt value with the following command (on subsequent installs, reuse the same value!):

      Code Block
      openssl rand -base64 36


    • idp.persistentId.generator = shibboleth.StoredPersistentIdGenerator
      (this selects the StoredPersistentIdGenerator defined in saml-nameid.xml

    • idp.persistentId.encoding = BASE64

      Note

      IdP version 3.3.x introduces a new property, idp.persistentId.encoding, which defaults to BASE32.  While this default has the intention to improve interoperability (with SPs which do not preserve case), it would break transition from a 2.x IdP which did not store the generated values.  If upgrading from a V2 IdP, please change this new property to BASE64 to preserve the same values.


    • idp.persistentId.dataSource = shibboleth.JPAStorageService.DataSource
      (this selects the DataSource bean that will be defined in conf/global.xml when configuring database storage)

      Note

      Please note that conf/saml-nameid.properties also allows to set idp.persistentId.store = PersistentIdStore (and this is what earlier versions of this document recommended).  However, this strategy does not work well with enabling the reverse lookup, so we now recommend to use idp.persistentId.dataSource, for linking StoredPersistentIDGenerator to the database.  With having idp.persistentId.store set as above, it is not necessary to set idp.persistentId.dataSource

      The earlier instructions were also including defining the persistent store bean: also assuming the JPA Storage Service will be configured further below, the instructions were define the PersistentIdStore just as a reference to the JPAStorageService DataSource:

      Code Block
      languagehtml/xml
          <bean id="PersistentIdStore" parent="shibboleth.JDBCPersistentIdStore"
              p:dataSource-ref="shibboleth.JPAStorageService.DataSource"
              p:queryTimeout="PT2S" />



  • Edit conf/saml-nameid.xml and:
    • In the definition of shibboleth.SAML2NameIDGenerators, uncomment the reference to shibboleth.SAML2PersistentGenerator

      Code Block
      languagehtml/xml
          <util:list id="shibboleth.SAML2NameIDGenerators">
      
              <ref bean="shibboleth.SAML2TransientGenerator" />
      
              <!-- Uncommenting this bean requires configuration in saml-nameid.properties. -->
              <ref bean="shibboleth.SAML2PersistentGenerator" />
      
              <!-- ...  -->
      
          </util:list>


    • And within the database pointed to by the JPAStorageService DataSource ( idb_db as per below, and also as possibly created earlier for sharedToken), create the shibpid table with the following DDL (taken from https://wiki.shibboleth.net/confluence/display/IDP30/PersistentNameIDGenerationConfiguration):

      Code Block
      languagesql
      CREATE TABLE shibpid (
          localEntity VARCHAR(255) NOT NULL,
          peerEntity VARCHAR(255) NOT NULL,
          persistentId VARCHAR(50) NOT NULL,
          principalName VARCHAR(50) NOT NULL,
          localId VARCHAR(50) NOT NULL,
          peerProvidedId VARCHAR(50) NULL,
          creationDate TIMESTAMP NOT NULL,
          deactivationDate TIMESTAMP NULL,
          PRIMARY KEY (localEntity, peerEntity, persistentId)
      );


  • Add the source attribute selected above.  The attribute must be configured in Attribute Resolver in order to be visible to the PersistentIDGenerator.
    • If not already defined, define the attribute in conf/attribute-resolver.xml.  If not intending to release this attribute to any SPs, the attribute definition does not need any SAML encoders - so that will also stop the attribute from being included in the outgoing AttributeStament, it would just be accessible to the PersistentIDGenerator.  A sample definition of the uid attribute would be:

      Code Block
      languagehtml/xml
          <AttributeDefinition id="uid" xsi:type="Simple" >
              <InputDataConnector ref="myLDAP" attributeNames="uid" />
          </AttributeDefinition>


      Note
      titleNo longer needed

      Earlier versions of this documentation were also instructing to explicitly release this attribute to make it visible to the PersistentID generator.  This was necessary for older versions of IdPv3, but for 3.2.0 and newer is no longer needed - see the last line in the ComputedID section of the upstream PersistentNameID documentation.

      The original instructions were:

      • Edit conf/attribute-filter.xml and add a rule to release the source Attribute:

        Code Block
        languagehtml/xml
            <!-- release uid to all SPs, so we can calculate Persistent NameID.
                 As we do not use an encoder in that definition, 
                 the attribute will not really be released. -->
            <AttributeFilterPolicy id="uid2all">
                <PolicyRequirementRule xsi:type="ANY" />
        
                <AttributeRule attributeID="uid">
                    <PermitValueRule xsi:type="ANY" />
                </AttributeRule>
            </AttributeFilterPolicy>

         

         



      • If the attribute is not released as per above, the IdP would log a message:

        Code Block
        2015-05-05 14:49:27,360 - INFO [net.shibboleth.idp.saml.nameid.impl.PersistentSAML2NameIDGenerator:218] - Attribute sources [uid] did not produce a usable source identifier



    • See https://issues.shibboleth.net/jira/browse/IDP-714 for further information.
  • To support mapping SAML2 Persistent NameIDs back to username (which is important for some advanced use cases - e.g., an SP making an explicit AttributeQuery about a user or an SP tries to confirm whether a user still exists at the home institution and still has the same privileges), please edit $IDP_HOME/conf/c14n/subject-c14n.xml and uncomment the reference to the c14n/SAML2Persistent bean:

    Code Block
    <ref bean="c14n/SAML2Persistent" />


  • And also, to avoid warnings for deprecated elements, edit $IDP_HOME/conf/c14n/subject-c14n.xml and comment out the c14n/LegacyPrincipalConnector bean:

    Code Block
    <!-- <ref bean="c14n/LegacyPrincipalConnector" /> -->


Expand
titleHistorical eduPersonTargetedID documentation


Note

 For historical purposes, we also include the original documentation on setting up eduPersonTargetedID.  However, as per above, we strongly encourage the migration to SAML2 Persistent NameID.

 


  1. Add the following attribute definition into attribute-resolver.xml (unfortunately, IdPV3 does NOT provide any template definition in the default configuration files):

    Code Block
    languagehtml/xml
        <resolver:AttributeDefinition xsi:type="ad:SAML2NameID" id="eduPersonTargetedID" 
                                      nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" sourceAttributeID="computedID">
            <resolver:Dependency ref="StoredIDConnector" />
            <resolver:DisplayName xml:lang="en">Targeted ID (opaque per-service username)</resolver:DisplayName>
            <resolver:AttributeEncoder xsi:type="enc:SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
            <resolver:AttributeEncoder xsi:type="enc:SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" />
        </resolver:AttributeDefinition>


  2. Add the connector definition.  To use the recommended StoredIDConnector connector, add the following definition:

    Code Block
    languagehtml/xml
        <resolver:DataConnector id="StoredIDConnector" 
                                xsi:type="dc:StoredId" 
                                sourceAttributeID="uid"
                                salt="SALSALSALTTTSALT"
                                generatedAttributeID="computedID">
            <resolver:Dependency ref="myLDAP" />
            <dc:ApplicationManagedConnection
                jdbcDriver="com.mysql.jdbc.Driver"
                jdbcURL="jdbc:mysql://localhost/idp_db?autoReconnect=true&amp;sessionVariables=wait_timeout=31536000"
                jdbcUserName="idp_admin"
                jdbcPassword="IDP_ADMIN_PASSWORD"
            />
        </resolver:DataConnector>


    making the following changes as needed:

    • Adjust the database connection accordingly (the above snippet assumes it would be reusing the idp_db database created for storing SharedToken values - storing the eduPersonTargetedID values in a separate table shibpidin the same database.
      • If choosing a different database, create that database.
      • Create the table shibpid with the following DDL code (coming from https://wiki.shibboleth.net/confluence/display/IDP30/PersistentNameIDGenerationConfiguration , and setting ENGINE to InnoDB to work around key length restrictions):

        Code Block
        languagesql
        CREATE TABLE shibpid (
            localEntity VARCHAR(255) NOT NULL,
            peerEntity VARCHAR(255) NOT NULL,
            persistentId VARCHAR(50) NOT NULL,
            principalName VARCHAR(50) NOT NULL,
            localId VARCHAR(50) NOT NULL,
            peerProvidedId VARCHAR(50) NULL,
            creationDate TIMESTAMP NOT NULL,
            deactivationDate TIMESTAMP NULL,
            PRIMARY KEY (localEntity, peerEntity, persistentId)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


    • If also adding storage support via JPA (see section Database Storage further below), it is possible to reuse the DataSource definition created for JPA instead of having a duplicate database connection definition in the ApplicationManagedConnection inside the StoredIDConnector.

      Code Block
      languagehtml/xml
       <dc:BeanManagedConnection>shibboleth.JPAStorageService.DataSource</dc:BeanManagedConnection>


    • Using just the username attribute (typically cn, uid or sAMAccountName) as the source attribute.
      • Note: the attribute chosen must be unique, persistent, and non-reassignable - if usernames are reused at your institution, you must choose a different attribute (e.g., objectGUID on AD servers works well for this purpose)
    • Using a value of salt generated (only at the first install, to be reused later) with:

      No Format
      openssl rand -base64 36

       


      • Note: if converting from an existing configuration using ComputeId connector, reuse the existing salt values.  The StoredIdConnector is designed to be backwards-compatible and if provided with the same salt, will generate the same values as ComputeId connector.

    • Make sure the id and the generatedAttributeID in the connector definition match the dependency ref and the sourceAttributeID in the attribute definition.
  3. If it is not possible to use the StoredIDConnector, use instead the ComputedId connector:

    Code Block
        <DataConnector xsi:type="ComputedId"
                                id="computedID"
                                generatedAttributeID="computedID"
                                sourceAttributeID="uid"
                                salt="abcef123YOURVALUE">
            <resolver:Dependency ref="myLDAP" />
        </DataConnector>

     


    • Remember to still populate the sourceAttributeID and salt values appropriately (using the same instructions as for StoredIdConnector above)
    • Update the dependency ref in the attribute definition to match the connector id="computedID"

 

 

 




For reference, to deactivate a particular value for a particular user, set the deactivationDate timestamp on that value's record directly in the database - e.g. with the following SQL code:

Code Block
languagesql
UPDATE shibpid SET deactivationDate=NOW() WHERE principalName='user123' AND peerEntity='https://sp.example.org/shibboleth';

 

 



eduPersonAssurance

The eduPersonAssurance expresses both levels of identity assurance and authentication assurance (i.e., both how sure an IdMS is about the identity of a user and how strong authentication mechanisms were used to establish the session). These attributes would ideally have per-user values, based on information captured about the users in the IdMS - e.g., an attribute tracking whether the business process for creating the user's credentials involved checking official photoID documents and e.g. what kind of password policy applies to the user.

...

  • Create a database. The data would be stored in a single table called StorageService, we recommend creating database idp_db (which, as per other section of this document, can also host the shibpid table for storing the values of the of the PersistentNameID / eduPersonTargetedID attribute and the tb_st table storing the auEduPersonSharedToken values).

    Code Block
    languagesql
     CREATE DATABASE idp_db CHARACTER SET utf8 COLLATE utf8_bin;
     CREATE USER 'idp_admin'@'localhost' IDENTIFIED BY 'IDP_ADMIN_PASSWORD';
     GRANT ALL PRIVILEGES ON idp_db.* TO 'idp_admin'@'localhost';


    Note

    It is strongly encouraged to create the databases with utf8 character encoding and utf8_bin collation (sorting).

    Earlier versions of this document did not specify these settings and the database (and all tables) would be created with the default system encoding and collation.

    To convert these to utf8utf8_bin, please run:

    Code Block
    languagesql
    ALTER DATABASE idp_db DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin;
    ALTER TABLE tb_st CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
    ALTER TABLE StorageRecords CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
    ALTER TABLE shibpid CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;



  • Create the StorageRecords table.  This part can be tricky, as different versions of IdP ship with different versions of Hibernate, which use different database mapping / field names.  IdP 3.0.0 used column names key (and expiration) instead ofid (and expires).  The key issue with that was key is a reserved word in MySQL - and therefore, the column name then must be quoted in all SQL statements.  IdP 3.1.1 reverts back to id (and expires), avoiding the clash with MySQL reserved words.  For IdP 3.1.1+, create the table with:

    Code Block
    CREATE TABLE `StorageRecords` (
     `context` varchar(255) NOT NULL,
     `id` varchar(255) NOT NULL,
     `expires` bigint(20) DEFAULT NULL,
     `value` longtext NOT NULL,
     `version` bigint(20) NOT NULL,
     PRIMARY KEY (`context`,`id`));


  • Add the following beans to $IDP_HOME/conf/global.xml - instead of duplicating them here, please use the MySQL versions from the IdPv3 Storage documentation (section Installation, unfold the snippets under DB-independent Configuration and MySQL Configuration).
    The beans to add are:

    No Format
    shibboleth.JPAStorageService
    shibboleth.JPAStorageService.EntityManagerFactory
    shibboleth.JPAStorageService.JPAVendorAdapter
    shibboleth.JPAStorageService.DataSource

     


    • Customize the  shibboleth.JPAStorageService.DataSourcebean with database connection parameters: 
      • Set the class to match the Tomcat JDBC pool (already comes preinstalled with Tomcat as tomcat-jdbc.jar), org.apache.tomcat.jdbc.pool.DataSource
      • Set the connection URL, username, password and driverClassName to match your database connection.
      • For MySQL, also set the autoReconnect and wait_timeout parameters (to avoid database connections timing out and to reconnect if they get dropped anyway).
      • Note that with Tomcat JDCBC pool, the JDBC URL property name is just url, not jdbcUrl
      • Set the validationQuery property to a simple query that would probe (validate) the database connection before it is handed out from the pool.  Note that the special syntax, starting with /* ping */ is crucial - this triggers a ping in the database driver; see the MySQL JDBC Driver documentation.
      • Set the testOnBorrow property to actually turn on connection validation on checkout.
      • With all these modifications, the bean could look like: 

        Code Block
        languagehtml/xml
        <bean id="shibboleth.JPAStorageService.DataSource"
            class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close" lazy-init="true"
            p:driverClassName="com.mysql.jdbc.Driver"
            p:url="jdbc:mysql://localhost:3306/idp_db?autoReconnect=true&amp;sessionVariables=wait_timeout=31536000"
            p:validationQuery="/* ping */ SELECT 1;"
            p:testOnBorrow="true"
            p:username="idp_admin"
            p:password="IDP_ADMIN_PASSWORD" />


    • And remember to install the database driver.  Note that as the driver will be used by classes outside the web application (the Tomcat JDBC pool), the driver also needs to be installed outside the web application.  The following will work on RHEL/CentOS 7 systems:

      Code Block
      languagebash
      yum install mysql-connector-java
      ln -s /usr/share/java/mysql-connector-java.jar /usr/share/tomcat/lib/


...

Please note that refresh intervals configured in services.properties only apply to resources directly referenced from the service configuration ( services.xml ) - but in the case of Metadata service, not to actual metadata - this applies only to the metadata-providers.xml file itself. See the documentation on configuring metadata above for details on adjusting metadata refresh intervals.

 


Load Attribute Filter

This step should be done only after fully registering your IdP into the federation.

...

Multiexcerpt include
nopaneltrue
MultiExcerptNameidp3-load-attribute-filter
nopaneltrue
PageWithExcerptConfiguring a Shibboleth Identity Provider to join the Tuakiri Federation

 


Alternatively, set up the fetching via an external script and configure the IdP to only load an additional local file:

  • Download the fetch-xml.sh script into /opt/shibboleth-idp/bin

    No Format
    wget -O /opt/shibboleth-idp/bin/fetch-xml.sh https://github.com/REANNZ/Tuakiri-public/raw/master/scripts/fetch-xml.sh
    chmod +x /opt/shibboleth-idp/bin/fetch-xml.sh


  • Determine a local email address that should be receiving notifications when fetching a fresh copy of the attribute filter fails.

     


  • Run the fetch-xml.sh script once to download a copy of your attribute filter into /opt/shibboleth-idp/conf/tuakiri-attribute-filter.xml (substituting the correct local values - URL and email address - into the following line):

    No Format
    /opt/shibboleth-idp/bin/fetch-xml.sh http://directory.tuakiri.ac.nz/attribute-filter/institution.domain.ac.nz.xml /opt/shibboleth-idp/conf/tuakiri-attribute-filter.xml errors@institution.domain.ac.nz


  • Create a cron job to periodically (every 2 hours) download the metadata and the attribute filter: run crontab -e and add the following entry (matching the command you had run on the command line earlier):

    No Format
    02 */2 * * * /opt/shibboleth-idp/bin/fetch-xml.sh https://directory.tuakiri.ac.nz/attribute-filter/institution.domain.ac.nz.xml /opt/shibboleth-idp/conf/tuakiri-attribute-filter.xml errors@institution.domain.ac.nz


  • Edit $IDP_HOME/conf/services.xml and add the additional attribute filter as an additional value in the shibboleth.AttributeFilterResources util:list bean:

    Code Block
    languagehtml/xml
    <value>%{idp.home}/conf/tuakiri-attribute-filter.xml</value> 

 



Note

For both federations, please note:

  • The attribute names used in the download policy file must match the local attribute names. Check that the attribute names in the downloaded attribute filter against their names in existing configuration files:
    • attribute-resolver.xml (attribute definitions, match against the ID in the AttributeDefinition element)
    • attribute-filter.xml (local attribute filter)
  • But please note that no attributes need to be renamed with the Federation Registry since December 2010 (current as of April 2015).

...

The Shibboleth IdP supports at least a minimalist implementation of Single Log Out (SLO). (This support has been added in 2.4.0 and provides the same functionality in the 3.0.x and 3.1.x release branches)

Multiexcerpt include
nopaneltrue
MultiExcerptNameSLO-overview
nopaneltrue
PageWithExcerptSingle Log Out (SLO)

...

  • Configure the IdP to track SP sessions, create a secondary index of the SPs by their SAML IDs, and display the elaborate list on the logout page:

    Code Block
    languagenone
    idp.session.trackSPSessions = true
    idp.session.secondaryServiceIndex = true
    idp.logout.elaboration = true


  • We strongly recommend configure the JPA/Hibernate storage service as per above and store the session information in the JPA storage service:

    Code Block
    languagenone
    idp.session.StorageService = shibboleth.JPAStorageService

     


    • If not configuring the JPA storage service, to get SLO and SP session tracking the work, it is necessary to at least switch the session storage to the in-memory-only (discarded on server restart) storage service (the default client-side cookie storage would not work for the logout functionality):

      Code Block
      languagenone
      idp.session.StorageService = shibboleth.StorageService


  • We also recommend increasing the duration for storing SP sessions: the default on the SP side is 8 hours (while the IdP default expectation of that value would be 2H), and some instances might be using longer value - so set the defaultSPlfetime property to the actual default SP value and add in a buffer to err on the side of caution:

    Code Block
    idp.session.defaultSPlifetime = PT8H
    idp.session.slop = P1D


...

  • The most important step is to remove the boilerplate notice saying the page should be customized.
    Remove the notice (expand here to see the exact changes): 

    Expand


    Code Block
    languagediff
    --- logout.vm.orig    2018-10-12 15:08:08.726832762 +1300
    +++ logout.vm    2018-10-17 13:41:20.651782569 +1300
    @@ -39,11 +39,6 @@
      
             <div class="content">
               <div class="column one">
    -            <p>This page is displayed when a logout operation at the Identity Provider completes. This page is an example
    -            and should be customized. It is not fully internationalized because the presentation will be a highly localized
    -            decision, and we don't have a good suggestion for a default.</p>
    -            <br>
    -   
                  #if ($rpContext)
                     <p>#springMessageText("idp.logout.sp-initiated", "You have been logged out of the following service:")</p>
                     <blockquote>



    Note

    If you enable Single Logout without customizing your Logout page (i.e., leaving in the original default page), users utilizing the Logout functionality will see an unflattering page saying: "This page is an example and should be customized."


  • Optionally, also add additional notices to the landing logout pages: ($IDP_HOME/views/logout-propagate.vm  and $IDP_HOME/views/logout-complete.vm).  You may wish to inform the users that sessions derived by the applications on the SPs might not have been terminated and that the only safe way to terminate the session is to close the browser.  Expand here to see our suggestion at the wording:

    Expand


    Code Block
    languagediff
    --- logout-complete.vm.orig    2018-10-12 15:08:08.725832770 +1300
    +++ logout-complete.vm    2018-10-17 13:43:03.532974734 +1300
    @@ -33,6 +33,8 @@
             <div class="content">
               <div class="column one">
                 <p>#springMessageText("idp.logout.local", "You elected not to log out of all the applications accessed during your session.")</p>
    +            <br>
    +            <p>We recommend to close your browser to close all the sessions at the Service Providers.</p>
               </div>
               <div class="column two">
                 <ul class="list list-help">
    --- logout-propagate.vm.orig    2018-10-12 15:08:08.726832762 +1300
    +++ logout-propagate.vm    2018-10-17 13:43:03.545974633 +1300
    @@ -37,6 +37,10 @@
               <div class="column one">
                   <p>#springMessageText("idp.logout.attempt", "Attempting to log out of the following services:")</p>
                   #parse("logout/propagate.vm")
    +              <br>
    +              <p>The logout process has now completed with the above results.</p>
    +              <br>
    +              <p> However, as application sessions derived from the initial login might have stayed on at these services, we still <strong>recommend to close your browser</strong> to reliably close all the sessions.</p>
               </div>
               <div class="column two">
                 <ul class="list list-help">

 




Step 3: Register the following additional endpoints as Single Logout Service in your IdP metadata the Federation Registry, with the following bindings names and URL values (substituting your IdP hostname in the URLs):

...

  • Check for value changes. In the default setting, the user would be asked to reconfirm only when the list of attributes being released changes. By turning on this feature, the user would be also asked when the values of the attributes change. Turn this feature on by adding the following line to $IDP_HOME/conf/idp.properties:

    Code Block
    languagenone
    idp.consent.compareValues = true


  • Configure server-side database storage. By default, consent information would be stored in client-side cookies. That might be unexpected behavior for end-users - consent once granted would disappear when they switch browsers or devices or otherwise discard cookies. We also do not recommend server-side in memory storage (the only other pre-configured option), where contents of the storage would disappear when the server is restarted. We recommend configuring the JPA/Hibernate storage as per above and then configuring the consent module to user the JPA storage with:

    Code Block
    languagenone
    idp.consent.StorageService=shibboleth.JPAStorageService


  • Remove the limit on the number of consent records held (by default, 10) by setting the limit to -1 (no limit):

    Code Block
    languagenone
    idp.consent.maxStoredRecords = -1


  • The following property can be accepted with their default value, or they could be adjusted as needed:

    Code Block
    languagenone
    #idp.consent.storageRecordLifetime = P1Y
    #idp.consent.allowDoNotRemember = true
    #idp.consent.allowGlobal = true
    #idp.consent.allowPerAttribute = false

     


    • The Storage Record Life Time of 1 year should be sufficient - consent records would expire after a year.
    • The users would be allowed to select to be asked again at next login ("do not remember")
    • The users would be allowed to grant "global consent" - i.e., not to be asked again, regardless of the services being accesses, or attributes and values being passed.
    • The users would not be allowed to make per attribute selection - this could make the user interface too confusing for ordinary users, even though it would give the users interested in doing so the power to hand-select which attributes get released.

  • We also recommend to configure the order in which the attributes are rendered on the consent screen.  As of 3.2.1, the consent module allows to set the attribute order through the order in which the attributes are listed in the AttributeDisplayOrder bean.  Edit IDP_HOME/conf/intercept/consent-intercept-config.xml and uncomment the shibboleth.consent.attribute-release.AttributeDisplayOrder bean and set the contents to:

    Code Block
    languagehtml/xml
        <util:list id="shibboleth.consent.attribute-release.AttributeDisplayOrder">
            <value>commonName</value>
            <value>displayName</value>
            <value>auEduPersonLegalName</value>
            <value>givenName</value>
            <value>surname</value>
            <value>email</value>
            <value>eduPersonPrincipalName</value>
            <value>uid</value>
            <value>auEduPersonSharedToken</value>
            <value>eduPersonTargetedID</value>
            <value>eduPersonEntitlement</value>
            <value>eduPersonAssurance</value>
            <value>eduPersonAffiliation</value>
            <value>eduPersonScopedAffiliation</value>
            <value>eduPersonPrimaryAffiliation</value>
            <value>auEduPersonAffiliation</value>
            <value>organizationName</value>
            <value>homeOrganization</value>
            <value>homeOrganizationType</value>
            <value>organizationalUnit</value>
            <value>postalAddress</value>
            <value>telephoneNumber</value>
            <value>mobileNumber</value>
        </util:list>


    Note

    Note: if setting this list, we recommend it includes all attributes defined by the IdP.  If some attributes are not included, they'd be displayed in random order after the attributes included in the list - which would not be a consistent user experience.


    Note
    titleNo longer needed

    Earlier versions of this documentation were instructing to explicitly release the attribute used for calculating the persistentNameID  to make it visible to the PersistentID generator - and to hide this attribute from the consent screen. This was necessary for older versions of IdPv3, but for 3.2.0 and newer is no longer needed - see the last line in the ComputedID section of the upstream PersistentNameID documentation.

    This documentation has been updated (in December 2016) in the configuring Persistent NameID section above to no longer add rules to explicitly release the attributes.  As long as these rules are not present, it is also no longer necessary to hide the attribute from the consent screen as the original documentation was instructing here.

    For completeness, the original instructions were:

    • Edit /opt/shibboleth-idp/dist/conf/intercept/consent-intercept-config.xml.dist, locate the shibboleth.consent.attribute-release.BlacklistedAttributeIDs and add the uid attribute to the list:

      Code Block
      --- /opt/shibboleth-idp/dist/conf/intercept/consent-intercept-config.xml.dist   2016-07-28 11:44:39.060776510 +1200
      +++ consent-intercept-config.xml        2016-07-29 14:56:08.804113011 +1200
      @@ -55,6 +55,7 @@
           </util:list>
      
           <util:list id="shibboleth.consent.attribute-release.BlacklistedAttributeIDs">
      +        <value>uid</value>
               <value>transientId</value>
               <value>persistentId</value>
               <value>eduPersonTargetedID</value>
      
      



...

Code Block
3 3 * * * IDP_HOME=/opt/shibboleth-idp JAVA_HOME=/usr/lib/jvm/java /opt/shibboleth-idp/bin/seckeygen.sh --versionfile /opt/shibboleth-idp/credentials/sealer.kver --storefile /opt/shibboleth-idp/credentials/sealer.jks --storepass changeit  --alias secret 

 

 



Centralized Usage Logging

...

Code Block
languagenone
F-TICKS/Tuakiri-TEST/1.0#TS=1467772333#RP=https://attributes.staging.tuakiri.ac.nz/shibboleth#AP=https://virtualhome.test.tuakiri.ac.nz/idp/shibboleth#PN=b61fca51c22df2e5ddb961bb5dfec9a672e627668b4bf2c45de0a719540179cc#RESULT=OK#

 


To enable this service, please make the following changes (based on upstream instructions at https://wiki.shibboleth.net/confluence/display/IDP30/FTICKSLoggingConfiguration):

...

Note

Please make sure the firewall permits outgoing UDP packets to port 514 (at least for the Tuakiri log collection server)

 


Configuring SELinux for Tomcat

...

Expand

Tomat needs to be able to connect to MySQL - and unfortunately, this has been so far omitted in the SELinux policy for target.  While we expect this to be fixed in future updates to the SELinux policy, for now, we have to use a workaround - create a custom policy module.

  • Create a policy type enforcement file defining a policy module tomcat-to-mysql - in a working directory (e.g., /root/inst) create tomcat-to-mysql.te with the following contents:

    No Format
    module tomcat-to-mysql 1.0;
    
    require {
            type tomcat_t;
            type mysqld_port_t;
            class tcp_socket name_connect;
    }
    
    #============= tomcat_t ==============
    allow tomcat_t mysqld_port_t:tcp_socket name_connect;


  • Compile, package and load the module with:

    No Format
    checkmodule -m -M -o tomcat-to-mysql.mod tomcat-to-mysql.te
    semodule_package -o tomcat-to-mysql.pp -m tomcat-to-mysql.mod
    semodule -i tomcat-to-mysql.pp


With these in place, Tomcat should have all the SELinux permissions required and the IdP should operate normally.

 


Enabling HSTS

Since version 3.4.0, the IdP supports HSTS - HTTP Strict Transport Security:

...

To enable HSTS, change its max-age property from the default value 0 (disabled) to a reasonably long value (industry practice is at least 6 months, preferably 1 year):

 

Code Block
idp.hsts = max-age=31536000

 


Additional Information

Please see the IdPv3 wiki for further information. Useful pages for additional configuration options are:

...

Code Block
languagecss
.column.two {
    display: none;
}

 


Overall, the pages under $IDP_HOME/views we recommend customizing are:

...

No Format
    <util:map id="shibboleth.AccessControlPolicies">

        <entry key="AccessByIPAddress">
            <bean parent="shibboleth.IPRangeAccessControl"
                p:allowedRanges="#{ {'127.0.0.1/32', '::1/128', '192.168.0.1/32' } }" />
        </entry>

    </util:map>

 


After configuring access, the administrative functions can be accessed with either a browser or any HTTP capable tool, by accessing the following URLs:

...

Other options for testing including using the UnsolicitedSSO: invoking a URL directly at the IdP and pretending as if an SP initiated the request. This can be used for testing even in situations where the IdP is not yet registered in the federation (but is already loading the federation metadata).  While the SSO would not be accepted by the SP in that case (the IdP would not be trusted through the federation), it allows to test the full login and attribute release process at the IdP.  To test SSO against the Tuakiri Attribute Reflector, open the following URL (substituting the correct IdP hostname): https://idp.institution.ac.nz/idp/profile/SAML2/Unsolicited/SSO?providerId=https://attributes.tuakiri.ac.nz/shibboleth