Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find out if user got permission to select/update/... a table/function/... in PostgreSQL

What is the recommended way to figure out if a user got a certain right (e.g. select or execute) on a certain class (e.g. table or function) in PostgreSQL?

At the moment I got something like

aclcontains(
    someColumnWithAclitemArray,
    makeaclitem(userOid,grantorOid,someRight,false))

but it's terrible since I have to check for every grantorOid that is possible and for every userOid the user can belong to.

On a related note: what are the possible rights you can test for? I haven't found any documentation but reading the source code I guess:

INSERT
SELECT
UPDATE
DELETE
TRUNCATE
REFERENCES
TRIGGER
EXECUTE
USAGE
CREATE
CONNECT

There also seems to be a CREATE TEMP right, but I can't figure out the correct text to use in the makeaclitem-function.

like image 929
finnsson Avatar asked Jun 03 '09 19:06

finnsson


People also ask

How do I check PostgreSQL user permissions?

Another way to do this is to use the information_schema schema and query the table_privileges table as: $ SELECT * FROM information_schema. table_privileges LIMIT 5; The above query will show detailed information about user privileges on databases as well as tables.

What is SELECT for update Postgres?

The select ... for update acquires a ROW SHARE LOCK on a table. This lock conflicts with the EXCLUSIVE lock needed for an update statement, and prevents any changes that could happen concurrently. All the locks will be released when the transaction ends.


2 Answers

I've found that a better approach (and I seem to remember this was taken from some queries built into psql, or maybe the information_schema views) is to use the has_*_privilege functions, and simply apply them to a set of all possible combinations of user and object. This will take account of having access to an object via some group role as well.

For example, this will show which users have which access to non-catalogue tables and views:

select usename, nspname || '.' || relname as relation,
       case relkind when 'r' then 'TABLE' when 'v' then 'VIEW' end as relation_type,
       priv
from pg_class join pg_namespace on pg_namespace.oid = pg_class.relnamespace,
     pg_user,
     (values('SELECT', 1),('INSERT', 2),('UPDATE', 3),('DELETE', 4)) privs(priv, privorder)
where relkind in ('r', 'v')
      and has_table_privilege(pg_user.usesysid, pg_class.oid, priv)
      and not (nspname ~ '^pg_' or nspname = 'information_schema')
order by 2, 1, 3, privorder;

The possible privileges are detailed in the description of the has_*_privilege functions at http://www.postgresql.org/docs/current/static/functions-info.html#FUNCTIONS-INFO-ACCESS-TABLE.

'CREATE TEMP' is a database-level privilege: it permits a user to use a pg_temp_* schema. It can be tested with has_database_privilege(useroid, datoid, 'TEMP').

like image 126
araqnid Avatar answered Oct 10 '22 01:10

araqnid


Take a look at the "Access Privilege Inquiry Functions" and also the "GRANT" reference page.

like image 37
Milen A. Radev Avatar answered Oct 10 '22 03:10

Milen A. Radev