Berechtigungen in CDS und RAP — eine Übersicht
In Kundenprojekten fällt uns immer wieder auf, dass das Thema Berechtigungen oft sehr unbeliebt ist. Nicht selten wird das Berechtigungskonzept auf „S_START" beschränkt – also auf die Startberechtigungsprüfung, die von SAP technisch gefordert wird.
Dieser Artikel soll das Thema etwas durchleuchten – mit praktischen Tipps aus realen Softwareprojekten und ein wenig RAP-Hintergrundwissen 😊. Wir starten mit den verschiedenen Ebenen eines Berechtigungskonzeptes und erklären anhand einiger Leitsätze, worauf es wirklich ankommt. Wir schließen mit Sonderfällen und Tipps und Tricks ab.
Die Ebenen der Berechtigungsprüfung
Die Grundarchitektur von RAP-basierten Anwendungen bzw. Services besteht aus dem OData-Service als Endpunkt, den Lesezugriffen auf der Datenbank über CDS Views sowie den transaktionalen Änderungen über RAP Business Objects und deren Implementierung im ABAP.
| Ebene | Lesen | Schreiben |
|---|---|---|
| 1 — Start | S_START: Die Startberechtigung – wer darf den OData-Service im SAP-Backend ausführen, um damit Daten zu lesen oder Änderungen vorzunehmen? (gilt für Lesen und Schreiben gleichermaßen) | |
| 2 — Global | Für globale Berechtigungsprüfungen wird per Konvention das Activity-Feld ACTVT mit dem Wert '03' verwendet, um damit zu prüfen, ob der aktuelle Nutzer überhaupt lesen darf – so auch in der DCL zu dem exponierten CDS View. Man kann argumentieren, dass die S_START-Berechtigungsprüfung die globale Leseprüfung im Kontext eines OData-Services überflüssig macht, denn das Ändern ohne Lesen macht in der Regel wenig Sinn, und wer weder lesen noch schreiben darf, benötigt auch keine Startberechtigung. Wir raten allerdings dazu, beide Konzepte einzusetzen, um für andere Zugriffe auf die Daten vorbereitet zu sein. | RAP BOs bieten mit dem "authorization master ( global )" die Möglichkeit, globale Prüfungen für die Änderungsoperationen per Authority-Check zu realisieren: Darf der aktuelle Nutzer die Operation CREATE, UPDATE, DELETE oder eine der Actions generell ausführen? Das kann pro Operation einzeln gesteuert werden. Da Actions konzeptionell spezielle Update-Operationen sind, gibt es eine nützliche Deklaration, um die Prüfung der Update-Operation wiederzuverwenden bzw. dorthin zu delegieren. |
| 3 — Instanz | Neben der globalen ACTVT-Prüfung können natürlich auch weitere Berechtigungsfelder hinzugefügt werden, z. B. für welche SalesOrg bin ich berechtigt? Während die ACTVT-Prüfung instanzübergreifend immer das gleiche Ergebnis liefert, wird die SalesOrg pro Zeile geprüft, und so werden bereits auf der Datenbank die nicht berechtigten Instanzen herausgefiltert. Damit kann der OData-Lesezugriff auf einem CDS View durch RAP (genauer gesagt durch SADL) funktional korrekt in einem einzigen Statement auf der Datenbank ausgeführt werden – inklusive Paging mit Limit und Offset sowie weiteren Filteroperationen. | Mit dem "authorization master ( instance )" können Instanz-Operationen auf Instanzebene geprüft werden: Darf der aktuelle Benutzer (der global berechtigt ist – das wird sinnvollerweise von RAP vorab geprüft) diese Instanz mit dieser Operation ändern bzw. löschen? Die Operation Read ist in einem managed RAP BO nicht zu prüfen, da die RAP-Laufzeit hier ebenfalls aus dem per DCL geschützten CDS View liest und damit die Prüfung der DCL bereits indirekt greift. |
Leitsätze der Berechtigungsprüfungen
Die Berechtigungsprüfung findet immer auf dem I- oder R-Layer statt, nicht auf dem C-Layer
Berechtigungen sind essenzielle Eigenschaften der Daten und unabhängig von Szenario oder Protokoll. Der Consumption-Layer gehört semantisch zur Service-Ebene – für verschiedene Services oder Apps gibt es unterschiedliche Projektionen mit unterschiedlichen Daten-Selektionen und relevanten BO-Operationen. Die dahinterliegende Berechtigungsprüfung ist aber in jedem Fall identisch – genauso wie die Geschäftslogik und die Daten (keine Regel ohne Ausnahmen).
Der transaktionale Puffer muss zu jedem Zeitpunkt berechtigungskonform sein
Es dürfen keine Daten in den Puffer gelangen, für die der Benutzer nicht berechtigt ist. Das Risiko ist zu groß, dass Funktionalität ausgeführt wird, die auf den nicht berechtigten Daten beruht, und dies in einem Angriff ausgenutzt wird. Aus dem Leitsatz folgen drei Pflichten:
(a) Nichts Unberechtigtes darf hinein — Create. Die Instanzprüfung ist, wie oben beschrieben, bei statischen Operationen nicht relevant, sondern nur die globale Berechtigungsprüfung. Die globale Prüfung kennt allerdings die Daten nicht. Daher ist über einen Precheck zu prüfen, dass keine unerlaubten Werte beim Create (oder einer statischen Factory-Methode) übergeben wurden. Eine Validierung ist an dieser Stelle nicht zu empfehlen, denn bei deren Ausführung stehen die Daten bereits im Puffer.
(b) Nichts darf durch Änderung unberechtigt werden — Update. Das wird leider meist übersehen: Die Instanzprüfung sieht den alten Zustand. Der neue Zustand ist allerdings auch zu prüfen. Wenn ich für eine bestimmte Region berechtigt bin, darf ich Daten nicht in eine andere Region „schieben". Die Instanzberechtigung prüft den Ausgangszustand, der Precheck den Zielzustand – beides ist nötig.
(c) Der eigene Code darf nichts Unberechtigtes hineinschreiben. Interne Logik wie Determinations oder Actions via EML "IN LOCAL MODE" läuft an der Berechtigungsprüfung vorbei. Das sollte man bei der Realisierung wissen und berücksichtigen.
Geprüft wird am Eingang — danach nur noch privilegierte Zugriffe
Berechtigungen werden am exponierten Eingang geprüft, d. h. bei allen im OData-Service exponierten Daten und Operationen. In Application Jobs ist es der führende Datentopf, auf den sich die Select Options beziehen.
Technisch ist das über einen Privileged Mode für die Sekundärzugriffe realisierbar – aber leider nicht überall:
| Technologie | Unterstützung Privileged Mode |
|---|---|
| CDS | "WITH PRIVILEGED ACCESS" ist eine klare Konsumentenentscheidung und für alle CDS Views verfügbar |
| RAP | "PRIVILEGED" in EML setzt voraus, dass das konsumierte RAP BO den Privileged Mode anbietet und auch konsistent implementiert hat |
| BAPI | BAPIs bieten in der Regel keinen Privileged Mode an (das wäre bei RFC-fähigen Funktionsbausteinen wohl auch ziemlich gefährlich) |
DSGVO/GDPR übertrumpft alles
Im Kontext der Datenschutzgrundverordnung zum Schutze von Privatpersonen müssen neben vielen anderen Aspekten auch die Datenminimierung und die kontextgebundene Freigabe nach dem Need-to-know-Prinzip berücksichtigt werden:
- In einer Wertehilfe aller Geschäftspartner ist es sicherlich keine gute Idee, deren Adresse anzuzeigen.
- Die Person, die eine SalesOrder bearbeitet, hat aber ein berechtigtes Interesse an der Lieferadresse.
Sensible Daten dürfen nicht über Wertehilfen exponiert werden. Daten auf einer Fiori-ObjectPage sind höchstens dann zu sehen, wenn der Zugriff auf das führende Objekt berechtigt ist. Wenn z. B. der Zugriff auf die SalesOrder berechtigt ist, dann darf (höchstens) auch die Lieferadresse des Käufers zu sehen sein.
Aber wie wird verhindert, dass über das OData-Protokoll alle Adressen angefragt werden? Dazu muss der CDS View mit dem Zugriff Privileged-Only versehen und die Assoziation von der SalesOrder zum BusinessPartner privilegiert werden.
Diese Erläuterungen sind als Hinweise zu verstehen; das Thema DSGVO/GDPR ist sehr komplex.
Sonderfälle
Kundeneigene Views auf SAP-Standard-Views (im Clean-Core-Umfeld)
Nicht selten sehen wir Z-Views, die SAP-Standard-Views verschalen und exponieren – ohne DCL. In 99 % der Fälle sollte man die DCL des Standard-Views erben. Im Clean-Core-Umfeld gilt darüber hinaus, dass SAP sich vorbehält, die DCL im SAP-View zu ändern, z. B. durch die Einführung eines weiteren Berechtigungsfeldes im Berechtigungsobjekt und im CDS View.
Dies könnte zu einem Syntaxfehler im Z-View führen. Um dem vorzubeugen, wird empfohlen, die Berechtigungsprüfung auf einen assoziierten View zu delegieren:
... inheriting conditions from entity <SAP View>
replacing { root with _DCLOrigin };
Dabei ist "_DCLOrigin" eine Assoziation, die wiederum auf den SAP-View zeigt. Das heißt: Zur Laufzeit wird die WHERE-Clause auf dem Assoziationsziel ausgeführt; damit wird die Assoziation zu einem Inner Join, und die Instanzen des Z-Views werden entsprechend eingeschränkt.
Unmanaged Query / Custom Entity
Die Prüfung muss in der Query-Implementierung selbst erfolgen.
Zusätzliche Logik in der Projektion oder in BO-Interfaces
Die Berechtigung aus dem Basis-BO wird automatisch geerbt. Für neu in der Projektion definierte Actions und Functions kann eine eigene Berechtigungssteuerung definiert werden.
Tipps und Tricks
SACMSEL
Interessant bei Berechtigungsproblemen im CDS-Umfeld. Erwartete Daten nicht sichtbar? Dann hier mal reinschauen.
Authorization Context in der BDEF
Während die Berechtigungsprüfung in der DCL eher deklarativen Charakter hat, damit die ASQL-Laufzeit die Prüfung auf der Datenbank realisieren kann, ist in RAP bzw. in ABAP der klassische Authority-Check nach wie vor die Lösung. Für unmanaged RAP BOs soll die vorhandene Logik so weiterlaufen, wie sie ist; daher ergibt ein deklaratives Konzept für die Laufzeitimplementierung höchstens für managed RAP BOs Sinn.
Im Zuge der ABAP-Cloud-C1-Freigabe von S/4HANA-BOs wurden die Authorization Contexts eingeführt. Mit diesen kann definiert werden:
- Welche Berechtigungsprüfungen im BO stattfinden – einmal beschrieben, führen nicht aufgelistete Berechtigungsprüfungen zur Laufzeit zu einem Kontraktfehler in RAP, also zu einem Dump.
- Welche Berechtigungsprüfungen im BO ignoriert werden sollen – das ist auf SAP-Seite beim Bauen von RAP-BO-Fassaden für Legacy Code wichtig, damit nicht relevante Prüfungen unterdrückt werden können, ohne eine Disruption des Bestandscodes herbeizuführen.
- Welche Berechtigungsprüfungen im Privileged Mode unterdrückt werden sollen. Das ist standardmäßig die gleiche Liste wie im ersten Punkt – DSGVO/GDPR spielen hier aber noch mit hinein.
Zentrale Berechtigungsklasse
Insbesondere globale Berechtigungsprüfungen im transaktionalen Kontext lassen sich sehr elegant über ein zentrales Berechtigungsobjekt, eine zentrale Berechtigungsprüfung und eine zentrale Klasse zur Ausführung dieser Prüfung realisieren. Wir nutzen diesen Ansatz gerne als Teil des ganzheitlichen Berechtigungskonzeptes in Kundenprojekten – analog zu S_START ein Z_EDIT mit dem Namen der Anwendung als Parameter: Hat der aktuelle Benutzer die Berechtigung, Änderungen in dieser App durchzuführen?
Infografik



