Postgres: empty table though permissions granted to the role - postgresql

I have a problem with SELECT when granting permission for the role.
I need to create a Customer role with the privilege to SELECT from 2 tables.
And then I need to create a personalized role for one client, and GRANT customer to this role.
I did it this way:
CREATE ROLE customer;
GRANT SELECT ON public.payment TO customer;
GRANT SELECT ON public.customer TO customer;
ALTER TABLE public.payment ENABLE ROW LEVEL SECURITY;
CREATE POLICY policy_payments
ON public.payment TO customer
USING (customer_id = (
SELECT customer_id
FROM public.customer c
WHERE 'client_' || lower(c.first_name || '_' || c.last_name) = current_role));
CREATE role client_julie_sanchez;
GRANT customer TO client_julie_sanchez;
SET ROLE client_julie_sanchez;
SELECT * FROM public.payment p
I see an empty table for both roles - Customer and client_julie_sanchez.
What's wrong with the code?

Related

create partitions by a non-owner user

I am the owner of a partitioned table (table_name) and I have granted the privileges to another user (user2).
GRANT All ON table_name TO user2
But whenn user2 want to create a partition of table_name :
create table table_name_1 partition of table_name for values from (0) to (10)
the next error appears:
must be owner of table table_name
Is there any way to allow this user to create a partition without making him the owner of this table?
Only the table owner (that extends to members of that role) or a superuser can create a partition. You cannot grant the privilege to anyone else unless you make them a member of the table owner:
GRANT my_user TO user2;

"GRANT SELECT table TO role" is not working

I have very simple db (PostgreSQL)
And i created one role: manage
command: CREATE ROLE manage WITH NOSUPERUSER NOCREATEDB LOGIN;
Then, I executed
set role postgres;
GRANT SELECT ON public.orders TO manage;
SET ROLE manage;
SELECT * FROM orders;
But, when I try to execute:
select * from orders
I see empty output
But, in that table, there are some rows:
Here is the output using the role postgres.
I want give right to read to "manage" role.
Two possibilities:
There are two tables with the same name in different schemas
Row level security is active on the table.

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.

Create trigger on create role

I have a PostgreSQL database. I create new READ-ONLY users as follows:
$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly;
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
postgres=# BEGIN;
postgres=# CREATE ROLE "<PUT_READONLY_USERNAME_HERE>" WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE' IN ROLE readonly;
postgres=# COMMIT;
Also I have a table "is_admin" where I manually add new users (it happens really rarely). If it is read-only user users.is_admin = false and if it is user with all priveleges users.is_admin = true.
users.oid users.is_admin (bool)
1 true
2 false
3 false
... ...
Then in code I check if user is admin or not with this query:
SELECT users.is_admin
FROM users.users
JOIN pg_authid ON pg_authid.oid = users.oid::oid
WHERE rolname = "PUT_ROLNAME";
So, the main question is how to automatically add new users to "is_admin" table? I read that trigger or smth like that can help me (for example, trigger ON CREATE ROLE).
You can't create triggers on administrative change, like create role.
But I think you don't need is_admin column at all. You can simply use
select pg_has_role('username', 'rolename', 'MEMBER');
to determine if user has some role or not.

Alter default privileges for a group role in 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