I am running PostgreSQL 9.3.1. I have test database and backup user which is used to backup the database. I have no problems with granting privileges to all current tables, but I have to grant privileges each time the new table is added to schema.
createdb test
psql test
test=# create table foo();
CREATE TABLE
test=# grant all on all tables in schema public to backup;
GRANT
test=# create table bar();
CREATE TABLE
psql -U backup test
test=> select * from foo;
test=> select * from bar;
ERROR: permission denied for relation bar
Is it possible to grant access to tables which will be created in future without making user owner of the table?
It looks like the solution is to alter default privileges for backup user:
alter default privileges in schema public grant all on tables to backup;
alter default privileges in schema public grant all on sequences to backup;
From the comment by Matt Schaffer:
As caveat, the default only applies to the user that executed the
alter statement. This confused me since I was driving most of my
permissions statements from the postgres user but creating tables from
an app user. In short, you might need something like this depending on
your setup:
ALTER DEFAULT PRIVILEGES FOR USER webapp IN SCHEMA public GRANT SELECT ON SEQUENCES TO backup;
ALTER DEFAULT PRIVILEGES FOR USER webapp IN SCHEMA public GRANT SELECT ON TABLES TO backup;
Where webapp is the user that will be creating new tables in the futrue and backup is the user that will be able to read from new tables created by webapp.
If you want the backup user to have access to the future tables of userN,
you must run the code below under each userN who creates new tables,
because ALTER DEFAULT PRIVILEGES...
works only for objects by that user under whom you run ALTER DEFAULT PRIVILEGES...
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO backup;
I am trying to create a role, grant connect access to the role and then alter default privileges to keep access for future objects. However, it seems that the below command doesn't work at role level.
alter default privileges in schema public grant all on tables to backup;
I followed the below documentation but seems that there are two command do not work for roles.
DOC: https://aws.amazon.com/blogs/database/managing-postgresql-users-and-roles/
First command:
GRANT CONNECT ON DATABASE mydatabase TO readonly;
Second command:
GRANT USAGE ON SCHEMA myschema TO readonly;
(For ROLES usually it needs TO ROLE, I also tried TO ROLE but still doesn't work.
Related
I have an application schema U32_C5 and another schema MIG_SRC which has some tables and then we have a ROLE RO_ROLE on which we have some grants of tables from Schema U32_C5.
The RO_ROLE is assigned to another Schema MRGO_RO which is Read Only.
Here I need to grant select on tables from MIG_SRC to MRGO_RO catch here is that the process which and from where I can include these grants is run from application schema U32_C5 in production so when I tried to to something like below it says table or view does not exists (which seems to be obvious)
execute Grant from U32_C5
grant select on MIG_SRC.MOBILE_CELLPHONE_PAIRINGS to MRGO_RO;
Another way which I think of is creating DB link on MRGO_RO for MIG_SRC Schema but it enables read/write operation as well on MIG_SRC tables which is not allowed on production.
DB Links is present on U32_C5 Schema for MIG_SRC Schema
So looking for a way to accomplish above task without creating DB Link any suggestion is welcome.
Sample Script of requirement what I want to achieve Please Remember I cannot and do not want Login to MIG_SRC and only way I am looking for is to do it by using U32_C5 and without DBA HELP
A RO ROLE Created by DBA's
Create role RO_ROLE;
/* Create application schema, table inside it and grant select on it to RO_ROLE*/
CREATE USER U32_C5 IDENTIFIED BY U32_C5 DEFAULT TABLESPACE;
GRANT ALTER SESSION TO U32_C5;
GRANT CREATE SESSION TO U32_C5;
GRANT CREATE database link TO U32_C5;
GRANT CREATE table TO U32_C5;
create table U32_C5_test_tab (id number);
grant select on U32_c5.U32_C5_Test_tab to RO_ROLE;
/* Create Read Only schema, grant RO_ROLE to it */
CREATE USER mrgo_ro IDENTIFIED BY mrgo_ro DEFAULT TABLESPACE;
GRANT ALTER SESSION TO mrgo_ro;
GRANT CREATE SESSION TO mrgo_ro;
grant ro_role to mrgo_ro;
/* Create SRC schema, table inside it */
CREATE USER MIG_SRC IDENTIFIED BY MIG_SRC DEFAULT TABLESPACE;
GRANT ALTER SESSION TO MIG_SRC;
GRANT CREATE SESSION TO MIG_SRC;
GRANT CREATE database link TO MIG_SRC;
GRANT CREATE table TO MIG_SRC;
create table mig_src_test_tab (id number);
/* login to Apllication Schema U32_C5 */
sqlplus U32_C5/U32_C5#SID
grant select on mig_src.mig_src_test_tab to mrgo_ro; -- for me it gives error here at this step table or does not exist
/* login to Read Only Schema mrgo_ro */
sqlplus mrgo_ro/mrgo_ro#SID
select * from mig_src.mig_src_test_tab;
or
select * from mig_src_test_tab;
If I understood you correctly, then WITH GRANT OPTION is what you're missing.
Once someone (A) grants privileges on their own objects to someone else (B), and that (B) has to "forward" those privileges to (C), then it is the WITH GRANT OPTION that helps.
Documentation says:
Specify WITH GRANT OPTION to enable the grantee to grant the object privileges to other users and roles.
Restriction on Granting WITH GRANT OPTION You can specify WITH GRANT OPTION only when granting to a user or to PUBLIC, not when granting to a role.
It means that you should grant privileges directly, not via role. That fact doesn't have to be a drawback because of named PL/SQL procedures, where privileges acquired via roles won't work anyway, so you might end up in direct grants anyway.
Other option - which you might consider - is related to what you said:
when I tried to to something like below it says table or view does not exists
If you created a synonym for those tables, then you wouldn't get such an error.
Database link isn't an option, as you said - by using it, you have full access (as you have to know username/password to create the DB link, and that isn't really read only access).
I have a user db_owner who is owner to my database called 'Sales'.
Now i have to create two groups(sales_ro and sales_riu) and then i will add users to this groups.
sales_ro group should inherit(from db_owner) read access on tables and execute on functions in Sales db
sales_riu group should inherit(from db_owner) insert and update access on tables and execute on functions in Sales db.
can we create such two groups in Postgres ?
You don't need to create groups to achieve this. You can just create Roles and assign them to the users you want. For example:
CREATE ROLE sales_ro;
CREATE ROLE sales_riu;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO sales_ro;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO sales_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO sales_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT EXECUTE ON FUNCTIONS TO sales_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT,INSERT,UPDATE ON TABLES TO sales_riu;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT EXECUTE ON FUNCTIONS TO sales_riu;
After that just grant role to expected users:
GRANT sales_ro TO your_user_1;
GRANT sales_riu TO your_user_2;
Please refer link 1 and link 2 to know more about ALTER DEFAULT PRIVILEGES and CREATE ROLE respectively.
Quoting below points from above links:
CREATE ROLE adds a new role to a PostgreSQL database cluster. A role
is an entity that can own database objects and have database
privileges; a role can be considered a “user”, a “group”, or both
depending on how it is used.
A role having the LOGIN attribute can be thought of as a user. Roles
without this attribute are useful for managing database privileges
I'm testing database permissions on PostgreSQL and i'm trying to prevent a common user (readuser) from executing an 'ALTER DEFAULT PRIVILEGES' statement. However i cannot find a way to revoke this specific permission, and couldn't find anything about it on documentation.
I started a local PostgreSQL 11.2 instance, removed connect permisssions, created a database testdb and revoked table creation on the public schema.
revoke connect on database postgres from public;
create database testdb with template template0 --lc_collate "pt_BR.utf8" lc_ctype "pt_BR.utf8";
revoke connect on database testdb from public;
\c :database
revoke all on schema public from public;
grant all on schema public to postgres;
create schema private;
After that, I created a user with read permissions only:
create user readuser
with nosuperuser
nocreatedb
nocreaterole
noreplication
login
encrypted password 'testpassword';
grant connect
on database testdb
to readuser;
Then create a schema testschema and granted read permissions on it's tables:
grant usage
on schema testschema
to readuser;
grant select
on all tables
in schema testschema
to readuser;
Even though i only set read permissions on all schemas and tables, the 'readuser' user can still perform 'alter default privileges' query without a permission error:
alter default privileges in schema testschema grant select on tables to readuser;
ALTER DEFAULT PRIVILEGES
I would like some help on preventing a user from altering it's default privileges, so that it cannot mess up permissions for tables created in the future.
Try this by revoking the EXECUTE from the role postgres that granted the default privilege of execute to readuser
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA testschema REVOKE EXECUTE ON FUNCTIONS FROM readuser;
I was trying to delete PostgreSQL user:
DROP USER ryan;
I received this error:
Error in query:
ERROR: role "ryan" cannot be dropped because some objects depend on it
DETAIL: privileges for database mydatabase
I looked for a solution from these threads:
PostgreSQL - how to quickly drop a user with existing privileges
How to drop user in postgres if it has depending objects
Still have the same error.
This happens after I grant all permission to user "ryan" with:
GRANT ALL PRIVILEGES ON DATABASE mydatabase ON SCHEMA public TO ryan;
DROP USER (or DROP ROLE, same thing) cannot proceed while the role still owns anything or has any granted privileges on other objects.
Get rid of all privileges with DROP OWNED (which isn't too obvious from the wording). The manual:
[...] Any privileges granted to the given roles on objects in the current
database and on shared objects (databases, tablespaces) will also be revoked.
So the reliable sequence of commands to drop a role is:
REASSIGN OWNED BY ryan TO postgres; -- or some other trusted role
DROP OWNED BY ryan;
Run both commands in every database of the same cluster where the role owns anything or has any privileges!
And finally:
DROP USER ryan;
REASSIGN OWNED changes ownership for all objects currently owned by the role.
DROP OWNED then only revokes privileges (ownerships out of the way).
Alternatively, you can skip REASSIGN OWNED. Then DROP OWNED will (also) drop all objects owned by the user. (Are you sure?!)
Related:
Drop a role with privileges (with a function to generate commands for all relevant DBs)
Find objects linked to a PostgreSQL role
What worked for me was to follow these steps:
Connecting to the database
\c mydatabase
Reassigning ownership
REASSIGN OWNED BY ryan TO <newuser>;
Or/and just deleting the object
DROP OWNED BY ryan;
Executing REVOKE PRIVILEGES
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM ryan;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM ryan;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM ryan;
Dropping the user
DROP USER ryan;
PS: You might not need to execute both Step 2 and 3, just one of the two steps might be usually enough.
What worked for me on RDS Postgres 13:
REVOKE ALL PRIVILEGES ON DATABASE <my_db> FROM <my_user>;
I also had a similar error where the role was owner for tables so it couldn't be dropped, had to re-assign table owner with:
ALTER TABLE <my_table> OWNER TO <trusted_role>;
Doing a REASSIGN like this didn't work for me on RDS because AWS doesn't give you full superuser to your master user:
REASSIGN OWNED BY <olduser> TO <newuser>;
REVOKE ALL ON SCHEMA "public" FROM "<user>";
Worked for me.
What worked for me was to recreate template1 database and then drop some role:
$ psql -U postgres postgres
postgres=# update pg_database set datistemplate = false where datname='template1';
UPDATE 1
postgres=# drop database template1;
DROP DATABASE
postgres=# create database template1 template=template0;
CREATE DATABASE
postgres=# update pg_database set datistemplate = true where datname='template1';
UPDATE 1
postgres=# DROP ROLE test;
DROP ROLE
For people who use AWS Postgresql RDS, you may try following
login to postgres user, then grant owner
postgres=> GRANT target_user to old_user;
GRANT ROLE
Login to target db using user that would like to remove(old_user), then reassign
target_db=> REASSIGN OWNED BY old_user TO target_user;
REASSIGN OWNED
Login back to postgres user, revoke all privileges then drop user
postgres=> REVOKE ALL PRIVILEGES ON DATABASE target_db FROM old_user;
REVOKE
postgres=> DROP USER old_user;
DROP ROLE
Ref. https://aws.amazon.com/premiumsupport/knowledge-center/rds-postgresql-drop-user-role/
I am running PostgreSQL 9.3.2 on Linux.
I have a group role 'data_scientist' and permissions to a particular (already populated) schema like so
grant usage on schema schemaname to data_scientist;
grant select, references, trigger
on all tables in schema schemaname
to data_scientist;
This fixes the problem of data_scientist using past tables. For future tables I added
alter default privileges in schema schemaname
grant select, references on tables
to data_scientist;
Still, whenever a new table is added, other data_scientist's permissions fail on the new tables.
By default, ALTER DEFAULT PRIVILEGES only applies to the role that ran the command. Suppose we have 2 users: ramfjord and animalito. If I (ramfjord) run
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO public; CREATE TABLE ramfjord_table;
Then animalito will be able to see it. If animalito runs
CREATE TABLE animalito_table
Then ramfjord won't be able to see it, because ramfjord's default privileges don't apply. See default privileges and their owners with \ddp
Because of this, we've stopped using default privileges at my company, and started using explicit GRANT's. To remove default privs, you have to run
ALTER DEFAULT PRIVILEGES FOR ROLE <owner> REVOKE...
The owner, schema, relation type and privileges have to match those listed in \ddp for this command to do anything. Do not just delete everything from the internal table that stores default privileges... trust me.