Co dokładnie robi GRANT USAGE ON SCHEMA?

122

Po raz pierwszy próbuję stworzyć bazę danych Postgres, więc to chyba głupie pytanie. Przypisałem podstawowe uprawnienia tylko do odczytu roli db, która musi mieć dostęp do bazy danych z moich skryptów php i mam ciekawość: jeśli wykonam

GRANT some_or_all_privileges ON ALL TABLES IN SCHEMA schema TO role;

czy istnieje potrzeba wykonania również

GRANT USAGE ON SCHEMA schema TO role;

?

Z dokumentacji :

UŻYCIE: W przypadku schematów umożliwia dostęp do obiektów zawartych w określonym schemacie (przy założeniu, że spełnione są również wymagania dotyczące uprawnień obiektów). Zasadniczo umożliwia to beneficjentowi „wyszukiwanie” obiektów w schemacie.

Myślę, że jeśli potrafię wybrać lub manipulować dowolnymi danymi zawartymi w schemacie, mogę uzyskać dostęp do dowolnych obiektów samego schematu. Czy się mylę? Jeśli nie, do czego GRANT USAGE ON SCHEMAsłuży? A co dokładnie oznacza dokumentacja „przy założeniu, że spełnione są również wymagania dotyczące uprawnień obiektu”?

Marco Sulla
źródło

Odpowiedzi:

127

GRANTs na różnych obiektach są oddzielne. GRANTw bazie danych nie ma GRANTuprawnień do schematu w niej zawartego. Podobnie, GRANTumieszczanie w schemacie nie daje praw do tabel w nim zawartych.

Jeśli masz uprawnienia do SELECTz tabeli, ale nie masz prawa do wyświetlania jej w schemacie, który ją zawiera, nie możesz uzyskać dostępu do tabeli.

Testy uprawnień są wykonywane w kolejności:

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.

Twoje zamieszanie może wynikać z faktu, że publicschemat ma domyślnie GRANTwszystkie uprawnienia do roli public, której członkiem jest każdy użytkownik / grupa. Więc każdy ma już zastosowanie w tym schemacie.

Fraza:

(zakładając, że spełnione są również własne wymagania dotyczące uprawnień obiektu)

Mówi, że musisz mieć USAGEna schemacie, aby używać obiektów w nim zawartych, ale posiadanie USAGEna schemacie nie jest samo w sobie wystarczające do używania obiektów w schemacie, musisz również mieć uprawnienia do samych obiektów.

To jest jak drzewo katalogów. Jeśli utworzysz katalog somedirzawierający plik somefile, a następnie ustawisz go tak, aby tylko twój własny użytkownik mógł uzyskać dostęp do katalogu lub pliku (tryb rwx------w katalogu, tryb rw-------na pliku), nikt inny nie może wyświetlić katalogu, aby zobaczyć, czy plik istnieje.

Gdybyś miał nadać prawa do odczytu pliku na całym świecie (tryb rw-r--r--), ale nie zmieniałby uprawnień do katalogu, nie miałoby to żadnego znaczenia. Nikt nie mógł zobaczyć pliku, aby go przeczytać, ponieważ nie ma uprawnień do wyświetlenia katalogu.

Jeśli zamiast tego ustawisz rwx-r-xr-xkatalog, ustawiając go tak, aby ludzie mogli wyświetlać i przechodzić przez katalog, ale nie zmieniając uprawnień do pliku, ludzie mogliby wyświetlić plik, ale nie mogliby go odczytać , ponieważ nie mieliby dostępu do pliku.

Musisz ustawić oba uprawnienia, aby ludzie mogli faktycznie wyświetlać plik.

To samo na str. Potrzebujesz zarówno USAGEpraw do schematu, jak i praw do obiektu, aby wykonać akcję na obiekcie, na przykład SELECTz tabeli.

(Analogia nieco spada, ponieważ PostgreSQL nie ma jeszcze zabezpieczeń na poziomie wiersza, więc użytkownik może nadal "zobaczyć", że tabela istnieje w schemacie, bezpośrednio SELECTz niej pg_class. Nie mogą z nią w żaden sposób współdziałać , więc to tylko część „listy” nie jest taka sama).

Craig Ringer
źródło
2
Teraz jest to bardzo jasne z przykładem katalogu :) Muszę powiedzieć, że jest to problem, jeśli wstawisz jakąś tabelę lub wiersz z superużytkownikiem, na przykład podczas dodawania postGIS za pomocą CREATE EXTENSION. To mniej więcej ten sam problem z plikami utworzonymi w systemie Linux, gdy ty su. Będzie dobrze, jeśli sudo -ew pqsl jest coś w rodzaju instrukcji for.
Marco Sulla
W każdym razie teraz zdałem sobie sprawę, że GRANTinstrukcje nie specyficzne dla tabel nie są tym, czego chcę, ponieważ wpływają na wszystkie bazy danych ...: s
Marco Sulla
1
@LucasMalor Er ... nie, nie robią. GRANTna schemacie wpływa na ten schemat. GRANT ... ON ALL TABLES IN SCHEMA ...wpływa na wszystkie tabele w schemacie w określonej bazie danych. Nie ma żadnych, GRANTktóre wpływają na wszystkie bazy danych (ok, z wyjątkiem GRANTprzypisania roli użytkownika).
Craig Ringer
Ach, przepraszam, wykonałem polecenia, gdy byłem zalogowany jako superużytkownik "postgres" i wpłynęły one na bazę danych "postgres". Pomyślałem, że jeśli działasz psqlbez -d dbdziałania „poza” jakąkolwiek bazą danych, ale zawsze jesteś połączony z bazą danych i domyślnie łączysz się z bazą danych o tej samej nazwie, co Twoja rola. db = role = user = group ... to trochę zagmatwane: D
Marco Sulla
@LucasMalor Pomyśl o tym w ten sposób. Domyślnie łączysz się z bazą danych o tej samej nazwie, co rola logowania („użytkownik”), z którą się łączysz. „Użytkownicy” to tylko role, które mają WITH LOGIN; zasadniczo wszystko może być grupą i można ustawić grupy tak, aby mogły się logować.
Craig Ringer
72

W przypadku systemu produkcyjnego możesz użyć tej konfiguracji:

--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
źródło
Nie powinno adminbyć również przyznawane CREATEw schemacie?
Dan
2
Dostęp jest przydzielany według modelu hierarchicznego: BD -> SCHEMA -> TABLES . Dzięki GRANT USAGE ON SCHEMA, administrator nie może utworzyć tabeli, ale może to zrobić za pomocą ALL GRANT ALL ON SCHEMA
bilelovitch
@bilelovitch: masz na myśli grant all on schema public to admin? PS: Dodałem też 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

Cóż, to moje ostateczne rozwiązanie dla prostej bazy danych dla systemu 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
źródło
1
Którego użytkownika należy użyć do „# Utwórz wszystkie tabele i obiekty, a następnie:”? Kto jest właścicielem tabel i innych przedmiotów w Twoim przypadku?
Christophe Furmaniak
@ChristopheFurmaniak masz rację, poprawiłem proces. Właścicielem bazy danych i jej obiektów jest $ ROLE_LOCAL i po utworzeniu struktury db musimy wrócić do superużytkownika postgres.
Marco Sulla
Wydaje mi się, że masz problem z poleceniami „ALTER DEFAULT PRIVILEGES…”. To polecenie jest używane do wyzwalania nadawania uprawnień jednemu użytkownikowi (roli), gdy inny użytkownik (rola) tworzy obiekt. Aby uzyskać wyjaśnienie, patrz strona 11, sekcja 7.1 niniejszego dokumentu . Obecnie Twój ROLE_REMOTE nie będzie miał dostępu do żadnych obiektów, które utworzyłby ROLE_LOCAL. Polecenia ROLE_LOCAL dają tylko uprawnienia, które rola już ma jako właściciela tych obiektów. To samo dotyczy poleceń ROLE_REMOTE.
emispowder