Dans quel ordre PostgreSQL vérifie-t-il les autorisations des objets?


16

Étant donné un rôle de base de données user1, une fonction something()définie comme une procédure stockée et une vue créée comme:

CREATE VIEW view1 AS select * from something()

Et, étant donné ces autorisations:

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

Lorsque je cours SELECT * FROM view1, j'obtiens une erreur permission denied for function something().

Ma question est, si je révoque les autorisations de sélection sur la vue, pourquoi la fonction est appelée? Je m'attendais à recevoir quelque chose comme:

permission denied for relation view1

Je vous remercie!


2
AFAIK il n'y a pas d'ordre défini dans lequel les autorisations sont vérifiées.
Craig Ringer

@CraigRinger Merci! Je suppose que c'est le comportement attendu alors. Comme j'expose la vue dans une API, j'essayais d'éviter de révéler les détails d'implémentation de la vue (étant donné le message d'erreur se plaignant des autorisations de la fonction au lieu de la vue).
santios

1
Je soupçonne que les autorisations sont évaluées à peu près de la même manière que les plans de requête (par exemple de bas en haut), et en tant que tel, l'objet le plus bas est évalué en premier, ce qui dans votre cas est la something()fonction. Un test rapide serait de modifier la requête afin d'obtenir un plan d'explication différent, d'ajuster les autorisations en conséquence, puis de voir si l'erreur d'autorisation est levée sur la something()fonction ou si elle suit la façon dont le nouveau plan d'exécution est réévalué.
John Eisbrener

Si vous accordez des autorisations sur la fonction et les révoquez dans la vue, cela devrait omettre toute mention de la fonction sous-jacente
amenadiel

Réponses:


3

Le problème dans ce cas ne concerne pas exactement l'ordre d'autorisation, mais l'ordre d'exécution.

En résumé, pour PostgreSQL:

1- Les vues qui accèdent aux tables remplaceront l'autorisation des tables

2- Les vues d'accès aux fonctions, devront évaluer toutes les fonctions, avant d'être vérifiées - donc les fonctions doivent être exécutées avant d'accéder à la vue, même si la vue n'a pas les autorisations de sélection ...

Comment pouvons-nous prouver cela?

Dans postgresql, les vues peuvent vous donner des autorisations pour effectuer une sélection dans une table, même si l'utilisateur ne dispose pas de ces autorisations.

Par exemple:

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

Connectez-vous en tant qu'utilisateur 1:

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

Dans le cas, l'utilisateur pourra sélectionner view2 même sans avoir l'autorisation de sélectionner la table.

Mais que faire si nous faisons la même chose avec une fonction ? Le comportement n'est PAS le même. Permet de créer une fonction qui attend 5 secondes avant de renvoyer 1 (afin que nous puissions déboguer si postgresql exécute la fonction chaque fois que nous appelons la vue)

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; 

Connectez-vous en tant qu'utilisateur 1:

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

L'autorisation de sélectionner dans la vue ne remplace pas l'autorisation de fonction, et pire encore si nous révoquons les autorisations de view1, le message montre toujours que postgresql a arrêté notre requête à cause de la fonction, quelle que soit l'autorisation de la vue. (c'est exactement ce qui se passe dans la question)

Mais la fonction est-elle vraiment vérifiée en premier? Si nous accordons les autorisations «tous» à la fonction, mais que nous révoquons l'autorisation d'affichage ...

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

Comme vous le voyez, postgresql a ATTENDU 5 SECONDES avant de dire que nous n'avons pas l'autorisation de sortir la vue , montrant que la fonction "quelque chose ()" est exécutée. Le retour des données de fonction doit donc exister avant la vérification de la vue.

Donc maintenant avec ces tests, nous savons maintenant que PostgreSQL devait d'abord évaluer toutes les fonctions avant de continuer notre requête, c'est comme si la requête n'existait toujours pas jusqu'à ce que toutes les fonctions envisagées soient complètement terminées, donc la vue ne peut pas être résolue pour postgresql savoir si nous avons ou non l'autorisation de le sélectionner.

Je pense que cela répond à votre question en termes de "permission order", mais pourquoi postgresql doit évaluer toutes les fonctions avant de continuer, c'est une autre question ...

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.