refs #740: enforce carrier VPD by MCP user
This commit is contained in:
323
database/adb/84_hmm_carrier_team_vpd.sql
Normal file
323
database/adb/84_hmm_carrier_team_vpd.sql
Normal file
@@ -0,0 +1,323 @@
|
||||
-- ============================================================
|
||||
-- 84_hmm_carrier_team_vpd.sql
|
||||
--
|
||||
-- Row security for HMM_CARRIER_ASSIGNMENTS_V:
|
||||
-- HMM_HR_VIEWER -> current employee only
|
||||
-- HMM_HR_MANAGER -> current employee and direct reports
|
||||
-- HMM_HR_ADMIN -> all assignments
|
||||
--
|
||||
-- Run as ADMIN after 72_hmm_leave_team_vpd.sql and
|
||||
-- 81_hmm_carrier_access_groups.sql. Plain bearer tokens are
|
||||
-- never stored by this script.
|
||||
-- ============================================================
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
SET ECHO OFF
|
||||
SET FEEDBACK ON
|
||||
SET DEFINE OFF
|
||||
|
||||
PROMPT === 1. Registering the protected carrier object ===
|
||||
DECLARE
|
||||
v_object_id NUMBER;
|
||||
BEGIN
|
||||
BEGIN
|
||||
SELECT object_id
|
||||
INTO v_object_id
|
||||
FROM hmm_access_objects
|
||||
WHERE owner = 'ADMIN'
|
||||
AND object_name = 'HMM_CARRIER_ASSIGNMENTS_V';
|
||||
|
||||
UPDATE hmm_access_objects
|
||||
SET enabled_yn = 'Y',
|
||||
description = 'Employee-to-carrier assignments protected by employee hierarchy',
|
||||
ords_path = 'cb-ords/cb-object-query/admin/hmm_carrier_assignments_v'
|
||||
WHERE object_id = v_object_id;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
SELECT NVL(MAX(object_id), 0) + 1
|
||||
INTO v_object_id
|
||||
FROM hmm_access_objects;
|
||||
|
||||
INSERT INTO hmm_access_objects (
|
||||
object_id, owner, object_name, ords_path, enabled_yn, description
|
||||
) VALUES (
|
||||
v_object_id,
|
||||
'ADMIN',
|
||||
'HMM_CARRIER_ASSIGNMENTS_V',
|
||||
'cb-ords/cb-object-query/admin/hmm_carrier_assignments_v',
|
||||
'Y',
|
||||
'Employee-to-carrier assignments protected by employee hierarchy'
|
||||
);
|
||||
END;
|
||||
|
||||
FOR c IN (
|
||||
SELECT column_name
|
||||
FROM user_tab_columns
|
||||
WHERE table_name = 'HMM_CARRIER_ASSIGNMENTS_V'
|
||||
ORDER BY column_id
|
||||
) LOOP
|
||||
MERGE INTO hmm_access_object_columns dst
|
||||
USING (
|
||||
SELECT v_object_id object_id, c.column_name column_name FROM dual
|
||||
) src
|
||||
ON (dst.object_id = src.object_id AND dst.column_name = src.column_name)
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
column_id, object_id, column_name, sensitive_yn,
|
||||
sensitivity_level, redaction_method
|
||||
) VALUES (
|
||||
(SELECT NVL(MAX(column_id), 0) + 1 FROM hmm_access_object_columns),
|
||||
src.object_id, src.column_name, 'N', 'PUBLIC', 'NONE'
|
||||
);
|
||||
END LOOP;
|
||||
END;
|
||||
/
|
||||
|
||||
PROMPT === 2. Registering role rules ===
|
||||
DECLARE
|
||||
PROCEDURE ensure_permission(
|
||||
p_role_name IN VARCHAR2,
|
||||
p_rule_type IN VARCHAR2
|
||||
) AS
|
||||
v_role_id NUMBER;
|
||||
v_perm_id NUMBER;
|
||||
BEGIN
|
||||
SELECT role_id
|
||||
INTO v_role_id
|
||||
FROM hmm_access_roles
|
||||
WHERE role_name = p_role_name
|
||||
AND active_yn = 'Y';
|
||||
|
||||
BEGIN
|
||||
SELECT perm_id
|
||||
INTO v_perm_id
|
||||
FROM hmm_access_permissions
|
||||
WHERE role_id = v_role_id
|
||||
AND target_name = 'HMM_CARRIER_ASSIGNMENTS_V'
|
||||
AND action_name = 'SELECT';
|
||||
|
||||
UPDATE hmm_access_permissions
|
||||
SET permission_effect = 'ALLOW'
|
||||
WHERE perm_id = v_perm_id;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
SELECT cb_permission_seq.NEXTVAL INTO v_perm_id FROM dual;
|
||||
INSERT INTO hmm_access_permissions (
|
||||
perm_id, role_id, target_name, action_name, permission_effect
|
||||
) VALUES (
|
||||
v_perm_id, v_role_id, 'HMM_CARRIER_ASSIGNMENTS_V', 'SELECT', 'ALLOW'
|
||||
);
|
||||
END;
|
||||
|
||||
DELETE FROM hmm_access_permission_rules WHERE perm_id = v_perm_id;
|
||||
INSERT INTO hmm_access_permission_rules (
|
||||
rule_id, perm_id, rule_column, rule_type, rule_value
|
||||
) VALUES (
|
||||
cb_permission_rule_seq.NEXTVAL,
|
||||
v_perm_id,
|
||||
'EMPLOYEE_ID',
|
||||
p_rule_type,
|
||||
NULL
|
||||
);
|
||||
END;
|
||||
BEGIN
|
||||
ensure_permission('HMM_HR_VIEWER', 'SELF');
|
||||
ensure_permission('HMM_HR_MANAGER', 'MANAGED_TEAM');
|
||||
ensure_permission('HMM_HR_ADMIN', 'ALL');
|
||||
END;
|
||||
/
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT === 3. Creating the carrier VPD predicate ===
|
||||
CREATE OR REPLACE FUNCTION hmm_carrier_vpd_filter(
|
||||
p_schema IN VARCHAR2,
|
||||
p_object IN VARCHAR2
|
||||
) RETURN VARCHAR2
|
||||
AUTHID DEFINER
|
||||
AS
|
||||
v_employee_id NUMBER;
|
||||
v_all_rule NUMBER := 0;
|
||||
v_team_rule NUMBER := 0;
|
||||
v_self_rule NUMBER := 0;
|
||||
BEGIN
|
||||
IF UPPER(TRIM(p_schema)) != 'ADMIN'
|
||||
OR UPPER(TRIM(p_object)) != 'HMM_CARRIER_ASSIGNMENTS_V' THEN
|
||||
RETURN '1 = 0';
|
||||
END IF;
|
||||
|
||||
BEGIN
|
||||
v_employee_id := TO_NUMBER(
|
||||
SYS_CONTEXT('HMM_ACCESS_CTX', 'EMPLOYEE_ID')
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RETURN '1 = 0';
|
||||
END;
|
||||
|
||||
IF v_employee_id IS NULL THEN
|
||||
RETURN '1 = 0';
|
||||
END IF;
|
||||
|
||||
SELECT NVL(MAX(CASE WHEN rule.rule_type = 'ALL' THEN 1 ELSE 0 END), 0),
|
||||
NVL(MAX(CASE WHEN rule.rule_type = 'MANAGED_TEAM' THEN 1 ELSE 0 END), 0),
|
||||
NVL(MAX(CASE WHEN rule.rule_type = 'SELF' THEN 1 ELSE 0 END), 0)
|
||||
INTO v_all_rule, v_team_rule, v_self_rule
|
||||
FROM (
|
||||
SELECT employee_role.role_id
|
||||
FROM hmm_employee_access_roles employee_role
|
||||
WHERE employee_role.employee_id = v_employee_id
|
||||
UNION
|
||||
SELECT group_role.role_id
|
||||
FROM hmm_access_group_members group_member
|
||||
JOIN hmm_access_groups access_group
|
||||
ON access_group.group_id = group_member.group_id
|
||||
AND access_group.active_yn = 'Y'
|
||||
JOIN hmm_group_access_roles group_role
|
||||
ON group_role.group_id = group_member.group_id
|
||||
WHERE group_member.employee_id = v_employee_id
|
||||
) effective_role
|
||||
JOIN hmm_access_roles role
|
||||
ON role.role_id = effective_role.role_id
|
||||
AND role.active_yn = 'Y'
|
||||
JOIN hmm_access_permissions permission
|
||||
ON permission.role_id = role.role_id
|
||||
AND permission.target_name = 'HMM_CARRIER_ASSIGNMENTS_V'
|
||||
AND permission.action_name = 'SELECT'
|
||||
AND permission.permission_effect = 'ALLOW'
|
||||
JOIN hmm_access_permission_rules rule
|
||||
ON rule.perm_id = permission.perm_id
|
||||
AND UPPER(TRIM(rule.rule_column)) = 'EMPLOYEE_ID';
|
||||
|
||||
IF v_all_rule = 1 THEN
|
||||
RETURN '1 = 1';
|
||||
END IF;
|
||||
|
||||
IF v_team_rule = 1 THEN
|
||||
RETURN 'EMPLOYEE_ID IN ('
|
||||
|| 'SELECT employee.employee_id '
|
||||
|| 'FROM ADMIN.HMM_HR_EMPLOYEES employee '
|
||||
|| 'WHERE employee.employee_id = '
|
||||
|| 'TO_NUMBER(SYS_CONTEXT(''HMM_ACCESS_CTX'', ''EMPLOYEE_ID'')) '
|
||||
|| 'OR employee.manager_employee_id = '
|
||||
|| 'TO_NUMBER(SYS_CONTEXT(''HMM_ACCESS_CTX'', ''EMPLOYEE_ID''))'
|
||||
|| ')';
|
||||
END IF;
|
||||
|
||||
IF v_self_rule = 1 THEN
|
||||
RETURN 'EMPLOYEE_ID = TO_NUMBER('
|
||||
|| 'SYS_CONTEXT(''HMM_ACCESS_CTX'', ''EMPLOYEE_ID''))';
|
||||
END IF;
|
||||
|
||||
RETURN '1 = 0';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RETURN '1 = 0';
|
||||
END;
|
||||
/
|
||||
|
||||
SHOW ERRORS FUNCTION hmm_carrier_vpd_filter
|
||||
|
||||
PROMPT === 4. Attaching the VPD policy ===
|
||||
BEGIN
|
||||
BEGIN
|
||||
DBMS_RLS.DROP_POLICY(
|
||||
object_schema => 'ADMIN',
|
||||
object_name => 'HMM_CARRIER_ASSIGNMENTS_V',
|
||||
policy_name => 'HMM_CARRIER_SCOPE_POLICY'
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE != -28102 THEN
|
||||
RAISE;
|
||||
END IF;
|
||||
END;
|
||||
|
||||
DBMS_RLS.ADD_POLICY(
|
||||
object_schema => 'ADMIN',
|
||||
object_name => 'HMM_CARRIER_ASSIGNMENTS_V',
|
||||
policy_name => 'HMM_CARRIER_SCOPE_POLICY',
|
||||
function_schema => 'ADMIN',
|
||||
policy_function => 'HMM_CARRIER_VPD_FILTER',
|
||||
statement_types => 'SELECT',
|
||||
update_check => FALSE,
|
||||
enable => TRUE,
|
||||
policy_type => DBMS_RLS.CONTEXT_SENSITIVE
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
PROMPT === 5. Granting the non-exempt runtime read boundary ===
|
||||
GRANT SELECT ON hmm_carrier_assignments_v TO cb_ords;
|
||||
GRANT SELECT ON hmm_rds_carriers_v TO cb_ords;
|
||||
GRANT SELECT ON hmm_rds_carrier_perf_v TO cb_ords;
|
||||
GRANT SELECT ON hmm_rds_carrier_latest_v TO cb_ords;
|
||||
|
||||
CREATE OR REPLACE SYNONYM cb_ords.hmm_carrier_assignments_v
|
||||
FOR admin.hmm_carrier_assignments_v;
|
||||
CREATE OR REPLACE SYNONYM cb_ords.hmm_rds_carriers_v
|
||||
FOR admin.hmm_rds_carriers_v;
|
||||
CREATE OR REPLACE SYNONYM cb_ords.hmm_rds_carrier_perf_v
|
||||
FOR admin.hmm_rds_carrier_perf_v;
|
||||
CREATE OR REPLACE SYNONYM cb_ords.hmm_rds_carrier_latest_v
|
||||
FOR admin.hmm_rds_carrier_latest_v;
|
||||
|
||||
PROMPT === 6. Recording policy notes ===
|
||||
MERGE INTO hmm_access_vpd_filter_notes dst
|
||||
USING (
|
||||
SELECT 'ADMIN' function_owner,
|
||||
'HMM_CARRIER_VPD_FILTER' function_name,
|
||||
'Filters carrier assignments by the authenticated employee role and employee hierarchy.' description
|
||||
FROM dual
|
||||
) src
|
||||
ON (dst.function_owner = src.function_owner AND dst.function_name = src.function_name)
|
||||
WHEN MATCHED THEN UPDATE SET
|
||||
dst.description = src.description,
|
||||
dst.updated_at = SYSTIMESTAMP
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
function_owner, function_name, description, updated_at
|
||||
) VALUES (
|
||||
src.function_owner, src.function_name, src.description, SYSTIMESTAMP
|
||||
);
|
||||
|
||||
MERGE INTO hmm_access_vpd_policy_notes dst
|
||||
USING (
|
||||
SELECT 'ADMIN' object_owner,
|
||||
'HMM_CARRIER_ASSIGNMENTS_V' object_name,
|
||||
'HMM_CARRIER_SCOPE_POLICY' policy_name,
|
||||
'Restricts carrier assignments to self, direct reports, or explicit HR administrator access.' description
|
||||
FROM dual
|
||||
) src
|
||||
ON (
|
||||
dst.object_owner = src.object_owner
|
||||
AND dst.object_name = src.object_name
|
||||
AND dst.policy_name = src.policy_name
|
||||
)
|
||||
WHEN MATCHED THEN UPDATE SET
|
||||
dst.description = src.description,
|
||||
dst.updated_at = SYSTIMESTAMP
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
object_owner, object_name, policy_name, description, updated_at
|
||||
) VALUES (
|
||||
src.object_owner, src.object_name, src.policy_name,
|
||||
src.description, SYSTIMESTAMP
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT === 7. Verification inventory ===
|
||||
SELECT object_name, policy_name, function, sel, enable, policy_type
|
||||
FROM all_policies
|
||||
WHERE object_owner = 'ADMIN'
|
||||
AND object_name = 'HMM_CARRIER_ASSIGNMENTS_V'
|
||||
AND policy_name = 'HMM_CARRIER_SCOPE_POLICY';
|
||||
|
||||
SELECT role.role_name,
|
||||
permission.target_name,
|
||||
rule.rule_column,
|
||||
rule.rule_type
|
||||
FROM hmm_access_permissions permission
|
||||
JOIN hmm_access_roles role ON role.role_id = permission.role_id
|
||||
JOIN hmm_access_permission_rules rule ON rule.perm_id = permission.perm_id
|
||||
WHERE permission.target_name = 'HMM_CARRIER_ASSIGNMENTS_V'
|
||||
ORDER BY role.role_name;
|
||||
|
||||
PROMPT === HMM carrier team VPD ready ===
|
||||
Reference in New Issue
Block a user