
CDS - Berechtigungsprüfung (Teil 2)
Wie gehst du mit dem Thema Zugriffskontrolle bei Core Data Services in ABAP um und wie kannst du Fehler analysieren? Mehr dazu im Artikel.
Inhaltsverzeichnis
Vor einer ganzen Weile gab es den ersten Teil der Berechtigungsprüfungen und mittlerweile haben sich einige Punkte angesammelt, die wir in diesem Artikel mit dir teilen wollen.
Einleitung
Mit den neuen Table Entities gibt es nun auch Berechtigungsprüfungen direkt auf Tabellenebene. Doch wie sieht es eigentlich mit der Analyse von Fehlern und fehlenden Daten aus? In diesem Artikel schauen wir uns das Thema Berechtigungen im Core Data Service Umfeld an, wie du eine Analyse machen kannst und was es eigentlich mit der Vererbung zu tun hat und welche Fehler du dabei machen kannst.
Beispiel
Im ersten Schritt benötigen wir ein Beispiel, an dem wir üben können. Beim letzten Mal hatten wir ein Berechtigungsobjekt verwendet, doch es gibt auch weitere Alternativen, um die Daten einzuschränken und so dem Anwender eine eingeschränkte Sicht zu geben.
Core Data Service
Legen wir dazu auf der Tabelle ZBS_DMO_MATERIAL einen neuen Core Data Service an. Dazu gehen wir über das Kontext Menü:
Entsprechend geben wir dem View einen Namen und lassen uns eine VIEW ENTITY generieren. Da wir über das Objekt gegangen sind, wird uns auch das Paket bereits vorgeschlagen.
Im Anschluss normalisieren wir die Felder und setzen die Annotation "AccessControl.authorizationCheck" auf #CHECK, damit erhalten wir eine Warnung vom Compiler, wenn wir keine Berechtigungsprüfung hinterlegen.
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Authority base view'
define view entity ZBS_B_DMOAuthBase
as select from zbs_dmo_material
{
key material as Material,
name as MaterialName,
description as Description,
stock as Stock,
stock_unit as Unit,
price_per_unit as PricePerUnit,
currency as Currency
}
Starten wir nun den Preview über F8 im Objekt oder per ALT + F8 (Objekte starten), dann können wir uns die Daten anschauen, wie sie ohne Einschränkungen auf der Datenbank zu finden sind.
Access Control
Zum Abschluss generieren wir ein Access Control auf unserem Core Data Service, um nun die Daten für den Benutzer einzuschränken. Hier können wir über den Core Data Service im Project Explorer gehen, grundsätzlich empfiehlt sich diese Weise, da du schneller an die richtigen Objekte und Informationen kommst.
Das Access Control benennen wir wie den Core Data Service, grundsätzlich kann das Control auch einen anderen Namen haben. Als Template wählen wir im letzten Schritt "defineRoleWithSimpleCondition", das ist aber nicht unbedingt wichtig für den Inhalt, da wir diesen später noch verändern können.
@EndUserText.label: 'Access Control for ZBS_B_DMOAuthBase'
@MappingRole: true
define role ZBS_B_DMOAUTHBASE {
grant
select
on
ZBS_B_DMOAUTHBASE
where
Material LIKE 'F%';
}
Schauen wir nun in der View "CDS Navigator" unseres Core Data Services, dann finden wir unser neu erstellten Access Control. Der Views ist ein erster guter Anlaufpunkt, wenn wir in die Analyse der Berechtigungen einsteigen möchten.
Schauen wir uns nun die Daten im "Data Preview" an, dann ist hat sich die Menge auf alle Materialien mit einem F beginnend reduziert. Der Access Control ist damit auf den Daten aktiv. Ebenfalls sollte nun die Warnung des Compilers im CDS View verschwunden sein.
Vererbung
Nachdem wir nun unseren Core Data Service und das Access Control geniert haben, legen wir einen Interface View auf Basis unseres ersten Views an. Im Grunde machen wir keine weiteren Anpassungen an dem View.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Base for Auth Test'
define view entity ZBS_I_DMOAuthBase
as select from ZBS_B_DMOAuthBase
{
key Material,
MaterialName,
Description,
Stock,
Unit,
PricePerUnit,
Currency
}
Prüfen wir nun den CDS Navigator, dann werden wir feststellen, dass kein Access Control mehr an dem CDS Views aktiv ist, da wir dieses nur für den unteren View definiert haben.
Wenn wir also den Data Preview für unseren neuen Core Data Service ausführen, sehen wir alle Daten und unsere definierte Berechtigungsprüfung wurde ausgehebelt. In bestimmten Szenarien macht dies auch Sinn, vor allem wenn es sich um komplexe Prüfungen handelt und wir einen Core Data Service in einem neuen Szenario verwenden wollen. Wollen wir zum Beispiel nur eine Wertehilfe aufbauen und unkritische Daten des Core Data Service dafür nutzen, dann brauchen wir nicht alle Berechtigungsprüfungen des unteren Views, sondern vielleicht eine neue Prüfung.
Um das Verhalten zu korrigieren, legen wir ein Access Control auf dem CDS View an, dabei verwenden wir das Template "defineRoleWithInheritedConditions". Damit sparen wir uns die Implementierung von vielleicht komplexen Berechtigungsprüfungen und Objekten und vererben die Prüfung von unserem Basis-View.
@EndUserText.label: 'Inherit access control'
@MappingRole: true
define role ZBS_I_DMOAUTHBASE {
grant
select
on
ZBS_I_DMOAUTHBASE
where
inheriting conditions from entity ZBS_B_DMOAUTHBASE;
}
Zugriff
In diesem Kapitel schauen wir uns den Zugriff über ABAP, aber auch in ABAP Unit an und wie wir die Berechtigungen testen können.
ABAP
Im nächsten Schritt lesen wir die Daten in unserem Prozess und verwenden dabei einen einfachen SELECT. Da wir nicht mehr direkt über die Tabelle lesen sollten, verwenden wir den Core Data Service für den Zugriff. So haben wir gleich die Berechtigungsprüfung inkludiert und die englischen Langnamen.
SELECT FROM ZBS_I_DMOAuthBase
FIELDS Material, MaterialName, Description
INTO TABLE @DATA(data_with_restriction).
Sind wir allerdings in einem technischen Prozess, zum Beispiel in einer Validierung oder Hintergrundverarbeitung, dann wollen wir vielleicht auf alle Daten zugreifen können. Dann macht eine Einschränkung der Daten keinen Sinn. Allerdings wollen wir auch keinen zusätzlichen Core Data Service ohne ACL anlegen. Daher lohnt es sich den Zusatz PRIVILEGED ACCESS zu verwenden.
SELECT FROM ZBS_I_DMOAuthBase
FIELDS Material, MaterialName, Description
INTO TABLE @DATA(data_without_restriction)
PRIVILEGED ACCESS.
Schauen wir uns nun das Ergebnis an, dann sehen wir im ersten Schritt die eingeschränkten Daten und im zweiten Zugriff dann ohne Einschränkung den Zugriff.
ABAP Unit
Wie sieht es nun beim Zugriff über ABAP Unit aus? Dazu erstellen wir zuerst unser Grund-Setup, um dann die Prüfung durchführen zu können. Dazu legen wir einen Core Data Service Double an und Mocken erste Daten für den Zugriff. Da wir nur Materialien mit F am Anfang lesen, legen wir auch andere Materialien an.
CLASS ltc_cds_access DEFINITION FINAL
FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PRIVATE SECTION.
CLASS-DATA cds_environment TYPE REF TO if_cds_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS with_access_control FOR TESTING.
ENDCLASS.
CLASS ltc_cds_access IMPLEMENTATION.
METHOD class_setup.
DATA double_data TYPE STANDARD TABLE OF ZBS_B_DMOAuthBase WITH EMPTY KEY.
cds_environment = cl_cds_test_environment=>create( 'ZBS_I_DMOAuthBase' ).
double_data = VALUE #( ( Material = 'F001'
MaterialName = 'Find 1' )
( Material = 'F002'
MaterialName = 'Find 2' )
( Material = 'Z001'
MaterialName = 'Find 3' ) ).
cds_environment->insert_test_data( double_data ).
ENDMETHOD.
METHOD class_teardown.
cds_environment->destroy( ).
ENDMETHOD.
METHOD with_access_control.
SELECT FROM ZBS_I_DMOAuthBase
FIELDS Material, MaterialName, Description
INTO TABLE @DATA(data_with_restriction).
cl_abap_unit_assert=>assert_equals( exp = 2
act = lines( data_with_restriction ) ).
ENDMETHOD.
ENDCLASS.
Grundsätzlich würden wir im Setup erwarten, dass das Access Control ohne Einfuss von uns greift. Wenn wir allerdings die Methode ausführen, dann erhalten wir vom Test Double alle Daten ohne Einschränkung geliefert und unser Unit Test schlägt fehlt.
Wollen wir nun das Access Control validieren, müssen wir dieses in unserem Testfall aktivieren. Dazu verwenden wir die Klasse CL_CDS_TEST_DATA, um einen Control Objekt zu erhalten. Da wir keine PFCG Objekte prüfen wollen, übergeben wir eine leere Tabelle an die Methode. Über die ENABLE Methode am CDS Double aktivieren wir dann die Prüfung in unserer Testmethode.
DATA(control_data) = cl_cds_test_data=>create_access_control_data( VALUE #( ) ).
cds_environment->get_access_control_double( )->enable_access_control( control_data ).
In der Dokumentation ist beschrieben, dass wir in der SETUP Methode immer den DISABLE aufrufen müssen, wenn wir den ENABLE verwenden. Daher implementieren wir noch die SETUP Methode und fügen den folgenden Code ein.
cds_environment->get_access_control_double( )->disable_access_control( ).
Damit klappt nun unser Unit Test und mit einer zweiten Methode können wir mit und ohne Access Control testen. Den gesamten Unit Test findest du im unten verlinkten GitHub Repository.
Data Preview
Im Beispiel oben haben wir den Data Preview verwendet, dort aber einen eingeschränkten Blick auf die Daten bekommen. Du kannst den Preview auch in der SQL Console starten und dem SELECT Statement den Zusatz WITH PRIVILEGED ACCESS geben, dann kannst du dir auch alle Daten auf der Datenbank anschauen.
Die Credits für den Tipp gehen an den SAP Developers YouTube Kanal, den Link zum Video findest du unten in den Quellen.
Analyse
Wie können wir nun in die Analyse einsteigen, wenn unser User nicht alle Daten sieht? In diesem Kapitel wollen wir uns verschiedene Wege und Methodiken anschauen.
Debugging
Handelt es sich um ein Remote Szenario, wo der User per RFC oder HTTP Verbindung ins System kommt, können wir als Entwickler per Debugging für einen anderen User unterstützen. Je nach Komplexität des Szenarios oder des Codes, können wir uns die SELECTs anschauen und die zurückgelieferten Daten analysieren.
Access Control
Wissen wir, welcher Core Data Service zu wenig Daten zurückliefert, lohnt sich meist ein Blick in das Access Control des Views, um die nötigen Berechtigungsobjekte oder Einschränkungen zu finden. In einigen Fällen muss es nicht einmal eine fehlende Berechtigung sein, sondern wie in unserem Beispiel oben liefert der Views nicht alle Daten, weil er über Werte abgegrenzt wurde.
Trace
Beim Umgang mit Traces haben wir oft die Erfahrung gemacht, dass in einem Berechtigungstrace nur die halbe Wahrheit steckt und Einschränkungen in Core Data Services bereits beim Zugriff auf Datenbankebene gemacht werden. Damit tauchen sie in den klassischen Analysetools nicht auf und müssen über andere Wege analysiert werden.
On-Premise / Private Cloud
Wie kannst du nun genauer in die Analyse der Berechtigungen einsteigen, wenn du auf einem On-Premise System unterwegs bist? Dazu gibt es die Transaktion SACMSEL um einen View im Detail prüfen zu können. Hierbei verwenden wir einen recht komplexen View (I_OperationalAcctgDocItem) mit vielen Berechtigungsprüfungen aus dem Finanzbereich. Den Report kannst du für einen beliebigen User ausführen und so für diesen das Ergebnis prüfen.
Nach der Ausführung erhalten wir ein detailliertes Ergebnis der Prüfung für den User und können so besser fehlende Berechtigungen nachvollziehen.
Hat der User keine Berechtigungen oder fehlen noch Berechtigungen, würde das Bild entsprechend anders aussehen. Nun kann der Berechtigungsadmin auf die Suche gehen, welche Berechtigungen dem User noch fehlen.
Zusammenfassung
Das Access Control bietet eine einfache Möglichkeit die Daten des Core Data Services für den Anwender einzuschränken und nur die benötigten Informationen nach außen zu geben. Allerdings solltest du bei der Wiederverwendung auch darauf achten, neben dem neuen View, auch ein Access Control zu definieren, sonst verlierst du den Vorteil wieder.
Verwendest du den View in einem SELECT, dann sparst du dir die manuelle Berechtigungsprüfung der Daten und damit auch verlorene Performance, gegenüber der klassischen Entwicklung. Benötigst du den vollen Zugriff, kannst du dies mit einem einfachen Zusatz ergänzen.
Vollständiges Beispiel
Das Beispiel von Heute findest du in unseren Unterlagen für Core Data Services im GitHub Repository. In diesem Commit findest du die Änderungen aus diesem Artikel, um diese spezifisch nachzuvollziehen.
Fazit
Der Schutz der Daten beim Zugriff ist mittlerweile einfacher als früher, da wir per Auslieferung am Core Data Service eine Berechtigungsprüfung erhalten. Allerdings müssen wir bei neuen Objekten auch darauf achten, dass die Berechtigungsprüfung vorhanden ist und diese uns in unserer Verarbeitung nicht blockiert.
Quelle:
SAP Help - PRIVILEGED ACCESS
YouTube - Short Data Preview
YouTube - SAP TechBytes Access Control