How to check permissions to functions under psql console - privileges

Could you tell me please how to check permissions to functions with psql console but without being overwhelmed with source code and descirption (like when using \df+).

For a simpler query, use:
SELECT proacl FROM pg_proc WHERE proname='FUNCTION-NAME';
The results is like:
proacl
----------------------------------------------------
{=X/postgres,postgres=X/postgres,test1=X/postgres}
(1 row)
which shows that test1 user also has access to this function.
For more details, see the discussion on psql's mailing list: psql missing feature: show permissions for functions.

You could query the system tables:
SELECT proname, rolname
FROM pg_proc pr,
pg_type tp,
pg_authid id
WHERE proowner = id.oid
AND tp.oid = pr.prorettype
AND pr.proisagg = FALSE
AND tp.typname <> 'trigger'
AND pr.pronamespace IN (
SELECT oid
FROM pg_namespace
WHERE nspname NOT LIKE 'pg_%'
AND nspname != 'information_schema'
);

Related

How to check if Redshift user can alter table

In Redshift, I am checking Users' grants. How do I know if they can alter tables?
I can know if they can drop tables because "Only the owner of the table, the schema owner, or a superuser can drop a table." - https://docs.aws.amazon.com/redshift/latest/dg/r_DROP_TABLE.html No such qualification exists for alter table: https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE.html
HAS_TABLE_PRIVILEGE provides info about other privileges, but not alter table: https://docs.aws.amazon.com/redshift/latest/dg/r_HAS_TABLE_PRIVILEGE.html
I got a response from AWS Support. tl;dr: alter table can be run by those, and only those, who can drop table.
"""
This is because, determining whether or not a user can alter a table, works in a similar way to that were one determines whether or not a given user can drop a table. That is, only the owner of the table, the schema owner, or a superuser can Alter a table. According to our documentation, "The right to modify or destroy an object is always the privilege of the owner only." [1].
[1] Default database user privileges - https://docs.aws.amazon.com/redshift/latest/dg/r_Privileges.html
Therefore, to see the users with alter table permissions for a specific table, there is need to determine the owner of that specific table by running the following command:
Kindly note that in this example, the 'sales' table is used. You can edit this as you see fit. To see all the table owners, the AND section of the WHERE clause can be removed.
====Query to see table owners====
SELECT n.nspname AS schema_name
, pg_get_userbyid(c.relowner) AS table_owner
, c.relname AS table_name
, CASE WHEN c.relkind = 'v' THEN 'view' ELSE 'table' END
AS table_type
, d.description AS table_description
FROM pg_class As c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
LEFT JOIN pg_description As d
ON (d.objoid = c.oid AND d.objsubid = 0)
WHERE c.relkind IN('r', 'v')
AND c.relname = 'sales'
ORDER BY n.nspname, c.relname;
You can also see all the superusers who have permissions to Alter table by running the following query:
====Query to see superusers====
SELECT usename FROM pg_user WHERE usesuper = 'true';
The combination of both results will enable you to see all the users which have alter table permissions.
"""

Can psql output a description of all tables, but only tables?

When I do \d public.* I get a list of descriptions of tables, but also of all other indices etc.
When I do \dt public.* I get a list of tablenames, but not the full descriptions of those tables.
Is there a command that gives me the full descriptions of all tables without the other object types?
Version used: psql --version outputs psql (PostgreSQL) 11.5
You can use obj_description() for that:
select tbl.relname as table_name,
obj_description(tbl.oid) as comment
from pg_class tbl
join pg_namespace n on n.oid = tbl.relnamespace
where n.nspname = 'public'
and tbl.relkind = 'r' ;

Get DB owner's name in PostgreSql

I have DB "test" in PostgreSql. I want to write sql to get owner my database.
You can find such things in the system catalog
SELECT d.datname as "Name",
pg_catalog.pg_get_userbyid(d.datdba) as "Owner"
FROM pg_catalog.pg_database d
WHERE d.datname = 'database_name'
ORDER BY 1;
If you use the psql command-line tool, you can simply use \l
You can use the combination of pg_database, pg_users system tables and current_database() function in this way:
SELECT u.usename
FROM pg_database d
JOIN pg_user u ON (d.datdba = u.usesysid)
WHERE d.datname = (SELECT current_database());
can just cast the role OID with magic ::regrole to give the role name of owner:
SELECT datdba::regrole FROM pg_database WHERE datname = 'test' ;
This work with database owned by group role:
SELECT
U.rolname
,D.datname
FROM
pg_roles AS U JOIN pg_database AS D ON (D.datdba = U.oid)
WHERE
D.datname = current_database();
Using pg_authid (as I did in my previous version) instead of pg_roles is limited to SuperUser because it holds password (see documentation):
Since this catalog contains passwords, it must not be publicly
readable. pg_roles is a publicly readable view on pg_authid that
blanks out the password field.
The follwing query displays info for all tables in the public schema:
select t.table_name, t.table_type, c.relname, c.relowner, u.usename
from information_schema.tables t
join pg_catalog.pg_class c on (t.table_name = c.relname)
join pg_catalog.pg_user u on (c.relowner = u.usesysid)
where t.table_schema='public';
source :http://cully.biz/2013/12/11/postgresql-getting-the-owner-of-tables/
Remember in SQL including postgres that you have a heirarchy within a given sql server instance: catalog/db > schema > tables
When looking for perms/metadata for within a catalog you want to look at information_schema
Example: information_schema.role_table_grants for table perms
Example: information_schema.role_usage_grants for SEQUENCE/schema perms
https://www.postgresql.org/docs/current/information-schema.html
For catalog/db-level config/meta, you need to look another level up in pg_catalog.
https://www.postgresql.org/docs/current/catalogs.html
Example:
SELECT dbs.datname, roles.rolname
FROM pg_catalog.pg_database dbs, pg_catalog.pg_roles roles
WHERE dbs.datdba = roles.oid;
pg_catalog.pg_database.datdba has ID of owner role.
pg_catalog.pg_roles.oid has ID of owner role (join)
pg_catalog.pg_roles.rolname has name/string of owner role

Dumping tables and schemas that are accessible to me only?

Is it possible to dump tables and schemas that are accessible to me only in PostgreSQL?
First find the relations you have access to (this can be tweaked to pull schemas too)
with relnames as (SELECT relname FROM pg_class
WHERE relkind='r' and relnamespace = (select oid from pg_namespace where nspname = 'public'))
select array_agg(relname) from relnames WHERE has_table_privilege(SESSION_USER, relname, 'SELECT');
Now we aren't quite done now because that just creates an array of tables we have access to. We now need to change this to use array_to_string to get something we can feed into pg_dump:
with relnames as (SELECT relname FROM pg_class
WHERE relkind='r' and relnamespace = (select oid from pg_namespace where nspname = 'public'))
select array_to_string(array_agg(relname), ' -t ') from relnames WHERE has_table_privilege(SESSION_USER, relname, 'SELECT');
the above queries can be tweaked (changing the pg_namespace subquery) to pull namespaces you have access to and you could change it to a join to pull fully qualified table names.

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.
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').
Take a look at the "Access Privilege Inquiry Functions" and also the "GRANT" reference page.
Because Redshift is supporting values() only in INSERT INTO queries, the below query can be used with the obviously not-so-nice union all select.
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,
(select 'select' as priv,1 as privorder union all select 'insert',2 union all select 'update',3 union all select 'delete',4)
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;
Edit:
Also, I realized, that in our db Dataiku creates tables that can have CAPITAL letter in them, so, if table not exist error happens, you should use the lower() function