了解触发器函数中的掩蔽行为 - Amazon Aurora
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

了解触发器函数中的掩蔽行为

pg_columnmask 策略应用于表时,了解掩蔽如何与触发器函数交互非常重要。触发器是指为响应表上的某些事件(例如 INSERT、UPDATE 或 DELETE 操作)而自动执行的数据库函数。

默认情况下,DDM 根据触发器的类型应用不同的掩蔽规则:

表触发器

转换表未掩蔽:表上的触发器函数可以访问其转换表中未掩蔽的数据,无论是对于旧的行版本还是新的行版本

表所有者创建触发器并拥有数据,因此他们拥有有效管理表的完全访问权限

查看触发器(INSTEAD OF 触发器)

转换表已掩蔽:视图上的触发器函数根据当前用户的权限查看掩蔽的数据

视图所有者可能与基表所有者不同,应遵从有关底层表的掩蔽策略

两个服务器级别的配置参数控制对掩蔽表的触发器行为。这些只能通过 rds_superuser 设置:

  • 限制掩蔽表上的触发器:当掩蔽的用户对具有适用的掩蔽策略的表执行 DML 操作时,防止触发器执行。

  • 限制带有掩蔽表的视图上的触发器:当视图定义包括具有适用于当前用户的掩蔽策略的表时,防止在视图上执行触发器。

例 :函数应用于表和视图之间的区别

以下示例创建一个触发器函数,该函数可打印旧的行值和新的行值,然后演示同一个函数在附加到表与附加到视图时的行为有何不同。

-- Create trigger function CREATE OR REPLACE FUNCTION print_changes() RETURNS TRIGGER AS $$ BEGIN RAISE NOTICE 'Old row: name=%, email=%, ssn=%, salary=%', OLD.name, OLD.email, OLD.ssn, OLD.salary; RAISE NOTICE 'New row: name=%, email=%, ssn=%, salary=%', NEW.name, NEW.email, NEW.ssn, NEW.salary; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Create trigger CREATE TRIGGER print_changes_trigger BEFORE UPDATE ON hr.employees FOR EACH ROW EXECUTE FUNCTION print_changes(); -- Grant update to analyst role GRANT UPDATE ON hr.employees TO analyst_role; -- Unmasked data must be seen inside trigger even for masked user for the OLD and NEW -- row passed to trigger function BEGIN; SET ROLE mike_analyst; UPDATE hr.employees SET id = id + 10 RETURNING *; NOTICE: Old row: name=John Doe, email=john.doe@example.com, ssn=123-45-6789, salary=50000.00 NOTICE: New row: name=John Doe, email=john.doe@example.com, ssn=123-45-6789, salary=50000.00 NOTICE: Old row: name=Jane Smith, email=jane.smith@example.com, ssn=987-65-4321, salary=60000.00 NOTICE: New row: name=Jane Smith, email=jane.smith@example.com, ssn=987-65-4321, salary=60000.00 id | name | email | ssn | salary ----+------------+------------------------+-------------+---------- 11 | John Doe | john.doe@example.com | XXX-XX-6789 | 45000.00 12 | Jane Smith | jane.smith@example.com | XXX-XX-4321 | 54000.00 (2 rows) ROLLBACK; -- Triggers on views (which are supposed to see masked data for new/old row) CREATE VIEW hr.view_over_employees AS SELECT * FROM hr.employees; GRANT UPDATE, SELECT ON hr.view_over_employees TO analyst_role; -- Create trigger for this view CREATE TRIGGER print_changes_trigger INSTEAD OF UPDATE ON hr.view_over_employees FOR EACH ROW EXECUTE FUNCTION print_changes(); -- Masked new and old rows should be passed to trigger if trigger is on view BEGIN; SET ROLE mike_analyst; UPDATE hr.view_over_employees SET id = id + 10 RETURNING *; NOTICE: Old row: name=John Doe, email=john.doe@example.com, ssn=XXX-XX-6789, salary=45000.00 NOTICE: New row: name=John Doe, email=john.doe@example.com, ssn=XXX-XX-6789, salary=45000.00 NOTICE: Old row: name=Jane Smith, email=jane.smith@example.com, ssn=XXX-XX-4321, salary=54000.00 NOTICE: New row: name=Jane Smith, email=jane.smith@example.com, ssn=XXX-XX-4321, salary=54000.00 id | name | email | ssn | salary ----+------------+------------------------+-------------+---------- 11 | John Doe | john.doe@example.com | XXX-XX-6789 | 45000.00 12 | Jane Smith | jane.smith@example.com | XXX-XX-4321 | 54000.00 (2 rows) ROLLBACK;

我们建议在掩蔽表上实现触发器之前,先检查触发器行为。表触发器可以访问转换表中的未掩蔽数据,而视图触发器可以看到掩蔽的数据。

例 :重命名掩蔽策略

以下示例演示如何使用 rename_masking_policy 过程重命名现有策略。

-- Rename the strict policy CALL pgcolumnmask.rename_masking_policy( 'employee_mask_strict', 'hr.employees', 'intern_protection_policy' ); -- Verify the rename SELECT policyname, roles, weight FROM pgcolumnmask.pg_columnmask_policies WHERE tablename = 'employees' ORDER BY weight DESC; policyname | roles | weight --------------------------+----------------+-------- employee_mask_light | {analyst_role} | 100 employee_mask_moderate | {support_role} | 50 intern_protection_policy | {intern_role} | 10
例 :更改策略权重

以下示例演示如何更改策略权重以更改其权重。

-- Change weight of moderate policy CALL pgcolumnmask.alter_masking_policy( 'employee_mask_moderate'::NAME, 'hr.employees'::REGCLASS, NULL, -- Keep existing masking expressions NULL, -- Keep existing roles 75 -- New weight ); -- Verify the changes SELECT policyname, roles, weight FROM pgcolumnmask.pg_columnmask_policies WHERE tablename = 'employees' ORDER BY weight DESC; policyname | roles | weight --------------------------+----------------+-------- employee_mask_light | {analyst_role} | 100 employee_mask_moderate | {support_role} | 75 intern_protection_policy | {intern_role} | 10
例 :清理

以下示例演示如何删除所有策略、表和用户。

-- Drop policies CALL pgcolumnmask.drop_masking_policy( 'intern_protection_policy', 'hr.employees' ); CALL pgcolumnmask.drop_masking_policy( 'employee_mask_moderate', 'hr.employees' ); CALL pgcolumnmask.drop_masking_policy( 'employee_mask_light', 'hr.employees' ); -- Drop table and functions DROP VIEW IF EXISTS hr.view_over_employees; DROP TABLE IF EXISTS hr.employees; DROP SCHEMA IF EXISTS hr; DROP FUNCTION IF EXISTS public.mask_ssn(text); DROP FUNCTION IF EXISTS public.mask_salary(numeric, numeric); -- Drop users DROP USER sarah_intern, lisa_support, mike_analyst, ethan_support_intern, john_analyst_intern; DROP ROLE intern_role, support_role, analyst_role;