Jeśli uprawnienia na poziomie ról i tabel to "ochroniarz przy drzwiach wejściowych", to Row-Level Security to taki osobisty ochroniarz, który sprawdza, czy dany użytkownik może wejść do każdego konkretnego pokoju w budynku.
RLS pomaga ogarnąć, żeby użytkownik mógł pracować tylko z tymi wierszami w tabeli, do których ma dostęp. Na przykład:
- W sklepie internetowym menedżer powinien widzieć tylko swoje zamówienia.
- W platformie CRM pracownik widzi tylko klientów swojej drużyny.
- W systemie bankowym klient powinien mieć dostęp tylko do swoich kont.
Jak działa RLS
Podstawą działania RLS jest koncepcja polityk dostępu. Polityki określają, które wiersze tabeli są widoczne dla roli lub użytkownika i które są dostępne do zmian (INSERT, UPDATE, DELETE).
Domyślnie RLS jest wyłączony dla wszystkich tabel i trzeba go włączyć ręcznie.
Włączanie RLS dla tabeli
Stwórzmy tabelę orders, gdzie trzymamy zamówienia sklepu internetowego:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
product_name TEXT NOT NULL,
price NUMERIC NOT NULL
);
Dodajmy kilka testowych danych:
INSERT INTO orders (user_id, product_name, price)
VALUES
(1, 'Smartfon', 500),
(2, 'Laptop', 1000),
(1, 'Słuchawki', 100),
(3, 'Klawiatura', 50);
Teraz włączmy RLS dla tej tabeli:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
Co zrobiliśmy? Aktywowaliśmy mechanizm RLS, ale same polityki jeszcze nie są ustawione. Dopóki polityki nie zostaną stworzone, RLS w praktyce nie wpływa na dostęp do tabeli.
Tworzenie polityki dostępu
Żeby dodać reguły do zarządzania dostępem, używamy komendy:
CREATE POLICY nazwa_polityki
ON tabela
[FOR { SELECT | INSERT | UPDATE | DELETE }]
TO rola
USING (warunek_dostępu)
WITH CHECK (warunek_sprawdzenia);
FOR: określa, dla jakich operacji polityka się stosuje (SELECT,INSERT,UPDATE,DELETE). Jeśli pominiesz ten parametr, polityka dotyczy wszystkich operacji.TO: wskazuje, dla jakich ról polityka jest aktywna. Jeśli nie podasz, polityka dotyczy każdej roli.USING: ustawia warunek, przy którym wiersze będą widoczne dla użytkownika.WITH CHECK: określa warunek sprawdzania dla operacjiINSERTiUPDATE.
Przykład: dostęp tylko do swoich zamówień
Stwórzmy politykę, która pozwala użytkownikom widzieć tylko swoje zamówienia. Załóżmy, że identyfikator aktualnego użytkownika zgadza się z user_id w tabeli:
CREATE POLICY user_can_view_own_orders
ON orders
FOR SELECT
USING (user_id = current_user::INT);
Co tu się dzieje?
- Polityka nazywa się
user_can_view_own_orders. - Dotyczy operacji
SELECT. - Tylko wiersze, gdzie
user_idzgadza się z identyfikatorem aktualnego użytkownika (current_user), są widoczne.
Czyli jeśli jesteś zalogowany jako użytkownik z user_id = 1, zobaczysz tylko swoje zamówienia.
Sprawdzanie działania RLS
Stwórzmy dwóch użytkowników: user1 i user2.
CREATE ROLE user1 LOGIN PASSWORD 'password1';
CREATE ROLE user2 LOGIN PASSWORD 'password2';
Przyznajmy rolom dostęp do tabeli:
GRANT SELECT ON orders TO user1, user2;
Teraz przełączmy się na użytkownika user1 i spróbujmy wykonać zapytanie:
SELECT * FROM orders;
Efekt: zobaczysz tylko wiersze, gdzie user_id = 1.
Polityki dla INSERT
Załóżmy, że chcemy pozwolić użytkownikom dodawać tylko swoje zamówienia (czyli wiersz z user_id musi zgadzać się z identyfikatorem aktualnego użytkownika).
Stwórzmy politykę na INSERT:
CREATE POLICY user_can_insert_own_orders
ON orders
FOR INSERT
WITH CHECK (user_id = current_user::INT);
Teraz, jeśli użytkownik user1 spróbuje dodać zamówienie, gdzie user_id nie jest równe 1, zapytanie zakończy się błędem.
Polityki dla UPDATE i DELETE
Podobnie można tworzyć polityki do zmiany i usuwania danych. Na przykład:
Do aktualizacji swoich danych:
CREATE POLICY user_can_update_own_orders
ON orders
FOR UPDATE
USING (user_id = current_user::INT)
WITH CHECK (user_id = current_user::INT);
Do usuwania swoich danych:
CREATE POLICY user_can_delete_own_orders
ON orders
FOR DELETE
USING (user_id = current_user::INT);
Stosowanie kilku polityk
Możesz stworzyć kilka polityk dla jednej tabeli. Wszystkie będą działać jednocześnie. Na przykład, jeśli dla jednej roli działa kilka reguł, PostgreSQL sprawdzi je wszystkie (logiczne AND).
Sprawdzanie i debugowanie RLS
Żeby sprawdzić, jakie polityki są ustawione dla tabeli, użyj komendy:
\di+ nazwa_tabeli
Jeśli chcesz tymczasowo wyłączyć RLS (np. dla admina), wykonaj:
ALTER TABLE orders DISABLE ROW LEVEL SECURITY;
Rola administratora SUPERUSER domyślnie nie jest ograniczona przez RLS, więc widzi wszystkie dane.
Typowe błędy przy ustawianiu RLS
Błędy mogą się pojawić, jeśli zapomnisz:
- Aktywować RLS komendą
ALTER TABLE ... ENABLE ROW LEVEL SECURITY. - Ustawić odpowiednie polityki dla wszystkich operacji (
SELECT,INSERT,UPDATE,DELETE). - Poprawnie podać warunek w
USINGiWITH CHECK. Na przykład, jeśli nie sprawdziszuser_id, możesz przypadkiem otworzyć dostęp do wszystkich wierszy.
Row-Level Security to jeden z najmocniejszych narzędzi bezpieczeństwa w PostgreSQL. Pozwala ustawić dostęp z dokładnością do wiersza i automatyzować zarządzanie dostępem, co jest mega ważne dla złożonych aplikacji z wysokimi wymaganiami co do ochrony danych.
GO TO FULL VERSION