Alter default privileges for a group role in PostgreSQL - postgresql

I have created two group roles in Postgres 9.2: one is called admins and the other is called readers.
The idea is very simple: admins create tables and readers have read access to these tables.
After granting privileges to both group roles everything worked as expected for exisintg objects. But now what about new objects?
So after reading this post I altered the default privileges to grant SELECT privileges to readers for any new table that admins create:
ALTER DEFAULT PRIVILEGES FOR ROLE admins IN SCHEMA public GRANT SELECT ON TABLES TO readers;
ALTER DEFAULT PRIVILEGES FOR ROLE admins IN SCHEMA public GRANT SELECT ON SEQUENCES TO readers;
But apparently, ALTER DEFAULT PRIVILEGES only affects the role itself but not the members of the role. Let me show you.
If I login as userX (a member of admins) and create a new table, no default privileges are granted (and therefore, readers cannot access this table):
test=# CREATE TABLE table1 (name VARCHAR(10)); -- Creating table as userX
test=# \dp table1
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+--------+-------+-------------------+--------------------------
public | table1 | table | |
However, the default privileges are granted if I create the table as admins (readers can access this table):
test=# SET ROLE admins;
test=# CREATE TABLE table2 (name VARCHAR(10)); -- Creating table as admins
test=# \dp table2
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+--------+-------+-----------------------+--------------------------
public | table2 | table | readers=r/admins +|
| | | admins=arwdDxt/admins |
Is there a way to alter the default privileges for ALL members of a group role? Or should I just alter default privileges for each user?
UPDATE: In this PostgreSQL forum someone asked a very similar question and the answer was:
Unfortunately I can't see a way to achieve what you want without granting default privileges to everybody involved.
However this question was asked 2 years ago. Is there a solution now?

If a user creates a table then this user becomes the owner of the table. So in your case any default privileges for userX apply, not those of admins. the solution is to SET ROLE admins before creating your table:
SET ROLE admins;
CREATE TABLE ... -- This now applies default privileges of admins
;
RESET ROLE;
More in general, you would want to do this always: Create all tables and views through a group role or some other role not used in daily operations and grant access to the relations to another group role whose privileges are inherited by regular login roles (users). This greatly facilitates security management.
Cheers,
Patrick

Related

Grant readaccess to all existing (and future) Postgres schematas

I have a Postgres database (PostgreSQL-Version 11), which has a lot schematas. Each schemata has a lot of tables. So, now I've got a user xyz, which should have readaccess to all of those schematas and all future ones. I found this gist, which explains how to create a readaccess group and how to add a user to this group:
-- Create a group
CREATE ROLE readaccess;
-- Grant access to existing tables
GRANT USAGE ON SCHEMA public TO readaccess;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readaccess;
-- Grant access to future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readaccess;
-- Create a final user with password
CREATE USER tomek WITH PASSWORD 'secret';
GRANT readaccess TO xyz;
But this is only working for the public schemata. Lets assume, i create a new schemata called "new_schema", the user xyz don't have readaccess to this this schema.
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readaccess;
is creating readaccess to all future tables inside a specific schemata, but not for future schematas.
Long story short: How can i give readaccess to all existing and future schematas for a specific user?

Why doesnt ALTER DEFAULT PRIVILEGES work as expected?

I have 2 users. User1 is writing and member of the role writing, while User2 is member of the role "reader".
The reader role received subsequent permissions:
GRANT CONNECT ON DATABASE to reader
GRANT USAGE ON SCHEMA x TO reader
I want the reader to be able to read/select all existing and new tables from the given schema but using
ALTER DEFAULT PRIVILEGES IN SCHEMA x GRANT SELECT ON TABLES TO reader;
does't work. User2 won't receive any permission for new tables created by User1/the writer role.
Using:
ALTER DEFAULT PRIVILEGES FOR ROLE writer IN SCHEMA x GRANT SELECT ON TABLES TO reader;
doesn't work either. I have to explitly name the Owner of that table. To solve this I had to use:
ALTER DEFAULT PRIVILEGES FOR ROLE User1 IN SCHEMA x GRANT SELECT ON TABLES TO reader;
which I actually don't want, because there may be other users than User1 who are going to publish tables into that schema as well.
Am I missing anything?

Remove ability view/list all table from schema

Using a Amazon Redshift database. I have a schema called 'Public', and another schema called 'SchemaX'. I have created a user called 'User1'; and give him access to 'SchemaX'. I want to stop 'User1' from viewing or listing the available tables in my 'Public' schema. How does one go about doing this?
To disallow users from creating objects in the PUBLIC schema of a database, use the REVOKE command to remove that privilege.
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | DELETE | REFERENCES } [,...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...] | ALL TABLES IN SCHEMA schema_name [, ...] }
FROM { username | GROUP group_name | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
SELECT
Revokes the privilege to select data from a table or a view using a SELECT statement.
INSERT
Revokes the privilege to load data into a table using an INSERT statement or a COPY statement.
UPDATE
Revokes the privilege to update a table column using an UPDATE statement.
DELETE
Revokes the privilege to delete a data row from a table.
REFERENCES
Revokes the privilege to create a foreign key constraint. You should revoke this privilege on both the referenced table and the referencing table.
ALL [ PRIVILEGES ]
Revokes all available privileges at once from the specified user or group. The PRIVILEGES keyword is optional.
ON [ TABLE ] table_name
Revokes the specified privileges on a table or a view. The TABLE keyword is optional.
ON ALL TABLES IN SCHEMA schema_name
Revokes the specified privileges on all tables in the referenced schema.
GROUP group_name
Revokes the privileges from the specified user group.
PUBLIC
Revokes the specified privileges from all users. PUBLIC represents a group that always includes all users. An individual user's privileges consist of the sum of privileges granted to PUBLIC, privileges granted to any groups that the user belongs to, and any privileges granted to the user individually.
CASCADE
If a user holds a privilege with grant option and has granted the privilege to other users, the privileges held by those other users are dependent privileges. If the privilege or the grant option held by the first user is being revoked and dependent privileges exist, those dependent privileges are also revoked if CASCADE is specified; otherwise, the revoke action fails.
For example, if user A has granted a privilege with grant option to user B, and user B has granted the privilege to user C, user A can revoke the grant option from user B and use the CASCADE option to in turn revoke the privilege from user C.
RESTRICT
Revokes only those privileges that the user directly granted. This behavior is the default.

Revoke SELECT from inherited role

I am having a slight problem getting permissions to work the way I want them.
I have a role that should generally be allowed to SELECT everywhere, there are a bunch of members to this role. One of them should NOT be allowed to select from a certain table.
I thought this would be possible by granting role membership to the general reader role and revoking SELECT from the restricted table.
It seems the the permissions of the parent role apply and not the specific permissions. Is there a way around this without having to maintain the permissions of the more restricted role or am I applying the role concept in PostgreSQL in a wrong way?
Here's a sample script:
-- as superuser
CREATE DATABASE permission_test;
\c permission_test
CREATE ROLE r_general_select;
CREATE ROLE r_restricted_select IN ROLE r_general_select;
-- set the default permissions
ALTER DEFAULT PRIVILEGES IN SCHEMA "public" GRANT SELECT ON TABLES TO "r_general_select";
CREATE TABLE "open"(
id SERIAL,
payload TEXT
);
insert into "open"(payload) values ('test');
-- covered by default privileges
GRANT SELECT ON "open" TO PUBLIC;
-- Tests
-- this is good
SET ROLE r_general_select;
SELECT * FROM "open";
RESET ROLE;
-- this is good
SET ROLE r_restricted_select;
SELECT * FROM "open";
RESET ROLE;
CREATE TABLE "restricted" (
id SERIAL,
payload TEXT
);
insert into "restricted"(payload) values ('test');
-- the role and it's members should be able to read
GRANT SELECT ON "restricted" TO r_general_select;
-- except for this one!
REVOKE SELECT ON "restricted" FROM r_restricted_select;
-- Tests
-- this is good
SET ROLE r_general_select;
SELECT * FROM restricted;
RESET ROLE;
-- this should barf with a permission violation
SET ROLE r_restricted_select;
SELECT * FROM restricted;
RESET ROLE;
--- CLEANUP
DROP OWNED BY "r_restricted_select" CASCADE;
DROP ROLE r_restricted_select ;
DROP OWNED BY "r_general_select" CASCADE;
DROP ROLE r_general_select ;
In PostgreSQL, role permissions are purely additive. There is no way in such a model to revoke from a descendant, inheriting role a permission granted on the inherited one.
To fix this you need to change your permissions approach and base it on permissions that always occur together. I usually do this by looking at functional dependencies and operational dependencies together.

PostgreSQL Revoking Permissions from pg_catalog tables

Is there a way I can revoke permissions from a user to the catalog objects (i.e. information_schema) and PostgreSQL tables (i.e. pg_catalog)? I've tried several things and scoured the net. I'm not having any luck. The only thing I read that is partially helpful is I may not want to remove "public" from the system tables in case user defined functions rely on an object in one of those schemas. The commands below are a small snap shot of what I have not gotten to work with the exception of a single table.
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM PUBLIC; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM public; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM user1; -- didn't work
REVOKE SELECT ON pg_catalog.pg_roles FROM user1; -- worked
REVOKE SELECT ON pg_catalog.pg_database FROM user1; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM g_users; -- didn't work
REVOKE SELECT ON pg_catalog.pg_database FROM g_users; -- didn't work
Any ideas? Or is this just not possible? Thanks...
Leslie
let me help you about this:
1st: because the pg_catalog is owned by the superuser postgres, so make sure you login to the server with this role:
pg_catalog schema permission
2nd: make sure you connect to the right database that needs to GRANT/REVOKE permissions on. GRANT/REVOKE only affect to the current database that you connected to. That means after you login with superuser account, issue: \c [the db] to connect to that database, the shell will change to: [the db]=>
3rd: tables in pg_catalog defaults granted SELECT to PUBLIC: tables in pg_catalog. So, you have to run REVOKE SELECT FROM PUBLIC and then GRANT SELECT to appropriate users:
REVOKE SELECT ON ALL TABLES IN SCHEMA pg_catalog FROM PUBLIC;
GRANT SELECT ON TABLE [table] TO [user];
For list tables in a database: pg_class and pg_namespace.
And that's all :)
What you are trying to accomplish is denied in PostgreSQL by design.
If a user could not access pg_catalog schema (as you try to do with REVOKE commands), he/she would not be able to run even simplest SELECT query - planner would have no access to table definitions.
Your goal might be achieved by REVOKE'ing access to all schemas - hence locking user only in his private schema (with CREATE SCHEMA AUTHORIZATION username).
If any rights are already GRANT'ed to public, you cannot block them selectively for one user - you can only REVOKE ... FROM public.
Relevant documentation:
Creating a Schema
Schemas and Privileges