Implementación de pg_columnmask en un flujo de trabajo integral
En esta sección se muestra una implementación completa del pg_columnmask mediante el uso de un ejemplo de tabla de empleados con información confidencial. Obtendrá información sobre cómo crear funciones de enmascaramiento personalizadas, definir múltiples políticas de enmascaramiento con diferentes niveles de peso para roles diferentes (pasante, de soporte, analista) y a observar cómo los usuarios que pertenecen a uno o varios roles ven diferentes niveles de datos enmascarados. Los ejemplos también incluyen el comportamiento de enmascaramiento en las instrucciones DML con cláusulas RETURNING, los activadores que utilizan tablas frente a vistas y las operaciones de administración de políticas, como el cambio de nombre, la modificación de los pesos y la limpieza.
Cree una tabla de ejemplo con información confidencial:
CREATE SCHEMA hr; CREATE TABLE hr.employees ( id INT PRIMARY KEY, name TEXT NOT NULL, email TEXT, ssn TEXT, salary NUMERIC(10,2) ); INSERT INTO hr.employees VALUES (1, 'John Doe', 'john.doe@example.com', '123-45-6789', 50000.00), (2, 'Jane Smith', 'jane.smith@example.com', '987-65-4321', 60000.00);-
Cree funciones de enmascaramiento personalizadas:
CREATE OR REPLACE FUNCTION public.mask_ssn(ssn TEXT) RETURNS TEXT AS $$ BEGIN RETURN 'XXX-XX-' || RIGHT(ssn, 4); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION public.mask_salary(salary NUMERIC, multiplier NUMERIC DEFAULT 0.0) RETURNS NUMERIC AS $$ BEGIN RETURN salary * multiplier; END; $$ LANGUAGE plpgsql; -
Cree varias políticas con diferentes niveles de enmascaramiento en función de los roles de los usuarios:
-- Create different roles CREATE ROLE analyst_role; CREATE ROLE support_role; CREATE ROLE intern_role; GRANT USAGE ON SCHEMA hr TO analyst_role, support_role, intern_role; GRANT SELECT ON hr.employees TO analyst_role, support_role, intern_role; ---------------------------------------------------------------------- -- Low-Weight Policy (Intern) CALL pgcolumnmask.create_masking_policy( 'employee_mask_strict', 'hr.employees', JSON_BUILD_OBJECT('name', 'pgcolumnmask.mask_text(name, ''*'')', 'email', 'pgcolumnmask.mask_email(email)', 'ssn', 'pgcolumnmask.mask_text(ssn, ''*'')', 'salary', 'public.mask_salary(salary)')::JSONB, ARRAY['intern_role'], 10 -- Lowest weight ); ---------------------------------------------------------------------- -- Medium-Weight Policy (Support) CALL pgcolumnmask.create_masking_policy( 'employee_mask_moderate', 'hr.employees', JSON_BUILD_OBJECT('email', 'pgcolumnmask.mask_email(email, ''#'')', 'ssn', 'public.mask_ssn(ssn)', 'salary', 'public.mask_salary(salary)')::JSONB, ARRAY['support_role'], 50 -- Medium weight ); ---------------------------------------------------------------------- -- High-Weight Policy (Analyst) CALL pgcolumnmask.create_masking_policy( 'employee_mask_light', 'hr.employees', JSON_BUILD_OBJECT('ssn', 'public.mask_ssn(ssn)', 'salary', 'public.mask_salary(salary, 0.9)')::JSONB, ARRAY['analyst_role'], 100 -- Highest weight ); -
Los siguientes ejemplos muestran cómo los diferentes usuarios ven los datos en función de la pertenencia a un rol y los pesos de las políticas.
-- Create users CREATE USER sarah_intern; GRANT intern_role TO sarah_intern; CREATE USER lisa_support; GRANT support_role TO lisa_support; CREATE USER mike_analyst; GRANT analyst_role TO mike_analyst; CREATE USER ethan_support_intern; GRANT support_role, intern_role TO ethan_support_intern; CREATE USER john_analyst_intern; GRANT analyst_role, intern_role TO john_analyst_intern;Como pasante (enmascaramiento más estricto):
SET ROLE sarah_intern; SELECT * FROM hr.employees; id | name | email | ssn | salary ----+------------+------------------------+-------------+-------- 1 | ******** | XXXXXXXX@XXXXXXX.com | *********** | 0.00 2 | ********** | XXXXXXXXXX@XXXXXXX.com | *********** | 0.00Como usuario de apoyo (enmascaramiento moderado):
SET ROLE lisa_support; SELECT * FROM hr.employees; id | name | email | ssn | salary ----+------------+------------------------+-------------+-------- 1 | John Doe | ########@#######.com | XXX-XX-6789 | 0.00 2 | Jane Smith | ##########@#######.com | XXX-XX-4321 | 0.00Como analista (el enmascaramiento más ligero):
SET ROLE mike_analyst; SELECT * FROM hr.employees; id | name | email | ssn | salary ----+------------+------------------------+-------------+---------- 1 | John Doe | john.doe@example.com | XXX-XX-6789 | 45000.00 2 | Jane Smith | jane.smith@example.com | XXX-XX-4321 | 54000.00Como usuario ethan_support_intern, que es a la vez pasante y usuario de soporte:
SET ROLE ethan_support_intern; -- masking policies appliable to this user: employee_mask_strict and employee_mask_moderate -- id : unmasked because no masking policy appliable on ethan_support_intern -- masks these columns -- name : masked because of employee_mask_strict policy -- email, ssn, salary : both employee_mask_strict and employee_mask_moderate mask these columns -- but employee_mask_moderate will be use because of higher weight SELECT * FROM hr.employees; id | name | email | ssn | salary ----+------------+------------------------+-------------+-------- 1 | ******** | ########@#######.com | XXX-XX-6789 | 0.00 2 | ********** | ##########@#######.com | XXX-XX-4321 | 0.00Como john_analyst_intern, que es a la vez pasante y analista:
SET ROLE john_analyst_intern; -- masking policies appliable to this user: employee_mask_strict and employee_mask_light -- id : unmasked because no masking policy appliable on john_analyst_intern -- masks these columns -- name, email : masked because of employee_mask_strict -- ssn, salary : both employee_mask_strict and employee_mask_light mask these columns -- but employee_mask_light will be use because of higher weight SELECT * FROM hr.employees; id | name | email | ssn | salary ----+------------+------------------------+-------------+---------- 1 | ******** | XXXXXXXX@XXXXXXX.com | XXX-XX-6789 | 45000.00 2 | ********** | XXXXXXXXXX@XXXXXXX.com | XXX-XX-4321 | 54000.00