postgreSQL: How to use ROLE to allow full access to all users part of a given role (without using SET ROLE prior accessing a table for instance) - postgresql

I'm coming to postgreSQL with a SQL Server background and was naively applying the same concepts to postgreSQL in order to allow different users to share 'by default' some objects within a database.
This is what I did:
CREATE DATABASE testdb;
CREATE ROLE testdb_role_full INHERIT;
GRANT ALL PRIVILEGES ON DATABASE testdb TO testdb_role_full;
CREATE USER user1 INHERIT;
GRANT testdb_role_full TO user1;
CREATE USER user2 INHERIT;
GRANT testdb_role_full TO user2;
Once done, I created a table t1 using the user1.
Then, I tried, as user2, to read the t1 table and I received a "permission denied error"... :-(
By reading the documentation, it seems that I have to issue a SET ROLE testdb_role_full first so as to act as the testdb_role_full.
However, this is not really that I want. I do not want the user to be aware of this.
So my question:
Is there any way to make this work?
Thanks a lot,
José

You've granted some privileges on the database, but that doesn't mean any user with the role testdb_role_full would have all privileges on all objects inside that database. To quote from the documentation:
When an object is created, it is assigned an owner. The owner is normally the role that executed the creation statement. For most kinds of objects, the initial state is that only the owner (or a superuser) can do anything with the object. To allow other roles to use it, privileges must be granted.
So after the user1 created the table t1, he is the owner and only he has the privileges on it. He would need to run
GRANT ALL PRIVILEGES ON TABLE t1 TO testdb_role_full;
then user2 would be able to access it as well (without having to switch any roles - that's only necessary when it has the NOINHERIT attribute on the role).
If you don't want your users to have to execute GRANT each time they create a new object in the database, you can alter the default privileges that will be applied whenever an object is created by user2:
ALTER DEFAULT PRIVILEGES FOR user2
GRANT ALL PRIVILEGES ON TABLES TO testdb_role_full;
Notice these specify the initial value only, and user2 could revoke the privileges on his tables if he wanted to prevent others from seeing them.

Related

How to add admin user to existing postgres database?

We have an existing postgres database gsrdb in production with superuser gsr. We have been doing all the database maintenance with that user gsr. Also, the same user gsr is used by our app service to do transactions on the database.
We want to change this now. We want a separate superuser gsr_admin(whose credentials are managed by Vault) that can do the dba maintenance but still have our app service use existing user gsr.
The problem I am facing is that all the database objects so far are owned by gsr user and if I run updates, as user gsr_admin, on the database w.r.t. either table constraints or sequences it fails saying error: must be owner of relation...blah blah
How can I fix this?
So I was thinking if I could create a superuser admin group role called admin_group and reassign all the ownerships of all the database objects to it from user gsr and then alter both users gsr and gsr_admin to belong to this admin group role. Wouldn't that way everything that has been created so far would be owned by role admin_group ? And whether I create new objects as a user gsr or as gsr_admin either of them can still update the objects?
I might be wrong. Would really appreciate some inputs.
Simply run
ALTER ROLE gsr NOSUPERUSER;
ALTER ROLE gsr RENAME TO gsr_admin; -- needs a new password now
CREATE ROLE gsr LOGIN;
GRANT USAGE ON SCHEMA myschema TO gsr;
GRANT SELECT, INSERT, UPDATE, DELETE
ON ALL TABLES IN SCHEMA myschema TO gsr;
Similarly, grant USAGE on sequences and other required privileges. You may want to run some ALTER DEFAULT PRIVILEGES for future objects as well.

Permission denied for relation <table_name>

So I'm making this app and I'm using Postgres and I've already created a database, a user and a password and granted all privileges on the database to the user I've created.
The thing is, when I switch the database in psql using \c <database_name> I get in just fine and can use queries on it.
But when I run psql using postgres://user_name:password#localhost:5432/databasename on terminal and try to select * from the <table_name> it gives me this message
permission denied for relation <table_name>
Can you please tell me what to do, I've had this problem before and I had to create another database or change the user but I want a better solution please.
PS: I've tried to use this :
GRANT ALL PRIVILEGES ON TABLE <table_name> to <user_name>
This is how I created and accessed my database:
rawan95=# create database food ;
CREATE DATABASE
rawan95=# create user meal with password '123';
CREATE ROLE
rawan95=# grant all privileges on database food to meal;
GRANT
rawan95=# \c food
You are now connected to database "food" as user "rawan95".
After that, I've built it using
food=# \i src/database/db_build.sql
BEGIN
DROP TABLE
CREATE TABLE
INSERT 0 1
COMMIT
Then I selected data from the table just fine, but when I try to access it using this, I get an error: psql postgres://meal:123#localhost:5432/food
food=> select * from foods;
ERROR: permission denied for relation foods
You are granting the privileges before you create the tables.
As there are no tables at that moment nothing is granted. The tables you created are not owned by the user meal but the user rawan95 (which the \c command told you).
Plus: granting "all privileges" on a database, does not grant any select privilege. As documented in the manual "all privileges" are: CREATE, CONNECT, TEMPORARY, TEMP. The CREATE privilege would allow the user meal to create tables in that database.
If you want all those tables to be owned by the user meal you need to run your setup script after you connected as the user meal (the \c command did not change the current user)
If you do want rawan95 to be the owner of the tables, you need to either grant the select privilege after creating all tables:
grant select on all tables in schema public to meal;
Or, you can change the default privilege before creating the tables (before running db_build.sql), so that they are applied to all tables in the future:
alter default privileges in schema public
grant select on all tables to meal;
The alter default privileges only has an effect for tables that are created after that. So to fix your current setup, you need to first grant select on the existing tables, and the change the default privileges for all tables that are created in the future.
Have you granted usage on the schema? Without that the table permissions are useless.
GRANT USAGE ON SCHEMA schema_name TO username
EDIT: Based on comment thread below we have established.
The table is in public schema.
The table belongs to rawan95 but the schema does not (public schema belongs to root postgres user).
The OP is attempting to connect and access the table as user 'meal' they have granted table permissions using the rawan95 user but are unable to grant schema permissions.
From the above, the problem could still be that the user 'meal' does not have usage on the public schema. If you are on Linux the quickest way to sort this is to switch to the super user to make this change from terminal:
sudo -u postgres psql -c "GRANT USAGE ON SCHEMA public TO meal"
FURTHER EDIT - having read your new clarification this is not correct (or at least not useful). The issue is as pointed out by the other answerer that you didn't have a table at the time you did the grant.

Restrict create table privilege to newly created users in RDS PostgreSQL 9.6

I am facing an issue while creating a readonly users in RDS PostgreSQL 9.6. I am executing the following SQL commands:
---- ###### CREATE ROLE ################
CREATE ROLE readonlyrole_dev;
-- Grant access to existing tables
GRANT USAGE ON SCHEMA public TO readonlyrole_dev;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyrole_dev;
-- set the privileges that will be applied to objects created in the future.
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonlyrole_dev;
CREATE USER readonly_dev WITH PASSWORD 'welcome1';
GRANT readonlyrole_dev TO readonly_dev;
When I login with the readonly_dev user, it has privilege to create the new tables by default but I don't want to do that. I want to keep readonly_dev only a read only user.
Note: To revoke the access from the user I am executing
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
which revokes create objects privilege to all old users as well. I only want to revoke create privilege from newly created user.
How can I do that?
You cannot do that, and it is not necessary either.
Just deny the user the CREATE permission on all schemas. You should use user groups for that - put all users who should have the privilege to create tables in a group that has the required privilege on the schema and revoke CREATE from PUBLIC.
If you insist that you must have this, try creating an event trigger that throws an exception whenever a certain user tries to create a table.

Postgres create database user with grant access to schema only

I have a database with a template_schema.I cloned this template schema and created a database user with password. I need to provide access to cloned schema only, for the created user.
SELECT clone_schema('my_template_schema','john_smith_gmail_com');
CREATE USER john_smith_gmail_com WITH PASSWORD 'mypassword';
Upto this Ok. Then I need to grant access to this user for this cloned schema(john_smith_gmail_com) only
Method :1
I tried to revoke all privileges on all tables of cloned schema(john_smith_gmail_com) for the user and grant select to the user. But my question is, can this user get SELECT access on other schema tables?
REVOKE ALL ON ALL TABLES IN SCHEMA john_smith_gmail_com FROM john_smith_gmail_com;
GRANT SELECT ON ALL TABLES IN SCHEMA john_smith_gmail_com TO john_smith_gmail_com;
Method :2
Create a role with only SELECT access and assign or grant this role to newly created user. If I do this, for which schema I grant access,because I clone schema dynamically?
Which method is best one?
From postgresql version 9.0 and forward, the best way is probably to use ALTER DEFAULT PRIVILEGES.
...the default privileges for any object type normally grant all grantable permissions to the object owner, and may grant some privileges to PUBLIC as well. However, this behavior can be changed by altering the global default privileges with ALTER DEFAULT PRIVILEGES.
So if all users like "john_smith_gmail_com" should only have SELECT access to tables in "their own" schema, after creating the schema and user, you can run:
ALTER DEFAULT PRIVILEGES IN SCHEMA john_smith_gmail_com GRANT SELECT ON TABLES TO john_smith_gmail_com;

Grant privileges to all users, current and future

I have a multi-schema, multi-user Postgres DB. There is one table that I would like ALL users, both current and future, to be able to SELECT from.
I can GRANT SELECT to all current users... but how can I create a table that allows any future user to select? Is there a way to set table permissions, rather than granting user privileges?
A filesystem analogy would be using chmod to make a file to be readable by the public.
grant select on the_table to public;
From the manual:
The key word PUBLIC indicates that the privileges are to be granted to all roles, including those that might be created later. PUBLIC can be thought of as an implicitly defined group that always includes all roles