16

Given a database role, user1, a function something() defined as a stored procedure and a view created like:

CREATE VIEW view1 AS select * from something()

And, given this permissions:

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

When I run SELECT * FROM view1, I get an error permission denied for function something().

My question is, if I revoke the select permissions on the view, why the function is called? I was expecting to receive something like:

permission denied for relation view1

Thank you!

4
  • 2
    AFAIK there's no defined order in which permissions are checked. Commented May 5, 2017 at 8:01
  • @CraigRinger Thank you! I guess that's the expected behavior then. As I'm exposing the view in an api, I was trying to avoid revealing implementation details of the view (given the error message complaining about the function's permissions instead of the view).
    – santios
    Commented May 5, 2017 at 15:41
  • 1
    I would suspect permissions are evaluated in much the same fashion query plans are (e.g. from the bottom up), and as such the lowest object is evaluated first, which in your case is the something() function. A quick test would be to modify the query so that you get a different explain plan, adjusting permissions accordingly, and then see if the permission error is thrown on the something() function or if it follows how the new execution plan is being reevaluated. Commented May 9, 2017 at 17:30
  • If you grant permissions on the function and revoke them on the view, it should omit any mention to the underlying function
    – ffflabs
    Commented Mar 13, 2018 at 10:59

1 Answer 1

3

The problem in that case is not exactly about permission order, but execution order.

In resume, for PostgreSQL :

1- Views that are acessing tables will override the tables permission

2- Views acessing functions, will need to evaluate all the functions, before being checked - so the functions must be executed before acessing the view, even if the view does not has select permissions...

How can we prove that?

In postgresql, views are able to give you permissions for doing a select in a table, even if the user don't have this permissions.

For example:

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

Log in as user 1:

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

In the case, the user will be able to select view2 even don't having permission to select the table.

But what if we do the same thing with a function? The behavior are NOT the same. Lets create a function that wait 5 seconds before returning 1 (so we can debug if postgresql is running the function everytime that we call the view)

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; 

Log in as user 1:

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

The permission to do select on the view do not overrides the function permission, and even worst if we revoke the permissions from view1, the message still shows that postgresql stopped our query because of the function, no matter what the permission of the view.. (that is exactly what is happening in the question)

But is the function really being checked first? If we give the 'all' permissions to the function, but revoke the view permission...

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

As you see postgresql WAITED 5 SECONDS before saying that we dont have permission to output the view, showing that the "something()" function are executed. So the function data return must exist before the check of the view.

So now with this tests, we now know that PostgreSQL needed to first evaluate all the functions before continuing our query, is just like the query still does not exist until all the functions envolved are fully completed, so the view cant be solved for postgresql to know if we have or not permission to select it.

I think this answer your question in the terms of "permission order", but why does postgresql needs to evaluate all the functions before continuing, thats is another question...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.