So I have created two extensions with my superuser but when I try to use these extensions as a (non-super) user, it cannot find them.
As superuser:
postgres=# SELECT e.extname
postgres-# , n.nspname AS home_schema_of_extension
postgres-# , extrelocatable AS extension_can_be_relocated
postgres-# FROM pg_catalog.pg_extension e
postgres-# JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace;
extname | home_schema_of_extension | extension_can_be_relocated
---------------+--------------------------+----------------------------
adminpack | pg_catalog | f
plpgsql | pg_catalog | f
fuzzystrmatch | public | t
btree_gist | public | t
(4 rows)
And as another user:
toggleme=> SELECT e.extname
toggleme-> , n.nspname AS home_schema_of_extension
toggleme-> , extrelocatable AS extension_can_be_relocated
toggleme-> FROM pg_catalog.pg_extension e
toggleme-> JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace;
extname | home_schema_of_extension | extension_can_be_relocated
---------+--------------------------+----------------------------
plpgsql | pg_catalog | f
(1 row)
Why is the non-super-user unable to use these extensions? Non-super-user has public in his search path but still can't even see that these extensions exist.
The superuser and normal user are connected to different databases in the same PostgreSQL instance.
CREATE EXTENSION is database-local.
Related
Is there an alternative to using psql \du to retrieve the Member of column using a builtin Postgres function or view? Thank you.
In psql you can echo the actual queries generated by backslash commands.
Use the --echo-hidden parameter
psql --echo-hidden ...
or set the variable ECHO_HIDDEN in psql, example:
test=# \set ECHO_HIDDEN on
test=# \du
********* QUERY **********
SELECT r.rolname, r.rolsuper, r.rolinherit,
r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,
r.rolconnlimit, r.rolvaliduntil,
ARRAY(SELECT b.rolname
FROM pg_catalog.pg_auth_members m
JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
WHERE m.member = r.oid) as memberof
, r.rolreplication
, r.rolbypassrls
FROM pg_catalog.pg_roles r
ORDER BY 1;
******************************
Read about psql in the documentation.
I figured it out and here's my answer:
SELECT
pg_roles.rolname,
pg_auth_members.member,
(SELECT pg_roles.rolname FROM pg_roles WHERE oid = pg_auth_members.member)
FROM
pg_roles, pg_auth_members
WHERE
pg_auth_members.roleid = ( SELECT oid FROM pg_roles WHERE rolname = 'my_group') and pg_roles.rolname = 'my_group';
So, this query would return something like this:
rolname | member | rolname
------------+--------+---------
my_group | 18068 | first_member
my_group | 18069 | second_member
(2 rows)
I have postgres database.
I want the list of users with access privileges they are being assigned.
I tried to find query and also looked in to psql command line help. (\nu and all) but I haven't found any usefull information.
Is anyone knows about that can help me out.
Thanks.
Here as a supplement to the previous.
To check the privileges of user by following:
SELECT * FROM pg_user;
As the same way, to check roles:
SELECT * FROM pg_roles;
There are few basic command like \du and \l that will provide the general information.
For getting the detailed information you may use the below function.
CREATE OR REPLACE FUNCTION database_privs(text) RETURNS table(username text,dbname name,privileges text[])
AS
$$
SELECT $1, datname, array(select privs from unnest(ARRAY[
( CASE WHEN has_database_privilege($1,c.oid,'CONNECT') THEN 'CONNECT' ELSE NULL END),
(CASE WHEN has_database_privilege($1,c.oid,'CREATE') THEN 'CREATE' ELSE NULL END),
(CASE WHEN has_database_privilege($1,c.oid,'TEMPORARY') THEN 'TEMPORARY' ELSE NULL END),
(CASE WHEN has_database_privilege($1,c.oid,'TEMP') THEN 'CONNECT' ELSE NULL END)])foo(privs) WHERE privs IS NOT NULL) FROM pg_database c WHERE
has_database_privilege($1,c.oid,'CONNECT,CREATE,TEMPORARY,TEMP') AND datname not in ('template0');
$$ language sql;
and then call the same function by providing the username/role that you get from \du
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
test | | {}
test2 | | {}
test3 | | {}
postgres=# select * from database_privs('test');
username | dbname | privileges
----------+-----------+-----------------------------
test | postgres | {CONNECT,TEMPORARY,CONNECT}
test | template1 | {CONNECT}
test | test | {CONNECT,TEMPORARY,CONNECT}
(3 rows)
I am trying to audit all of the permissions for an application before release and I want to ensure no role has more access than it needs. I have looked at the different functions and system tables, but everything is very piecemeal.
Is there a good query or method to be able to dump out every grant a particular role has?
I am using pg 9.5.
The column relacl of the system catalog pg_class contains all informations on privileges.
Example data in schema public owned by postgres with grants to newuser:
create table test(id int);
create view test_view as select * from test;
grant select, insert, update on test to newuser;
grant select on test_view to newuser;
Querying the pg_class:
select
relname,
relkind,
coalesce(nullif(s[1], ''), 'public') as grantee,
s[2] as privileges
from
pg_class c
join pg_namespace n on n.oid = relnamespace
join pg_roles r on r.oid = relowner,
unnest(coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)::text[])) acl,
regexp_split_to_array(acl, '=|/') s
where nspname = 'public'
and relname like 'test%';
relname | relkind | grantee | privileges
-----------+---------+----------+------------
test | r | postgres | arwdDxt <- owner postgres has all privileges on the table
test | r | newuser | arw <- newuser has append/read/write privileges
test_view | v | postgres | arwdDxt <- owner postgres has all privileges on the view
test_view | v | newuser | r <- newuser has read privilege
(4 rows)
Comments:
coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)) - Null in relacl means that the owner has all privileges;
unnest(...) acl - relacl is an array of aclitem, one array element for a user;
regexp_split_to_array(acl, '=|/') s - split aclitem into: s[1] username, s[2] privileges;
coalesce(nullif(s[1], ''), 'public') as grantee - empty username means public.
Modify the query to select individual user or specific kind of relation or another schemas, etc...
Read in the documentation:
The catalog pg_class,
GRANT with the description of acl system.
In a similar way you can get information about privileges granted on schemas (the column nspacl in pg_namespace) and databases (datacl in pg_database)
The relacl column (and others of type aclitem) doesn't have to be parsed as text.
The function aclexplode unnests array, which makes it suitable for lateral join. Result is record with well named fields, just convert oid to human-readable name:
select c.*, n.nspname,
acl.grantor, acl.grantee,
pg_catalog.pg_get_userbyid(acl.grantor), pg_catalog.pg_get_userbyid(acl.grantee),
acl.privilege_type, acl.is_grantable
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace,
lateral aclexplode(c.relacl) acl;
The sqlite3 CLI has a command .schema that will display the columns of all tables in the database.
The psql CLI for PostgreSQL has a meta-commands \d that shows columns for all "relations" (table, view, index, sequence, or foreign table) and a meta-command \dt that lists the relations that are tables but does not show the columns of those tables.
Is there a way to get psql to show output like sqlite3's .schema - show the output of \d on just relations that are tables? \d * shows columns for all relations, which in my database of 32 tables contains 63 tables and sequences. The pattern (* in this example) seems able to match on relation name but not relation type. Is there a pattern for "match all tables"?
If you want this like output:
sqlite> .schema t24
CREATE TABLE t24 (
i integer,
t text
);
You should use pg_dump -s, not psql:
bash>pg_dump -t t24 -s
CREATE TABLE t24 (
i integer,
t text
);
It created DDL just like .schema...
Now regarding the queries in comments, if you modify them a little:
t=# \d t24
Table "public.t24"
Column | Type | Modifiers
--------+---------+-----------
i | integer |
t | text |
t=# SELECT a.attname as "Column",pg_catalog.format_type(a.atttypid, a.atttypmod) as "Type",
(SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
FROM pg_catalog.pg_attrdef d
WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) as "Modifiers"
FROM pg_catalog.pg_attribute a
join pg_catalog.pg_class c on a.attrelid = c.oid
WHERE true
AND relname like 't24'
AND c.relkind = 'r'::"char"
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY relname, a.attnum;
Column | Type | Modifiers
--------+---------+-----------
i | integer |
t | text |
(2 rows)
This query will show only tables in same manner as \d meta-command.
BTW I took the query from this metacommand. If you launch psql -E, and run '\d table_name` you will see that all meta commands are just wraps for select queries...
This query is working as expected:
select nspname, relname, max(attnum) as num_cols
from pg_attribute a, pg_namespace n, pg_class c
where n.oid = c.relnamespace and a.attrelid = c.oid
and c.relname not like '%pkey'
and n.nspname not like 'pg%'
and n.nspname not like 'information%'
group by 1, 2
order by 1, 2;
nspname | relname | num_cols
--------+----------+----------
public | category | 4
public | date | 8
public | event | 6
public | listing | 8
public | sales | 10
public | users | 18
public | venue | 5
But how do I get the list of columns per table?
Expected output:
nspname | relname | num_cols
--------+----------+----------
public | category | col1, col2, col3, col4
public | date | col1, col2, col3, col4 ..., col8
Mysql has group_concat function that would apply here.
http://docs.aws.amazon.com/redshift/latest/dg/c_join_PG_examples.html
The following query mentioned on that page does not return any rows for me.
select distinct attrelid, rtrim(name), attname, typname
from pg_attribute a, pg_type t, stv_tbl_perm p
where t.oid=a.atttypid and a.attrelid=p.id
and a.attrelid between 100100 and 110000
and typname not in('oid','xid','tid','cid')
order by a.attrelid asc, typname, attname;
Make sure to include all the schemas that you want to look at in search path.
http://docs.aws.amazon.com/redshift/latest/dg/r_search_path.html
set search_path to '$user', public, enterprise;
Redshift without the schemas in your user id's search path cant show you the columns. For accessing table structure you may want to have usage rights on the schema too.