Introduction
Data has become an essential part of every business and everyone wants to be a data-driven company. However, due to its volume, variety and velocity, it is necessary to find ways to organise the information in a modern solution. That’s why a key element is a data warehouse.
As a data engineer, sometimes you may need to provide access to the DWH, but how do you manage that?
The stakeholders
As Data Enginners, we often receive requests from different stakeholders: finance, marketing, sales, etc.
The requests
To handled this example a stakeholder requests access to specific table in a specific schema.
Get started
- Create a read only group
CREATE GROUP ro_group;
- Create user
CREATE USER "read_user" PASSWORD 'PASSWORD';
- Add user to read only group
ALTER GROUP ro_group ADD USER "read_user";
- Grant usage permission to read only group to specific schema
GRANT USAGE ON SCHEMA "schema_name" TO GROUP ro_group;
- Grant select permission to read only group to specific schema
GRANT SELECT ON ALL TABLES IN SCHEMA "schema_name" TO GROUP ro_group;
- Alter default privileges to maintain the permission on new tables
ALTER DEFAULT PRIVILEGES IN SCHEMA "schema_name" GRANT SELECT ON TABLES TO GROUP ro_group;
At this point you have a group with read-only permissions and a user who belongs to that group.
More general
A few days ago I was asked to create a new group and grant select to all tables in all schemas, I was looking for a function to handle that but I couldn’t find it so I created a procedure.
At this point you need to have a group and a user added to the group, but you know how to do that.
The first thing to do is to find a way to generate all the grants for all the schemas.
- Query to get the syntax to grant a read-only group permission to a specific schema.
--Note: The following query only returns the syntax but does not make any changes to the base.
SELECT 'GRANT USAGE ON SCHEMA ' || schema_name || ' TO GROUP ro_group;'
FROM information_schema.schemata
WHERE schema_name NOT LIKE 'pg_%' AND schema_name <> 'information_schema'
To apply the grant usage on all schemas I created the following procedure:
CREATE OR REPLACE procedure grant_usage_all_schemas_to_group()
LANGUAGE plpgsql
AS $$
DECLARE
schema_record record;
BEGIN
FOR schema_record in
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name NOT LIKE 'pg_%' AND schema_name <> 'information_schema'
LOOP
EXECUTE 'GRANT USAGE ON SCHEMA ' || schema_record.schema_name || ' TO GROUP ro_group;';
END LOOP;
END;
$$ ;
and to apply I ran the following:
call grant_usage_all_schemas_to_group();
Now you need to Grant select permission to read only group to all schemas
- Grant select permission to read only group to specific schema
--Note: The following query only returns the syntax but does not make any changes to the base.
SELECT 'GRANT SELECT ON ALL TABLES IN SCHEMA ' || schema_name || ' TO GROUP RO_GROUP;'
FROM information_schema.schemata
WHERE schema_name NOT LIKE 'pg_%' AND schema_name <> 'information_schema'
To apply the grant select on all schemas I created the following procedure:
CREATE OR REPLACE procedure grant_select_all_tables_to_group()
LANGUAGE plpgsql
AS $$
DECLARE
schema_record record;
BEGIN
FOR schema_record in
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name NOT LIKE 'pg_%' AND schema_name <> 'information_schema'
LOOP
EXECUTE 'GRANT SELECT ON ALL TABLES IN SCHEMA ' || schema_record.schema_name || ' TO GROUP ro_group;';
END LOOP;
END;
$$ ;
To apply the grant select on all tables I created the following procedure:
call grant_select_all_tables_to_group();
- Alter default privileges to maintain the permission on new tables
--Note: The following query only returns the syntax but does not make any changes to the base.
SELECT 'ALTER DEFAULT PRIVILEGES IN SCHEMA ' || schema_name || ' GRANT SELECT ON TABLES TO GROUP ro_group;'
FROM information_schema.schemata
WHERE schema_name not like 'pg_%' and schema_name <> 'information_schema'
CREATE OR REPLACE procedure grant_alter__default_all_tables_to_group()
LANGUAGE plpgsql
AS $$
DECLARE
schema_record record;
BEGIN
FOR schema_record in
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name NOT LIKE 'pg_%' AND schema_name <> 'information_schema'
LOOP
EXECUTE 'ALTER DEFAULT PRIVILEGES IN SCHEMA ' || schema_record.schema_name || ' GRANT SELECT ON TABLES TO GROUP ro_group;';
END LOOP;
END;
$$ ;
call grant_alter__default_all_tables_to_group()
Final Thoughts
At this point you have a group with read only permissions and you only need added users to grant the select, I think it is possible to be more DRY and use a single procedure to do the last 3…maybe in a few days I will do an update.
For now this works for me.