4

I have a table t and some functions which access t. For example:

create function list_t() returns setof t as $$
    select * from t;
$$ language sql stable;

Is it possible to define role permissions to only allow the execution of list_t(), while not allowing plain SELECT, UPDATE, DELETE and INSERT queries on t?

I tried the following:

grant execute on all functions in schema public to my_user;
revoke all on t from my_user;

While this indeed disallows SELECT * FROM t, it also disallows SELECT list_t().

2 Answers 2

6

You need to create the function as a user that has (select) access to the underlying table. Then define the function with the option security defined which means when the function is called, it operates with the privileges of the function owner, not the caller:

create function list_t() returns setof t 
  security definer
as $$
    select * from t;
$$ language sql stable;

Another way of doing this is to create a view, then grant SELECT privileges to the view (not the table):

create view v_t
as
select *
from t;

grant select on v_t to my_user;

Note that a set returning function should be used in the FROM clause like a table:

select *
from list_t();
5
  • Adding 'security definer' works, interesting concept. Just wondering, what is wrong with select list_t()?
    – Katrin
    Commented Sep 21, 2018 at 8:49
  • @Katrin: The expressions in the select list should be scalar values (single values), not a set of rows. Would you think that select some_table makes sense?
    – user1822
    Commented Sep 21, 2018 at 8:51
  • I can see that in case of plain columns and regular tables, but not in the context of functions. Isn't that the same as select unnest('{1,2,3}'::int[]), which gives the same output as select * from unnest('{1,2,3}'::int[])?
    – Katrin
    Commented Sep 21, 2018 at 8:54
  • 1
    That is not recommended either
    – user1822
    Commented Sep 21, 2018 at 8:56
  • Oh really, I did not really know that. I appreciate it that you brought it up!
    – Katrin
    Commented Sep 21, 2018 at 9:01
0

The issue brought up here is easily resolved by using SECURITY DEFINER. However, it's worth noting that code that runs in procedures and functions marked as SECURITY DEFINER cannot utilize transaction support (such as COMMIT or ROLLBACK).

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.