Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
de:shibidp3userdepro [2018/07/19 15:26]
Wolfgang Pempe
de:shibidp3userdepro [2020/04/16 09:38] (aktuell)
Silke Meyer
Zeile 1: Zeile 1:
 +~~NOTOC~~
 ====== User Deprovisionierung via Attribute Query ====== ====== User Deprovisionierung via Attribute Query ======
 +{{INLINETOC 2}}
  
 =====Einleitung===== =====Einleitung=====
Zeile 71: Zeile 72:
 </​code>​ </​code>​
  
-Will man nun vom SP aus automatisiert Anfragen stellen so empfiehlt es sich auf den **Attribute Handler** bzw. die [[https://​bitbucket.org/​PEOFIAMP/​shibsp-plugin-attributequery-handler/​|Erweiterung der Gakunin-Föderation]] zurückgreifen.+Will man nun vom SP aus automatisiert Anfragen stellenso existiert hierfür der. sog. Attribute ​Resolver ​Handler:
  
 <file xml /​etc/​shibboleth/​shibboleth2.xml>​ <file xml /​etc/​shibboleth/​shibboleth2.xml>​
 <!-- ... --> <!-- ... -->
  <​OutOfProcess>​  <​OutOfProcess>​
- <​Extensions>​ +            ​<​Extensions>​ 
- <Library path="attributequery-handler.so" fatal="​true"/>​ +                <Library path="plugins.so" fatal="​true"/>​ 
- </​Extensions>​+            </​Extensions>​
  </​OutOfProcess>​  </​OutOfProcess>​
  
  <​InProcess>​  <​InProcess>​
- <​Extensions>​ +            ​<​Extensions>​ 
- <Library path="attributequery-handler-lite.so"​ fatal="​true"/>​ +                <Library path="plugins-lite.so"​ fatal="​true"/>​  
- </​Extensions>​+      </​Extensions>​
  </​InProcess>​  </​InProcess>​
  
Zeile 90: Zeile 91:
  <​Sessions...>​  <​Sessions...>​
  <!-- ... -->  <!-- ... -->
- <​Handler type="AttributeQuery" Location="/​AttributeQuery" acl="​127.0.0.1 ::1" />+ <​Handler type="AttributeResolver" Location="/​AttributeResolver" acl="​127.0.0.1 ::1" />
  <!-- ... -->  <!-- ... -->
  </​Sessions>​  </​Sessions>​
Zeile 103: Zeile 104:
 <​code>​ <​code>​
 !!!ACHTUNG!!! !!!ACHTUNG!!!
-persistnetId ​muss codiert übergeben werden, da Sonderzeichen zu Misserfolg führen!!!+persistentId ​muss codiert übergeben werden, da Sonderzeichen zu Misserfolg führen!!!
 Stichwort URLencoding!!! Stichwort URLencoding!!!
  
-# curl -k "​https://​your-sp.de/​Shibboleth.sso/​AttributeQuery?​entityID=https://​your-idp.de/​idp/​shibboleth"​ --data-urlencode "​nameId=+9Blu1I8v96axDXHj01Gmpg36fM="​+# curl -k "​https://​your-sp.de/​Shibboleth.sso/​AttributeResolver?​entityID=https://​your-idp.de/​idp/​shibboleth"​ --data-urlencode "​nameId=+9Blu1I8v96axDXHj01Gmpg36fM="​
 </​code>​ </​code>​
  
-Alternativ kann dies auch mit Hilfe des mitgelieferten Python-Skriptes ausgeführt werden. 
- 
-<​code>​ 
-# /​etc/​shibboleth/​attributequery.py https://​your-sp.de/​Shibboleth.sso/​AttributeQuery https://​your-idp.de/​idp/​shibboleth +9Blu1I8v96axDXHj01Gmpg36fM= 
-</​code>​ 
  
 =====Verlässlichkeit von Queries===== =====Verlässlichkeit von Queries=====
  
-Hat man seine ersten Queries erfolgreich gestellt kommen schnell die Fragen auf:\\+Hat man seine ersten Queries erfolgreich gestelltkommen schnell die Fragen auf:\\
 **Wann kann ich den Nutzer löschen?** und **Wie verlässlich ist die Rückgabe?​** **Wann kann ich den Nutzer löschen?** und **Wie verlässlich ist die Rückgabe?​**
  
Zeile 143: Zeile 139:
 Denn wenn man einen definierten Wert für das Attribut erhält kann man zumindest davon ausgehen, dass alles funktioniert hat und der Query erfolgreich abgearbeitet wurde und auch sonst keine Probleme bei der Abfrage des LDAP oder sonst irgendwo bei der Kommunikation zwischen den Systemen aufgetreten sind! Denn wenn man einen definierten Wert für das Attribut erhält kann man zumindest davon ausgehen, dass alles funktioniert hat und der Query erfolgreich abgearbeitet wurde und auch sonst keine Probleme bei der Abfrage des LDAP oder sonst irgendwo bei der Kommunikation zwischen den Systemen aufgetreten sind!
  
-Um den LDAP nicht mit **Leichen** voll zu müllen, so wäre eine Möglichkeit die Struktur des LDAP wie folgt zu erweitern:+Um den LDAP nicht mit **Karteileichen** vollzumüllen, so wäre eine Möglichkeit die Struktur des LDAP wie folgt zu erweitern:
  
-   * ou=users,​dc=einrichtung,​dc=de (nur aktive Nutzer) +   ​* ​''​ou=users,​dc=einrichtung,​dc=de'' ​(nur aktive Nutzer) 
-   * ou=archive,​dc=einrichtung,​dc=de +   ​* ​''​ou=archive,​dc=einrichtung,​dc=de''​ 
-      * ou=users,​ou=archive,​dc=einrichtung,​dc=de (nur archivierte Nutzer) +      * ''​ou=users,​ou=archive,​dc=einrichtung,​dc=de'' ​(nur archivierte Nutzer) 
-         * ou=inactive,​ou=users,​ou=archive,​dc=einrichtung,​dc=de (nur inaktive Nutzer+         ​* ​''​ou=disabled,​ou=users,​ou=archive,​dc=einrichtung,​dc=de'' ​(gelöscht, kann aber wieder angelegt werden
-         * ou=blocked,​ou=users,​ou=archive,​dc=einrichtung,​dc=de (nur blockierte Nutzer+         ​* ​''​ou=locked,​ou=users,​ou=archive,​dc=einrichtung,​dc=de'' ​(vorübergehend gesperrt, z.B. aus Sicherheitsgründen
- +         * ''​ou=deleted,​ou=users,​ou=archive,​dc=einrichtung,​dc=de''​ (endgültig gelöschte Nutzer, falls die Identitäten noch gespeichert werden sollen, z.B. um sicherzustellen,​ dass User IDs nicht neu vergeben werden) 
-Scheidet ein Nutzer aus oder muss z.B. auf Grund eines Sicherheitsvorfalls kurzfristig deaktiviert werden, so verschiebt man diesen zunächst nach "​inactive"​.\\+Scheidet ein Nutzer aus oder muss z.B. auf Grund eines Sicherheitsvorfalls kurzfristig deaktiviert werden, so verschiebt man diesen zunächst nach ''​locked''​.\\
 Damit kann er sich schon mal nicht mehr am IdP authentifizieren (da nicht mehr im baseDN).\\ Damit kann er sich schon mal nicht mehr am IdP authentifizieren (da nicht mehr im baseDN).\\
-Kommt der Nutzer nach x-Tagen nicht mehr zurück an die Einrichtung so kann man ihn dauerhaft löschen und nach "blocked" ​verschieben.+Kommt der Nutzer nach x-Tagen nicht mehr zurück an die Einrichtung so kann man ihn dauerhaft löschen und nach ''​disabled''​ oder ''​deleted''​ verschieben. 
 + 
 +Generell reicht es zu, wenn die Einträge unter ''​ou=archive''​ nur noch die "uid" ​beinhalten und nicht mehr alle Attribute(das spart Speicher ^^)
  
-Generell reicht es zuwenn die Einträge unter "​ou=archive"​ nur noch die "​uid"​ beinhalten und nicht mehr alle Attribute. (das spart Speicher ^^)+Jetzt definieren wir im IdP das Attribut [[de:​common_attributes#​a15|schacUserStatus]], das den Status der betreffenden Identität abbilden soll:
  
-Jetzt definieren wir im IdP ein neues Attribut was den zukünftigen Status abbilden soll.+Vokabular für schacUserStatus:​ 
 +  * Attributwert:​ ''​urn:​schac:​userStatus:​de:​aai.dfn.de:​idmStatus:​STATUS'',​ wobei ''​STATUS''​ die folgenden Werte annehmen kann: 
 +  * ''​active''​ (optional) (entspricht AD '​enabled'​) 
 +  * ''​locked''​ (optional) (vorübergehend gesperrt, z.B. aus Sicherheitsgründen) 
 +  * ''​disabled''​ (optional) (gelöscht, kann aber wieder angelegt werden) 
 +  * ''​deleted''​ (mandatory) (Account und Benutzerinformationen gelöscht)
  
 <file xml conf/​attribute-resolver.xml>​ <file xml conf/​attribute-resolver.xml>​
Zeile 164: Zeile 167:
  <!-- schacUserStatus -->  <!-- schacUserStatus -->
  <​AttributeDefinition xsi:​type="​ScriptedAttribute"​ id="​schacUserStatus">​  <​AttributeDefinition xsi:​type="​ScriptedAttribute"​ id="​schacUserStatus">​
- <Dependency ​ref="​archiveLDAP"​ />+ <InputDataConnector ​ref="​archiveLDAP"​ />
  <​DisplayName xml:​lang="​de">​Benutzerstatus</​DisplayName>​  <​DisplayName xml:​lang="​de">​Benutzerstatus</​DisplayName>​
  <​DisplayName xml:​lang="​en">​Userstatus</​DisplayName>​  <​DisplayName xml:​lang="​en">​Userstatus</​DisplayName>​
Zeile 174: Zeile 177:
  <​![CDATA[  <​![CDATA[
  if (typeof entryDN != "​undefined"​ && entryDN.getValues().size() > 0) {  if (typeof entryDN != "​undefined"​ && entryDN.getValues().size() > 0) {
- var prefix = "​urn:​schac:​userStatus:​de:​einrichtung.de:";​ + var prefix = "​urn:​schac:​userStatus:​de:​aai.dfn.de:";​ 
- var ​inactive ​= "ou=inactive,​ou=users,​ou=archive,​dc=einrichtung,​dc=de";​ + var ​disabled= "ou=disabled,​ou=users,​ou=archive,​dc=einrichtung,​dc=de";​ 
- var ​blocked ​= "ou=blocked,​ou=users,​ou=archive,​dc=einrichtung,​dc=de";​+ var ​locked ​ = "​ou=locked,​ou=users,​ou=archive,​dc=einrichtung,​dc=de";​ 
 +                                        var deleted ​= "ou=deleted,​ou=users,​ou=archive,​dc=einrichtung,​dc=de";​
  
  for (i=0; i<​entryDN.getValues().size();​ i++) {  for (i=0; i<​entryDN.getValues().size();​ i++) {
  var tmp = entryDN.getValues().get(i);​  var tmp = entryDN.getValues().get(i);​
  
- if (tmp.endsWith(inactive)) { + if (tmp.endsWith(disabled)) { 
- schacUserStatus.addValue(prefix + "affiliation:inactive");+ schacUserStatus.addValue(prefix + "idmStatus:disabled");
  }  }
- if (tmp.endsWith(blocked)) { + else if (tmp.endsWith(locked)) { 
- schacUserStatus.addValue(prefix + "affiliation:blocked");+ schacUserStatus.addValue(prefix + "idmStatus:locked"​);​ 
 +
 + else if (tmp.endsWith(deleted)) { 
 + schacUserStatus.addValue(prefix + "​idmStatus:​deleted"​);​ 
 +
 + else { 
 + schacUserStatus.addValue(prefix + "​idmStatus:​active");
  }  }
  }  }
Zeile 226: Zeile 236:
 </​file>​ </​file>​
  
-Bekommt ein SP nun bei einem Query einen der folgenden ​beiden ​Werte, so kann er den Nutzer verlässlich sperren oder gar löschen.\\ +Bekommt ein SP nun bei einem Query einen der folgenden Werte, so kann er den Nutzer verlässlich sperren oder gar löschen.\\ 
-   * urn:​schac:​userStatus:​de:​einrichtung.de:affiliation:inactive +   ​* ​''​urn:​schac:​userStatus:​de:​aai.dfn.de:idmStatus:disabled''​ 
-   * urn:​schac:​userStatus:​de:​einrichtung.de:affiliation:blocked +   ​* ​''​urn:​schac:​userStatus:​de:​aai.dfn.de:idmStatus:locked''​ 
 +   * ''​urn:​schac:​userStatus:​de:​aai.dfn.de:​idmStatus:​deleted''​ 
 +   *  
 +Als Beispiel für eine Attribute Query, die ein solches Attribut liefert, kann dieser URL genutzt werden: \\ 
 +https://​testsp3.aai.dfn.de/​Shibboleth.sso/​AttributeResolver?​entityID=https://​testidp.aai.dfn.de/​idp/​shibboleth&​nameId=MCE6NXEQ3FC3PUKY4M75EYCOWN4TGKBH&​format=urn:​oasis:​names:​tc:​SAML:​2.0:​nameid-format:​persistent \\ 
 +(zuvor bitte bei der DFN-AAI Hotline Bescheid sagen, damit die ACL für diesen Handler entsprechend erweitert wird)
 =====Queries einschränken===== =====Queries einschränken=====
  
Zeile 353: Zeile 367:
  # - Die Condition MUSS daher an die LDAP-Dependency (DataConnector) gehangen werden, um die Ausführung der LDAP-Anfragen zu steuern/​vermeiden  # - Die Condition MUSS daher an die LDAP-Dependency (DataConnector) gehangen werden, um die Ausführung der LDAP-Anfragen zu steuern/​vermeiden
  
- <​AttributeDefinition xsi:​type="​Simple"​ id="​uid"​ sourceAttributeID="​uid">​ + <​AttributeDefinition xsi:​type="​Simple"​ id="​uid">​ 
- <Dependency ​ref="​myLDAP"​ />+ <InputDataConnector ​ref="​myLDAP" attributeNames="​uid"/>
  <​!--...-->​  <​!--...-->​
  </​AttributeDefinition>​  </​AttributeDefinition>​
Zeile 364: Zeile 378:
  # Bei Attributen, die zusätzliche Conditions erhalten sollen können diese direkt am Attribut referenziert werden  # Bei Attributen, die zusätzliche Conditions erhalten sollen können diese direkt am Attribut referenziert werden
  
- <​AttributeDefinition xsi:​type="​Simple"​ id="​isMemberOf" sourceAttributeID="​cn" activationConditionRef="​SP-consumes-isMemberOf">​ + <​AttributeDefinition xsi:​type="​Simple"​ id="​isMemberOf"​ activationConditionRef="​SP-consumes-isMemberOf">​ 
- <Dependency ​ref="​groupLDAP"​ />+ <InputDataConnector ​ref="​groupLDAP" attributeNames="​cn"/>
  <​!--...-->​  <​!--...-->​
  </​AttributeDefinition>​  </​AttributeDefinition>​
Zeile 374: Zeile 388:
  
  <​AttributeDefinition xsi:​type="​ScriptedAttribute"​ id="​schacUserStatus"​ activationConditionRef="​SP-consumes-schacUserStatus">​  <​AttributeDefinition xsi:​type="​ScriptedAttribute"​ id="​schacUserStatus"​ activationConditionRef="​SP-consumes-schacUserStatus">​
- <Dependency ​ref="​archiveLDAP"​ />+ <InputDataConnector ​ref="​archiveLDAP"​ />
  <​!--...-->​  <​!--...-->​
  </​AttributeDefinition>​  </​AttributeDefinition>​
Zeile 409: Zeile 423:
  
 Desweiteren sollte man **kleine Pausen zwischen einzelnen Queries** lassen, damit man als SP nicht Gefahr läuft z.B. durch Mechanismen wie Fail2Ban ausgesperrt zu werden.\\ Desweiteren sollte man **kleine Pausen zwischen einzelnen Queries** lassen, damit man als SP nicht Gefahr läuft z.B. durch Mechanismen wie Fail2Ban ausgesperrt zu werden.\\
-Als Betreiber eines IdP ist es durchaus denkbar sich ähnlich wie im Thema [[de:shibidp3fail2ban|Abwehr Brute Force]] Gedanken zu machen um sich gegen zu viele Query-Anfragen zu schützen.+Als Betreiber eines IdP ist es durchaus denkbar sich ähnlich wie im Thema [[de:shibidp:​fail2ban|Abwehr Brute Force]] Gedanken zu machen um sich gegen zu viele Query-Anfragen zu schützen.
  
 Am Besten man nutzt also eine Cachefile, in der man hinterlegt, wann der Nutzer das letzte Mal erfolgreich abgefragt wurde.\\ Am Besten man nutzt also eine Cachefile, in der man hinterlegt, wann der Nutzer das letzte Mal erfolgreich abgefragt wurde.\\
Zeile 430: Zeile 444:
    * https://​wiki.shibboleth.net/​confluence/​display/​IDP30/​SecurityAndNetworking#​SecurityAndNetworking-PortsandConnectors    * https://​wiki.shibboleth.net/​confluence/​display/​IDP30/​SecurityAndNetworking#​SecurityAndNetworking-PortsandConnectors
    * https://​wiki.shibboleth.net/​confluence/​display/​SHIB2/​NativeSPAccountChecking    * https://​wiki.shibboleth.net/​confluence/​display/​SHIB2/​NativeSPAccountChecking
 +
 +{{tag>​idp3}}
  • Zuletzt geändert: vor 23 Monaten