343 lines
14 KiB
SQL
343 lines
14 KiB
SQL
-- =============================================================================
|
|
-- Administration Rules Tests
|
|
-- =============================================================================
|
|
-- Tests the admin meta-policy system: who can manage policies, roles, and users.
|
|
--
|
|
-- is_admin_allowed(user_id, org_id, admin_activity, admin_target) is the main API.
|
|
-- Helper functions: can_manage_roles(), can_manage_policies(), can_manage_user_role().
|
|
--
|
|
-- Scenarios:
|
|
-- 1. Default deny: no admin rule = no admin access
|
|
-- 2. Grant admin permission to a role, verify the role holder can manage
|
|
-- 3. Admin prohibition blocks management even with permission
|
|
-- 4. Role hierarchy applies: senior role inherits admin permissions
|
|
-- 5. Admin helper functions
|
|
-- 6. can_manage_user_role() per-role management permission
|
|
-- 7. Admin rules are org-scoped
|
|
--
|
|
-- Company context:
|
|
-- Grace (hr_manager) can manage users (assign_role) for employee-level roles
|
|
-- Carol (manager) can create rules
|
|
-- Alice (CEO) inherits Carol's admin perms via hierarchy
|
|
--
|
|
-- Prerequisites: 00_setup.sql -> 07_audit.sql
|
|
-- =============================================================================
|
|
|
|
\echo ''
|
|
\echo '================================================================'
|
|
\echo '08 — ADMINISTRATION RULES'
|
|
\echo '================================================================'
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Section 1: Default deny — no admin rule means no admin access
|
|
-- ---------------------------------------------------------------------------
|
|
\echo ''
|
|
\echo '--- 1. Default deny: no admin rule ---'
|
|
|
|
-- Nobody has admin rules yet — all should be denied
|
|
SELECT morbac.t('Alice (CEO, no admin rule yet) creates rules [default deny]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000001'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'create_rule', 'rules'
|
|
), FALSE);
|
|
|
|
SELECT morbac.t('Grace (hr_manager, no admin rule) assigns roles [default deny]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000007'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'assign_role', 'employee'
|
|
), FALSE);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Section 2: Grant admin permissions
|
|
-- ---------------------------------------------------------------------------
|
|
\echo ''
|
|
\echo '--- 2. Grant admin permissions ---'
|
|
|
|
-- Grant manager role: can create and delete rules
|
|
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality)
|
|
VALUES
|
|
('10000000-0000-0000-0000-000000000001',
|
|
'20000000-0001-0000-0000-000000000003', -- manager
|
|
'create_rule', 'rules',
|
|
(SELECT id FROM morbac.contexts WHERE name = 'always'),
|
|
'permission'),
|
|
('10000000-0000-0000-0000-000000000001',
|
|
'20000000-0001-0000-0000-000000000003', -- manager
|
|
'delete_rule', 'rules',
|
|
(SELECT id FROM morbac.contexts WHERE name = 'always'),
|
|
'permission');
|
|
|
|
-- Grant hr_manager role: can assign employee and intern roles
|
|
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality)
|
|
VALUES
|
|
('10000000-0000-0000-0000-000000000001',
|
|
'20000000-0001-0000-0000-000000000008', -- hr_manager
|
|
'assign_role', 'employee',
|
|
(SELECT id FROM morbac.contexts WHERE name = 'always'),
|
|
'permission'),
|
|
('10000000-0000-0000-0000-000000000001',
|
|
'20000000-0001-0000-0000-000000000008', -- hr_manager
|
|
'assign_role', 'intern',
|
|
(SELECT id FROM morbac.contexts WHERE name = 'always'),
|
|
'permission');
|
|
|
|
-- Grant director role: can manage roles and policies
|
|
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality)
|
|
VALUES
|
|
('10000000-0000-0000-0000-000000000001',
|
|
'20000000-0001-0000-0000-000000000002', -- director
|
|
'manage', 'roles',
|
|
(SELECT id FROM morbac.contexts WHERE name = 'always'),
|
|
'permission'),
|
|
('10000000-0000-0000-0000-000000000001',
|
|
'20000000-0001-0000-0000-000000000002', -- director
|
|
'manage', 'policies',
|
|
(SELECT id FROM morbac.contexts WHERE name = 'always'),
|
|
'permission');
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Section 3: Verify admin permissions
|
|
-- ---------------------------------------------------------------------------
|
|
\echo ''
|
|
\echo '--- 3. Verify admin permissions ---'
|
|
|
|
-- Carol (manager) can create rules
|
|
SELECT morbac.t('Carol (manager) creates rules',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000003'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'create_rule', 'rules'
|
|
), TRUE);
|
|
|
|
-- Carol (manager) can delete rules
|
|
SELECT morbac.t('Carol (manager) deletes rules',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000003'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'delete_rule', 'rules'
|
|
), TRUE);
|
|
|
|
-- Grace (hr_manager) can assign employee role
|
|
SELECT morbac.t('Grace (hr_manager) assigns employee role',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000007'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'assign_role', 'employee'
|
|
), TRUE);
|
|
|
|
-- Grace (hr_manager) can assign intern role
|
|
SELECT morbac.t('Grace (hr_manager) assigns intern role',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000007'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'assign_role', 'intern'
|
|
), TRUE);
|
|
|
|
-- Grace (hr_manager) cannot assign manager role (no rule for that)
|
|
SELECT morbac.t('Grace (hr_manager) assigns manager role [no admin rule for manager]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000007'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'assign_role', 'manager'
|
|
), FALSE);
|
|
|
|
-- Dave (employee) has no admin permissions
|
|
SELECT morbac.t('Dave (employee) creates rules [no admin rule for employee]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000004'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'create_rule', 'rules'
|
|
), FALSE);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Section 4: Role hierarchy applies to admin permissions
|
|
-- ---------------------------------------------------------------------------
|
|
\echo ''
|
|
\echo '--- 4. Role hierarchy applies to admin permissions ---'
|
|
|
|
-- Bob (director) has own admin perm (manage roles/policies) and
|
|
-- inherits manager's admin perms (create_rule, delete_rule) via director->manager hierarchy
|
|
|
|
-- Bob (director) creates rules — inherited from manager via director->manager hierarchy
|
|
SELECT morbac.t('Bob (director, inherits manager admin) creates rules',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000002'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'create_rule', 'rules'
|
|
), TRUE);
|
|
|
|
-- Bob (director) manages roles — own admin perm
|
|
SELECT morbac.t('Bob (director) manages roles [own admin perm]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000002'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'manage', 'roles'
|
|
), TRUE);
|
|
|
|
-- Alice (CEO) inherits everything through CEO->director->manager chain
|
|
SELECT morbac.t('Alice (CEO, inherits director+manager) manages roles',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000001'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'manage', 'roles'
|
|
), TRUE);
|
|
|
|
SELECT morbac.t('Alice (CEO) manages policies',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000001'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'manage', 'policies'
|
|
), TRUE);
|
|
|
|
-- Eve (intern) inherits nothing useful for admin
|
|
SELECT morbac.t('Eve (intern) creates rules [no admin permission in hierarchy]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000005'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'create_rule', 'rules'
|
|
), FALSE);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Section 5: Admin prohibition overrides permission
|
|
-- ---------------------------------------------------------------------------
|
|
\echo ''
|
|
\echo '--- 5. Admin prohibition overrides permission ---'
|
|
|
|
-- Carol (manager) currently can create rules. Add a prohibition.
|
|
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality)
|
|
VALUES (
|
|
'10000000-0000-0000-0000-000000000001',
|
|
'20000000-0001-0000-0000-000000000003', -- manager
|
|
'create_rule', 'rules',
|
|
(SELECT id FROM morbac.contexts WHERE name = 'always'),
|
|
'prohibition'
|
|
);
|
|
|
|
-- Prohibition overrides permission
|
|
SELECT morbac.t('Carol (manager, now prohibited) creates rules [prohibition wins]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000003'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'create_rule', 'rules'
|
|
), FALSE);
|
|
|
|
-- Carol can still delete rules (prohibition only applied to create_rule)
|
|
SELECT morbac.t('Carol (manager, prohibition only on create) deletes rules [still allowed]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000003'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'delete_rule', 'rules'
|
|
), TRUE);
|
|
|
|
-- Remove the prohibition for subsequent tests
|
|
DELETE FROM morbac.admin_rules
|
|
WHERE org_id = '10000000-0000-0000-0000-000000000001'
|
|
AND role_id = '20000000-0001-0000-0000-000000000003'
|
|
AND admin_activity = 'create_rule' AND admin_target = 'rules'
|
|
AND modality = 'prohibition';
|
|
|
|
-- Carol can again create rules after prohibition removed
|
|
SELECT morbac.t('Carol (manager) creates rules after prohibition removed',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000003'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'create_rule', 'rules'
|
|
), TRUE);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Section 6: Admin helper functions
|
|
-- ---------------------------------------------------------------------------
|
|
\echo ''
|
|
\echo '--- 6. Admin helper functions ---'
|
|
|
|
-- can_manage_roles: wraps is_admin_allowed('manage', 'roles')
|
|
SELECT morbac.t('Bob (director) can_manage_roles',
|
|
morbac.can_manage_roles(
|
|
'30000000-0000-0000-0000-000000000002'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid
|
|
), TRUE);
|
|
|
|
SELECT morbac.t('Dave (employee) can_manage_roles [denied]',
|
|
morbac.can_manage_roles(
|
|
'30000000-0000-0000-0000-000000000004'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid
|
|
), FALSE);
|
|
|
|
-- can_manage_policies: wraps is_admin_allowed('manage', 'policies')
|
|
SELECT morbac.t('Bob (director) can_manage_policies',
|
|
morbac.can_manage_policies(
|
|
'30000000-0000-0000-0000-000000000002'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid
|
|
), TRUE);
|
|
|
|
SELECT morbac.t('Carol (manager) can_manage_policies [no manage policies rule for manager]',
|
|
morbac.can_manage_policies(
|
|
'30000000-0000-0000-0000-000000000003'::uuid,
|
|
'10000000-0000-0000-0000-000000000001'::uuid
|
|
), FALSE);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Section 7: can_manage_user_role — per-role management check
|
|
-- ---------------------------------------------------------------------------
|
|
\echo ''
|
|
\echo '--- 7. can_manage_user_role ---'
|
|
|
|
-- Grace (hr_manager) has assign_role perm for 'employee'
|
|
-- can_manage_user_role checks is_admin_allowed('assign_role', role_name)
|
|
|
|
SELECT morbac.t('Grace (hr_manager) can manage employee role assignments',
|
|
morbac.can_manage_user_role(
|
|
'30000000-0000-0000-0000-000000000007'::uuid, -- Grace
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'20000000-0001-0000-0000-000000000004'::uuid -- employee role
|
|
), TRUE);
|
|
|
|
SELECT morbac.t('Grace (hr_manager) can manage intern role assignments',
|
|
morbac.can_manage_user_role(
|
|
'30000000-0000-0000-0000-000000000007'::uuid, -- Grace
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'20000000-0001-0000-0000-000000000005'::uuid -- intern role
|
|
), TRUE);
|
|
|
|
SELECT morbac.t('Grace (hr_manager) cannot manage manager role assignments [no rule]',
|
|
morbac.can_manage_user_role(
|
|
'30000000-0000-0000-0000-000000000007'::uuid, -- Grace
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'20000000-0001-0000-0000-000000000003'::uuid -- manager role
|
|
), FALSE);
|
|
|
|
SELECT morbac.t('Dave (employee) cannot manage any role assignments',
|
|
morbac.can_manage_user_role(
|
|
'30000000-0000-0000-0000-000000000004'::uuid, -- Dave
|
|
'10000000-0000-0000-0000-000000000001'::uuid,
|
|
'20000000-0001-0000-0000-000000000005'::uuid -- intern role
|
|
), FALSE);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Section 8: Admin rules are org-scoped
|
|
-- ---------------------------------------------------------------------------
|
|
\echo ''
|
|
\echo '--- 8. Admin rules are org-scoped ---'
|
|
|
|
-- Carol (manager at GlobalTech) cannot manage Engineering rules
|
|
-- (her admin rule is for GlobalTech org only)
|
|
SELECT morbac.t('Carol (GlobalTech manager) creates Engineering rules [wrong org]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000003'::uuid,
|
|
'10000000-0000-0000-0000-000000000002'::uuid, -- Engineering org
|
|
'create_rule', 'rules'
|
|
), FALSE);
|
|
|
|
-- Alice (CEO at GlobalTech) cannot manage Engineering rules via admin (same org scoping)
|
|
SELECT morbac.t('Alice (GlobalTech CEO) creates Engineering rules [org-scoped]',
|
|
morbac.is_admin_allowed(
|
|
'30000000-0000-0000-0000-000000000001'::uuid,
|
|
'10000000-0000-0000-0000-000000000002'::uuid, -- Engineering org
|
|
'manage', 'roles'
|
|
), FALSE);
|
|
|
|
\echo ''
|
|
\echo '=== Administration Rules Tests Completed ==='
|