Dropping postgres role and database after many grants - sql

I'm trying to efficiently drop role from a postgres instance, and running into some problems. I'm looking for some SQL to drop role so that I can stop reading error messages and don't have to do this manually.
In the setup I'm working in, every roles gets its own database of the same name:
CREATE ROLE alpha_user;
CREATE DATABASE alpha_user;
ALTER DATABASE alpha_user OWNER TO alpha_user;
Users often grant access to schemas in their database to other users:
-- alpha_user logs in to the alpha_user database
GRANT USAGE ON SCHEMA myschema TO beta_user;
When I attempt to drop beta_user, this happens:
-- log in as superuser
DROP ROLE beta_user;
-- ERROR: role "beta_user" cannot be dropped because some objects depend on it
-- DETAIL: N objects in database alpha_user
I can connect to the alpha_user database, and drop OWNED BY, but this is inefficient:
-- log in as superuser
\c alpha_user;
DROP OWNED BY beta_user CASCADE;
DROP beta_user;
-- success
Users can grant access to any number of databases, and there are many users. Is there a statement (or series of statements) that a super user can execute to DROP OWNED BY for a user across all databases where the user has been granted access?

Maybe this will help you:
with
user_id as (select oid, rolname as my_user from pg_authid where rolname in('abc', 'xyz'))
select 'REVOKE ' || rolname || ' FROM ' || my_user || ' CASCADE;' as sql
from pg_auth_members
join pg_authid on pg_auth_members.roleid = pg_authid.oid
JOIN user_id ON pg_auth_members.member = user_id.oid
union
SELECT 'REVOKE ALL ON ' || datname || ' FROM ' || my_user || ' CASCADE;'
FROM pg_database
JOIN user_id ON pg_database.datdba = user_id.oid

Related

Oracle: How can you clean up every grant a user has?

I'm looking for a quick easy way to revoke every privilege a user has to tables, views, etc. Is there any simple magic that can do this?
The purpose of doing this is to start fresh on what access should have.
When you find out which privileges user has, e.g.
SQL> select * From user_sys_privs;
USERNAME PRIVILEGE ADM
------------------------------ ---------------------------------------- ---
SCOTT CREATE DATABASE LINK NO
SCOTT CREATE ROLE NO
SCOTT CREATE VIEW NO
SCOTT CREATE TYPE NO
SCOTT CREATE PROCEDURE NO
SCOTT UNLIMITED TABLESPACE NO
SCOTT CREATE PUBLIC SYNONYM NO
SCOTT CREATE TABLE NO
SCOTT CREATE TRIGGER NO
SCOTT CREATE SEQUENCE NO
SCOTT CREATE SESSION NO
11 rows selected.
SQL>
then write query which will write some code for you:
SQL> select 'revoke ' || privilege || ' from scott;'
2 from user_sys_privs;
'REVOKE'||PRIVILEGE||'FROMSCOTT;'
--------------------------------------------------------
revoke CREATE DATABASE LINK from scott;
revoke CREATE VIEW from scott;
revoke CREATE ROLE from scott;
revoke UNLIMITED TABLESPACE from scott;
revoke CREATE PROCEDURE from scott;
revoke CREATE TYPE from scott;
revoke CREATE PUBLIC SYNONYM from scott;
revoke CREATE TABLE from scott;
revoke CREATE TRIGGER from scott;
revoke CREATE SESSION from scott;
revoke CREATE SEQUENCE from scott;
11 rows selected.
SQL>
Now copy/paste those revoke statements and run them.
However, that's not all. User can have additional privileges, so - as a privileged user - query DBA_SYS_PRIVS, DBA_ROLE_PRIVS, DBA_TAB_PRIVS.
In order not to think too much :), have a look at how Pete Finnigan did that. Script dates from 2003, but - it'll give you idea how to do it.
Also, probably the simplest way to do it would be to drop that user (but that's, I suppose, not an option).
I kept thinking there was some sort of REVOKE ALL command
Alas, no. Privileges are revoked (and granted) atomically, which is the way it should be. Wanting to revoke all privileges from a user is a product of the same mindset which lead to granting too many and/or too powerful privileges in the first place.
There are three classes of granted privilege:
role
system (CREATE TABLE, CREATE SESSION, etc)
object access (tables, views, procedures etc in other schemas)
Each has a different set of views over the data dictionary.
USER_ROLE_PRIVS ( also ALL_, DBA_ )
USER_SYS_PRIVS ( also ALL_, DBA_ )
USER_TABLE_PRIVS ( also ALL_, DBA_ )
We can use these views to generate REVOKE statements. It seems peculiar to do this as the user in question. So, a a power user (i.e. a DBA) execute something like this:
begin
dbms_output.put_line('Revoking granted roles ...');
for r in ( select * from dba_role_privs
where grantee = 'JOESOAP' )
loop
dbms_output.put_line('revoke ' || r.granted_role ||' from ' || r.grantee ||';');
end loop;
dbms_output.put_line('Revoking granted system privileges ...');
for r in ( select * from dba_sys_privs
where grantee = 'JOESOAP' )
loop
dbms_output.put_line('revoke ' || r.privilege ||' from ' || r.grantee ||';');
end loop;
dbms_output.put_line('granted access privileges ...');
for r in ( select * from dba_tab_privs
where grantee = 'JOESOAP' )
loop
dbms_output.put_line('revoke ' || r.privilege || ' on ' || r.owner||'.'||r.table_name ||' from ' || r.grantee ||';');
end loop;
end;
/
This will output commands to the screen - use an IDE like SQL Developer to make this less tricky - which you can review and save as an executable script. I suggest you do this rather than have the loops EXECUTE IMMEDIATE simply because you need to have a record of what privileges you've zapped, and also to stop you accidentally de-authorising something or somebody which might come back to bite you later.
In fact, rather than revoking all privileges and re-granting some of them it would be better to see all the privileges the user has and just revoke the ones which shouldn't have been granted.

Oracle Users Tables

I've created some TABLES in 1 DB with the user name DEVICE.
Querying the tables I see that they belong to the user DEVICE
SELECT owner, table_name FROM dba_tables
Then I created a user named CAR, I logged in the DB with that user and create some tables, I've tried to query the other tables with
SELECT * FROM DEVICE.table_name;
with the result
00942. 00000 - "table or view does not exist"
and logged with the user CAR and don't see the user DEVICE in others users from SQL Developer
This error comes up because CAR doesn't have privileges to query the DEVICE's table.
You need to grant access to this table to CAR.
1- login as DEVICE
2- Issue the following grant:
GRANT SELECT ON TABLE_NAME TO CAR;
If you want to do it for all the tables of the DEVICE user, create a script like that:
select 'GRANT SELECT ON ' || table_name || ' TO CAR;' FROM USER_TABLES;
My advice would be to create a ROLE if you do that:
CREATE ROLE DEVICE_READ_ROLE;
select 'GRANT SELECT ON ' || table_name || ' TO DEVICE_READ_ROLE;' FROM USER_TABLES;
GRANT DEVICE_READ_ROLE TO CAR;
Note that if you create new tables in the DEVICE schema you will need to grant select on the new table to the ROLE for CAR to have access to it.
Here the script to generate grant select on all the tables.
select 'grant select on Admin.' || object_name || ' to User;'
from user_objects
where object_type in('TABLE');
Then you have to create a script to run these grant statements at once or you can use PL/SQL as well. Type the following in the SQL prompt.
SQL> spool grant_statements.sql
SQL> set pagesize 0
SQL> set feedback off
SQL> set linesize 300
SQL> set trimout on
SQL> set trimspool on
SQL> select 'grant select on Admin.' || object_name || ' to User;' from user_objects where object_type in('TABLE','SYNONYM')
/
SQL> spool off
And you have got the script file you can run it.
OR
You can run the following PL/SQL block (Run as admin user).
BEGIN
FOR s IN (SELECT *
FROM user_objects where object_type in('TABLE','SYNONYM'))
LOOP
EXECUTE IMMEDIATE 'grant select on admin.' || s.object_name || ' to user';
END LOOP;
END;
you need to grant access to user CAR for the tables created by DEVICE . login using DEVICE user and grant access to the tables CAR should be able to access using sql like below
GRANT SELECT , UPDATE , INSERT ON TABLE_NAME TO CAR;

how do I find what privileges a group has in redshift?

I'm having a peculiar problem with one group.
I have revoked all database access for this group
I have revoked all schema access for this group
I have revoked all table access for this group
I have revoked all execute privileges on functions
When I try to drop the group, I get an error saying it cannot be dropped because the group have a privilege on some object.
How can I find out what privileges a group has on redshift?
Thanks
I remember seeing somewhere that this could be accomplished via terminal on the server. However, you may have the same issue that I had, preventing you from dropping a group. I had default privileges set. I had to do something like this:
alter default privileges in schema seeds revoke all on tables from xyz cascade;
The answer from jbasko was almost right, I've got mine working this way:
select
'alter default privileges for user ' || u.usename || ' in schema '||s.schemaname||' revoke all on tables from group groupname;'
from pg_default_acl d
join pg_user u on d.defacluser = u.usesysid
cross join
(select distinct schemaname from pg_tables) s
where array_to_string(defaclacl, ',') like '%group groupname=%'
and u.usename = 'some username';
You can see the default group privileges in pg_default_acl table. It's those entries in defaclacl column that are in format group <groupname>=<privileges>/<grantor>.
You have to issue the alter default privileges for each creating user that the privileges are set for. It's the defacluser column which refers to pg_user.usesysid.
Replace groupname and schemaname accordingly and generate the queries to revoke the privileges:
select 'alter default privileges for ' || pg_user.usename || ' in schema schemaname revoke all on tables from group groupname;'
from pg_default_acl
join pg_user on pg_default_acl.defacluser = pg_user.usesysid
where array_to_string(defaclacl, ',') like '%group groupname=%';
select 'alter default privileges for ' || pg_user.usename || ' in schema schemaname revoke all on functions from group groupname;'
from pg_default_acl
join pg_user on pg_default_acl.defacluser = pg_user.usesysid
where array_to_string(defaclacl, ',') like '%group groupname=%';

Select access to all tables

In oracle 11g, I have a owner schema which contains the relevant tables required for an app.
For my external application i am trying to create another user which should have select access on certain tables to the above schema.
Lets call the owner schema A and the new schema B
create user B identified by blah;
grant connect to B;
After logging into the original schema A i ran the following (for demo i am giving select on all tables)
begin
FOR x IN (select * from user_tables)
LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON ' || x.table_name || ' TO some_role';
END LOOP;
end;
grant some_role to B;
If i login as user B and execute a query like
select count(*) from A.some_table ;
it works. But without creating a public synonym is it possible for me to grant
in such a way that the following works when logged in as user B?
select count(*) from some_table;
Thanks
You can create private synonyms for user B to use.
As user B, run the following block:
begin
FOR t IN (SELECT * FROM role_tab_privs WHERE grantee = 'SOME_ROLE' and owner = 'A')
LOOP
EXECUTE IMMEDIATE 'CREAETE SYNONYM ' || table_name || ' FOR A.' || table_name';
END LOOP;
end;
if you are just reading data from tables owned by userB, you can set below command and run SELECT on tables as if they were in userA schema:
alter session set current_schema=userB
(logged as UserA)
Then below two commands will be equivalent (have same result):
select ... from userB.TABLE1
select ... from TABLE1
GRANT SELECT ANY TABLE TO YOUR_USER_OR_ROL;

Revoking Oracle Permissions to multiple users at once

We're rationalising our database user permissions and to that end we'd like to revoke all select permissions across all tables in a schema granted to all users (but not a specific role).
With some regular expressions I've tried creating a universal revoke for each table giving something like:
revoke select on TABLE1 from USER1,USER2,USER3...;
revoke select on TABLE2 from USER1,USER2,USER3...;
However as not all users were granted permissions to all tables, this results in the oracle error:
01927. 00000 - "cannot REVOKE privileges you did not grant"
Which makes sense but isn't helpful.
I also tried using All_Tab_Privs to get a list of all tables with the requisite grants to be revoked, and this works, but I can't see how to easily get from this to actually revoking the permissions.
SELECT * From All_Tab_Privs where grantor = 'GRANTING_USER' and grantee != 'READROLE' and grantee != 'PUBLIC' and grantee != 'SYS';
Any suggestions for how to do this without spending hours in a spreadsheet? I'm guessing some PL/SQL? Thanks.
A general pattern for this kind of job is to use an implicit cursor to return the data you want and then to build the DDL and execute them.
begin
for x in (select attribute_1, attribute_2 ... from ... where ...)
loop
execute immediate 'REVOKE ...'||x.attribute1||' etc';
end loop;
end;
/
A nice alternative is to build the SQL you want to execute in the SELECT and then just execute that. It's easier to test but the SQL then looks a bit clunky.
-- Revoke Privs Granted to Users
BEGIN
FOR r IN (SELECT * FROM all_tab_privs WHERE grantee IN ('USER_1', 'USER_2'))
LOOP
EXECUTE IMMEDIATE 'REVOKE '||r.privilege||' ON '||r.table_name||' FROM '||r.grantee;
END LOOP;
END;
/
Some PL/SQL and dynamic SQL:
begin
for r in (SELECT * From All_Tab_Privs
where grantor = 'GRANTING_USER'
and grantee != 'READROLE'
and grantee != 'PUBLIC'
and grantee != 'SYS')
loop
execute immediate 'revoke '||r.privilege||' from '||r.grantee;
end loop;
end;
I had a quite interesting situation on my database. Oracles own SQL Developer still listed the existing grants for each table, although they were gone from the all_tab_privs table (a SELECT brought no result for the searched grantees).
I've fixed that by using the following construct:
BEGIN
FOR r IN (SELECT owner, table_name FROM dba_tables WHERE owner IN ('owner1', 'owner2'))
LOOP
EXECUTE IMMEDIATE 'REVOKE ALL ON '||r.owner||'.'||r.table_name||' FROM grantee1, grantee2';
END LOOP;
END;
/
This first selects all owners and table names from each table of certain owners. Then it revokes all grants for certain grantees.
The good thing is, that this won't fail if there aren't any grants for one of the listed grantee for one of the selected tables.
Mind that this should be executed from an administrator account, like system, so the current user has the right to revoke grants for tables of another user.