트리거 함수의 마스킹 동작 이해 - Amazon Aurora

트리거 함수의 마스킹 동작 이해

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;