Was genau macht GRANT USAGE ON SCHEMA?

121

Ich versuche zum ersten Mal, eine Postgres-Datenbank zu erstellen, daher ist dies wahrscheinlich eine dumme Frage. Ich habe der Datenbankrolle, die über meine PHP-Skripte auf die Datenbank zugreifen muss, grundlegende schreibgeschützte Berechtigungen zugewiesen, und ich bin neugierig: Wenn ich sie ausführe

GRANT some_or_all_privileges ON ALL TABLES IN SCHEMA schema TO role;

Gibt es eine Notwendigkeit, auch auszuführen

GRANT USAGE ON SCHEMA schema TO role;

?

Aus der Dokumentation :

VERWENDUNG: Ermöglicht für Schemas den Zugriff auf Objekte, die im angegebenen Schema enthalten sind (vorausgesetzt, die eigenen Berechtigungsanforderungen der Objekte werden ebenfalls erfüllt). Im Wesentlichen ermöglicht dies dem Berechtigten, Objekte innerhalb des Schemas nachzuschlagen.

Ich denke, wenn ich im Schema enthaltene Daten auswählen oder bearbeiten kann, kann ich auf alle Objekte des Schemas selbst zugreifen. Liege ich falsch? Wenn nicht, wofür GRANT USAGE ON SCHEMAwird verwendet? Und was bedeutet die Dokumentation genau mit "vorausgesetzt, dass auch die eigenen Berechtigungsanforderungen der Objekte erfüllt sind"?

Marco Sulla
quelle

Antworten:

126

GRANTs auf verschiedenen Objekten sind getrennt. GRANTWenn Sie sich in einer Datenbank befinden, haben Sie keine GRANTRechte an dem darin enthaltenen Schema. In ähnlicher Weise GRANTgewährt das Verwenden eines Schemas keine Rechte für die darin enthaltenen Tabellen.

Wenn Sie Rechte an SELECTeiner Tabelle haben, aber nicht das Recht, sie in dem Schema anzuzeigen, das sie enthält, können Sie nicht auf die Tabelle zugreifen.

Die Rechtstests werden in der folgenden Reihenfolge durchgeführt:

Do you have `USAGE` on the schema? 
    No:  Reject access. 
    Yes: Do you also have the appropriate rights on the table? 
        No:  Reject access. 
        Yes: Check column privileges.

Ihre Verwirrung kann sich aus der Tatsache ergeben, dass das publicSchema standardmäßig GRANTalle Rechte an der Rolle hat public, zu der jeder Benutzer / jede Gruppe gehört. Jeder hat also bereits Verwendung für dieses Schema.

Der Satz:

(unter der Annahme, dass auch die eigenen Berechtigungsanforderungen der Objekte erfüllt sind)

Das heißt, Sie müssen USAGEein Schema haben, um Objekte darin zu verwenden, aber USAGEein Schema allein reicht nicht aus, um die Objekte innerhalb des Schemas zu verwenden. Sie müssen auch Rechte an den Objekten selbst haben.

Es ist wie ein Verzeichnisbaum. Wenn Sie ein Verzeichnis somedirmit einer darin enthaltenen Datei erstellen, somefilestellen Sie es so ein, dass nur Ihr eigener Benutzer auf das Verzeichnis oder die Datei zugreifen kann (Modus im Verzeichnis rwx------, Modus rw-------in der Datei), und niemand anderes kann das Verzeichnis auflisten, um festzustellen, ob die Datei vorhanden ist.

Wenn Sie der Datei (Modus rw-r--r--) weltweite Leserechte gewähren, aber die Verzeichnisberechtigungen nicht ändern würden, würde dies keinen Unterschied machen. Niemand konnte sehen Sie die Datei , um es zu lesen, weil sie nicht die Rechte , um das Verzeichnis aufzulisten.

Wenn Sie stattdessen setzen rwx-r-xr-xauf das Verzeichnis, das Einstellen so können die Menschen das Verzeichnis aufgelistet und durchqueren , aber nicht die Dateiberechtigungen zu ändern, könnten die Menschen Liste die Datei konnte aber nicht lesen , weil sie keinen Zugriff auf die Datei haben würde.

Sie müssen beide Berechtigungen festlegen , damit Benutzer die Datei tatsächlich anzeigen können.

Gleiches in Pg. Sie benötigen sowohl Schema- USAGEals auch Objektrechte, um eine Aktion für ein Objekt auszuführen, z. B. SELECTaus einer Tabelle.

(Die Analogie fällt insofern ein wenig insofern, als PostgreSQL noch keine Sicherheit auf Zeilenebene hat, sodass der Benutzer immer noch "sehen" kann, dass die Tabelle im Schema vorhanden ist, indem er direkt von dort SELECTaus pg_class. Sie können in keiner Weise mit ihr interagieren Es ist jedoch nur der "Listen" -Teil, der nicht ganz gleich ist.)

Craig Ringer
quelle
2
Jetzt ist es mit dem Verzeichnisbeispiel sehr klar :) Ich muss sagen, dass dies ein Problem ist, wenn Sie eine Tabelle oder Zeile mit einem Superuser einfügen, zum Beispiel wenn Sie postGIS mit hinzufügen CREATE EXTENSION. Es ist mehr oder weniger das gleiche Problem mit Dateien, die unter Linux erstellt wurden, während Sie sind su. Es ist gut, wenn es sudo -ein pqsl eine Art for-Anweisungen gibt.
Marco Sulla
Jedenfalls wurde mir jetzt klar, dass GRANTAnweisungen, die nicht spezifisch für Tabellen sind, nicht das sind, was ich will, da sie alle Datenbanken betreffen ...: s
Marco Sulla
1
@ LucasMalor Äh ... nein, das tun sie nicht. GRANTin einem Schema wirkt sich auf dieses Schema aus. GRANT ... ON ALL TABLES IN SCHEMA ...wirkt sich auf alle Tabellen in einem Schema in einer bestimmten Datenbank aus. Es gibt keine GRANTs, die alle Datenbanken betreffen (ok, außer die GRANTRollenmitgliedschaft für einen Benutzer).
Craig Ringer
Ich entschuldige, ich habe die Anweisungen ausgeführt, als ich als "Postgres" -Superuser angemeldet war, und sie haben sich auf die "Postgres" -Datenbank ausgewirkt. Ich dachte, wenn Sie psqlohne eine -d dbDatenbank "außerhalb" arbeiten, aber immer mit einer Datenbank verbunden sind und standardmäßig mit der Datenbank mit demselben Namen wie Ihre Rolle verbunden sind. db = Rolle = Benutzer = Gruppe ... es ist ein bisschen verwirrend: D
Marco Sulla
@ LucasMalor Betrachten Sie es so. Standardmäßig stellen Sie eine Verbindung zu einer Datenbank mit demselben Namen wie die Anmelderolle ("Benutzer") her, unter der Sie eine Verbindung herstellen. "Benutzer" sind nur Rollen, die haben WITH LOGIN; Im Wesentlichen kann alles eine Gruppe sein, und Gruppen können so eingestellt werden, dass sie sich anmelden können.
Craig Ringer
72

Für ein Produktionssystem können Sie diese Konfiguration verwenden:

--ACCESS DB
REVOKE CONNECT ON DATABASE nova FROM PUBLIC;
GRANT  CONNECT ON DATABASE nova  TO user;

--ACCESS SCHEMA
REVOKE ALL     ON SCHEMA public FROM PUBLIC;
GRANT  USAGE   ON SCHEMA public  TO user;

--ACCESS TABLES
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC ;
GRANT SELECT                         ON ALL TABLES IN SCHEMA public TO read_only ;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO read_write ;
GRANT ALL                            ON ALL TABLES IN SCHEMA public TO admin ;
bilelovitch
quelle
Sollte nicht adminauch für CREATEdas Schema gewährt werden ?
Dan
2
Der Zugriff erfolgt nach einem hierarchischen Modell: BD -> SCHEMA -> TABLES . Mit GRANT USAGE ON SCHEMAkann der Administrator keine Tabelle erstellen, aber er kann es mit ALL GRANT ALL ON SCHEMA...
bilelovitch
@bilelovitch: meinst du grant all on schema public to admin? PS: Ich habe auch hinzugefügt grant usage, select on all sequences in schema public to read_only/read_write; grant execute on all functions in schema public to read_only/read_write;
Marco Sulla
2

Nun, dies ist meine endgültige Lösung für eine einfache Datenbank für Linux:

# Read this before!
#
# * roles in postgres are users, and can be used also as group of users
# * $ROLE_LOCAL will be the user that access the db for maintenance and
#   administration. $ROLE_REMOTE will be the user that access the db from the webapp
# * you have to change '$ROLE_LOCAL', '$ROLE_REMOTE' and '$DB'
#   strings with your desired names
# * it's preferable that $ROLE_LOCAL == $DB

#-------------------------------------------------------------------------------

//----------- SKIP THIS PART UNTIL POSTGRES JDBC ADDS SCRAM - START ----------//

cd /etc/postgresql/$VERSION/main
sudo cp pg_hba.conf pg_hba.conf_bak
sudo -e pg_hba.conf

# change all `md5` with `scram-sha-256`
# save and exit

//------------ SKIP THIS PART UNTIL POSTGRES JDBC ADDS SCRAM - END -----------//

sudo -u postgres psql

# in psql:
create role $ROLE_LOCAL login createdb;
\password $ROLE_LOCAL
create role $ROLE_REMOTE login;
\password $ROLE_REMOTE

create database $DB owner $ROLE_LOCAL encoding "utf8";
\connect $DB $ROLE_LOCAL

# Create all tables and objects, and after that:

\connect $DB postgres

revoke connect on database $DB from public;
revoke all on schema public from public;
revoke all on all tables in schema public from public;

grant connect on database $DB to $ROLE_LOCAL;
grant all on schema public to $ROLE_LOCAL;
grant all on all tables in schema public to $ROLE_LOCAL;
grant all on all sequences in schema public to $ROLE_LOCAL;
grant all on all functions in schema public to $ROLE_LOCAL;

grant connect on database $DB to $ROLE_REMOTE;
grant usage on schema public to $ROLE_REMOTE;
grant select, insert, update, delete on all tables in schema public to $ROLE_REMOTE;
grant usage, select on all sequences in schema public to $ROLE_REMOTE;
grant execute on all functions in schema public to $ROLE_REMOTE;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on tables to $ROLE_LOCAL;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on sequences to $ROLE_LOCAL;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on functions to $ROLE_LOCAL;

alter default privileges for role $ROLE_REMOTE in schema public
    grant select, insert, update, delete on tables to $ROLE_REMOTE;

alter default privileges for role $ROLE_REMOTE in schema public
    grant usage, select on sequences to $ROLE_REMOTE;

alter default privileges for role $ROLE_REMOTE in schema public
    grant execute on functions to $ROLE_REMOTE;

# CTRL+D
Marco Sulla
quelle
1
Welcher Benutzer muss für "# Alle Tabellen und Objekte erstellen und danach:" verwendet werden? Wer ist in Ihrem Fall der Besitzer der Tische und anderer Objekte?
Christophe Furmaniak
@ChristopheFurmaniak du hast recht, ich habe den Prozess korrigiert. Der Eigentümer der Datenbank und ihrer Objekte ist $ ROLE_LOCAL. Nach dem Erstellen der Datenbankstruktur müssen wir zum Postgres-Superuser zurückkehren.
Marco Sulla
Ich glaube, Sie haben ein Problem mit Ihren Befehlen "ALTER DEFAULT PRIVILEGES ...". Dieser Befehl wird verwendet, um einem Benutzer (Rolle) Berechtigungen zu erteilen, wenn ein anderer Benutzer (Rolle) ein Objekt erstellt. Weitere Informationen finden Sie auf Seite 11, Abschnitt 7.1 dieses Dokuments . Derzeit hat Ihr ROLE_REMOTE keinen Zugriff auf Objekte, die ROLE_LOCAL erstellen würde. Die ROLE_LOCAL-Befehle geben nur Privilegien an, die die Rolle bereits als Eigentümer dieser Objekte hat. Gleiches gilt für ROLE_REMOTE-Befehle.
Emispowder