I am very new to Postgress security topic. I have used the following commands to create a user.
CREATE USER myuser WITH PASSWORD 'PASSWORD';
GRANT CONNECT ON DATABASE "MyDB" TO myuser;
GRANT ALL PRIVILEGES ON DATABASE "MyDB" TO myuser;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO myuser;
Immediately afterwards I wanted to drop this user by I receive an error similar to:
ERROR: role "tempuser" cannot be dropped because some objects depend on it
DETAIL:
privileges for view myView
privileges for table myTable
... [rest of views and tables]
It kinda scares me. How can I safely drop a user without affecting the data and other objects in database?
Reverse each of your GRANT with a corresponding REVOKE.
It kinda scares me. How can I safely drop a user without affecting the data and other objects in database?
If you consider a REVOKE to be "affecting the objects", then you can't drop the user without affecting the objects. Why does this scare you? As you can see, the system won't let you do this implicitly, so what is there to be scared of?
Related
I have an application which uses a postgres database. I have a superadmin user. Now I need two more users: One "application-user" with CRUD-privileges and one with ALTER and CREATE-privileges (to apply migrations). These are all users I need, because the application has its own User-Access management and it is not at all planned to change that.
I want something like: GRANT SELECT, INSERT, UPDATE, DELETE ON DATABASE MyDatabase TO myuser
I've read here that postgres provides pre defined roles. This is good - but these roles apply globally (as pointed out in one comment). MyDatabase is on public schema which becomes problematic because some system tables are on public too - and I don't want myuser to be able to read from or write to these.
I'd be fine with GRANT pg_read_all_data, pg_write_all_data ON DATABASE MyDatabase TO myuser but this doesn't work.
As I'll not change these privileges often I'd even be fine with GRANT pg_read_all_data ON MyDatabase.MyTable TO myuser as well. But this doesn't work either.
Any ideas on this?
There are no ALTER and CREATE privileges in PostgreSQL. The database user that should be able to run ALTER and CREATE statements will have to be the owner of the database objects. If you already have objects owned by a different user, you will have to change the ownership.
For the other user, you will have to grant privileges on each and every object. Privileges on the database won't help – there is no inheritance of privileges between objects. Don't forget to grant USAGE on the schemas.
I recommend that you create more schemas than public. If you have a separate schema for your application's objects, you can use statements like
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA myapp TO someuser;
I am having issues with dropping a user becauase it has default privileges, but I am as well unable to revoke those privileges.
To reproduce my issue:
-- executed with master user redshift_master
CREATE USER anton_test_user PASSWORD '***' IN GROUP redshift_dev;
Then using anton_test_user
CREATE SCHEMA anton_test_schema;
CREATE TABLE anton_test_schema.anton_test_table AS SELECT 1 AS anton;
ALTER DEFAULT PRIVILEGES IN SCHEMA anton_test_schema
GRANT SELECT ON TABLES TO GROUP redshift_readonly;
Again with redshift_master
ALTER SCHEMA anton_test_schema OWNER TO redshift_master;
ALTER TABLE anton_test_schema.anton_test_table OWNER TO redshift_master;
Now trying to drop the user it complains about default privileges:
DROP USER anton_test_user;
Result as expected:
owner of default privileges on new relations belonging to user
anton_test_user in schema anton_test_schema;
Now to the weird part, still with redshift_master
ALTER DEFAULT PRIVILEGES FOR USER anton_test_user IN SCHEMA anton_test_schema
REVOKE ALL ON TABLES FROM redshift_readonly;
Gives Invalid operation: permission denied for schema anton_test_schema. What?
If running with anton_test_user
ALTER DEFAULT PRIVILEGES IN SCHEMA anton_test_schema
REVOKE ALL ON TABLES FROM redshift_readonly;
As well gives Invalid operation: permission denied for schema anton_test_schema.
The only way for me to solve this and being able to drop anton_test_user was to, with redshift_master drop the schema and table completely
DROP TABLE anton_test_schema.anton_test_table;
DROP SCHEMA anton_test_schema;
DROP USER anton_test_user; -- it works now
Transfering ownership back to anton_test_user and then revoking default privileges did not help - dropping the table and schema was the only solution I could find.
My completely uninformed guess is that anton_test_user had lost permissions to the schema, so no grants for the user could be applied or revoked in that schema.
Question(s):
Is there any way to avoid dropping anton_test_schema and anton_test_table while also dropping anton_test_user?
Is it supposed to work this way?
Do Postgres behave in the same way?
This is a bit of a follow up to a question already asked, to which I gave an answer - but I have no idea what is going on even though I came up with a "solution" ("" because dropping objects was a solution, albeit a pretty poor one). It might be that I have completely misunderstood user privileges in Redshift as well.
The original question is not completely the same as this - and I would like to know what is going on, so it is not really a repost even though it might look like it.
I had the same issue myself. I was able to avoid dropping the user/schema by first re-granting access of the schema to my end user (my version of anton_test_user).
grant all on schema analyst_data to anton_test_user;
After doing so, I was able to run my alter default privileges command
ALTER DEFAULT PRIVILEGES for user <user> in schema <schema> REVOKE ALL on tables FROM group <group>;
Your uninformed guess was spot on 😀
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.
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.
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.