Tönjes Consulting
SAP Technologie · Elsfleth · seit 2018
BTP Security

Role Collections aus der BTP zentral verwalten

Import in SAP Cloud Identity Services, Mitgliederzuweisung und der Weg zurück in die BTP

Wer Berechtigungen in SAP BTP über Role Collections steuert, kennt das Problem: Sobald mehrere Subaccounts oder ein Global Account im Spiel sind, wird die Mitgliederpflege schnell unübersichtlich, wenn sie direkt in jedem einzelnen BTP Cockpit passiert. Eine saubere Alternative ist, die Role Collections zentral in SAP Cloud Identity Services (Identity Authentication / Identity Provisioning) abzubilden, dort die Mitgliederzuweisung zu pflegen und die Änderungen anschließend automatisiert zurück in die BTP zu schreiben.

Dieser Artikel beschreibt die drei Schritte dieses Musters und geht am Ende auf eine Feinheit ein, die in der Praxis zu einem schwer zu deutenden Fehler führen kann, wenn man sie nicht kennt.

Schritt 1: Role Collections aus der BTP in den IAS importieren

Im ersten Schritt wird ein Identity-Provisioning-Job angelegt, der die SAP BTP XS Advanced UAA (Cloud Foundry) als Quellsystem und die Local Identity Directory (also den IAS-eigenen Verzeichnisdienst) als Zielsystem verwendet. Dieser Job liest die Role Collections der BTP als Gruppen und legt sie im IAS als Gruppen an – inklusive ihrer bisherigen Mitglieder.

Für diesen Schritt braucht es keine besondere, angepasste Transformation – der Standard-Job reicht aus. Wichtig ist lediglich eine einzige Property: ips.application.id muss sowohl im Quellsystem (BTP) als auch im Zielsystem (IAS) gepflegt sein. Erst dadurch werden die importierten Gruppen im IAS korrekt als sogenannte Authorization Groups angelegt, also als Gruppen, die eindeutig einer bestimmten Applikation zugeordnet sind – und nicht als generische, freischwebende Gruppen ohne Anwendungsbezug. Diese Zuordnung wird später beim Rückschreiben in Schritt 3 wichtig, da sie sich über die Funktion isApplicationSpecificGroup() gezielt ansprechen lässt.

Nach einem erfolgreichen Lauf liegen die Role Collections als Authorization Groups im IAS vor.

Schritt 2: Mitglieder zuweisen

Ab diesem Punkt findet die eigentliche Verwaltung statt: In der Identity Authentication Admin Console werden die importierten Gruppen geöffnet, und über den Reiter "User Members" lassen sich Nutzer hinzufügen oder entfernen – ganz normal über die Oberfläche, per SCIM-API oder in Kombination mit weiteren, regelbasierten Zuweisungen über eigene Transformationen. Der Vorteil: Diese Zuweisung passiert zentral im IAS, unabhängig davon, in wie vielen BTP Subaccounts oder im Global Account die jeweilige Role Collection tatsächlich existiert.

Hinweis: SAP plant für Q4 die Funktionen Group Nesting und Composite Role. Hoffentlich wird das dann ein echter Gamechanger, denn die Target Variable assignGroup in den Transformations ist aktuell der limitierende Faktor für Szenarien wie dieses.

Schritt 3: Gruppen wieder in die BTP provisionieren

Im dritten Schritt läuft die Richtung um: Jetzt ist die Local Identity Directory die Quelle, und die jeweilige BTP-Umgebung (Subaccount oder Global Account, wieder über den XSUAA-Connector) das Ziel. Dieser Job schreibt die im IAS gepflegten Mitgliederlisten zurück in die entsprechenden Role Collections.

  • Zusätzlich haben wir die Möglichkeit eingebaut, über einen Filter (customgroup.filter) weitere Gruppen hinzuzunehmen, statt den Job auf eine feste, explizit konfigurierte Gruppenmenge zu beschränken.

Die Gruppen-Transformation für die Schreibrichtung sieht vom Prinzip her so aus:

{
  "condition": "isAttributeWithOptionalPrefix($.displayName, xsuaa.group.prefix) && (isRegularGroup() || isApplicationSpecificGroup()) && (('%customgroup.filter%' === 'null') || ($.displayName =~ /%customgroup.filter%.*/))",
  "mappings": [
    {
      "sourcePath": "$.displayName",
      "targetPath": "$.displayName",
      "targetVariable": "entityIdTargetSystem",
      "functions": [
        {
          "function": "replaceFirstString",
          "condition": "isAttributeWithMandatoryPrefix(@, xsuaa.group.prefix)",
          "regex": "%xsuaa.group.prefix%",
          "replacement": ""
        }
      ]
    },
    {
      "sourceVariable": "entityIdTargetSystem",
      "targetPath": "$.id"
    },
    {
      "sourcePath": "$.members",
      "preserveArrayWithSingleElement": true,
      "optional": true,
      "targetPath": "$.members",
      "functions": [
        { "function": "resolveEntityIds" }
      ]
    },
    {
      "constant": "USER",
      "preserveArrayWithSingleElement": true,
      "optional": true,
      "targetPath": "$.members[*].type"
    }
  ]
}

Wichtig hierbei ist die Variable entityIdTargetSystem: Da das IAS die interne BTP-ID einer Role Collection nicht kennt, wird als stabiler Korrelationsschlüssel der (ggf. vom Präfix befreite) Gruppenname verwendet. Über diesen Schlüssel soll Identity Provisioning im Zielsystem die passende, bereits bestehende Role Collection wiederfinden und deren Mitglieder aktualisieren – statt versehentlich eine neue, doppelte Role Collection anzulegen.

Die Feinheit: scim.group.unique.attribute

Genau an dieser Korrelation kann es zu einem Fehler kommen, der auf den ersten Blick widersprüchlich wirkt:

error=The request to create an entity has failed with: 409 Conflict
The attempt to retrieve the existing entity from the target system was unsuccessful. More than one entity found

Das Verblüffende daran: Die betroffene Role Collection existiert nachweislich nur einmal in der BTP – ein Blick ins BTP Cockpit unter Security → Role Collections zeigt keinen Duplikateintrag. Trotzdem meldet Identity Provisioning beim Schreiben, es habe mehr als eine passende Entität gefunden.

Der Grund liegt in der Art, wie Identity Provisioning standardmäßig korreliert: Es fragt das Zielsystem per SCIM-Filter ab (GET /Groups?filter=displayName eq "<Name>"), um zu prüfen, ob die Gruppe bereits existiert. Bei der SCIM-Groups-Implementierung der SAP BTP XS Advanced UAA (Cloud Foundry) wird dieser filter-Parameter jedoch nicht zuverlässig ausgewertet – die Abfrage liefert unabhängig vom Filterwert schlicht den kompletten, ungefilterten Gruppenkatalog der Zone zurück. Sobald in der Zone mehr als eine Gruppe existiert (bei einer Global-Account-Zone mit Standard-Rollensammlungen praktisch immer der Fall), bekommt Identity Provisioning bei jeder Korrelationsanfrage automatisch mehr als ein Ergebnis zurück und bricht sicherheitshalber mit dem beschriebenen 409-Fehler ab, statt ein potenziell falsches Update durchzuführen.

Das lässt sich mit zwei direkten API-Aufrufen gegen dieselbe Schnittstelle nachvollziehen: Ein GET /Groups?filter=... liefert unabhängig vom Filter immer alle Gruppen der Zone zurück, während ein direkter, pfadbasierter Aufruf GET /Groups/{id} – bei dem id in diesem Fall dem Klartextnamen der Gruppe entspricht – zuverlässig genau ein Ergebnis liefert.

Die Lösung besteht darin, Identity Provisioning explizit anzuweisen, für die Korrelation den direkten, pfadbasierten Lookup zu verwenden statt der defekten Filtersuche. Das steuert die Zielsystem-Property:

scim.group.unique.attribute = id

Da id in diesem Szenario ohnehin dem über entityIdTargetSystem berechneten Gruppennamen entspricht, findet Identity Provisioning die bestehende Role Collection darüber zuverlässig und eindeutig und aktualisiert nur noch deren Mitgliederliste, statt eine neue Entität anzulegen oder mit einem Konfliktfehler abzubrechen.

Praktischer Hinweis

Diese Eigenschaft der SCIM-Groups-Schnittstelle betrifft grundsätzlich jedes Zielsystem vom Typ SAP BTP XS Advanced UAA (Cloud Foundry) – also jeden einzelnen Subaccount und den Global Account gleichermaßen. Es lohnt sich daher, scim.group.unique.attribute = id von Anfang an bei jedem so konfigurierten Zielsystem zu setzen, statt erst zu warten, bis der Fehler in einem weiteren Subaccount auftritt. Wie bei jeder Änderung an einer produktiven Transformation empfiehlt sich vorher ein Testlauf in einer Sandbox-Umgebung mit einer einzelnen, klar abgegrenzten Gruppe.

Zusammenfassung

Das Muster – Role Collections aus der BTP importieren, Mitgliedschaft zentral im IAS pflegen, Änderungen zurückschreiben – funktioniert zuverlässig, sobald die Korrelation beim Rückschreiben über die ID statt über eine (in der Praxis nicht immer verlässliche) Filtersuche läuft. Die Property scim.group.unique.attribute = id ist dabei der entscheidende Baustein, der aus einem scheinbar unlösbaren Konfliktfehler ein stabil funktionierendes Provisioning macht.

← Zur Übersicht

Weiterlesen

Ähnliche Artikel