I can't revoke execute from function in custom schema - sql

I want to revoke execute from app.my_function function, so users with role doctor can't call it, I can't figure out what wrong with my code, I spend the whole day trying to find a solution.
CREATE SCHEMA app;
CREATE ROLE doctor;
GRANT USAGE ON SCHEMA app TO doctor;
CREATE FUNCTION app.my_function() AS $$ ... $$ LANGUAGE SQL;
REVOKE ALL ON FUNCTION app.my_function() FROM doctor;

here's the solution of my problem, I didn't know that user defined roles inherit from PUBLIC role which have EXECUTE privilege.
...
REVOKE ALL ON SCHEMA PUBLIC FROM PUBLIC;
ALTER DEFAULT PRIVILEGES REVOKE ALL ON FUNCTIONS FROM PUBLIC;
...

The default privileges for functions (which you can change with ALTER DEFAULT PRIVILEGES) allow EXECUTE to PUBLIC, that is everybody. Revoking the privilege from some other role will have no effect.

Related

How to set SELECT default privileges in PostgreSQL schema for new tables? [duplicate]

Currently I am using this to grant permissions:
grant select on all tables in schema public to <user_name>;
alter default privileges in schema public grant select on tables to <user_name>;
According to the documentation, the second statement should have resolved the problem. It does not however auto grant permissions to user_name when a new table is added to the public schema.
I am using this user (user_name) to copy data over to another database.
Found the answer. It is in this line in the ALTER DEFAULT PRIVILEGES documentation.
You can change default privileges only for objects that will be created by yourself or by roles that you are a member of.
I was using alter default privileges from a different user than the one creating the tables.
Make sure to set the role to the user creating the table before the alter default privilege statement:
SET ROLE <user_that_creates_new_tables>;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO <user_name>;
To grant default privileges, you need to grant to the user you are creating the table with.
You are creating the tables as SA_user, but reading the tables as READ_user. Your code needs to look like:
ALTER DEFAULT PRIVILEGES
FOR USER SA_user
IN SCHEMA schema_name
GRANT SELECT ON TABLES TO READ_user;
So whenever the SA_user creates a table, it will grant select rights for the READ_user.
I was looking for same thing, I found other way to solve this. Based on postgresql documentation we can create event trigger, so when new table is created, grant query will execute automatically. So no matter who created new table, other user allowed to use it.
CREATE OR REPLACE FUNCTION auto_grant_func()
RETURNS event_trigger AS $$
BEGIN
grant all on all tables in schema public to <username>;
grant all on all sequences in schema public to <username>;
grant select on all tables in schema public to <username>;
grant select on all sequences in schema public to <username>;
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER auto_grant_trigger
ON ddl_command_end
WHEN TAG IN ('CREATE TABLE', 'CREATE TABLE AS')
EXECUTE PROCEDURE auto_grant_func();

Revoking right for user to DROP table

I am a big fan of PostgreSQL but can't figure out one aspects of it's built in user management.
My problem is that I have set up pgAdmin and will have some non-developers manually update data in some specific tables. For this reason I have created a new user called "admin" and are looking to restrict this users rights.
I have tried to delete all rights for the user with the following query (from another user):
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM admin;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM admin;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM admin;
The above did lead to the following error when I wrote a simple SELECT statement from the user admin on a table called "crap": ERROR: permission denied for relation crap.
But what I was able to do with the user admin which by now shouldn't have any rights was the following: DROP TABLE crap; which worked!?
I am really surprised by this. This user is not a Postgres superuser. How can I remove this right to drop tables for a specific user?
You're one level off in hierarchy for the permissions.
REVOKE ALL PRIVILEGES FROM SCHEMA public FROM <role_name>;
You were affecting permissions within the table. You must also go one level up to the schema as well to protect create/drop access. You may also want to revoke access at the database level as well to protect the schema.
REVOKE ALL PRIVILEGES FROM DATABASE <database_name> FROM <role_name>;
You could also simply remove the user. Alternatively you could simply disable that user's ability to login.
ALTER ROLE <role_name> SET NOLOGIN;
If these don't work for you, you can go down a somewhat more complicated route and make an event trigger that watches for DROP TABLE events, compares against the role, and either allows it to continue or aborts the transaction.
CREATE OR REPLACE FUNCTION no_admin_drop()
RETURNS event_trigger LANGUAGE plpgsql AS $$
BEGIN
IF CURRENT_USER = 'admin'::regrole THEN
RAISE EXCEPTION 'command is disabled';
END IF;
END;
$$;
CREATE EVENT TRIGGER no_admin_drop ON sql_drop
EXECUTE FUNCTION no_admin_drop();

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;

Grant privileges on future tables in PostgreSQL?

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.

Revoking access to specific columns not working in postgresql on table pg_proc

My goal is to only enable a specific user to execute functions in a specific schema, list the functions available by name but not see the source code of the function or list other schema.
It is possible to achieve the above without the ability to list the available function names via carrying out the following:
First create a test user role:
CREATE ROLE test_user WITH LOGIN PASSWORD 'secret';
Now revoke all permissions from the public on all schemas:
REVOKE ALL PRIVILEGES ON DATABASE test_db 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;
REVOKE ALL ON SCHEMA public FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA function_schema FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA function_schema FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA function_schema FROM PUBLIC;
REVOKE ALL ON SCHEMA function_schema FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA table_schema FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA table_schema FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA table_schema FROM PUBLIC;
REVOKE ALL ON SCHEMA table_schema FROM PUBLIC;
Setup restricted access for test user:
GRANT CONNECT ON DATABASE test_db TO test_user;
GRANT USAGE ON SCHEMA function_schema TO test_user;
REVOKE ALL ON SCHEMA public FROM test_user;
REVOKE ALL ON SCHEMA table_schema FROM test_user;
GRANT EXECUTE ON FUNCTION function_schema.function1() TO test_user;
GRANT EXECUTE ON FUNCTION function_schema.function2(integer) TO test_user;
Now to hid the schema structure and code form the test users and public:
REVOKE SELECT ON TABLE pg_proc FROM public;
REVOKE SELECT ON TABLE pg_proc FROM test_user;
This all works well, the test user can execute the functions but they can't see the code inside the functions, nor can they see the schema and table structure.
--
I'd like to allow the test user to now see the functions by name in the test_functions schema.I've tried the following according to GRANT Postgresql 9.3 (this is granting select on every column in pg_proc):
GRANT SELECT (proname,pronamespace,proowner,prolang,procost,prorows,
provariadic,protransform,proisagg,proiswindow,prosecdef,proleakproof,
proisstrict,proretset,provolatile,pronargs,pronargdefaults,prorettype,
proargtypes,proallargtypes,proargmodes,proargnames,proargdefaults,prosrc,
probin,proconfig,proacl) ON TABLE pg_proc TO test_user;
The result here is that the test user does not get all the same select permissions as if they had access to the whole table. They still can't see the function names.
Another test was to do the reverse, grant select to the table then revoke select on all columns accouding to REVOKE postgresql 9.3:
GRANT SELECT ON TABLE pg_proc TO test_user;
REVOKE SELECT (proname,pronamespace,proowner,prolang,procost,prorows,
provariadic,protransform,proisagg,proiswindow,prosecdef,proleakproof,
proisstrict,proretset,provolatile,pronargs,pronargdefaults,prorettype,
proargtypes,proallargtypes,proargmodes,proargnames,proargdefaults,prosrc,
probin,proconfig,proacl) ON TABLE pg_proc FROM test_user;
Again this doesn't work, they now can see all schemas, code and tables (on allowed schemas).
It appears that the grant/revoke on specific columns doesn't work the way the documentation suggests.
Searching extensively yielded How to restrict access to code in a function wich suggests revoking access to only the pg_proc.prosrc column which clearly doesn't work from the tests above.
I'm using postgresql 9.3
Please feel free to suggest any other solution that comes to mind.
Working with column permissions should work but is probably not the best approach here. Maintaining privileges in this way is rather burdensome in PostgreSQL. Using this approach you have to set and track your security policy for individual users on all affected system catalog relations. Just imagine having to update your security policy when you have more than a few users.
Rather than applying detailed security roles on relations, I suggest that you lock everything in the system catalogs down (as you did) and then create views to selectively expose parts of the system catalogs (this is already the case in the standard setup, but apparently not strict enough for your case). GRANT SELECT on those views to a group role and then grant that group role to login roles (which should have the INHERIT property). This way it is much easier to track what you have done and to update your security policy as all policy is contained in a set of views (content) and group roles (accessibility). If you are using PostgreSQL-9.2+ check out the with security-barrier option on the views as this will prevent optimizer-spoofing by malicious users.