Dies ist eine alte Version des Dokuments!


Sonderfälle bei Generierung und Weitergabe der Persistent ID

Zur Persistent ID allgemein siehe unter Storage und Persistent Identifier.

Beispiel der Hochschule Bremen zur Generierung des Quellattributes zur persistentId mithilfe von „uid“ und „uidNumber“:

attribute-resolver.xml
 <AttributeDefinition xsi:type="ScriptedAttribute" id="uniqueIdentifier" >
    <InputAttributeDefinition ref="uid" />       
    <InputAttributeDefinition ref="uidNumber" />       
    <Script>
            <![CDATA[
     	            uid= uid.getValues().get(0);
      	            uidNumber = uidNumber.getValues().get(0);
       	            stringUidNumber = String(uidNumber);
                    newIdentifier = uid+stringUidNumber;
                    uniqueIdentifier.getValues().add(newIdentifier);
           ]]>       
    </Script>
</AttributeDefinition>

Sofern Sie die persistendId nicht pauschal an alle SPs weitergeben wollen, kann dies in einem RelyingPartyOverride definiert werden.

Dazu muss Folgendes gemacht werden:

  • im Default-Block wird nur die TransientId freigegeben
  • einen Override definieren, in dem für gewisse EntityIds die persistentId freigegeben wird
relying-party.xml
<beans ...>
  <!-- ... -->
  <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
    <property name="profileConfigurations">
       <list>
         <bean parent="Shibboleth.SSO" 
               p:postAuthenticationFlows="#{{'terms-of-use', 'attribute-release'}}" />
         <!-- ... -->
         <bean parent="SAML2.SSO" 
               p:postAuthenticationFlows="#{{'terms-of-use', 'attribute-release'}}" 
               p:nameIDFormatPrecedence="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" />
         <!-- ... -->
        </list>
    </property>
  </bean>
  <util:list id="shibboleth.RelyingPartyOverrides">
     <!-- ... -->
     <!-- komma-separierte Liste der Entity IDs der berechtigten SPs, hier inkl. DFNConf -->
     <bean parent="RelyingPartyByName" 
         c:relyingPartyIds="#{{'https://testsp3.aai.dfn.de/shibboleth', 'https://testsp2.aai.dfn.de/shibboleth', 'https://webconf.vc.dfn.de/shibboleth', 'https://my.conf.dfn.de/shibboleth', 'https://self.conf.dfn.de/shibboleth', 'https://www.conf.dfn.de/shibboleth'}}">
         <property name="profileConfigurations">
           <list>
             <bean parent="SAML2.SSO" 
                   p:postAuthenticationFlows="#{{'terms-of-use', 'attribute-release'}}"
                   p:nameIDFormatPrecedence="#{{'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'}}" />
              <ref bean="SAML2.Logout" />
              <ref bean="SAML2.AttributeQuery" />
              <ref bean="SAML2.ArtifactResolution" />
           </list>
         </property>
     </bean>
  </util:list>
</beans>

Möchte man die Freigabe der persistentId an einen SP weiter einschränken, ähnlich den Attribut-Filterregeln, ohne dabei den V2-Legacy-Support zu aktivieren so muss man etwas tüfteln.

Da die persistentId in der aktuellen IdP-Version (3.2.1) standardmäßig nicht mehr als Attribut, sondern als NameIdentifier behandelt wird, so kann man diese zunächst nur global für bestimmte SPs in der /conf/relying-party.xml freischalten.
Siehe unter Weitere Konfigurationsschritte

Nun hat man zwar die Möglichkeit mit Hilfe von ActivationConditions die NameIDGeneration weiter einzuschränken, jedoch existiert zu diesem Augenblick noch kein AttributContext.
Somit kann man in der /conf/relying-party.xml keine Abhängigkeit zu anderen Attributen abbilden, da diese erst nach dem Login des Nutzers ausgelesen werden.

Um die persistentId wie gewünscht denoch nur dann an einen SP auszuliefern, wenn der Nutzer z.B. einen bestimmten Wert für das Attribut eduPersonEntitlement aufweist, so muss man dieses Vorhaben nun in zwei Schritte aufteilen.
Zunächst geben wir die ID global für den SP frei.

/conf/relying-party.xml
<!-- ... -->
 
<util:list id="shibboleth.RelyingPartyOverrides">
        <bean parent="RelyingPartyByName" c:relyingPartyIds="#{{
                'https://e5.onthehub.com'
                }}">
 
                <property name="profileConfigurations">
                        <list>
                                <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'}}" />
                                <ref bean="SAML2.Logout" />
                                <ref bean="SAML2.AttributeQuery" />
                                <ref bean="SAML2.ArtifactResolution" />
                        </list>
                </property>
        </bean>
 
<!-- ... -->

Anschließend definieren wir eine Condition mit all unseren Anforderungen an ein Attribut und referenzieren diese als Abhängigkeit bei der Generierung der ID.

/system/conf/saml-nameid-system.xml
<!-- ... -->
 
    <bean id="shibboleth.SAML2PersistentGenerator" lazy-init="true"
            class="net.shibboleth.idp.saml.nameid.impl.PersistentSAML2NameIDGenerator"
            p:useUnfilteredAttributes="%{idp.persistentId.useUnfilteredAttributes:true}"
            p:persistentIdGenerator-ref="#{'%{idp.persistentId.generator:shibboleth.ComputedPersistentIdGenerator}'.trim()}"
            p:activationCondition-ref="dreamspark">
        <property name="attributeSourceIds">
            <bean parent="shibboleth.CommaDelimStringArray" c:_0="#{'%{idp.persistentId.sourceAttribute:}'.trim()}" />
        </property>
    </bean>
 
        <bean id="dreamspark" parent="shibboleth.Conditions.OR">
                <constructor-arg>
                        <list>
                                <bean parent="shibboleth.Conditions.NOT">
                                        <constructor-arg>
                                                <bean parent="shibboleth.Conditions.RelyingPartyId" c:_0="https://e5.onthehub.com" />
                                        </constructor-arg>
                                </bean>
                                <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate" p:useUnfilteredAttributes="true">
                                        <property name="attributeValueMap">
                                                <map>
                                                        <entry key="eduPersonEntitlement">
                                                                <list>
                                                                        <value>Dreamspark-Premium-User-Wirtschaft</value>
                                                                        <value>Dreamspark-Premium-User-Informatik</value>
                                                                </list>
                                                        </entry>
                                                </map>
                                        </property>
                                </bean>
                        </list>
                </constructor-arg>
        </bean>
 
<!-- ... -->

Wenn es sich um den oben genannten SP handelt und der Nutzer keinen der oben genannten Attribut-Werte aufweist, dann schlägt die Condition fehl und es wird keine persistentID generiert.
In allen anderen Fällen sollte die Generierung der persistentID problemlos funktionieren.

Das folgende wurde uns netterweise von den Kollegen der Uni Jena zur Verfügung gestellt und soll als Beispiel dienen wie bei Bedarf das IdM-Quellattribut gewechselt werden kann und dabei schon bestehende persistentIds zu erhalten

Ziel der Aktion war das Auswechseln des Quellattributs der persistentId (gespeichert in einer PostgreSQL-Datenbank), die doch nicht so unique uid sollte hierbei durch die eduPersonUniqueId ersetzt werden. Die eduPersonUniqueId bilden wir im IDM aus einer UUID ohne Bindestriche mit Scope hinten dran (Beispiel: 0c845b14f1c643ccac9de204632512cd@uni-xy.de) und stellen sie per LDAP-Server zur Verfügung. Der Shibboleth IdP ist Version 3.2.1.

1.) Den IdP stoppen.

2.) In /opt/shibboleth-idp/conf/saml-nameid.properties wird die Eigenschaft idp.persistentId.sourceAttribute = eduPersonUniqueId gesetzt.

3.) Die Werte der Spalte localid in der Tabelle shibpid müssen auf die jeweiligen Werte des Attributs eduPersonUniqueId abgeändert werden. Ich habe mir für die ganze Aktion ein Shellskript geschrieben. 3.1. - Man erzeugt sich einen Dump der Tabelle shibpid. 3.2. - Man arbeitet sich zeilenweise durch diesen Dump. Die Spalte principalname in der Tabelle shibpid referenziert den Benutzernamen (uid). Über diesen sucht man nun im LDAP-Server nach der jeweiligen eduPersonUniqueId und setzt in der Spalte localid deren Wert anstelle des bisherigen ein.

Beispiel: Aus…

"https://idp.uni-xy.de/idp/shibboleth";"https://testsp2.aai.dfn.de/shibboleth";"aaidemo";"aaidemo";"Znc0wfn/YabcZe7neb73Es123456";"";"2014-08-12 14:10:47.29";""

…wird so…

"https://idp.uni-xy.de/idp/shibboleth";"https://testsp2.aai.dfn.de/shibboleth";"aaidemo";"0e2cba36852b44d8be29e4168ec71e0d@uni-xy.de";"Znc0wfn/YabcZe7neb73Es123456";"";"2014-08-12 14:10:47.29";""

3.3. - Man kopiert den modifizierten Dump zurück in die Tabelle shibpid.

4.) Den IdP wieder starten und überprüfen, ob die Sache funktioniert hat.

Übrig bleibt nun noch das Entfernen der uid als Bestandteil der Bildungsvorschriften anderer Attribute, z.B. beim eduPersonPrincipalName (= uid + „@uni-xy.de“). An den Bestandsnutzern kann man da nichts machen, der Plan ist aber, für neue Benutzer auch hier eduPersonPrincipalName = eduPersonUniqueId auszuliefern. Das sollte dann für eine ausreichende Kollisionsfreiheit sorgen.

  • Zuletzt geändert: vor 4 Jahren