lquerel
lquerel

Reputation: 183

Need help to strictly specify an ingester role with PostgreSQL

For a data ingester service, I'd like to strictly restrict its access to the database in the following way. This ingester service must be able to:

Another way to specify this ingester role is to look at what it shouldn't be able to do:

I didn't find any way to satisfy all these constraints with PostgreSQL. For example, to Alter a table the ingester role need to own the table, but when you own a table you automatically have access to DELETE, SELECT, UPDATE, ... operations on this table. Ideally, I'd like all these tables owned by a database admin user. This admin user will be the only user allowed to execute any destructive operations.

Can we use a combination of trigger and function to satisfy those constraints or can we specify that only based on roles and grant operations?

Upvotes: 0

Views: 48

Answers (2)

lquerel
lquerel

Reputation: 183

Thanks Laurenz for your help.

I came up on the following solution based on a combination of EVENT TRIGGER and FUNCTION with SECURITY DEFINER owned by an admin user.

The EVENT TRIGGER detects any CREATE TABLE done by the ingester user and then call a function executed with the permissions of the admin user. This function changes the owner of the table and grants the insert and select permissions to the ingester and reporting users respectively. The ingester user is now able to create table and insert data into it. But this ingester is no longer able to read, update or drop this table. The reporting user is only able to read the table.

CREATE OR REPLACE FUNCTION trg_create_table_set_owner()
 RETURNS event_trigger
 LANGUAGE plpgsql 
 SECURITY DEFINER
AS $$
DECLARE
  obj record;
BEGIN
  FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag='CREATE TABLE' LOOP
    EXECUTE format('ALTER TABLE %s OWNER TO service_admin', obj.object_identity);
    EXECUTE format('GRANT INSERT ON TABLE %s TO ingester_role;', obj.object_identity);
    EXECUTE format('GRANT SELECT ON TABLE %s TO reporting_role;', obj.object_identity);
  END LOOP;
END;
$$;

CREATE EVENT TRIGGER trg_create_table_set_owner
 ON ddl_command_end
 WHEN tag IN ('CREATE TABLE')
 EXECUTE PROCEDURE trg_create_table_set_owner();

Upvotes: 1

Laurenz Albe
Laurenz Albe

Reputation: 247235

This is definitely impossible.

Whoever creates a table is the table owner and can alter and drop it.

Two ways forward:

  • Event triggers like you suggest.

  • Have the tables be owned by someone else and provide SECURITY DEFINER functions to manipulate them.

Upvotes: 1

Related Questions