Wenn Owner-Sein das eine Extrem ist (alles dürfen) und gar kein Privileg das andere (nichts dürfen), liegt dazwischen die ganze Welt der Object Privileges. Postgres definiert für jeden Objekttyp einen festen Satz von Privilegien — sie werden mit GRANT vergeben und mit REVOKE entzogen.

Privilegien-Katalog

Welche Privilegien Postgres kennt, hängt vom Objekttyp ab:

ObjektPrivilegien
Tabelle / View / Foreign TableSELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER
SpalteSELECT, INSERT, UPDATE, REFERENCES
SequenceUSAGE, SELECT, UPDATE
SchemaUSAGE, CREATE
DatenbankCONNECT, CREATE, TEMPORARY (alias TEMP)
Function / ProcedureEXECUTE
Type / DomainUSAGE
Foreign Data WrapperUSAGE
Foreign ServerUSAGE
LanguageUSAGE
TablespaceCREATE
Large ObjectSELECT, UPDATE
Parameter (ab PG 15)SET, ALTER SYSTEM

ALL PRIVILEGES (oder kurz ALL) ist eine bequeme Abkürzung für den kompletten Satz des jeweiligen Objekttyps.

Grundsyntax

SQL GRANT und REVOKE
GRANT SELECT, INSERT ON orders TO app_user;
GRANT USAGE ON SCHEMA app TO app_user;
GRANT EXECUTE ON FUNCTION calc_tax(numeric) TO app_user;
GRANT CONNECT ON DATABASE myapp TO app_user;

REVOKE INSERT ON orders FROM app_user;
REVOKE ALL ON SCHEMA app FROM app_user;

Die Syntax ist konsistent: GRANT <privs> ON <objtype> <objname> TO <role>. <objtype> ist optional, wenn es sich aus dem Kontext ergibt (Standard ist TABLE).

Mehrere Objekte gleichzeitig

Postgres kennt drei nützliche Bulk-Varianten:

SQL ALL TABLES IN SCHEMA und Verwandte
-- Alle existierenden Tabellen in einem Schema:
GRANT SELECT ON ALL TABLES IN SCHEMA app TO reader;

-- Alle Sequenzen (haeufig zusammen mit INSERT-Rechten gebraucht):
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA app TO app_user;

-- Alle Funktionen:
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA app TO app_user;

Wichtig: das wirkt nur auf existierende Objekte. Tabellen, die nach diesem GRANT neu erstellt werden, sind nicht automatisch eingeschlossen. Wer das will, braucht zusätzlich ALTER DEFAULT PRIVILEGES (eigener Artikel: Default Privileges).

Spalten-Level-Privilegien

Postgres erlaubt Privilegien auch auf einzelne Spalten statt der ganzen Tabelle:

SQL Spaltenbasierter SELECT
-- Reader darf nur die nicht-sensitiven Spalten lesen:
GRANT SELECT (id, name, created_at) ON users TO reader;

-- Tabellen-weiter SELECT NICHT vergeben.

In der Praxis selten genutzt — meist setzt man stattdessen Views oder Row-Level Security ein, weil Spalten-Privilegien nicht alle Tools sauber unterstützen. Aber gut zu wissen, dass es geht.

PUBLIC — die Pseudo-Rolle „alle”

PUBLIC ist eine eingebaute „Rolle”, die jeden Datenbank-User repräsentiert. Privilegien, die an PUBLIC gehen, gelten für jeden:

SQL
GRANT SELECT ON pg_stat_activity TO PUBLIC;

Postgres vergibt selbst eine handvoll Default-Privilegien an PUBLIC — z. B. EXECUTE auf alle Funktionen, USAGE auf alle Languages und (bis PG 14) CREATE auf das public-Schema. Letzteres ist ein häufiger Sicherheits-Talkingpoint.

Seit PG 15 sind die Defaults restriktiver:

PrivilegBis PG 14Ab PG 15
CREATE auf Schema publicPUBLICnur Owner (postgres)
EXECUTE auf neue FunktionenPUBLICnur Owner

Wer eine Datenbank von einer alten auf eine neue Version migriert, sollte das prüfen — Anwendungen, die sich auf das alte Verhalten verließen, können brechen.

WITH GRANT OPTION

GRANT … WITH GRANT OPTION macht den Empfänger zu einem Privileg-Vermittler. Er darf das Privileg seinerseits weitergeben:

SQL
GRANT SELECT ON orders TO team_lead WITH GRANT OPTION;

-- team_lead darf nun selbst:
GRANT SELECT ON orders TO new_intern;

Wer ein mit GRANT OPTION vergebenes Privileg zurückzieht, muss CASCADE angeben, falls dadurch wiederum bei Dritten Privilegien wegfallen:

SQL
REVOKE SELECT ON orders FROM team_lead;
-- ERROR: dependent privileges exist
REVOKE SELECT ON orders FROM team_lead CASCADE;
-- OK: alle daraus abgeleiteten GRANTs werden mit entfernt

Privilegien anzeigen

In psql:

SQL
myapp=# \dp orders
                                 Access privileges
 Schema |  Name  | Type  |     Access privileges     | Column privileges | Policies
--------+--------+-------+---------------------------+-------------------+----------
 public | orders | table | app_owner=arwdDxt/app_owner+|                   |
        |        |       | app_user=arwd/app_owner   |                   |

Der kryptische Code übersetzt sich:

BuchstabePrivileg
rSELECT (read)
wUPDATE (write)
aINSERT (append)
dDELETE
DTRUNCATE
xREFERENCES
tTRIGGER
*… with GRANT OPTION (z. B. r*)

app_user=arwd/app_owner heißt also: User app_user darf SELECT/INSERT/UPDATE/DELETE; das Privileg wurde von app_owner vergeben.

Interessantes

USAGE auf Schema ist die haeufig vergessene Voraussetzung.

Selbst wer SELECT-Rechte auf alle Tabellen hat, sieht nichts, wenn er kein USAGE auf das umgebende Schema besitzt. USAGE ist quasi „Tür auf zum Raum”; die Tabellen-Privilegien sind erst danach relevant. In Migrations-Setups ist das die Fehlerquelle Nummer eins.

REVOKE entfernt nur eigens vergebene Privilegien.

Wer A das Recht via Owner-Rolle gegeben hat und später als Owner-Rolle abdankt, kann es nicht mehr direkt zurücknehmen — der GRANTOR muss derselbe sein. In komplexen Setups wird das schnell unübersichtlich; im Zweifel die Owner-Rolle nutzen oder DROP OWNED BY … als Aufräumer.

ON ALL TABLES schliesst Sequenzen NICHT ein.

Eine GRANT SELECT, INSERT ON ALL TABLES IN SCHEMA app TO app_user-Zeile reicht nicht: für INSERT mit serial/identity-Spalten wird zusätzlich USAGE/SELECT auf die zugehörigen Sequenzen gebraucht. Sonst kommt „permission denied for sequence …”.

PUBLIC hat seit PG 15 weniger Defaults.

Wer von PG 14 oder älter migriert, sollte prüfen, ob Funktionen, die früher implizit für PUBLIC ausführbar waren, jetzt explizite GRANTs brauchen. Genauso CREATE auf public-Schema — Apps, die im public-Schema Tabellen anlegen, verlieren das Recht und brauchen entweder GRANT CREATE ON SCHEMA public TO … oder ein eigenes Schema.

ALL PRIVILEGES kann mehr als du denkst.

GRANT ALL ON TABLE foo TO bar vergibt SELECT/INSERT/UPDATE/DELETE/TRUNCATE/REFERENCES/TRIGGER. Wer nur Lese-Schreib-Zugriff will, sollte explizit auflisten — sonst hat die App auch das Recht, Trigger einzurichten oder Foreign Keys zu setzen.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Server-Administration

Zur Übersicht