Obtaining sql permissions on views/tables/etc from command line - postgresql

These are permissions for ie. my_view view
pwx1=# \dp my_view
Access privileges
Schema | Name | Type | Access privileges | Column privileges | Policies
----------+-----------------+------+-----------------------+-------------------+----------
schema_x | my_view | view | user1=arwdDxt/user1 +| |
| | | user2=arwdDxt/user1 +| |
| | | user3=r/user1 | |
and I would like to get these grants in sql form like:
GRANT SELECT ON TABLE my_view TO user3;
I can get these grants using pgadmin, but want to do it from psql or command line if possible?

You can get the ACL information from pg_class and use the aclexplode function for more pretty presentation:
SELECT acl.grantor::regrole AS grantor,
acl.grantee::regrole AS grantee,
privilege_type,
is_grantable
FROM pg_catalog.pg_class AS t
CROSS JOIN LATERAL aclexplode(t.relacl) AS acl
WHERE t.oid = 'schema_x.my_view'::regclass;
In the long run, it is a good idea to learn to read PostgreSQL ACLs.

Related

Postgres - Can not 'SELECT' from tables even though my role/user has been granted 'READ'

I have an admin role/user and a developers role on postgres. The developers role enherits attributes from a 'readaccess' role which I created for convenience in the future. If I run \du I get:
Role name | Attributes | Member of
-----------------+------------------------------------------------------------+-------------------
developers | | {readaccess}
rds_replication | Cannot login | {}
rds_superuser | Cannot login | {rds_replication}
rdsadmin | Superuser, Create role, Create DB, Replication, Bypass RLS+| {}
| Password valid until infinity |
rdsrepladmin | No inheritance, Cannot login, Replication | {}
readaccess | Cannot login +| {}
| Password valid until infinity |
admin | Create role, Create DB +| {rds_superuser}
| Password valid until infinity |
I have granted read access to my developers account and my readaccess account via the following
GRANT SELECT ON ALL TABLES IN SCHEMA mySchema TO developers;
ALTER DEFAULT PRIVILEGES IN SCHEMA mySchema GRANT SELECT ON TABLES TO developers;
GRANT SELECT ON ALL TABLES IN SCHEMA mySchema TO readaccess;
ALTER DEFAULT PRIVILEGES IN SCHEMA mySchema GRANT SELECT ON TABLES TO readaccess;
If I run the command \z on one of my tables in mySchema
myDb=> \z mySchema.myTable;
Access privileges
Schema | Name | Type | Access privileges | Column privileges | Policies
---------+------------------------+-------+-------------------------+-------------------+----------
mySchema| myTable | table | admin=arwdDxt/admin+ | |
| | | developers=r/admin | |
(1 row)
However I can not run selects -- it says I have no permissions
myDB=> select * from mySchema.myTable;
ERROR: permission denied for schema mySchema
LINE 1: select * from mySchema.myTable;
Can anyone help out?
In addition to granting access to the tables, you must also grant access to the schema that contains them:
GRANT USAGE ON SCHEMA myschema TO readaccess, developers;

Restrict user to one schema in PostgreSQL?

Is it possible in PostgreSQL to create a user that can only access a single schema?
Here is what I tried:
REVOKE ALL ON DATABASE testdb FROM public;
GRANT CONNECT ON DATABASE testdb TO testuser;
When I connect as testuser indeed I cannot access the actual data:
> SELECT * FROM some_table;
ERROR: permission denied for relation some_table
However, I can still list all the tables, etc. in all the other schemas:
SELECT * FROM pg_tables;
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity
--------------------+-------------------------------------------+------------+------------+------------+----------+-------------+-------------
test2 | foo | postgres | | t | f | f | f
test2 | bar | postgres | | t | f | f | f
...
It is impossible to configure PostgreSQL so that a user can only see those objects in the system catalogs for which he or she has permissions.
If you need such a setup, you should create a database per user.
I was able to do this like so:
GRANT USAGE ON SCHEMA schema_name TO user_name;
ALTER USER user_name SET search_path = schema_name;
The ALTER USER statement like this is a way of permanently setting the search path for schemas the way you would set the schema search path of an individual sessions with
SET SEARCH_PATH= schema_name_1, schema_name_2;

Revoke privilege "create table" from public schema but not from custom made schema

I am trying to create an account that is only able to use "SELECT" within the mydb_schema.
I am able to revoke the creation of a tables in public schema in my database (mydb) from a specific role but I am not able to revoke the creation of tables within the schema (mydb_schema) the role (user_role) is assigned to.
Can someone assist? What am I missing?
Below are the commands I used as user postgres and as the owner of the schema. At the end I also altered the postgres account by using the noinherit just as a desperate test. No result.
\c mydb
mydb=# create role user_account
mydb=# alter role user_account login noinherit;
mydb=# alter role user_account set search_path = 'mydb_schema';
##Up until this point I don't have SELECT pivileges but I can create a table within mydb_schema only and not in public.
mydb=# grant select on all tables in schema mydb_schema to user_account;
mydb=# revoke CREATE on SCHEMA public from public;
These are my databases:
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description
--------------------------------------------------------------------------
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 6820 kB | pg_default | default administrative connection database
mydb | seeker | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/seeker +| 3465 MB | pg_default |
seeker=CTc/seeker
These are my schemas:
List of schemas
Name | Owner | Access privileges | Description
----------------+----------+----------------------+------------------------
public | postgres | postgres=UC/postgres | standard public schema
mydb_schema | seeker | seeker=UC/seeker +|
| | =UC/seeker |
Found the solution here in dba.stackexchange
alter role servers_admin set default_transaction_read_only = 'ON';

Postgres - permission denied on updating pg_catalog.pg_cast

I'd like to update pg_catalog.pg_cast from the restricted user (on Postgres 9.3).
However running the query I need:
update pg_cast set castcontext = 'i' where oid in ( select c.oid from pg_cast c inner join pg_type src on src.oid = c.castsource inner join pg_type tgt on tgt.oid = c.casttarget where src.typname like 'int%' and tgt.typname like 'bool%');
ends up with error:
ERROR: permission denied for relation pg_cast
However permissions seems to be correctly set. See the steps I made since DB and USER creation till query:
psql -c "create database test1 WITH ENCODING 'UTF8' LC_COLLATE='en_GB.UTF8' LC_CTYPE='en_GB.UTF8' TEMPLATE=template0;" -U postgres
psql -U postgres test1;
test1=# CREATE USER test1 PASSWORD 'test1';
test1=# GRANT ALL ON SCHEMA public TO test1;
test1=# GRANT ALL ON ALL TABLES IN SCHEMA public TO test1;
test1=# GRANT SELECT ON TABLE pg_catalog.pg_cast TO test1;
test1=# GRANT SELECT ON TABLE pg_catalog.pg_type TO test1;
test1=# GRANT UPDATE ON TABLE pg_catalog.pg_cast TO test1;
test1=# \q
sudo service postgresql-9.3 restart
PGPASSWORD=test1;psql -U test1 test1
test1=> \z pg_catalog.pg_cast
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
------------+---------+-------+-------------------+--------------------------
pg_catalog | pg_cast | table | =r/postgres +|
| | | test1=rw/postgres |
(1 row)
test1=> \z pg_catalog.pg_type
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
------------+---------+-------+-------------------+--------------------------
pg_catalog | pg_type | table | =r/postgres +|
| | | test1=r/postgres |
(1 row)
test1=> SELECT grantee, privilege_type FROM information_schema.role_table_grants WHERE table_name='pg_cast';
grantee | privilege_type
---------+----------------
test1 | SELECT
test1 | UPDATE
(2 rows)
test1=> update pg_cast set castcontext = 'i' where oid in ( select c.oid from pg_cast c inner join pg_type src on src.oid = c.castsource inner join pg_type tgt on tgt.oid = c.casttarget where src.typname like 'int%' and tgt.typname like 'bool%');
ERROR: permission denied for relation pg_cast
What more should I do, to enable query execution with the test1 user?
Thanks.
You really should not be updating system catalogs directly. The "permission denied" error is Postgres trying to protect you from shooting yourself in the foot.
If You really want that (and if you break something, you get to keep both pieces...) start here: https://serverfault.com/questions/300123/how-to-edit-system-catalogs-in-postgresql-8-1
I have had similar problem updating Greenplum system catalog, the cue is:
ERROR: permission denied: "pg_filespace_entry" is a system catalog,
the solution was using the following command before I tried to modify system table:
set allow_system_table_mods='dml';

Psql list all tables

I would like to list all tables in the liferay database in my PostgreSQL install. How do I do that?
I would like to execute SELECT * FROM applications; in the liferay database. applications is a table in my liferay db. How is this done?
Here's a list of all my databases:
postgres=# \list
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
liferay | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =Tc/postgres +
| | | | | postgres=CTc/postgres+
| | | | | liferay=CTc/postgres
lportal | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 |
postgres | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 |
template0 | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
postgres=#
If you wish to list all tables, you must use:
\dt *.*
to indicate that you want all tables in all schemas. This will include tables in pg_catalog, the system tables, and those in information_schema. There's no built-in way to say "all tables in all user-defined schemas"; you can, however, set your search_path to a list of all schemas of interest before running \dt.
You may want to do this programmatically, in which case psql backslash-commands won't do the job. This is where the INFORMATION_SCHEMA comes to the rescue. To list tables:
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
BTW, if you ever want to see what psql is doing in response to a backslash command, run psql with the -E flag. eg:
$ psql -E regress
regress=# \list
********* QUERY **********
SELECT d.datname as "Name",
pg_catalog.pg_get_userbyid(d.datdba) as "Owner",
pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding",
d.datcollate as "Collate",
d.datctype as "Ctype",
pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges"
FROM pg_catalog.pg_database d
ORDER BY 1;
**************************
so you can see that psql is searching pg_catalog.pg_database when it gets a list of databases. Similarly, for tables within a given database:
SELECT n.nspname as "Schema",
c.relname as "Name",
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type",
pg_catalog.pg_get_userbyid(c.relowner) as "Owner"
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r','')
AND n.nspname <> 'pg_catalog'
AND n.nspname <> 'information_schema'
AND n.nspname !~ '^pg_toast'
AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 1,2;
It's preferable to use the SQL-standard, portable INFORMATION_SCHEMA instead of the Pg system catalogs where possible, but sometimes you need Pg-specific information. In those cases it's fine to query the system catalogs directly, and psql -E can be a helpful guide for how to do so.
Connect to the database, then list the tables:
\c liferay
\dt
That's how I do it anyway.
You can combine those two commands onto a single line, if you prefer:
\c liferay \dt
To see the public tables you can do
list tables
\dt
list table, view, and access privileges
\dp or \z
or just the table names
select table_name from information_schema.tables where table_schema = 'public';
In SQL Query, you can write this code:
select table_name from information_schema.tables where table_schema='YOUR_TABLE_SCHEME';
Replace your table scheme with YOUR_TABLE_SCHEME;
Example:
select table_name from information_schema.tables where table_schema='eLearningProject';
To see all scheme and all tables, there is no need of where clause:
select table_name from information_schema.tables
A one-line example is:
\dt schemaname.*
In your scenario:
\dt public.*
And to get a list of schemas:
\dn
Note that public is the default schema when none is specified. Quoting the documentation:
In the previous sections we created tables without specifying any
schema names. By default such tables (and other objects) are
automatically put into a schema named “public”. Every new database
contains such a schema.
Using \dt *.* will output a long list of all tables in all schemas, including internal ones such as pg_catalog. The above can help with filtering.
This can be used in automation scripts if you don't need all tables in all schemas:
for table in $(psql -qAntc '\dt' | cut -d\| -f2); do
...
done