Kategorien: | PostgreSQL® |
---|---|
Tags: | PostgreSQL® |
Neu in PostgreSQL® 9.5 ist das Feature ROW LEVEL SECURITY
.
ROW LEVEL SECURITY
Mit Hilfe von ROW LEVEL SECURITY
lässt sich bestimmen, welche Voraussetzungen erfüllt sein müssen, damit ein Datenbankbenutzer ein Tupel sieht, einfügen, löschen oder bearbeiten darf.
Kurz gesagt, es beseht nun die Möglichkeit Zugriffsberechtigungen auf Tupelebene zu vergeben.
Zur Konfiguration dieser Zugriffsberechtigungen kommen die in PostgreSQL® 9.5 eingeführten, SECURITY POLICIES
zum Einsatz. Mit Hilfe dieser können feingranulare Regeln definiert werden, die bei den Zugriff auf Tuple ausgewertet werden.
In unserem Beispiel möchten wir den Zugriff auf eine Tabelle einschränken, die die Verkaufszahlen verschiedener Abteilungen beinhaltet. Wir möchten den Benutzern den Zugriff aber nicht komplett entziehen. Jeder Benutzer soll auf die Zahlen der Abteilung zuzugreifen können der er angehört. Die Zahlen der anderen Abteilungen sollen hingegen nicht sichtbar oder veränderbar sein.
Zunächst benötigen wir eine Zuordnung von Benutzern zu Abteilungen:
avo@[local]:5495 [postgres] > CREATE TABLE user_in_department ( username text, dep text, PRIMARY KEY (username, dep));
avo@[local]:5495 [postgres] > INSERT INTO user_in_department VALUES ('manuel_mueller' , 'games') , ('michael_schneider' , 'games') , ('michael_schneider' , 'tv') , ('bobdan_muel' , 'tv') , ('tizian_martin' , 'audio');
Nachdem wir nun eine Zuordnung von Benutzern zu Abteilungen haben, benötigen wir noch unsere „sales“ Tabelle:
avo@[local]:5495 [postgres] > CREATE TABLE sales ( id SERIAL PRIMARY KEY, department text NOT NULL, target_range tsrange, sum numeric);
Als Beispieldaten dienen uns die Verkaufszahlen vier verschiedener Abteilungen:
avo@[local]:5495 [postgres] > INSERT INTO sales (department, target_range, sum) VALUES ('tv' , '[2015-01-01 00:00 , 2015-02-01 00:00)' , 120000) , ('games' , '[2015-01-01 00:00 , 2015-02-01 00:00)' , 140000) , ('computer' , '[2015-01-01 00:00 , 2015-02-01 00:00)' , 2000) , ('audio' , '[2015-01-01 00:00 , 2015-02-01 00:00)' , 90000);
Die Prüfung der Zugriffsberechtigungen wird über die folgende SECURITY POLICY
definiert:
avo@[local]:5495 [postgres] > CREATE POLICY user_in_department ON sales FOR ALL TO public USING ( ( SELECT COUNT(uid.username) >= 1 FROM user_in_department uid WHERE uid.username = current_user AND uid.dep = department ) );
Zu guter Letzt müssen wir ROW LEVEL SECURITY
für die Tabelle „sales“ aktivieren, und einen Beispielbenutzer anlegen:
avo@[local]:5495 [postgres] > ALTER TABLE sales ENABLE ROW LEVEL SECURITY; CREATE USER manuel_mueller; GRANT SELECT ON user_in_department TO manuel_mueller; GRANT SELECT, INSERT, UPDATE, DELETE ON sales TO manuel_mueller;
Frag der Benutzer „manuel_mueller“ nun die Verkaufszahlen ab, so erhält er als Ergebnis nur die Verkaufszahlen der Abteilung der er angehört:
manuel_mueller@[local]:5495 [postgres] > SELECT * FROM sales; id | department | target_range | sum ----+------------+-----------------------------------------------+-------- 2 | games | ["2015-01-01 00:00:00","2015-02-01 00:00:00") | 140000 (1 row)
Selbst wenn es ihm ermöglicht ist, selber Eintragungen innerhalb der Tabelle sales vorzunehmen, wird verhindert, dass er Eintragungen für andere Abteilungen vornimmt. Auch ist es Ihm nicht möglich Eintragungen anderer Abteilungen zu bearbeiten:
manuel_mueller@[local]:5495 [postgres] > UPDATE sales SET sum=sum+100; UPDATE 1
Die aktuellen SECURITY POLICIES
können mit SELECT * FROM pg_policies;
oder mit Hilfe des Backslashcommands \dp
abgefragt werden. In unserem Beispiel sieht das Ergebnis wie folgt aus:
avo@[local]:5495 [postgres] > SELECT * FROM pg_policies ; -[ RECORD 1 ]------------------------------------------------------------------------------------- schemaname | public tablename | sales policyname | user_in_department roles | {public} cmd | ALL qual | ( SELECT (count(uid.username) >= 1) + | FROM user_in_department uid + | WHERE ((uid.username = ("current_user"())::text) AND (uid.dep = sales.department))) with_check | __NULL__
Zusätzlich zu USING
kann die WITH CHECK
Option angegeben werden. Diese greift, sobald ein Benutzer Tupel einfügen, ändern oder entfernen möchte.
Das folgende Beispiel unterbindet die nachträgliche Bearbeitung von Eintragungen:
ALTER POLICY user_in_department ON sales WITH CHECK ( target_range @> NOW()::timestamp );
Neben der Einschränkung aller Operationen können auch spezifische Operationen eingeschränkt werden. Dazu wird bei der Erstellung der SECURITY POLICY
nicht das Schlüsselwort ALL
, sondern die entsprechende Operation eingetragen (SELECT
, INSERT
, UPDATE
oder DELETE
).
In unserem Beispiel wirkt sich die Einschränkung auf alle Benutzer aus (TO
). Aber auch dies lässt sich spezifizieren. Soll die Überprüfung nur für einen gewissen Kreis an Benutzern geprüft werden, so kann anstelle von „public“ auch eine spezielle Gruppe angegeben werden. Achtung: allen anderen Benutzern wird der Zugriff ohne Prüfung verwehrt.
public
Mit ROW LEVEL SECURITY
wurde der Parameter row_security
eingeführt. Dieser nimmt einen von drei möglichen Werten an: off
, on
und force
.
SECURITY POLICIES
. Dies führt dazu, dass alle Tabellen für die ROW LEVEL SECURITY
aktiviert worden ist, für normale Benutzer gesperrt werden. Ein versuchter Zugriff auf solch eine Tabelle wird mir der Fehlermeldung „ERROR: insufficient privilege to bypass row security.“ geblockt.on
unterliegen in dieser Einstellung auch TABLE OWNER
der Überprüfung, welche normalerweise nicht von der Überprüfung betroffen sind.SUPERUSER
unterliegen der ROW LEVEL SECURITY
nicht.
Das oben genannte Beispiel ist nur eins von vielen denkbaren Einsatzszenarien. Zwar lassen sich viele Operationen auch mit entsprechenden VIEWS
oder TRIGGERN
realisieren, jedoch bietet PostgreSQL® mir ROW LEVEL SECURITY
nun eine einfacher zu administrierende Methode zur Umsetzung. Zugleich entfällt der zusätzliche Overhead für die Ausführung der entsprechenden Trigger.
Details können der PostgreSQL® Dokumentation entnommen werden.
über den Autor Technischer Leiter zur Person Adrian ist seit 2013 Mitarbeiter der credativ GmbH. Als technischer Leiter des Cloud Infrastructure Teams beschäftigt er sich hauptsächlich mit der Planung, Realisierung und Betreuung verteilter Infrastrukturen wie zum Beispiel Kubernetes und Ceph sowie mit der Erarbeitung von Deployment-Strategien. Zuvor war er Teil des Datenbank-Teams bei credativ und war dort unter anderem mit dem Aufbau und der Verwaltung von hochverfügbaren Datenbank-Systemen betreut. Seit 2015 beteiligt er sich aktiv am Debian-Projekt.ROW LEVEL SECURITY
ist nur eines von vielen neuen und interessanten Features, die mit Version 9.5 von PostgreSQL® eingeführt werden. Eine Übersicht über die neuen Features bietet das
Kategorien:
PostgreSQL®
Tags:
PostgreSQL®
Adrian Vondendriesch