How to drop user in postgres if it has depending objects - sql

Database idd owner is role idd_owner.
Database has 2 data schemas: public and firma1.
User may have directly or indirectly assigned rights in this database and objects.
User is not owner of any object. It has only granted rights.
How to drops such user ?
I tried
revoke all on all tables in schema public,firma1 from "vantaa" cascade;
revoke all on all sequences in schema public,firma1 from "vantaa" cascade;
revoke all on database idd from "vantaa" cascade;
revoke all on all functions in schema public,firma1 from "vantaa" cascade;
revoke all on schema public,firma1 from "vantaa" cascade;
revoke idd_owner from "vantaa" cascade;
ALTER DEFAULT PRIVILEGES IN SCHEMA public,firma1 revoke all ON TABLES from "vantaa";
DROP ROLE if exists "vantaa"
but got error
role "vantaa" cannot be dropped because some objects depend on it
DETAIL: privileges for schema public
DROP ROLE if exists "vantaa"
How to fix this so that user can dropped ?
How to create sql or plpgsql method which takes user name as parameter and drops this user in all cases without dropping data ?
Using Postgres 9.1+

Before dropping the user you can run :
REASSIGN OWNED BY vantaa TO <newuser>
you could just reassign to postgres if you don't know who to reassign that to ...
REASSIGN OWNED BY vantaa TO postgres;

Your reassignment can fail.
When you reassign to a new user/role
- you do it on the currently selected database
- the current user must belong to the 'from' role and 'to' (grant them and revoke them after)
Excerpt of a shell script of mine (a few things omitted)
# The DROP USER operation will fail if this user is the owner of an existing schema, table, index...
# The user creating a resource owns it. It should transfer the ownership to the role
# When reassigning, the current user needs to have the <<roles>> associated to BY and TO to execute the command.
GRANT $_roleservice TO $_superuser;
GRANT $_account TO $_superuser;
REASSIGN OWNED BY $_account TO $_roleservice;
# dropping the user removes it from the current user list of roles/users
DROP USER $_account;
REVOKE $_roleservice FROM $_superuser;

Related

Grant from schema A of Schema B tables to schema C

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).

How to revoke alter privilege from postgres?

My Postgres DB has a user - "myuser" who has access to everycommand in schema my_schema.
I want to restrict the user to use only basic sequelize commands like Create, Update, Delete, Select. But the user should not be able to Alter the table (in sequelize, he shouldn't be able to do .sync{} operation).
I have already tried doing:
REVOKE ALTER ALL TABLES IN SCHEMA my_schema from myuser
But the above command is giving error!
Commands I have used to create role is:
CREATE ROLE app_readwrite1;
GRANT CONNECT ON DATABASE dvdrental TO app_readwrite1;
GRANT USAGE, CREATE ON SCHEMA app_schema TO app_readwrite1;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app_schema TO app_readwrite1;
ALTER DEFAULT PRIVILEGES IN SCHEMA app_schema GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_readwrite1;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA app_schema TO app_readwrite1;
ALTER DEFAULT PRIVILEGES IN SCHEMA app_schema GRANT USAGE ON SEQUENCES TO app_readwrite1;
After creating role above, I am creating user and assigning him the role.
Still, I can use Model.sync()- basically "ALTER" command along with CRUD operations.
How can I restrict the user from using alter command?

Preventing users from altering default privileges on PostgreSQL

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;

Cannot drop PostgreSQL role. Error: `cannot be dropped because some objects depend on it`

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/

Cannot drop a role that is granted to connect database

I am using PostgreSQL 10.4 and I found a strange behavior.
If we create an role and grant it to CONNECT the database:
CREATE ROLE dummy;
GRANT CONNECT ON DATABASE test TO dummy;
Then we cannot drop this role, even if it owns no object at all, this command:
DROP ROLE dummy;
Raises:
ERROR: role "dummy" cannot be dropped because some objects depend on it
SQL state: 2BP01
Detail: privileges for database test
Documentation is a bit misleading:
Class 2B — Dependent Privilege Descriptors Still Exist
2B000 dependent_privilege_descriptors_still_exist
2BP01 dependent_objects_still_exist
It says dependent objects still exist, but it seems there are no objects dependent to this specific role, it owns nothing on the database.
Anyway, if we revoke the CONNECT privilege, then role can be dropped:
REVOKE CONNECT ON DATABASE test FROM dummy;
DROP ROLE dummy;
I just checked the behavior also exists on PostgreSQL 9.5. I feel it a bit strange and I cannot understand why this specific privilege makes dropping role fails.
Additional observations
This is really blocking, because we can neither reassign this object:
REASSIGN OWNED BY dummy TO postgres;
Nor drop the object:
DROP OWNED BY dummy;
Both raise related errors:
ERROR: permission denied to reassign objects
SQL state: 42501
ERROR: permission denied to drop objects
SQL state: 42501
As #RaymondNijland pointed out, this must be because the CONNECT privileges is viewed as a role dependent object. The following query:
WITH
R AS (SELECT * FROM pg_roles WHERE rolname = 'dummy')
SELECT
D.*
FROM
R, pg_shdepend AS D
WHERE
refobjid = R.oid;
Returns a single row when CONNECT is granted:
"dbid";"classid";"objid";"objsubid";"refclassid";"refobjid";"deptype"
0;1262;27961;0;1260;27966;"a"
And no row at all when the privilege is revoked. This at least explain why we cannot reassign the object.
About the Dependency Type, the documentation states:
SHARED_DEPENDENCY_ACL (a)
The referenced object (which must be a role) is mentioned in the
ACL (access control list, i.e., privileges list) of the dependent
object. (A SHARED_DEPENDENCY_ACL entry is not made for the owner of
the object, since the owner will have a SHARED_DEPENDENCY_OWNER entry
anyway.)
But I have not enough insight to understand it clearly.
My question are:
Do Postgres always require to revoke privileges before dropping a role?
If not, why this specific privilege behaves like this?
There are some very unintuitive permission requirements when using REASSIGN.
I have found that when a superuser account is not available (as in the case of RDS or Cloud SQL) I have to grant the target role to my current role in order to reassign or drop owned objects from the target role. For instance, if my active user is postsgres, and I'm trying to remove user_a:
> DROP OWNED BY user_a
ERROR: permission denied to drop objects
> GRANT user_a TO postgres;
GRANT ROLE
> DROP OWNED BY user_a;
DROP OWNED
Now, it becomes a little trickier if user_a happens to be a member of postgres, especially if it happens to inherit that membership through some other role, let's call it schema_admin...
> DROP OWNED BY user_a
ERROR: permission denied to drop objects
> GRANT user_a TO postgres;
ERROR: role "user_a" is a member of role "postgres"
-- Alright, let's try to revoke it...
> REVOKE postgres FROM user_a;
REVOKE ROLE
> GRANT user_a TO postgres;
ERROR: role "user_a" is a member of role "postgres"
-- It's still a member through the inherited grant - trying to revoke again doesn't work:
> REVOKE postgres FROM user_a;
WARNING: role "user_a" is not a member of role "postgres"
REVOKE ROLE
-- So you have to identify the role it's inheriting from, and revoke that:
> REVOKE schema_admin FROM user_a;
REVOKE ROLE
> GRANT user_a TO postgres;
GRANT ROLE
-- Now just to be safe, I'll reassign owned objects before actually dropping everything:
> REASSIGN OWNED BY user_a TO postgres;
REASSIGN OWNED
> DROP OWNED BY user_a;
DROP OWNED
> DROP ROLE user_a;
DROP ROLE;
Voila!
Note: There is another widely-referenced and effective answer here: https://sysadmintips.com/services/databases/postgresql-error-permission-denied-to-reassign-objects/ which works great, as long as you are able to create and log in as a new temporary user. However, in some contexts, that is a problem in itself (and then you also have the extra cleanup to handle of removing that temporary role when you're done), so I tried to avoid that here.