Zarządzanie uprawnieniami do obiektów jest istotną częścią pracy administratora. Uprawnienia nadawać możemy użytkownikom oraz rolom grupowym. Część uprawnień ( jak np. możliwość tworzenia baz danych czy użytkowników) wynika z własności roli. Takie uprawnienia konfigurujemy na poziomie całego klastra i nie ma możliwości ustawienia ich indywidualnie np. dla wybranej bazy danych.
Uprawnienia do obiektów (tabele, schematy etc.) nadajemy osobno rolom, przy czym rolą może być zwykły użytkownik lub rola grupowa służąca do masowego nadawania uprawnień. Uprawnienia po nadaniu wchodzą w życie, natychmiast nie jest potrzebne na przykład przelogowanie się użytkownika.
Właściciel obiektu ma wszelkie prawa do zarządzania tym obiektem - w tym nadawania do niego uprawnień innym użytkownikom. Może zarządzać uprawnieniami do obiektu, którego jest właścicielem, nawet jeśli obiekt został stworzony przez innego użytkownika, w tym superużytkownika.
Wszyscy użytkownicy są przypisywani do roli "public", a co za tym idzie (o ile własność "inherit" użytkownika jest ustawiona - a domyślnie jest) dziedziczą wszystkie uprawnienia wynikające z tej roli. Jakiekolwiek uprawnienie nadane roli "public" będzie nadane wszystkim użytkownikom. Ogólna składnia komendy do nadawania uprawnień wygląda następująco:
GRANT UPRAWNIENIE ON NAZWA_OBIEKTU
TO PUBLIC / GROUP NAZWA_GRUPY / NAZWA_UŻYTKOWNIKA
Przykładowe nadanie uprawnień:
grant select on abc to mapet;
Uprawnienia można też nadawać z klauzulą "with grant option" powodującą, że użytkownik, któremu dane uprawnienie zostanie nadane, będzie mógł przekazywać je dalej - nadawać to samo uprawnienie kolejnym użytkownikom. Takie nadawanie uprawnień może być jednak niebezpieczne, ponieważ może to zadziałać jak plotka i stracimy kontrolę nad rozpowszechnianiem się uprawnień. Przykład nadania uprawnienia z możliwością przekazywania go dalej:
grant select on abc to mapet with grant option;
Uprawnienia, jakie możemy nadawać, są następujące:
SELECT | Umożliwia odczyt tabel. |
UPDATE | Umożliwia aktualizację wierszy. |
INSERT | Umożliwia wstawianie nowych wierszy. |
DELETE | Umożliwia kasowanie wierszy. |
RULE | Umożliwia tworzenie reguł. |
ALL | Daje uprawnienia do wszystkiego powyższego. |
TRUNCATE | Umożliwia wykonywanie komendy truncate na wskazanej tabeli. |
CREATE | Nadane dla bazy pozwala na tworzenie nowych schematów w ramach tej bazy. Nadane dla schematu pozwala na tworzenie obiektów w ramach danego schematu. Nadane dla przestrzeni tabel pozwala na tworzenie obiektów w ramach danej przestrzeni tabel oraz wskazywania danej przestrzeni tabel jako domyślnej dla baz danych. |
CONNECT | Umożliwia łączenie się ze wskazaną bazą. |
EXECUTE | Pozwala wykorzystać wskazaną funkcję. |
REFERENCES | Pozwala zakładać klucze obce na tabelach. Aby móc założyć klucz obcy, trzeba mieć nadane to uprawnienie na kolumnach po obu stronach. Można to uprawnienie nadawać dla pojedynczych kolumn i dla całych tabel. |
TRIGGER | Pozwala na tworzenie wyzwalaczy na obiekcie. |
USAGE | Nadane dla języków proceduralnych pozwala na wykorzystanie danego języka proceduralnego do tworzenia funkcji. Dla sekwencji pozwala na pobieranie z nich wartości z użyciem currval i nextval. |
ALL PRIVILEGES | Wszystkie możliwe przywileje na danym typie obiektu. |
Nadanie uprawnień do wszystkich operacji CRUD (create, read, update, delete) na tabeli:
grant select, update, insert, delete on abc to mapet;
Nadanie wszystkich uprawnień do danej tabeli:
grant all privileges on abc to mapet;
Nadanie uprawnień do wywoływania funkcji:
grant execute on function funkcja(int) to mapet;
Pewna ciekawostka, nadanie uprawnień do select na wszystkich tabelach w schemacie:
grant select on all tables in schema dane to mapet;
Załóżmy taką sytuację, że posiadamy schemat i umieszczoną w nim tabelę. Chcemy użytkownikowi nadać uprawnienia do korzystania z tej tabeli. Tworzymy użytkownika, schemat i tabelę oraz nadajemy uprawnienia do select na tej tabeli nowo stworzonemu użytkownikowi:
create user uprawnienia_w_schematach with password 'postgresql_rulez';
create schema uws;
create table uws.dane(x integer);
grant select on uws.dane to uprawnienia_w_schematach;
Następnie logujemy się jako ten nowy użytkownik do psql (z poziomu użytkownika systemowego postgres) i sprawdzamy dostęp do tabeli:
psql -U uprawnienia_w_schematach -d postgres
select * from uws.dane;
I tu moglibyśmy się spodziewać, że skoro nadaliśmy uprawnienia do tabeli, to wszystko będzie działać, a tymczasem:
Problem wynika z tego, że mamy uprawnienia do tabeli, ale nie do schematu, w którym ta tabela się znajduje. Musimy więc nadać osobne uprawnienie do korzystania ze schematu:
grant usage on schema uws to uprawnienia_w_schematach;
Po tej operacji (bez przelogowywania sesji) mamy dostęp do tabeli:
Należy pamiętać, że dodanie uprawnienia USAGE do schematu nie nadaje uprawnień do dostępu do tabel w nich zawartych. Uprawnienia do tabel dajemy dodatkowo.
Do wersji 14 włącznie, jeśli nadanie uprawnień dotyczyło tabeli znajdującej się w schemacie “public”, nie trzeba było dodawać osobnych uprawnień do schematu. Od wersji 15 do schematu “public” nadajemy uprawnienia jak do każdego innego.
Listing uprawnień do obiektów możemy znaleźć w słowniku "information_schema.role_table_grants". Zróbmy mały przykład. Tworzymy tabelę, użytkownika i nadajemy użytkownikowi uprawnienia do SELECT, UPDATE, DELETE i INSERT na tej tabeli.
create table do_uprawnien(x integer);
create user do_uprawnien_user with password 'abc123';
grant select, update, delete, insert on do_uprawnien to do_uprawnien_user;
Sprawdźmy, kto i jakie ma uprawnienia do tej tabeli:
select * from information_schema.role_table_grants where table_name='do_uprawnien';
Jak widzimy, nowy użytkownik dostał uprawnienia, ale do tego samego obiektu wszelkie uprawnienia ma użytkownik “postgres”. Będzie tak zawsze, ale nie będzie to dotyczyło wszystkich superużytkowników, a jedynie użytkownika "postgres".
Jeśli chcemy sprawdzić, jakie uprawnienia ma konkretny użytkownik, wywołujemy:
select * from information_schema.role_table_grants where grantee='do_uprawnien_user';
Wynik działania:
Obu sprawdzeń dokonaliśmy, będąc zalogowanym jako użytkownik "postgres", dlatego w słowniku "information_schema.role_table_grants" widzimy wszystkie uprawnienia do wszystkich użytkowników i obiektów. Jeśli jednak zalogujemy się teraz jako użytkownik "do_uprawnien_user", to w tym słowniku widzieć będziemy tylko uprawnienia nadane temu użytkownikowi. W poniższym przykładzie wyświetlamy "całą" zawartość tego słownika jako użytkownik “do_uprawnien_user”, bez żadnych warunków "where", a widać tylko uprawnienia nadane nam:
psql -U do_uprawnien_user -d postgres
select * from information_schema.role_table_grants;
Do odbierania uprawnień stosujemy klauzulę "REVOKE". Podobnie jak w przypadku nadawania uprawnień, odbieranie uprawnień działa natychmiast. Nie jest wymagane np. przelogowanie się użytkownika. Do odbierania uprawnień stosujemy te same nazwy uprawnień, które wykorzystywaliśmy przy ich nadawaniu. Są one zestawione w tabeli w rozdziale "nadawanie uprawnień". Ogólna konstrukcja odbierania uprawnień wygląda następująco:
REVOKE NAZWA_UPRAWNIENIA FROM NAZWA_UZYTKOWNIKA [CASCADE]
Przykład odebrania uprawnień do select na tabeli abc użytkownikowi mapet:
revoke select on abc from mapet;
Jeśli nadaliśmy jakieś uprawnienie z możliwością jego dalszego przekazywania (with grant option), a chcielibyśmy odebrać tylko uprawnienie do przekazywania uprawnień dalej, możemy wykonać następujące polecenie:
revoke grant option for delete on abc from upr;
Jeśli jednak okaże się, że użytkownik ten już przekazał to uprawnienie, dalej zobaczymy komunikat:
Aby odebrać użytkownikowi jednocześnie możliwość przekazywania dalej danego uprawnienia i odebrać to uprawnienie wszystkim innym użytkownikom, którzy otrzymali to uprawnienie od niego, wywołujemy:
revoke grant option for delete on abc from upr cascade;
Dzięki klauzuli ALTER DEFAULT PRIVILEGES możesz w łatwy sposób zarządzać automatycznym nadawaniem uprawnień. Dzięki niej możesz np spowodować, że użytkownik B będzie miał automatyczne nadawanie uprawnienia SELECT do wszystkich tabel tworzonych przez użytkownika A.
Może to być użyteczne gdy masz np użytkownika będącego właścicielem wszystkich tabel aplikacji i użytkownika z poziomu którego działa sama aplikacja - a ten użytkownik potrzebuje dostępu do wszystkich obiektów. Przeanalizujmy najprostszy przykład. Tworzę użytkownika który ma uprawnienia do tworzenia obiektów w schemacie public, oraz użytkownika z poziomu którego będzie działała aplikacja:
create user wlasciciel_obiektow;
grant create,usage on schema public to wlasciciel_obiektow;
create user aplikacja with password 'aplikacja123';
Następnie loguję się za pomocą psql jako użytkownik “wlasciciel_obiektow” i powoduję że użytkownik “aplikacja” uzyska automatycznie uprawnienie select do każdego z tworzonych przez użytkownika “wlasciciel_obiektow” tabel. Następnie tworzę pustą tabelę:
psql -U wlasciciel_obiektow -d postgres
alter default privileges grant select on tables to aplikacja;
create table a();
Loguję się teraz na drugą sesję jako użytkownik “aplikacja” i sięgam do stworzonej przez użytkownika “wlasciciel_obiektow” tabeli:
psql -U aplikacja -d postgres
select * from a;
Jak widać, użytkownik “aplikacja” otrzymał automatycznie uprawnienia do tabeli stworzonej przez użytkownika “wlasciciel_obiektow”.
Należy pamiętać, że te uprawnienia będą nadawane tylko obiektom stworzonym po nadaniu uprawnień. Jeśli chcesz umożliwić dostęp do obiektów stworzonych przed nadanie uprawnień przez ALTER DEFAULT PRIVILEGES musisz użyć tradycyjnego GRANT.
Przyjrzyjmy się jednak składni ALTER DEFAULT PRIVILEGES i zobaczmy co jeszcze możemy za jego pomocą osiągnąć. Ogólna składnia:
ALTER DEFAULT PRIVILEGES
[ FOR { ROLE | USER } target_role [, ...] ]
[ IN SCHEMA schema_name [, ...] ]
{ GRANT privilege [, ...] ON object_type TO role [, ...] |
REVOKE privilege [, ...] ON object_type FROM role [, ...] }
Zajmijmy się zatem poszczególnymi elementami składni.
Zaczniemy od “FOR ROLE/USER”. Tej klauzuli możesz używać tylko jeśli jesteś zalogowany jako “postgres” lub inny superuser. Jeśli pominiesz ten fragment to domyślnie w “FOR ROLE/USER” zostanie wstawiony current_user, czyli aktualnie zalogowany użytkownik.
Dlatego wydając komendę “ALTER DEFAULT PRIVILEGES” z poziomu użytkownika “wlasciciel_obiektow” spowodowaliśmy automatyczne nadanie uprawnień użytkownikowi “aplikacja” do wszystkich obiektów tworzonych konkretnie przez użytkownika “wlasciciel_obiektow”. Teraz zaloguję się jako użytkownik “postgres”, z jego poziomu tworzę użytkownika “aplikacja2” i nadaję automatyczne uprawnienia do selecta na wszystkich tworzonych przez użytkownika “wlasciciel_obiektow” tabel użytkownikowi “aplikacja2”:
psql
create user aplikacja2;
alter default privileges for user wlasciciel_obiektow grant select on tables to aplikacja2;
Następnie loguję się jako użytkownk “wlasciciel_obiektow” i tworzę tabelę:
psql -U wlasciciel_obiektow -d postgres
create table b();
Z innej sesji podłączam się jako użytkownik “aplikacja2” i sięgam do tabeli “b”:
psql -U aplikacja2 -d postgres
select * from b;
I tym razem udało się sięgnąć do obiektu:
Kolejnym ciekawym elementem składni “ALTER DEFAULT PRIVILEGES” jest “IN SCHEMA”. Określa on schemat w którym znajdujące się tabele będą miały nadawane automatycznie uprawnienia. Jeśli pominiesz tę klauzulę, domyślnie przyjęte jest działanie dla wszystkich schematów.
Loguję się jako użytkownik “postgres”, tworzę dodatkowy schemat “drugi_schemat”, tworzę użytkownika “aplikacja3” i powoduję że wszystkie tabelki stworzone przez aktualnie zalogowanego użytkownika (dlatego że nie używam tu klauzuli FOR ROLE/USER) - tj użytkownika “postgres” w schemacie “drugi_schemat” będą dostępne do odczytu dla użytkownika “aplikacja3”. Nadaję uprawnienie “USAGE” na nowych schemacie. Tworzę też w tym nowym schemacie nową tabelę:
create schema drugi_schemat;
create user aplikacja3;
alter default privileges in schema drugi_schemat grant select on tables to aplikacja3;
grant usage on schema drugi_schemat to aplikacja3;
create table drugi_schemat.x();
Następnie loguję się jako użytkownik “aplikacja3” i sięgam do tabeli:
psql -U aplikacja3 -d postgres
select * from drugi_schemat.x;
Zwróć uwagę, że w przeciwieństwie do schematu “public” musiałem tu nadać uprawnienie “usage” na nowym schemacie.
Domyślne uprawnienia można konfigurować dla tabel, sekwencji, funkcji, typów, schematów. Poniżej przykład automatycznego nadawania uprawnień użytkownikowi “aplikacja3” do wszystkich tworzonych funkcji (tworzonych przez użytkownika nadającego uprawnienie - inaczej musielibyśmy użyć klauzuli “FOR USER/ROLE”).
alter default privileges grant execute on functions to aplikacja3;
Tutaj nadanie uprawnień do wykorzystywania sekwencji stworzonych od teraz w schemacie “drugi_schemat” użytkownik “aplikacja3” (pamiętaj jeszcze o ewentualnym dodaniu uprawnienia USAGE do schematu jeśli nie zrobiłeś tego wcześniej):
alter default privileges in schema drugi_schemat grant usage on sequences to aplikacja3;
We wszystkich kombinacjach, zamiast używać nazwy użytkownika możesz użyć nazwy roli. W poniższym przykładzie nadaje uprawnienia do selecta na wszystkich tabelach tworzonych od teraz w schemacie “sklep” każdemu posiadającemu rolę “public” - czyli domyślnie każdemu. Musiałem też dodać usage na schemacie w którym te tabele się znajdują:
alter default privileges in schema sklep grant select on tables to public;
grant usage on schema sklep to public;
Aby odebrać uprawnienie, w miejsce “GRANT” wprowadzamy “REVOKE” a w miejsce “TO” wprowadzamy “FROM”. Przykładowo uprawnienie nadane w ten sposób:
alter default privileges grant select on tables to aplikacja;
Możemy wycofać w ten sposób:
alter default privileges revoke select on tables from aplikacja;
Aby sprawdzić jakie mamy ustawione domyślne uprawnienia, wystarczy wykorzystać poniższe zapytanie:
SELECT
defaclrole::regrole AS tworca,
defaclnamespace::regnamespace AS schemat,
defaclobjtype AS typ_obiektu,
defaclacl AS uprawnienia_domyslne
FROM pg_default_acl;
Widzimy tu jaki użytkownik, ewentualnie w jakim schemacie i do czego ma uprawnienia. Co oznaczają poszczególne litery?
a | append - dodawanie wierszy |
r | read - odczyt wierszy w tabeli, odczyt sekwencji |
w | write - zmiana wierszy |
d | delete - kasowanie wierszy |
D | truncate - czyszczenie całej zawartości tabeli |
x | references - zakładanie kluczy obcych do tabeli |
t | trigger - zakładanie wyzwalaczy na tabelę |
X | execute - wykonanie funkcji |
Komentarze (0)
Brak komentarzy...