¿En qué orden verifica PostgreSQL los permisos de los objetos?

16

Dado un rol de base de datos user1, una función something()definida como un procedimiento almacenado y una vista creada como:

CREATE VIEW view1 AS select * from something()

Y, dados estos permisos:

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

Cuando corro SELECT * FROM view1, aparece un error permission denied for function something().

Mi pregunta es, si revoco los permisos de selección en la vista, ¿por qué se llama a la función? Esperaba recibir algo como:

permission denied for relation view1

¡Gracias!

santios
fuente
2
AFAIK no hay un orden definido en el que se verifican los permisos.
Craig Ringer
@CraigRinger ¡Gracias! Supongo que ese es el comportamiento esperado entonces. Como estoy exponiendo la vista en una API, estaba tratando de evitar revelar los detalles de implementación de la vista (dado el mensaje de error quejándose de los permisos de la función en lugar de la vista).
santios
1
Sospecho que los permisos se evalúan de la misma manera que los planes de consulta (por ejemplo, de abajo hacia arriba) y, como tal, el objeto más bajo se evalúa primero, que en su caso es la something()función. Una prueba rápida sería modificar la consulta para que obtenga un plan de explicación diferente, ajustando los permisos en consecuencia, y luego ver si se arroja el error de permiso en la something()función o si sigue cómo se está reevaluando el nuevo plan de ejecución.
John Eisbrener
Si otorga permisos sobre la función y los revoca en la vista, debe omitir cualquier mención a la función subyacente
amenadiel

Respuestas:

3

El problema en ese caso no es exactamente sobre el orden de permisos, sino el orden de ejecución.

En resumen, para PostgreSQL:

1- Las vistas que son tablas de acceso anularán el permiso de tablas

2- Las funciones de acceso a las vistas deberán evaluar todas las funciones antes de comprobarlas, por lo que las funciones deben ejecutarse antes de acceder a la vista, incluso si la vista no tiene permisos de selección ...

¿Cómo podemos probar eso?

En postgresql, las vistas pueden otorgarle permisos para realizar una selección en una tabla, incluso si el usuario no tiene estos permisos.

Por ejemplo:

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

Inicie sesión como usuario 1:

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

En el caso, el usuario podrá seleccionar view2 incluso sin tener permiso para seleccionar la tabla.

Pero, ¿ qué pasa si hacemos lo mismo con una función ? El comportamiento NO es el mismo. Creemos una función que espere 5 segundos antes de devolver 1 (para que podamos depurar si postgresql está ejecutando la función cada vez que llamamos a la vista)

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; 

Inicie sesión como usuario 1:

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

El permiso para seleccionar en la vista no anula el permiso de la función, e incluso peor si revocamos los permisos de view1, el mensaje aún muestra que postgresql detuvo nuestra consulta debido a la función, sin importar el permiso de la vista. (eso es exactamente lo que está sucediendo en la pregunta)

Pero, ¿se está comprobando realmente la función primero? Si otorgamos los permisos 'todos' a la función, pero revocamos el permiso de vista ...

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

Como puede ver postgresql ESPERÓ 5 SEGUNDOS antes de decir que no tenemos permiso para generar la vista , lo que muestra que la función "algo ()" se ejecuta. Por lo tanto, la función de retorno de datos debe existir antes de la verificación de la vista.

Entonces, ahora con estas pruebas, ahora sabemos que PostgreSQL necesitaba evaluar primero todas las funciones antes de continuar nuestra consulta, es como si la consulta aún no existiera hasta que todas las funciones involucradas se hayan completado por completo, por lo que la vista no se puede resolver para postgresql saber si tenemos o no permiso para seleccionarlo.

Creo que esto responde a su pregunta en términos de "orden de permiso", pero por qué postgresql necesita evaluar todas las funciones antes de continuar, esa es otra pregunta ...

777Anon
fuente