PostgreSQL Revoking Permissions from pg_catalog tables - postgresql

Is there a way I can revoke permissions from a user to the catalog objects (i.e. information_schema) and PostgreSQL tables (i.e. pg_catalog)? I've tried several things and scoured the net. I'm not having any luck. The only thing I read that is partially helpful is I may not want to remove "public" from the system tables in case user defined functions rely on an object in one of those schemas. The commands below are a small snap shot of what I have not gotten to work with the exception of a single table.
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM PUBLIC; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM public; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM user1; -- didn't work
REVOKE SELECT ON pg_catalog.pg_roles FROM user1; -- worked
REVOKE SELECT ON pg_catalog.pg_database FROM user1; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM g_users; -- didn't work
REVOKE SELECT ON pg_catalog.pg_database FROM g_users; -- didn't work
Any ideas? Or is this just not possible? Thanks...
Leslie

let me help you about this:
1st: because the pg_catalog is owned by the superuser postgres, so make sure you login to the server with this role:
pg_catalog schema permission
2nd: make sure you connect to the right database that needs to GRANT/REVOKE permissions on. GRANT/REVOKE only affect to the current database that you connected to. That means after you login with superuser account, issue: \c [the db] to connect to that database, the shell will change to: [the db]=>
3rd: tables in pg_catalog defaults granted SELECT to PUBLIC: tables in pg_catalog. So, you have to run REVOKE SELECT FROM PUBLIC and then GRANT SELECT to appropriate users:
REVOKE SELECT ON ALL TABLES IN SCHEMA pg_catalog FROM PUBLIC;
GRANT SELECT ON TABLE [table] TO [user];
For list tables in a database: pg_class and pg_namespace.
And that's all :)

What you are trying to accomplish is denied in PostgreSQL by design.
If a user could not access pg_catalog schema (as you try to do with REVOKE commands), he/she would not be able to run even simplest SELECT query - planner would have no access to table definitions.
Your goal might be achieved by REVOKE'ing access to all schemas - hence locking user only in his private schema (with CREATE SCHEMA AUTHORIZATION username).
If any rights are already GRANT'ed to public, you cannot block them selectively for one user - you can only REVOKE ... FROM public.
Relevant documentation:
Creating a Schema
Schemas and Privileges

Related

Postgres Azure: Grants for User Removed

I am the admin of a PostgreSQL 11 DB on Azure.
Some of the users only have access to specific views.
The users were created by:
CREATE USER M1234 WITH PASSWORD '1234!';
GRANT USAGE ON SCHEMA public TO M1234;
GRANT SELECT ON table v_xxx TO M1234;
GRANT SELECT ON table v_yyy TO M1234;
For some reason the grant for select on one or all the existing views is removed every so often and the users of course cannot access.
I would really appreciate it if anyone has any insight as to why and how this could happen and if there is a more long term solution.
You grant SELECT on existing tables, but for future tables, you need additional permissions
-- Grant access to future tables ALTER DEFAULT PRIVILEGES IN SCHEMA a_given_schema GRANT SELECT ON TABLES TO read access;

Redshift User managemt

Is there a way to restrict the user to view all the schemas in a database?
Scenario:
I have a database with multiple schemas. I need to give access to a user for a particular schema and it's tabled.
Even though I try revoking all the access to that particular user and PUBLIC group, still he can view all the schemas and its tables. (Only the data he can't view.
I tried below commands:
REVOKE ALL ON SCHEMA devops_test FROM testuser;
REVOKE ALL ON SCHEMA devops_test FROM PUBLIC;
REVOKE ALL on all tables IN SCHEMA devops_test FROM testuser;
Once connected to database, users can read a list of all databases, schema's, tables, and even table columns in the cluster from the system tables, even if they are prevented from reading the data within those tables through the use of REVOKE ALL FROM. Try this:
REVOKE USAGE ON SCHEMA information_schema FROM PUBLIC;
REVOKE USAGE ON SCHEMA pg_catalog FROM PUBLIC;
REVOKE SELECT ON TABLE pg_catalog.pg_database FROM PUBLIC;
If I’ve made a bad assumption please comment and I’ll refocus my answer.

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;

Create PostgreSQL 9 role with login (user) just to execute functions

I have been looking for this for years and I have tried everything on the web with no success.
I am able to do it in MSSQL, but I didn´t find a way to do it in PostgreSQL.
What I want to achieve is just create a role with login that cannot create, drop or alter databases, functions, tables or anything else. Just select specific functions.
For example, if I have a table called costumer and two functions called return_customers() and return_time() I just want a role with login that are able to select return_customers() and select return_time(). Nothing more than that.
Thank you very much for supporting this useful web site!
Execute this connected to the database you want to configure.
-- Create the user.
CREATE ROLE somebody WITH LOGIN PASSWORD '...';
-- Prevent all authenticated users from being able to use the database,
-- unless they have been explicitly granted permission.
REVOKE ALL PRIVILEGES ON DATABASE foo FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM PUBLIC;
-- Allow the user to only use the specified functions.
GRANT CONNECT ON DATABASE foo TO somebody;
GRANT EXECUTE ON FUNCTION return_customers(), return_time() TO somebody;
If you have more schemas than "public" then you will need to add those to the two REVOKE ALL PRIVILEGES ON ALL ... statements.
Do not forget that the functions must have been created with SECURITY DEFINER or this user will still be unable to execute them, as the contents of the function will be executed with the permissions of this user, instead of the user who created the function.
See:
CREATE FUNCTION particularly SECURITY DEFINER
GRANT both for adding users to roles and for assigning access rights to tables, sequences, etc
REVOKE
CREATE ROLE

How to quickly drop a user with existing privileges

I'm trying to make restricted DB users for the app I'm working on, and I want to drop the Postgres database user I'm using for experimenting. Is there any way to drop the user without having to revoke all his rights manually first, or revoke all the grants a user has?
How about
DROP USER <username>
This is actually an alias for DROP ROLE.
You have to explicity drop any privileges associated with that user, also to move its ownership to other roles (or drop the object).
This is best achieved by
REASSIGN OWNED BY <olduser> TO <newuser>
and
DROP OWNED BY <olduser>
The latter will remove any privileges granted to the user.
See the postgres docs for DROP ROLE and the more detailed description of this.
Addition:
Apparently, trying to drop a user by using the commands mentioned here will only work if you are executing them while being connected to the same database that the original GRANTS were made from, as discussed here:
https://www.postgresql.org/message-id/83894A1821034948BA27FE4DAA47427928F7C29922%40apde03.APD.Satcom.Local
The accepted answer resulted in errors for me when attempting REASSIGN OWNED BY or DROP OWNED BY. The following worked for me:
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM username;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM username;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM username;
DROP USER username;
The user may have privileges in other schemas, in which case you will have to run the appropriate REVOKE line with "public" replaced by the correct schema. To show all of the schemas and privilege types for a user, I edited the \dp command to make this query:
SELECT
n.nspname as "Schema",
CASE c.relkind
WHEN 'r' THEN 'table'
WHEN 'v' THEN 'view'
WHEN 'm' THEN 'materialized view'
WHEN 'S' THEN 'sequence'
WHEN 'f' THEN 'foreign table'
END as "Type"
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE pg_catalog.array_to_string(c.relacl, E'\n') LIKE '%username%';
I'm not sure which privilege types correspond to revoking on TABLES, SEQUENCES, or FUNCTIONS, but I think all of them fall under one of the three.
Here's what's finally worked for me :
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA myschem FROM user_mike;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA myschem FROM user_mike;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA myschem FROM user_mike;
REVOKE ALL PRIVILEGES ON SCHEMA myschem FROM user_mike;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschem REVOKE ALL ON SEQUENCES FROM user_mike;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschem REVOKE ALL ON TABLES FROM user_mike;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschem REVOKE ALL ON FUNCTIONS FROM user_mike;
REVOKE USAGE ON SCHEMA myschem FROM user_mike;
REASSIGN OWNED BY user_mike TO masteruser;
DROP USER user_mike ;
Also note, if you have explicitly granted:
CONNECT ON DATABASE xxx TO GROUP ,
you will need to revoke this separately from DROP OWNED BY, using:
REVOKE CONNECT ON DATABASE xxx FROM GROUP
This worked for me:
DROP OWNED BY dbuser
and then:
DROP USER dbuser
I had to add one more line to REVOKE...
After running:
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM username;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM username;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM username;
I was still receiving the error:
username cannot be dropped because some objects depend on it DETAIL: privileges for schema public
I was missing this:
REVOKE USAGE ON SCHEMA public FROM username;
Then I was able to drop the role.
DROP USER username;
There is no REVOKE ALL PRIVILEGES ON ALL VIEWS, so I ended with:
do $$
DECLARE r record;
begin
for r in select * from pg_views where schemaname = 'myschem'
loop
execute 'revoke all on ' || quote_ident(r.schemaname) ||'.'|| quote_ident(r.viewname) || ' from "XUSER"';
end loop;
end $$;
and usual:
REVOKE ALL PRIVILEGES ON DATABASE mydb FROM "XUSER";
REVOKE ALL PRIVILEGES ON SCHEMA myschem FROM "XUSER";
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA myschem FROM "XUSER";
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA myschem FROM "XUSER";
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA myschem FROM "XUSER";
for the following to succeed:
drop role "XUSER";
This should work:
REVOKE ALL ON SCHEMA public FROM myuser;
REVOKE ALL ON DATABASE mydb FROM myuser;
DROP USER myuser;
In commandline, there is a command dropuser available to do drop user from postgres.
$ dropuser someuser
https://dbtut.com/index.php/2018/07/09/role-x-cannot-be-dropped-because-some-objects-depend-on-it/
Checked and there was no ownership for any object in db and later realised it may be due to foreign data wrapper mapping created for user and grant permission.
So two actions were required
Drop user mapping
Revoke usage on foreign data wrapper.
sample queries
DROP USER MAPPING FOR username SERVER foreignservername
REVOKE ALL ON FOREIGN SERVER foreignservername FROM username
The Postgres documentation has a clear answer to this - this is the ONLY sanctioned answer:
REASSIGN OWNED BY doomed_role TO successor_role;
DROP OWNED BY doomed_role;
-- repeat the above commands in each database of the cluster
DROP ROLE doomed_role;
Key points:
-- repeat the above commands in each database of the cluster
"it's typically necessary to run both REASSIGN OWNED and DROP OWNED (in that order!) to fully remove the dependencies of a role to be dropped."
I faced the same problem and now found a way to solve it.
First you have to delete the database of the user that you wish to drop. Then the user can be easily deleted.
I created an user named "msf" and struggled a while to delete the user and recreate it. I followed the below steps and Got succeeded.
1) Drop the database
dropdb msf
2) drop the user
dropuser msf
Now I got the user successfully dropped.