Shibboleth IdPv5 in der Schulungs-VM

DFN Logo






Vorbereitung

Wir werden den Shibboleth Identity Provider im Verlauf des Workshops gemeinsam installieren und konfigurieren. Für den erfolgreichen Ablauf des Workshops ist es entscheidend, dass Sie sich im Vorfeld ein solides Basiswissen angeeignet haben. Um den Fokus im Workshop auf den Praxisteil zu legen, arbeiten Sie bitte eigenständig mindestens folgende Webseiten im Wiki durch:
  1. Was ist die DFN-AAI?
  2. Vorraussetzungen
  3. Portfolio DFN-AAI
  4. Metadatenverwaltung
  5. Discovery Service
  6. Attributes in a Nutshell
Nach der Lektüre sollten Sie folgende Fragen für sich beantworten können:
  • Was ist eine Föderation?
  • Was ist die Rolle des Föderationsbetreibers?
  • Was sind formale, technische und organisatorische Kriterien für eine Teilnahme an der DFN-AAI?
  • Was ist ein IdP, SP, Discovery Service?
  • Was sind Metadaten und wie werden sie verwaltet?
  • Was sind lokale Metadaten und wann kommen sie zum Einsatz?
  • Falls etwas unklar bleibt, notieren Sie sich Ihre Fragen und Unsicherheiten. Im Workshop gehen wir gern auf offene Punkte ein.

    Informationen zur Schulungs-VM

    Für den Workshop stellen wir eine Schulungs-VM zur Verfügung. Installieren Sie diese bitte vorab und machen sich mit der VM vertraut.
    1. Import des heruntergeladenen .ova-Images in Virtualbox: Datei -> Appliance importieren. Im BIOS muss Hardware-Virtualisierung angeschaltet sein.
    2. Für ein Copy & Paste ohne Gasterweiterungen können Sie diese Installationsanleitung selbstverständlich auch im Browser in der VM abrufen. Dazu finden Sie im Firefox ein Lesezeichen in der Leiste.
    3. Betriebssystem der Schulungs-VM: Debian 12
    4. Die Nutzerkennung lautet "shibboleth". Alle Passwörter lauten ebenfalls "shibboleth".
    5. Auf der VM befindet sich ein LDAP-Browser (phpLDAPadmin), der im Web-Browser (Firefox) als Lesezeichen gesetzt ist. Im Verzeichnis finden Sie sechs Test-Accounts mit verschiedenen Attributen.
    6. Zum besseren Verständnis des lokalen Setups (idp/sp1) hilft ein Blick in /etc/hosts und die Apache-Konfiguration unter /etc/apache2/sites-enabled.
    7. Die wichtigsten vorinstallierten Pakete sind Web-, Datenbank- und LDAP-Server:
    Hier starten wir mit dem Workshop

    Recap Basiswissen

    zur Präsentation: DFN AAI

    Shibboleth-Installation

    Erlangen Sie root-Rechte:
    su -
    Sie installieren in diesem Tutorial die Version 5.1.3 Laden Sie sich die 5.1.3 als tar-Archiv in das Verzeichnis /opt/install herunter. Die Dateien finden Sie im Download-Verzeichnis von Shibboleth.
    wget -P /opt/install https://shibboleth.net/downloads/identity-provider/latest/shibboleth-identity-provider-5.1.3.tar.gz
    wget -P /opt/install https://shibboleth.net/downloads/identity-provider/latest/shibboleth-identity-provider-5.1.3.tar.gz.sha256
    wget -P /opt/install https://shibboleth.net/downloads/identity-provider/latest/shibboleth-identity-provider-5.1.3.tar.gz.asc
    wget -P /opt/install https://shibboleth.net/downloads/PGP_KEYS
    gpg --import /opt/install/PGP_KEYS
    gpg --verify /opt/install/shibboleth-identity-provider-5.1.3.tar.gz.asc /opt/install/shibboleth-identity-provider-5.1.3.tar.gz
    cd /opt/install && sha256sum -c shibboleth-identity-provider-5.1.3.tar.gz.sha256
    tar -xzf /opt/install/shibboleth-identity-provider-5.1.3.tar.gz -C /opt/install/
    
    Führen Sie das interaktive Installerskript aus:
    /opt/install/shibboleth-identity-provider-5.1.3/bin/install.sh
    
    Achtung, bei "Hostname" müssen Sie die Standardvorgabe zu idp.local ändern.Bei den anderen Feldern können Sie einfach mit der ENTER-Taste bestätigen.
    Installation Directory: [/opt/shibboleth-idp] ? 
    
      INFO  - New Install.  Version: 5.1.3
      Host Name: [192.168.137.138] ? 
      idp.local
      INFO  - Creating idp-signing, CN = idp.local URI = https://idp.local/idp/shibboleth, keySize=3072
      INFO  - Creating idp-encryption, CN = idp.local URI = https://idp.local/idp/shibboleth, keySize=3072
      INFO  - Creating backchannel keystore, CN = idp.local URI = https://idp.local/idp/shibboleth, keySize=3072
      INFO  - Creating Sealer KeyStore
      INFO  - No existing versioning property, initializing...
      SAML EntityID: [https://idp.local/idp/shibboleth] ? 
      
      Attribute Scope: [local] ? 
      
    

    Shibboleth-Konfiguration

    Metadaten

    In diesem Schritt machen Sie dem neuen IdP den Service Provider bekannt, der in der VM bereits konfiguriert ist. Laden Sie die lokalen Metadaten des SPs in das entsprechende Verzeichnis des IdP. In einer Produktivinstanz würden Sie hier stattdessen die Föderationsmetadaten einbinden. (Den Zertifikatscheck überspringen Sie hier nur wegen der lokalen Domain bzw. des selbst signierten Zertifikates in der VM.)
    wget --no-check-certificate https://sp1.local/Shibboleth.sso/Metadata -O /opt/shibboleth-idp/metadata/sp1-metadata.xml
    
    Konfigurieren Sie diese Metadatensätze im IdP: Die Zeile gehört vor das schließende MetadataProvider-Tag in der Datei. Ja: Die Datei hat dann ein MetadataProvider-Tag im MetadataProvider-Tag.
    <!-- Datei: /opt/shibboleth-idp/conf/metadata-providers.xml -->
        <MetadataProvider id="SP1-Metadata"  xsi:type="FilesystemMetadataProvider" metadataFile="/opt/shibboleth-idp/metadata/sp1-metadata.xml"/>
    
    Bei der Installation wurde eine Datei mit den IdP-Metadaten automatisch erstellt. In der VM verwenden wir sie, um dem lokalen SP die IdP-Metadaten bekannt zu machen. (Im Produktivbetrieb werden stattdessen die Föderationsmetadaten verwendet.) In der IdP-Version 5.1.3 gibt es aktuell einen Fehler in diesen automatisch erstellte Metadaten. Korrigieren Sie das fehlende Leerzeichen in Zeile 7:
    <!-- Datei: /opt/shibboleth-idp/metadata/idp-metadata.xml -->
      <md:EntityDescriptorentityID="https://idp.local/idp/shibboleth"...>
      <!-- wird zu -->
      <md:EntityDescriptor entityID="https://idp.local/idp/shibboleth"...>
    
    zur Präsentation: Metadaten

    LDAP-Anbindung (Anbindung IdM)

    Konfigurieren Sie die Anbindung an den vorinstallierten LDAP-Server in der Schulungs-VM. Tipp für die Praxis: Der bind-Account sollte nur Leserechte haben! In einem realen Setup werden Sie sich - anders als innerhalb der Schulungs-VM - verschlüsselt mit dem LDAP-/AD-Server verbinden. Folgende Zeilen müssen editiert werden, der Rest bleibt so, wie er ist:
    # Datei: /opt/shibboleth-idp/conf/ldap.properties
    idp.authn.LDAP.authenticator                   = bindSearchAuthenticator
    idp.authn.LDAP.ldapURL                         = ldap://idp.local:389
    idp.authn.LDAP.useStartTLS                     = false
    # idp.authn.LDAP.trustCertificates                = %{idp.home}/credentials/ldap-server.crt
    idp.authn.LDAP.baseDN                          = dc=users,dc=nodomain
    idp.authn.LDAP.bindDN                          = cn=admin,dc=nodomain
    
    Das Bind-Passwort wird - zusammen mit anderen Credentials - in einer separaten Datei abgelegt. Sie hat eingeschränkte Zugriffsrechte. Sie enthält auch die bei der Installation gesetzten Passwörter:
    shibboleth@debian:~$ ls -la /opt/shibboleth-idp/credentials/secrets.properties 
      -rw------- 1 root tomcat 733 18. Dez 16:57 /opt/shibboleth-idp/credentials/secrets.properties  
    
    Passen Sie das Muster-Passwort aus der mitgelieferten Datei an. Achtung: Es darf kein Leerzeichen am Ende des Passwortes stehen!
    # Datei: /opt/shibboleth-idp/credentials/secrets.properties
    idp.authn.LDAP.bindDNCredential                = shibboleth
    

    Zugriff auf das Webinterface regeln

    Erlauben Sie den Zugriff auf das Webinterface vom kompletten /8er-Netz auf localhost: Tragen Sie statt der allowedRange 127.0.0.1/32 die 127.0.0.0/8 ein.
    <!-- Datei: /opt/shibboleth-idp/conf/access-control.xml -->
      <util:map id="shibboleth.AccessControlPolicies">
        
      <entry key="AccessByIPAddress">
        <bean id="AccessByIPAddress" parent="shibboleth.IPRangeAccessControl"
              p:allowedRanges="#{ {'127.0.0.0/8', '::1/128'} }" />
      </entry>
    
    Zur Darstellung der Status-Seite muss eine aktuelle Version der Jakarta JSTL eingebunden werden.
    wget -P /opt/shibboleth-idp/edit-webapp/WEB-INF/lib/ https://repo.maven.apache.org/maven2/org/glassfish/web/jakarta.servlet.jsp.jstl/3.0.1/jakarta.servlet.jsp.jstl-3.0.1.jar
    wget -P /opt/shibboleth-idp/edit-webapp/WEB-INF/lib/ https://repo.maven.apache.org/maven2/jakarta/servlet/jsp/jstl/jakarta.servlet.jsp.jstl-api/3.0.2/jakarta.servlet.jsp.jstl-api-3.0.2.jar
    
    build erneut ausführen und Tomcat neustarten
    /opt/shibboleth-idp/bin/build.sh 
    systemctl restart tomcat10.service 
    

    Konfiguration des Attribute Resolver

    zur Präsentation: Attribute

    Die zentrale Konfigurationsdatei für die Generierung von Attributen ist /opt/shibboleth-idp/conf/attribute-resolver.xml. Hier definieren Sie, welche Attribute Ihre Shibboleth-Instanz kennt, aus welchen Quellen dafür Attribute geholt werden und ggf. wie sie im IdP umgebaut werden sollen. Laden Sie sich bitte zunächst unsere Beispieldatei ins conf-Verzeichnis herunter:
    wget https://download.aai.dfn.de/ws/idp2025/idpv5-attribute-resolver.xml -O /opt/shibboleth-idp/conf/attribute-resolver.xml
    
    Diese xml-Datei enthält u.a. Javascript-Code, der ausgeführt werden soll, damit bestimmte Attribute IdP-seitig generiert werden. Unter OpenJDK 17 benötigt der IdP dafür ein Plugin, das bei früheren Java-Versionen nicht nötig war. So installieren Sie das Nashorn-Plugin:
    /opt/shibboleth-idp/bin/plugin.sh --truststore /opt/install/PGP_KEYS -I net.shibboleth.idp.plugin.nashorn
    

    Attribut-Definitionen

    Schauen Sie sich die Datei an: Im oberen Teil der Datei conf/attribute-resolver.xml finden Sie den Abschnitt "Attribute Definitions" mit den Attributen, die der IdP kennen soll. In diesem Beispiel-Ausschnitt steht sinngemäß: "Ich definiere für den IdP ein Attribut ou. Um es zu befüllen, hole ich aus dem Data Connector myLDAP das dortige Attribut ou."
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
        <AttributeDefinition xsi:type="Simple" id="ou">
            <InputDataConnector ref="myLDAP" attributeNames="ou"/>
        </AttributeDefinition>
    

    Data Connectors

    Im unteren Teil der conf/attribute-resolver.xml finden Sie den Abschnitt "DataConnectors", also die Datenquellen für die zu generierenden Attribute. Sie sehen dort drei aktive Konnektoren:
    1. einen LDAP-Connector,
    2. einen Connector mit statisch definierten Attributen, hier z.B. mit dem hartkodierten Namen der Hochschule
    3. einen Connector für die MySQL-Datenbank (mit den persistentIDs)
    Beispielauszug:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
        <DataConnector id="staticAttributes" xsi:type="Static">
            <Attribute id="o">
                <Value>Beispiel-Hochschule</Value>
            </Attribute>
        </DataConnector>
    
    Bitte beachten Sie im Data Connector "myLDAP" die Zeile "exportAttributes". Ab Shibboleth IdP 4.x können Sie so Attribute aus dem Identity Management direkt verwenden, wenn sie im IdM genau so heißen, wie in der IdP-internen Attribute Registry (dazu später mehr). Diese Attribute müssen nicht mehr als einzelne AttributeDefinitions oben aufgelistet werden.
    opt/shibboleth-idp/conf/attribute-resolver.xml -->
            <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
            ...
            exportAttributes="uid givenName sn mail displayName">
            ...
        </DataConnector>
    

    Transcoding-Regeln

    Ab Shibboleth IdP 4.x werden bestimmte Zusatzinformationen zu den definierten Attributen in der Attribute Registry vorgenommen. Die Konfiguration erfolgt über die Datei conf/attribute-registry.xml und diverse Dateien im Verzeichnis unterhalb von ./conf/attributes. Bei Neuinstallationen wird ein Standard-Regelsatz aus conf/attributes/default-rules.xml geladen. Dieser enthält Regeln für die Kodierung und Dekodierung gängiger Attribute. Die Informationen in der Attribute Registry müssen Sie v.a. beim initialen Aufsetzen des IdP kennen und ggf. anpassen. Schauen Sie sich die Datei /opt/shibboleth-idp/conf/attributes/inetOrgPerson.xml an. Für jedes Attribut aus dem inetOrgPerson-Schema ist hier das Standard-Set an Properties hinterlegt. Dieser Ausschnitt zeigt die Einstellungen für das mail-Attribut:
    1. Das mail-Attribut kann in SAML1 und SAML2 übergeben werden. SAML1 ist veraltet und in der DFN-AAI nicht mehr erforderlich. Sie können die Zeile <prop key="saml1.name">urn:mace:dir:attribute-def:mail</prop> daher auch getrost entfernen.
    2. Das mail-Attribut wird - wie der Spezifikation vorgesehen - in SAML2 als urn:oid:0.9.2342.19200300.100.1.3 übergeben. Dies ist die Information, die SPs für die Zuordnung der Attribute benötigen.
    3. Das mail-Attribut hat hier einen Anzeigenamen und eine Kurzbeschreibung in deutsch und englisch. Die Nutzer*innen bekommen dies zu sehen, wenn sie nach der Zustimmung zur Attributfreigabe gefragt werden.
    <!-- Datei: /opt/shibboleth-idp/conf/attributes/inetOrgPerson.xml (gekürzt!) -->
            <bean parent="shibboleth.TranscodingProperties">
                <property name="properties">
                    <props merge="true">
                        <prop key="id">mail</prop>
                        <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
                        <prop key="saml2.name">urn:oid:0.9.2342.19200300.100.1.3</prop>
                        <prop key="saml1.name">urn:mace:dir:attribute-def:mail</prop>
                        <prop key="displayName.en">E-mail</prop>
                        <prop key="displayName.de">E-Mail</prop>
                        <prop key="description.en">E-Mail: Preferred address for e-mail to be sent to this person</prop>
                        <prop key="description.de">E-Mail-Adresse</prop>
                    </props>
                </property>
            </bean>
    
    Jedes Attribut, das im Attribute Resolver verwendet wird - in einer Attribute Definition oder über exportAttributes - muss dem IdP über die Registry bekannt sein (dazu später mehr).

    Vorbereitung der MySQL-Datenbank

    zur Doku: Datenbank-Konfiguration

    Nun legen Sie eine Datenbank für Shibboleth an. Sie wird zwei Tabellen enthalten:
    1. "StorageRecords" für die Speicherung von User Consent und Sessions
    2. "shibpid" für die Speicherung von persistentIDs
    mariadb -uroot -pshibboleth
    SET NAMES 'utf8';
    SET CHARACTER SET utf8;
    CHARSET utf8;
    CREATE DATABASE IF NOT EXISTS shibboleth CHARACTER SET=utf8;
    USE shibboleth;
    
    CREATE TABLE IF NOT EXISTS 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)
    ) COLLATE utf8_bin;
     
    CREATE TABLE IF NOT EXISTS 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)
    );
     
    CREATE USER 'shibboleth'@'localhost' IDENTIFIED BY 'shibboleth'; 
    GRANT ALL PRIVILEGES ON shibboleth.* TO 'shibboleth'@'localhost';
    FLUSH PRIVILEGES;
    exit;
    

    Konfiguration von SAML2-NameIDs

    zur Doku: User Identifier

    Der IdP soll zusätzlich zu den Attributen in ./conf/attribute-resolver.xml zwei Arten von SAML2-NameIDs unterstützen:
    1. persistentIDs werden pro Useraccount und pro SP nach einem konfigurierbaren Schema generiert. Sie bleiben dann gleich, das heißt, SPs können anhand dieser Pseudonyme Accounts personalisieren, ohne Realnamen zu kennen. (Es sei denn, die werden auch übermittelt.)
    2. transientIDs werden auch pro Useraccount und pro SP generiert. Sie ändern sich aber bei jedem Login.

    Um die SAML Name IDs verwenden zu können, sind folgende Konfigurationsschritte nötig:
    1. in /opt/shibboleth-idp/conf/saml-nameid.properties definieren, dass und womit die persistentID generiert wird
    2. in /opt/shibboleth-idp/conf/saml-nameid.xml schalten wir die Generierung der persistentIDs an
    3. in /opt/shibboleth-idp/conf/attribute-resolver.xml die samlPairwiseID definieren (wird aus persistentID erstellt)
    4. in /opt/shibboleth-idp/conf/c14n/subject-c14n.xml die Verarbeitung der persistentIDs aktivieren
    5. Konfiguration der Datenbank-Anbindung

    1. saml-nameid.properties - Generierung definieren

    Ihre persistentIDs sollen aus dem Quellattribut uid mit einem Hash erstellt und in der MariaDB-Datenbank gespeichert bzw. aus ihr geholt werden. Dies stellen Sie in /opt/shibboleth-idp/conf/saml-nameid.properties ein. Behalten Sie die bereits bestehende Konfiguration und ändern bzw. aktivieren Sie nur folgende Zeilen:
    # Datei: /opt/shibboleth-idp/conf/saml-nameid.properties
    idp.persistentId.sourceAttribute = uid
    idp.persistentId.encoding = BASE32
    idp.persistentId.generator = shibboleth.StoredPersistentIdGenerator
    idp.persistentId.dataSource = shibboleth.MySQLDataSource
    
    Der Hash wird aus Sicherheitsgründen in der zugriffsbeschränkten Passwortdatei abgelegt. In einer produktiven Installation sollte dieser Salt-Hash möglichst beliebig, also zufällig generiert, und lang sein und mit niemandem geteilt werden.
    # Datei: /opt/shibboleth-idp/credentials/secrets.properties
    idp.persistentId.salt = my-very-very-long-hash
    

    2. saml-nameid.xml - Generierung aktivieren

    In der Datei /opt/shibboleth-idp/conf/saml-nameid.xml schalten Sie die Generierung der persistentIDs an: Entfernen Sie die Kommentarzeichen in den Zeilen 37 und 39, also vor und nach der Zeile mit "shibboleth.SAML2PersistentGenerator".
    <!-- Datei /opt/shibboleth-idp/conf/saml-nameid.xml -->
            <!-- Uncommenting this bean requires configuration in saml-nameid.properties. -->
            <ref bean="shibboleth.SAML2PersistentGenerator" />
    

    3. attribute-resolver.xml- samlPairwiseID definieren

    Der MySQL-Datenbank-Connector ist - wie eben gesehen - bereits in unserer Beispielkonfiguration in conf/attribute-resolver.xml enthalten. In conf/attribute-resolver.xml samlPairwiseID definieren:
    <!-- Datei /opt/shibboleth-idp/conf/attribute-resolver.xml-->
      <!-- Für samlPairwiseID wird die persistentId mit Scope übertragen -->
      <AttributeDefinition xsi:type="Scoped" id="samlPairwiseID" scope="%{idp.scope}">
      <InputDataConnector ref="StoredId" attributeNames="persistentID"/>
      </AttributeDefinition>
    
    

    4. Verarbeitung der persistentIDs aktivieren

    Gleich geschafft. Jetzt aktivieren Sie noch die Verarbeitung der persistentIDs, indem Sie in der Datei /opt/shibboleth-idp/conf/c14n/subject-c14n.xml folgende Zeile aktivieren, indem Sie die Kommentarzeichen am Anfang und am Ende der Zeile 110 entfernen:
    <!-- Datei: /opt/shibboleth-idp/conf/c14n/subject-c14n.xml -->
    <ref bean="c14n/SAML2Persistent" />
    

    5. Konfiguration der Datenbank-Anbindung

    Die Datenbank selbst haben Sie oben ja bereits angelegt. Der Shibboleth greift über ein Plugin auf die Datenbank zu. Dieses JDBC-Plugin installieren Sie so:
    /opt/shibboleth-idp/bin/plugin.sh --truststore /opt/install/PGP_KEYS -I net.shibboleth.plugin.storage.jdbc
    
    Fügen Sie dann für die MariaDB-Konfiguration folgende Zeilen zur Datei conf/global.xml hinzu, z.B. ganz unten vor das schließende </beans>-Tag:
    <!-- Datei /opt/shibboleth-idp/conf/global.xml -->
            <bean id="shibboleth.MySQLDataSource"
                  class="%{mysql.class}"
                  p:driverClassName="org.mariadb.jdbc.Driver"
                  p:url="%{mysql.url}"
                  p:username="%{mysql.username}"
                  p:password="%{mysql.password}"
                  p:maxWait="15000"
                  p:testOnBorrow="true"
                  p:maxActive="100"
                  p:maxIdle="100"
                  p:validationQuery="select 1"
                  p:validationQueryTimeout="5" />
    
            <bean id="JDBCStorageService"
                  parent="shibboleth.JDBCStorageService"
                  p:cleanupInterval="%{idp.storage.cleanupInterval:PT10M}"
                  p:dataSource-ref="shibboleth.MySQLDataSource" />
    
    Speichern Sie die Datenbank-Credentials, indem Sie diese Zeilen an die conf/idp.properties anhängen:
    # Datei /opt/shibboleth-idp/conf/idp.properties
    mysql.class    = org.apache.tomcat.jdbc.pool.DataSource
    mysql.url      = jdbc:mysql://localhost:3306/shibboleth
    mysql.username = shibboleth
    
    An derselben Stelle geben Sie an, dass Sie die Sessions und den User Consent in der MySQL-Datenbank speichern möchten:
    # Datei /opt/shibboleth-idp/conf/idp.properties
    idp.session.StorageService = JDBCStorageService
    idp.consent.StorageService = JDBCStorageService
    idp.consent.attribute-release.userStorageKey = shibboleth.consent.PrincipalConsentStorageKey
    idp.consent.attribute-release.userStorageKeyAttribute = %{idp.persistentId.sourceAttribute}
    idp.consent.terms-of-use.userStorageKey = shibboleth.consent.PrincipalConsentStorageKey
    idp.consent.terms-of-use.userStorageKeyAttribute = %{idp.persistentId.sourceAttribute}
    idp.consent.allowGlobal = false
    idp.consent.compareValues = true
    
    Fehlt nur noch das Datenbank-Passwort des Datenbank-Users "shibboleth". Es gehört ebenfalls in die credentials/secrets.properties:
    # Datei: /opt/shibboleth-idp/credentials/secrets.properties
    mysql.password = shibboleth
    

    Konfiguration von Attributfreigaben

    Die zentrale Konfigurationsdatei für Attributfreigaben: /opt/shibboleth-idp/conf/attribute-filter.xml

    Geben Sie einige Attribute für den lokalen Service Provider in der Schulungs-VM frei. Dazu fügen Sie den folgenden Schnipsel zwischen die AttributeFilterPolicyGroup-Tags ein.
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
        <!-- Release to local SPs  -->
        <AttributeFilterPolicy id="SPs_locals">
            <PolicyRequirementRule xsi:type="OR">
                <Rule xsi:type="Requester" value="https://sp1.local/shibboleth" />
            </PolicyRequirementRule>
            <AttributeRule attributeID="eduPersonScopedAffiliation" permitAny="true" />
            <AttributeRule attributeID="surname"                    permitAny="true" />
            <AttributeRule attributeID="givenName"                  permitAny="true" />
            <AttributeRule attributeID="mail"                       permitAny="true" />
            <AttributeRule attributeID="uid"                        permitAny="true" />
        </AttributeFilterPolicy>
    

    Anpassung von Dateirechten

    Stellen Sie sicher, dass der Tomcat-Benutzeraccount das Installationsverzeichnis besitzt.
    # chown -R tomcat:tomcat /opt/shibboleth-idp/

    Neustart von Diensten

    Beobachten Sie in einem Terminal das Tomcat-Log und starten Sie in einem anderen den Tomcat neu:
    # tail -f /var/log/tomcat10/catalina.DATUM.log
    # systemctl restart tomcat10.service
    In der Schulungs-VM müssen Sie auch den lokalen Shibboleth-SP hier einmal neustarten, weil er die neu hinzugekommenen IdP-Metadaten einlesen muss. shibd ist der SP, nicht der IdP!
    # systemctl restart shibd.service

    Prüfung des IdP-Status

    Versuchen Sie, die Statusseite des IdP zu erreichen: https://idp.local/idp/status. Ggf. müssen Sie die selbstsignierten Zertifikate des Webservers im Browser durchwinken.

    Auf der Statusseite sehen Sie u.a. die installierten Plugins und die aktivierten Module. Prüfen Sie dennoch auch auf der Kommandozeile, ob die beiden Plugins (JDBC und Nashorn) installiert sind, und welche Module bei einer Standardinstallation aktiviert sind:
    # /opt/shibboleth-idp/bin/plugin.sh -l
    # /opt/shibboleth-idp/bin/module.sh -l
    Wenn Ihr IdP noch nicht erreichbar ist, können Sie sich schon selbst auf die Fehlersuche begeben. Die relevanten Logdateien: In unserem Wiki finden Sie außerdem ein paar Hinweise zum Troubleshooting.

    Erstes Login für SP1

    Wenn Sie eine funktionierende Statusseite haben, können Sie versuchen, sich am SP1 anzumelden. Besuchen Sie im Firefox in der VM den SP1 (Lesezeichenliste). Sie sollten zum IdP umgeleitet werden. Dort melden Sie sich mit folgenden Zugangsdaten an:
    username: professorin
    password: shibboleth
    Bei Erfolg: Auf dem SP1 sollten Sie jetzt eine phpinfo-Seite sehen, auf der oben steht, dass dies der SP1 ist.

    Tipps und Tricks

    Neuladen des Shibboleth-IdP

    Es gibt verschiedene Wege, eine Shibboleth-Instanz neu zu laden: Sie können Tomcat das Servlet neu laden lassen. Für Tests ist das ein guter, schneller Weg, im Produktivbetrieb würde es jedoch eine kurze Störung des Betriebs geben.
    # touch /opt/shibboleth-idp/war/idp.war
    Sie können das war file neu bauen lassen. Dies ist nötig, wenn Sie im Ordner edit-webapp Veränderungen vorgenommen haben.
    # /opt/shibboleth-idp/bin/build.sh
    Sie können die Intervalle für automatisches Neuladen der Konfiguration anpassen. Standardwerte:
    # Datei: /opt/shibboleth-idp/conf/services.properties
    # Beispiele:
    idp.service.logging.checkInterval = PT5M
    idp.service.relyingparty.checkInterval = PT15M
    idp.service.attribute.resolver.checkInterval = PT15M
    idp.service.attribute.filter.checkInterval = PT15M
    Sie können so genannte Reload-URLs benutzen, um das Neuladen der Konfiguration über eine URL zu triggern.

    zur Doku: WebInterfaces

    # Beispiele:
    # attribute-resolver.xml neu laden
    curl https://idp.local/idp/profile/admin/reload-service?id=shibboleth.AttributeResolverService
    # attribute-filter.xml neu laden
    curl https://idp.local/idp/profile/admin/reload-service?id=shibboleth.AttributeFilterService

    Logging

    zur Doku: Logging

    Logfiles, Loglevel uvm. finden Sie in der Datei /opt/shibboleth-idp/conf/logback.xml. Die wichtigsten Logdateien im Überblick:

    Handler

    Sie können über URLs bestimmte Handler direkt aufrufen. Hier ein paar Beispiele:

    Identity Provider

    Logout (Session am IdP beenden): https://idp.local/idp/profile/Logout

    Service Provider

    Übungen

    Übung 1: IdP-Module - Das User Consent-Modul

    zur Präsentation: Plugins und Module

    Bei einer Standardinstallation des IdP 5.1.x fehlt ein wichtiger Schritt: Die Nutzer*innen sollen vor der Freigabe Ihrer Daten an einen SP die Attribute aufgelistet bekommen und der Übertragung zustimmen können. Danach werden sie nur bei Änderungen am Attributset wieder gefragt. Seit Version 4.1.0 muss dafür ein Modul aktiviert werden (Hintergrundinformationen zu IdP-Modulen). Die IdP-Module werden über das Skript /opt/shibboleth-idp/bin/module.sh verwaltet. Mit der Option --help schauen Sie sich die möglichen Parameter an, mit --list die Übersicht der aktivierten und nicht aktivierten installierten Module. Nach der Installation sind neben den drei Kern-Modulen nur das "Admin Hello"-Modul und das Password Authentication-Modul aktiv. Aktivieren Sie das Consent Intercept-Modul:
    /opt/shibboleth-idp/bin/module.sh -e idp.intercept.Consent
    Enabling idp.intercept.Consent...
            conf/intercept/consent-intercept-config.xml created
            views/intercept/attribute-release.vm created
            views/intercept/terms-of-use.vm created
    [OK]
    
    Die Terms of Use lassen wir hier weg, siehe dazu unsere oben verlinkte Dokumentation. Wir möchten jetzt lediglich die freizugebenden Attribute einblenden und abnicken lassen:

    Untersuchung der Änderungen

    Übung 2: Freigaben für easyroam

    Was benötigt der Service Provider? Werfen wir einen Blick in die Metadaten: Föderationsmetadaten

    Metadaten easyroam
    <EntityDescriptor entityID="https://get.eduroam.de/shibboleth">
      <Extensions>
        <mdrpi:RegistrationInfo registrationAuthority="https://www.aai.dfn.de" registrationInstant="2021-08-18T11:46:48Z">
        <mdrpi:RegistrationPolicy xml:lang="en">
          https://www.aai.dfn.de/fileadmin/documents/mrps_dfn-aai_1.0.pdf
        </mdrpi:RegistrationPolicy>
        </mdrpi:RegistrationInfo>
        <mdattr:EntityAttributes>
          <saml:Attribute Name="urn:oasis:names:tc:SAML:profiles:subject-id:req" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml:AttributeValue>pairwise-id</saml:AttributeValue>
          </saml:Attribute>
        </mdattr:EntityAttributes>
      </Extensions>
      <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
      <Extensions>
        <init:RequestInitiator Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="https://get.eduroam.de/Auth/Login"/>
        <init:RequestInitiator Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="https://www.easyroam.de/Auth/Login"/>
        <idpdisc:DiscoveryResponse Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://get.eduroam.de/Auth/Login" index="1"/>
        <idpdisc:DiscoveryResponse Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://www.easyroam.de/Auth/Login" index="2"/>
        <mdui:UIInfo>
          <mdui:DisplayName xml:lang="de">DFN easyroam</mdui:DisplayName>
          <mdui:DisplayName xml:lang="en">DFN easyroam</mdui:DisplayName>
          <mdui:Description xml:lang="de">DFN easyroam</mdui:Description>
          <mdui:Description xml:lang="en">DFN easyroam</mdui:Description>
          <mdui:Logo height="180" width="182">
            https://mdv.aai.dfn.de/media/logos/e15/Logo_easyroam_nur_Logo.png
          </mdui:Logo>
          <mdui:PrivacyStatementURL xml:lang="de">https://get.eduroam.de/Home/Privacy</mdui:PrivacyStatementURL>
        </mdui:UIInfo>
      </Extensions>
      <KeyDescriptor>
        <ds:KeyInfo>
        <ds:KeyName>get.eduroam.de</ds:KeyName>
        <ds:X509Data>
          <ds:X509SubjectName>
            CN=get.eduroam.de,OU=easyroam,O=Verein zur Förderung eines Deutschen Forschungsnetzes e. V.,ST=Berlin,C=DE
          </ds:X509SubjectName>
          <ds:X509Certificate>
            MIIGLDCCBBSgAwIBAgIURUgPxJMAvZ+IoxP0j98BkUacOGcwDQYJKoZIhvcNAQEL BQAwgZExCzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCZXJsaW4xRTBDBgNVBAoMPFZl cmVpbiB6dXIgRsO2cmRlcnVuZyBlaW5lcyBEZXV0c2NoZW4gRm9yc2NodW5nc25l dHplcyBlLiBWLjERMA8GA1UECwwIZWFzeXJvYW0xFzAVBgNVBAMMDmdldC5lZHVy b2FtLmRlMB4XDTI0MDgxMjEyNDIwOFoXDTI3MDgxMjEyNDIwOFowgZExCzAJBgNV BAYTAkRFMQ8wDQYDVQQIDAZCZXJsaW4xRTBDBgNVBAoMPFZlcmVpbiB6dXIgRsO2 cmRlcnVuZyBlaW5lcyBEZXV0c2NoZW4gRm9yc2NodW5nc25ldHplcyBlLiBWLjER MA8GA1UECwwIZWFzeXJvYW0xFzAVBgNVBAMMDmdldC5lZHVyb2FtLmRlMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA+iNKmXEOFXxbjy00Xyw2PAOGhWuY Z4T4pYux5juM8kQN9jRb1hynfkAxIJnG9fZyEH2saPzvIHf7dsM4FLljVyseuVVg 9K4I1gzdlrWjta5JbSvzPJm9Mi2uVXgtqvNnCof6Ez7JxfP2SDWSVDv8ewW+p2Je 6aXcnakRIf2CvzrX0GoWyNYRRjejQt/2x/iX8Tkq+4KAXLPEgcfbFDofrSAX9rh6 qUkAQ9xuGZZ30BbJ5S2mFeRrmd26SwkpY6r3w9MrMulAbWz0j0cMHBPfajgCj0WW XlyN+koVPj2uAzuHMZuoTJ6iRGEvXvyznTHx0l6hoaT8+chBEsAAqFmQ3lcwiptw TlIws13tr4BsITWgkV5DGYKqZI+TI84rvcQc6I31cVV+Xv1XVr5mzqgyZkFDYAez uo+r2ljOS4xtAG3PsoV3m6U/ZGrB6Aq1FUsOtxkuwdarQCmmI51FIxYWbztl/IyP HWgX2dgedjGZIxJN/4p6VYJsg/61xpBQLSd40kx/JTo3qCXzNEe0v15LxUl/88QC 5/COgdmOyzcLJLcGkFGBJaqHY5FV5P9TmI0uYc3aYvdQ2M7oX3fWLZuzjHWZwdC3 guKBPJIn45f7gPX65F+yoPWlVi0O6swFoC2yjpW0y//qf2dju+DW0NgqAS/j1h9a 1ws5ApXMiyDRyAsCAwEAAaN6MHgwDAYDVR0TAQH/BAIwADBJBgNVHREEQjBAghBh dXRoLmVhc3lyb2FtLmRlggtlYXN5cm9hbS5kZYIOZ2V0LmVkdXJvYW0uZGWCD3d3 dy5lYXN5cm9hbS5kZTAdBgNVHQ4EFgQU+TleYVuQeNEHCNG0JX/gUUPO6SYwDQYJ KoZIhvcNAQELBQADggIBAA8/O+oRbs7Gbt245Jvdmf9Jfy42rQ+VKqL0/ZHo6+vk rB87gN6GnHq5aUprjcreZSg6sMYRX+khwoezQd2V+Oh0wMTQ4bfKk248Z3qd8hbS e0VGmIrcaULJXWsUJc7cGy8AAw2f37rGbe74rkC5qGz8FN1UY/iQec8iSF/wVLu3 JvN5qVyf/9+isgB/aKNxuVHnfYkbc8GoZAYxogz3AYqvAQ6Lq9DEIS4qgsp3Q2Bl Tz/q1aZL5QjQQ6S+FbiAywTI4/3hvH8Z/k/FFf+/asOS5DBnJNw+3tmqqPVLcjv6 ATsbC5M0Ar6mawgncVDw8YYPZzuXVLIypz2lIGuu/Okvk8YgpS/NFsWPTFFYBTCK TF1+mu1SIcHVz/GonU4qYLIbbdHXdIp57R7PSwK+/R7MA1rzJsAYHJHBgWiP8XuL Ki1frtlBmurQMWfonLk/dcDIviwQsSVlimvfQLcikaTO3vAO2QWWci+dSZ0ATliW 7p8qY+Qh4AQBnkZd3GndsaFDK6zBoYu+lJh7RkQs/RqhiDHd/b5uKGwXPOIDFofw AZd0imUj7nTK25w6Rv2jsYmeMqyM7T9pY+c4KRPPNTCTjQiZXkRo8nNxb7C1Xk6G A+MKd/zpbb2BKk6MSwDuVDFcaxfpvIt6PrcYJDFlCmJ6nlpcC9MwnqJHkx7r++Fs
          </ds:X509Certificate>
        </ds:X509Data>
        </ds:KeyInfo>
        </KeyDescriptor>
      <ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://get.eduroam.de/Auth/Artifact/SOAP" index="1"/>
      <ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://www.easyroam.de/Auth/Artifact/SOAP" index="2"/>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://www.easyroam.de/Auth/SLO_ARTIFACT"/>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://get.eduroam.de/Auth/SLO_ARTIFACT"/>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://www.easyroam.de/Auth/SLO_POST"/>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://get.eduroam.de/Auth/SLO_POST"/>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://get.eduroam.de/Auth/SLO_REDIRECT"/>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://www.easyroam.de/Auth/SLO_REDIRECT"/>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://www.easyroam.de/Auth/SLO_SOAP"/>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://get.eduroam.de/Auth/SLO_SOAP"/>
      <NameIDFormat>
        urn:oasis:names:tc:SAML:2.0:nameid-format:transient
      </NameIDFormat>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://get.eduroam.de/Auth/ACS_POST" index="1"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://get.eduroam.de/Auth/ACS_SIGN" index="2"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://get.eduroam.de/Auth/ACS_ARTIFACT" index="3"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://get.eduroam.de/Auth/ACS_ECP" index="4"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://www.easyroam.de/Auth/ACS_POST" index="5"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://www.easyroam.de/Auth/ACS_SIGN" index="6"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://www.easyroam.de/Auth/ACS_ARTIFACT" index="7"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://www.easyroam.de/Auth/ACS_ECP" index="8"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://auth.easyroam.de/Auth/ACS_POST" index="9"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://auth.easyroam.de/Auth/ACS_SIGN" index="10"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://auth.easyroam.de/Auth/ACS_ARTIFACT" index="11"/>
      <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://auth.easyroam.de/Auth/ACS_ECP" index="12"/>
      <AttributeConsumingService index="1">
        <ServiceName xml:lang="de">DFN easyroam</ServiceName>
        <ServiceName xml:lang="en">DFN easyroam</ServiceName>
        <ServiceDescription xml:lang="de">DFN easyroam</ServiceDescription>
        <ServiceDescription xml:lang="en">DFN easyroam</ServiceDescription>
        <RequestedAttribute FriendlyName="eduPersonEntitlement" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
        <RequestedAttribute FriendlyName="eduPersonScopedAffiliation" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
      </AttributeConsumingService>
      </SPSSODescriptor>
      <Organization>
        <OrganizationName xml:lang="de">e15</OrganizationName>
        <OrganizationName xml:lang="en">e15</OrganizationName>
        <OrganizationDisplayName xml:lang="de">DFN-Verein - Deutsches Forschungsnetz</OrganizationDisplayName>
        <OrganizationDisplayName xml:lang="en">
          German National Research and Education Network, DFN
        </OrganizationDisplayName>
        <OrganizationURL xml:lang="de">http://www.dfn.de</OrganizationURL>
        <OrganizationURL xml:lang="en">http://www.dfn.de/en/</OrganizationURL>
      </Organization>
      <ContactPerson contactType="other" remd:contactType="http://refeds.org/metadata/contactType/security">
        <GivenName>EasyRoam4Edu Support</GivenName>
        <EmailAddress>mailto:eduroam@dfn.de</EmailAddress>
      </ContactPerson>
      <ContactPerson contactType="support">
        <GivenName>EasyRoam4Edu Support</GivenName>
        <EmailAddress>mailto:easyroam4edu@dfn.de</EmailAddress>
      </ContactPerson>
      <ContactPerson contactType="technical">
        <GivenName>Ralf</GivenName>
        <SurName>Paffrath</SurName>
        <EmailAddress>mailto:eduroam@dfn.de</EmailAddress>
      </ContactPerson>
      </EntityDescriptor>

    Für die Nutzung von easyroam sind einige Freigaben einzurichten. Die nachfolgenden Schritte entsprechen dieser Anleitung: easyroam

    Folgende Attribute werden für die Teilnahme an easyroam benötigt:

    Konfiguration der Attribute Resolver

    Im folgenden Beispiel wird der Wert https://www.dfn.de/entitlement/geteduroam/admin für eine(n) Administrator(in) anhand der uid der betreffenden Person gesetzt (im Beispiel 'professorin'), während der Wert https://www.dfn.de/entitlement/geteduroam/optin für alle Nutzenden vergeben wird. Bestehende Attribute Definitions für eduPersonEntitlement wären analog zu ergänzen.
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <AttributeDefinition xsi:type="ScriptedAttribute" id="eduPersonEntitlement">
      <InputAttributeDefinition ref="uid" />
      <Script><![CDATA[
          if (uid.getValues().get(0) == "professorin") {
             eduPersonEntitlement.getValues().add("https://www.dfn.de/entitlement/geteduroam/admin");
          }
          eduPersonEntitlement.getValues().add("https://www.dfn.de/entitlement/geteduroam/optin");
          ]]>
          </Script>
      </AttributeDefinition>
    

    Konfiguration der Attributefreigaben

    Geben Sie die benötigten Attribute nun für den SP1 frei. Dazu fügen Sie folgenden Schnipsel ein.
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
      <AttributeFilterPolicy id="get_eduroam">
        <PolicyRequirementRule xsi:type="Requester" value="https://sp1.local/shibboleth" />
        <AttributeRule attributeID="eduPersonEntitlement">
          <PermitValueRule xsi:type="ValueRegex" regex="^https://www\.dfn\.de/entitlement/geteduroam/.*$" /> 
        </AttributeRule>
        <AttributeRule attributeID="eduPersonScopedAffiliation" permitAny="true"/>
        <AttributeRule attributeID="samlPairwiseID"             permitAny="true"/>
      </AttributeFilterPolicy>
    
    Um Fehler in den Logfiles zu sehen, erhöhen wir das Loglevel:
    <!-- Datei: /opt/shibboleth-idp/conf/logback.xml -->
      <variable name="idp.loglevel.idp" value="DEBUG" />
      <variable name="idp.loglevel.ldap" value="INFO" />
      <variable name="idp.loglevel.messages" value="DEBUG" />
      <variable name="idp.loglevel.encryption" value="DEBUG" />
      <variable name="idp.loglevel.opensaml" value="INFO" />
      <variable name="idp.loglevel.props" value="INFO" />
      <variable name="idp.loglevel.httpclient" value="INFO" />
    
    Stoßen Sie das Neuladen des Servlets manuell an:
    touch /opt/shibboleth-idp/war/idp.war
    
    Dann schauen wir uns die Logfiles an:
    tail -f /opt/shibboleth-idp/logs/idp-process.log
    
    Anschließend öffnen wir den Webbrowser und loggen uns mit dem User professorin beim SP1 ein.

    Fehlerbehandlung

    Was sagt das Logfile? (ausklappbares Feld)

    Auszug Logfile Im Logfile finden wir eine Warnung und einen Fehler:
    WARN [net.shibboleth.shared.spring.custom.AbstractCustomBeanDefinitionParser:60] - Duplicate Definition 'eduPersonEntitlement' of type 'net.shibboleth.idp.attribute.resolver.ad.impl.ScriptedAttributeDefinition'
    
    ERROR [net.shibboleth.shared.service.AbstractReloadableService:179] - Service 'shibboleth.AttributeResolverService': Initial load failed
    net.shibboleth.shared.service.ServiceException: Failed to load [file [/opt/shibboleth-idp/conf/attribute-resolver.xml], class path resource [net/shibboleth/idp/conf/attribute-resolver-syste
    m.xml]]
            at net.shibboleth.shared.spring.service.ReloadableSpringService.doReload(ReloadableSpringService.java:385)
    Caused by: net.shibboleth.shared.service.ServiceException: Unable to initialize attribute resolver for ApplicationContext:shibboleth.AttributeResolverService
            at net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverServiceStrategy.apply(AttributeResolverServiceStrategy.java:96)
    Caused by: net.shibboleth.shared.component.ComponentInitializationException: Attribute Resolver 'ShibbolethAttributeResolver': Plugin 'eduPersonEntitlement' has a dependency on attribute de
    finition 'uid' which doesn't exist
            at net.shibboleth.idp.attribute.resolver.impl.AttributeResolverImpl.checkPlugInDependencies(AttributeResolverImpl.java:704)
      
    Wenn wir das Loglevel nicht erhöhen ist die Fehlermeldung nicht sehr hilfreich:
    
    ERROR [net.shibboleth.idp.profile.impl.ResolveAttributes:289] - Profile Action ResolveAttributes: Invalid AttributeResolver configuration
    net.shibboleth.shared.service.ServiceException: Service component shibboleth.AttributeResolverService is unavailable
    	at net.shibboleth.shared.spring.service.ReloadableSpringService.getServiceableComponent(ReloadableSpringService.java:458)
    

    Fehler 'uid' which doesn't exist beheben, indem die Attribute Definition für uid hinzugefügt wird und im Data Connector uid aus der Liste der zu exportierenden Attributen entfernt wird.
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <AttributeDefinition xsi:type="Simple" id="uid">
      <InputDataConnector ref="myLDAP" attributeNames="uid"/>
      </AttributeDefinition>
    
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
        ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
        baseDN="%{idp.attribute.resolver.LDAP.baseDN}" 
        principal="%{idp.attribute.resolver.LDAP.bindDN}"
        principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
        useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
        connectTimeout="%{idp.attribute.resolver.LDAP.connectTimeout}"
        responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}"
        exportAttributes="givenName sn mail displayName"> 
    
    Bleibt noch die Warnung mit der doppelten Definition für eduPersonEntitlement. Die beiden Definitionen werden zu einer zusammen gefasst:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <AttributeDefinition xsi:type="ScriptedAttribute" id="eduPersonEntitlement">
        <InputAttributeDefinition ref="eduPersonAffiliation" />
        <InputAttributeDefinition ref="uid" />
          <Script><![CDATA[
            eduPersonEntitlement.getValues().add("https://www.dfn.de/entitlement/geteduroam/optin");
            if (eduPersonAffiliation.getValues().contains("member")) {
              eduPersonEntitlement.getValues().add("urn:mace:dir:entitlement:common-lib-terms");
            }
            if (uid.getValues().get(0) == "professorin") {
              eduPersonEntitlement.getValues().add("https://www.dfn.de/entitlement/geteduroam/admin");
            }
        ]]></Script>
      </AttributeDefinition>
      
    Stoßen Sie erneut das Neuladen des Servlets manuell an:
    touch /opt/shibboleth-idp/war/idp.war
    
    Dann schauen wir uns die Logfiles an:
    tail -f /opt/shibboleth-idp/logs/idp-process.log
    
    Anschließend öffnen wir den Webbrowser und loggen uns mit dem User professorin beim SP1 ein.

    Übung 3: An den SP übertragene Attribute

    Jetzt möchten wir uns anschauen, welche Attribute und Attributwerte an den SP übertragen werden und welche Fehler auftauchen können. Um die komplette SAML-Assertion einzusehen, setzen Sie das Loglevel für idp, messages und encryption auf DEBUG.
    <!-- Datei: /opt/shibboleth-idp/conf/logback.xml -->
      <variable name="idp.loglevel.idp" value="DEBUG" />
      <variable name="idp.loglevel.ldap" value="INFO" />
      <variable name="idp.loglevel.messages" value="DEBUG" />
      <variable name="idp.loglevel.encryption" value="DEBUG" />
      <variable name="idp.loglevel.opensaml" value="INFO" />
      <variable name="idp.loglevel.props" value="INFO" />
      <variable name="idp.loglevel.httpclient" value="INFO" />
    
    Stoßen Sie das Neuladen des Servlets manuell an:
    touch /opt/shibboleth-idp/war/idp.war
    
    Als erstes prüfen wir idp-process.log mit welchem Algorithmus die Assertion verschlüsselt wurde. Ab Shibboleth IdP 3.4 wurde eine Einstellung aufgenommen, mit der der Algorithmus eingestellt werden kann, mit dem die Assertions verschlüsselt werden. Der alte Standard-Algorithmus AES-CBC gilt nicht mehr als sicher, daher ist bei neu installierten IdPs ab Version 4.x die Voreinstellung AES-GCM. Einige Nicht-Shibboleth-Service Provider können mit dem aktuell als sicher betrachteten Algorithmus AES-GCM noch nicht umgehen. Eine Liste der uns bekannten SPs mit diesem Problem finden Sie auf folgender Seite im Wiki:
    https://doku.tid.dfn.de/de:shibidp:config-encryption#konfiguration_des_verschluesselungsalgorithmus
    Dort finden Sie ebenfalls Lösungsvorschläge.
    INFO [Shibboleth-Audit.SSO:333] - 127.0.0.1|2025-02-05T10:23:49.890217440Z|2025-02-05T10:24:07.963174270Z|extern|https://sp1.local/shibboleth|_c01dc0b5c564afedad1dd|password|2025-02-05T10:24:01.652597568Z|eduPersonEntitlement,uid,samlPairwiseID,mail,givenName|eVIQHtaTn2vBt6bbxWexuYw+D/87vOYyvoaRomKPmkhwGvYg==|transient|false|false|AES128-GCM|Redirect|POST||Success||1291d44|Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
    
    Suchen Sie nun nach Assertion before encryption. Hier finden Sie die vom IdP an den SP übertragenen Attribute.

    Assertion
    <!-- Datei: /opt/shibboleth-idp/logs/idp-process.log -->
      2025-02-05 11:24:07,874 - 127.0.0.1 - DEBUG [org.opensaml.saml.saml2.encryption.Encrypter:332] - Assertion before encryption:
      <?xml version="1.0" encoding="UTF-8"?><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_c01dc0b5c564af29d378db6eeedad1dd" IssueInstant="2025-02-05T10:24:07.697Z" Version="2.0">
        <saml2:Issuer>https://idp.local/idp/shibboleth</saml2:Issuer>
        <saml2:Subject>
          <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" NameQualifier="https://idp.local/idp/shibboleth" SPNameQualifier="https://sp1.local/shibboleth" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">AAdzZWNyZXQxVY9g+piuV1rz6NzqpxxCJbueMqErv/HtVmXkzQz1CTCfs2VRFHb7XaqSb3iWm8nn3AUGOSMeqK/K39+v1peVIQHtaTn2vBt6bbxWexuYw+D/87vOYyvoaRomKPmkhwGvYg==
          <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
            <saml2:SubjectConfirmationData Address="127.0.0.1" InResponseTo="_38ae57a85200d167d971742ef2af5d56" NotOnOrAfter="2025-02-05T10:29:07.804Z" Recipient="https://sp1.local/Shibboleth.sso/SAML2/POST"/>
          </saml2:SubjectConfirmation>
        </saml2:Subject>
        <saml2:Conditions NotBefore="2025-02-05T10:24:07.697Z" NotOnOrAfter="2025-02-05T10:29:07.697Z">
          <saml2:AudienceRestriction>
            <saml2:Audience>https://sp1.local/shibboleth</saml2:Audience>
          </saml2:AudienceRestriction>
        </saml2:Conditions>
        <saml2:AuthnStatement AuthnInstant="2025-02-05T10:24:01.652Z" SessionIndex="_3fc69447bf5408f41d919b9c4b7b4d38">
          <saml2:SubjectLocality Address="127.0.0.1"/>
          <saml2:AuthnContext>
            <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
          </saml2:AuthnContext>
          </saml2:AuthnStatement>
          <saml2:AttributeStatement>
            <saml2:Attribute FriendlyName="mail" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
              <saml2:AttributeValue>hans.nichts@external.nodomain.local</saml2:AttributeValue>
            </saml2:Attribute>
            <saml2:Attribute FriendlyName="uid" Name="urn:oid:0.9.2342.19200300.100.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
              <saml2:AttributeValue>extern</saml2:AttributeValue>
            </saml2:Attribute>
            <saml2:Attribute FriendlyName="eduPersonEntitlement" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
              <saml2:AttributeValue>https://www.dfn.de/entitlement/geteduroam/optin</saml2:AttributeValue>
            </saml2:Attribute>
            <saml2:Attribute FriendlyName="samlPairwiseID" Name="urn:oasis:names:tc:SAML:attribute:pairwise-id" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
              <saml2:AttributeValue>EJZ54S4NWQ6HJVARSKXPHC7NP5MTKPHI@local</saml2:AttributeValue>
            </saml2:Attribute>
            <saml2:Attribute FriendlyName="givenName" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
              <saml2:AttributeValue>Hans</saml2:AttributeValue>
            </saml2:Attribute>
          </saml2:AttributeStatement>
        </saml2:Assertion>
    

    Link zum Troubleshooting

    Übung 4: Freigabe der persistentID

    Sie haben bei der Vorbereitung in mehreren Schritten die persistentID konfiguriert. Sie wird aus einem Quellattribut (hier: uid) und mit einem Hash errechnet und pro User und Service Provider in der MariaDB-Datenbank abgelegt. Geben Sie die persistentID für alle Service Provider frei. (Ob Sie das auf Ihrem Produktivsystem so machen, steht auf einem anderen Blatt. Hier lernen Sie erst einmal nur, wo das geht, siehe auch unsere Doku.)

  • Editieren Sie die Datei /opt/shibboleth-idp/conf/relying-party.xml.
  • Suchen Sie den Abschnitt shibboleth.DefaultRelyingParty und
  • ergänzen Sie die bean-parent-Zeile wie folgt, um beim Profil SAML2.SSO eine präferierte Rangfolge der NameIDs anzugeben:
  • <!-- Datei: /opt/shibboleth-idp/conf/relying-party.xml-->
      <bean parent="SAML2.SSO" p:postAuthenticationFlows="#{{'attribute-release'}}" p:nameIDFormatPrecedence="#{{'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'}}" />
    

    Übung 5: Schemata einbinden

    dfnEduPerson-Schema

    Das dfnEduPerson-Schema wird nicht mit dem Shibboleth IdP ausgeliefert. Importieren Sie es in die Attribute Registry des IdP, wie im Wiki beschrieben. Schauen Sie in die xml-Datei, um zu sehen, welche zusätzlichen Attribute das Schema mitbringt. Laden Sie sich unsere .xml-Datei herunter und legen Sie sie in den Ordner ./conf/attributes. Editieren Sie die Datei ./conf/attributes/default-rules.xml und importieren Sie dort das neue Schema.
     # Download der Transcoding Properties für dfnEduPerson:
      wget https://download.aai.dfn.de/schema/dfnEduPerson.xml -O /opt/shibboleth-idp/conf/attributes/dfnEduPerson.xml
      ls /opt/shibboleth-idp/conf/attributes/
      custom  default-rules.xml  dfnEduPerson.xml  eduCourse.xml  eduPerson.xml  inetOrgPerson.xml  samlSubject.xml
      # Einbinden in default-rules.xml
      [...]
          <import resource="dfnEduPerson.xml" />
      [...]

    dfnMisc-Schema

    Auch die veraltete, aber noch viel benutzte eduPersonTargetedID ist nicht vordefiniert. Da viele SPs sie noch verlangen, sollten Sie sie hinterlegen. Wir haben eine kleine Sammlung verbreiteter, nicht mitgelieferter Attribute für den IdP zusammengestellt. Laden Sie sich die Datei dfnMisc.xml herunter und legen Sie sie nach ./conf/attributes/dfnMisc.xml. Referenzieren Sie sie in ./conf/attributes/default-rules.xml.
     # Download der Transcoding Properties für dfnEduPerson:
      wget https://download.aai.dfn.de/schema/dfnMisc.xml -O /opt/shibboleth-idp/conf/attributes/dfnMisc.xml
      ls /opt/shibboleth-idp/conf/attributes/
      custom  default-rules.xml  dfnEduPerson.xml  eduCourse.xml  eduPerson.xml  inetOrgPerson.xml  samlSubject.xml dfnMisc.xml
      # Einbinden in default-rules.xml
      [...]
          <import resource="dfnMisc.xml" />
      [...]

    Übung 6 eduPersonTargetedID

    Etliche Service Provider sind immer noch nicht in der Lage, die SAML pairwise-id oder die persistentID zu verarbeiten. Sie erwarten den entsprechenden Wert in Form des veralteten Attributs eduPersonTargetedID.

    So konfigurieren Sie den IdP, dass er die persistentId aus der Datenbank holt und als eduPersonTargetedID herausgibt. Die Freigabe erfolgt analog zu allen anderen Attributen in ./conf/attribute-filter.xml

    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <AttributeDefinition id="eduPersonTargetedID" xsi:type="SAML2NameID" nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
        <InputDataConnector ref="myStoredId" attributeNames="persistentId"/>
      <AttributeDefinition>
     
    <!-- ========================================== -->
    <!--      Data Connectors                       -->
    <!-- ========================================== -->    
     
    <DataConnector id="myStoredId"
        xsi:type="StoredId"
        generatedAttributeID="persistentId"
        salt="%{idp.persistentId.salt}">
        <InputAttributeDefinition ref="%{idp.persistentId.sourceAttribute}" />
        <BeanManagedConnection>shibboleth.MySQLDataSource</BeanManagedConnection>
        </DataConnector>