W jakiej kolejności PostgreSQL sprawdza uprawnienia do obiektów?

16

Biorąc pod uwagę rolę bazy danych, user1funkcja something()zdefiniowana jako procedura składowana i widok utworzony jak:

CREATE VIEW view1 AS select * from something()

I biorąc pod uwagę te uprawnienia:

REVOKE ALL ON FUNCTION something FROM user1
REVOKE SELECT ON view1 FROM user1

Po uruchomieniu SELECT * FROM view1pojawia się błąd permission denied for function something().

Moje pytanie brzmi: jeśli odwołam uprawnienia wyboru w widoku, dlaczego wywoływana jest ta funkcja? Spodziewałem się czegoś takiego:

permission denied for relation view1

Dziękuję Ci!

Santios
źródło
2
AFAIK nie ma zdefiniowanej kolejności sprawdzania uprawnień.
Craig Ringer
@CraigRinger Dziękujemy! Myślę, że takie jest oczekiwane zachowanie. Podczas wyświetlania widoku w interfejsie API starałem się unikać ujawniania szczegółów implementacji widoku (biorąc pod uwagę komunikat o błędzie narzekający na uprawnienia funkcji zamiast widoku).
Santios
1
Podejrzewam, że uprawnienia są oceniane w taki sam sposób, jak w przypadku tych samych modnych planów zapytań (np. Od dołu do góry) i jako taki najpierw oceniany jest najniższy obiekt, który w twoim przypadku jest something()funkcją. Szybki test polegałby na zmodyfikowaniu zapytania, tak aby uzyskać inny plan wyjaśniania, odpowiednio dostosowując uprawnienia, a następnie sprawdzić, czy błąd funkcji został zgłoszony w something()funkcji lub czy wynika ze sposobu ponownej oceny nowego planu wykonania.
John Eisbrener,
Jeśli przyznasz uprawnienia do funkcji i odwołasz je w widoku, należy pominąć jakąkolwiek wzmiankę o podstawowej funkcji
ffflabs

Odpowiedzi:

3

Problem w tym przypadku nie dotyczy dokładnie kolejności uprawnień, ale kolejności wykonania.

W CV dla PostgreSQL:

1- Widoki będące tabelami dostępu zastępują uprawnienia do tabel

2- Widoki uzyskujące dostęp do funkcji, będą musiały ocenić wszystkie funkcje, zanim zostaną sprawdzone - więc funkcje muszą zostać wykonane przed uzyskaniem dostępu do widoku, nawet jeśli widok nie ma uprawnień wyboru ...

Jak możemy to udowodnić?

W postgresql widoki są w stanie dać ci uprawnienia do dokonywania wyboru w tabeli, nawet jeśli użytkownik nie ma takich uprawnień.

Na przykład:

create view view2 as select * from table1;
revoke all on table1 from user1;
grant select on view2 to user1; 

Zaloguj się jako użytkownik 1:

select * from table1 (permission denied) 
select * from view2 (sucess - the query executes)

W takim przypadku użytkownik będzie mógł wybrać widok 2, nawet nie mając uprawnień do wyboru tabeli.

Ale co jeśli zrobimy to samo z funkcją ? Zachowanie NIE jest takie samo. Stwórzmy funkcję, która czeka 5 sekund przed zwróceniem 1 (abyśmy mogli debugować, jeśli postgresql uruchamia funkcję za każdym razem, gdy wywołujemy widok)

CREATE OR REPLACE FUNCTION something() RETURNS integer
AS 'select 1 from pg_sleep(5);'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT; --this function will delay 5 seconds

create view view1 as select * from something();
revoke all on function something() from user1;
grant select on view1 to user1; 

Zaloguj się jako użytkownik 1:

select * from something(); (permission denied for something) 
select * from view1 (permission denied for something )

Zezwolenie na dokonanie wyboru w widoku nie zastępuje uprawnienia funkcji, a nawet najgorsze, jeśli cofniemy uprawnienia z widoku 1, komunikat nadal pokazuje, że postgresql zatrzymał nasze zapytanie z powodu funkcji, bez względu na pozwolenie na widok. (dokładnie to dzieje się w pytaniu)

Ale czy funkcja naprawdę jest najpierw sprawdzana? Jeśli damy tej funkcji uprawnienia „wszystkie”, ale cofniemy uprawnienie do wyświetlania ...

grant all on function something to user1; 
revoke all on view1 from user1; 
select * from view1;
Delayed 5 seconds... (the function executed!) 
Permission denied for select on view1

Jak widzisz postgresql ODCZYTAŁ 5 SEKUND, zanim powiedział, że nie mamy pozwolenia na wyświetlenie widoku , pokazując, że funkcja „coś ()” jest wykonywana. Zatem powrót danych funkcji musi istnieć przed sprawdzeniem widoku.

Teraz dzięki tym testom wiemy, że PostgreSQL musiał najpierw ocenić wszystkie funkcje przed kontynuowaniem zapytania, jest tak, jakby zapytanie wciąż nie istniało, dopóki wszystkie włączone funkcje nie zostaną w pełni zakończone, więc widok nie może zostać rozwiązany dla postgresql, aby wiemy, czy mamy pozwolenie na jego wybór.

Myślę, że to odpowiedź na twoje pytanie w kategoriach „kolejności zezwoleń”, ale dlaczego postgresql musi ocenić wszystkie funkcje przed kontynuowaniem, to kolejne pytanie ...

777Anon
źródło