add unixuser prototype as preparation for testability of grants
This commit is contained in:
@ -629,19 +629,21 @@ create or replace function queryAllRbacUsersWithPermissionsFor(objectId uuid)
|
||||
language sql as $$
|
||||
select *
|
||||
from RbacUser
|
||||
where uuid in (with recursive grants as (select descendantUuid,
|
||||
ascendantUuid
|
||||
from RbacGrants
|
||||
where descendantUuid = objectId
|
||||
union all
|
||||
select "grant".descendantUuid,
|
||||
"grant".ascendantUuid
|
||||
from RbacGrants "grant"
|
||||
inner join grants recur on recur.ascendantUuid = "grant".descendantUuid)
|
||||
select ascendantUuid
|
||||
from grants);
|
||||
where uuid in (
|
||||
-- @formatter:off
|
||||
with recursive grants as (
|
||||
select descendantUuid, ascendantUuid
|
||||
from RbacGrants
|
||||
where descendantUuid = objectId
|
||||
union all
|
||||
select "grant".descendantUuid, "grant".ascendantUuid
|
||||
from RbacGrants "grant"
|
||||
inner join grants recur on recur.ascendantUuid = "grant".descendantUuid
|
||||
)
|
||||
-- @formatter:on
|
||||
select ascendantUuid
|
||||
from grants);
|
||||
$$;
|
||||
|
||||
--//
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ select *
|
||||
where isGranted(currentSubjectIds(), r.uuid)
|
||||
) as unordered
|
||||
-- @formatter:on
|
||||
order by objectIdName;
|
||||
order by objectTable || '#' || objectIdName || '.' || roleType;
|
||||
grant all privileges on rbacrole_rv to restricted;
|
||||
--//
|
||||
|
||||
@ -49,7 +49,7 @@ select userName, objectTable||'#'||objectIdName||'.'||roletype as roleIdName,
|
||||
where isGranted(currentSubjectIds(), r.uuid)
|
||||
) as unordered
|
||||
-- @formatter:on
|
||||
order by objectIdName;
|
||||
order by roleIdName;
|
||||
grant all privileges on rbacrole_rv to restricted;
|
||||
--//
|
||||
|
||||
|
@ -9,6 +9,6 @@ create table if not exists package
|
||||
uuid uuid unique references RbacObject (uuid),
|
||||
customerUuid uuid references customer (uuid),
|
||||
name varchar(5),
|
||||
description varchar(80)
|
||||
description varchar(96)
|
||||
);
|
||||
--//
|
||||
|
@ -0,0 +1,14 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-unixuser-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table if not exists UnixUser
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid),
|
||||
packageUuid uuid references package (uuid),
|
||||
name character varying(32),
|
||||
description character varying(96)
|
||||
);
|
||||
--//
|
@ -0,0 +1,211 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-package-rbac-CREATE-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates the related RbacObject through a BEFORE INSERT TRIGGER.
|
||||
*/
|
||||
drop trigger if exists createRbacObjectForUnixUser_Trigger on UnixUser;
|
||||
create trigger createRbacObjectForUnixUser_Trigger
|
||||
before insert
|
||||
on UnixUser
|
||||
for each row
|
||||
execute procedure createRbacObject();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-unixuser-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace function unixUserOwner(uu UnixUser)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return roleDescriptor('unixuser', uu.uuid, 'owner');
|
||||
end; $$;
|
||||
|
||||
create or replace function unixUserAdmin(uu UnixUser)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return roleDescriptor('unixuser', uu.uuid, 'admin');
|
||||
end; $$;
|
||||
|
||||
create or replace function unixUserTenant(uu UnixUser)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return roleDescriptor('unixuser', uu.uuid, 'tenant');
|
||||
end; $$;
|
||||
|
||||
create or replace function createUnixUserTenantRoleIfNotExists(unixUser UnixUser)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
unixUserTenantRoleDesc RbacRoleDescriptor;
|
||||
unixUserTenantRoleUuid uuid;
|
||||
begin
|
||||
unixUserTenantRoleDesc = unixUserTenant(unixUser);
|
||||
unixUserTenantRoleUuid = findRoleId(unixUserTenantRoleDesc);
|
||||
if unixUserTenantRoleUuid is not null then
|
||||
return unixUserTenantRoleUuid;
|
||||
end if;
|
||||
|
||||
return createRole(
|
||||
unixUserTenantRoleDesc,
|
||||
grantingPermissions(forObjectUuid => unixUser.uuid, permitOps => array ['view']),
|
||||
beneathRole(unixUserAdmin(unixUser))
|
||||
);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-unixuser-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates the roles and their assignments for a new UnixUser for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace function createRbacRulesForUnixUser()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
parentPackage package;
|
||||
unixuserOwnerRoleId uuid;
|
||||
unixuserAdminRoleId uuid;
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
select * from package where uuid = NEW.packageUuid into parentPackage;
|
||||
|
||||
-- an owner role is created and assigned to the package's admin group
|
||||
unixuserOwnerRoleId = createRole(
|
||||
unixUserOwner(NEW),
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']),
|
||||
beneathRole(packageAdmin(parentPackage))
|
||||
);
|
||||
|
||||
-- and a unixuser admin role is created and assigned to the unixuser owner as well
|
||||
unixuserAdminRoleId = createRole(
|
||||
unixUserAdmin(NEW),
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['edit']),
|
||||
beneathRole(unixuserOwnerRoleId),
|
||||
beingItselfA(packageTenant(parentPackage))
|
||||
);
|
||||
|
||||
-- a tenent role is only created on demand
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new UnixUser.
|
||||
*/
|
||||
drop trigger if exists createRbacRulesForUnixUser_Trigger on UnixUser;
|
||||
create trigger createRbacRulesForUnixUser_Trigger
|
||||
after insert
|
||||
on UnixUser
|
||||
for each row
|
||||
execute procedure createRbacRulesForUnixUser();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-unixuser-rbac-ROLES-REMOVAL:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Deletes the roles and their assignments of a deleted UnixUser for the BEFORE DELETE TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace function deleteRbacRulesForUnixUser()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP = 'DELETE' then
|
||||
call deleteRole(findRoleId(unixUserOwner(OLD)));
|
||||
call deleteRole(findRoleId(unixUserAdmin(OLD)));
|
||||
call deleteRole(findRoleId(unixUserTenant(OLD)));
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
|
||||
end if;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An BEFORE DELETE TRIGGER which deletes the role structure of a UnixUser.
|
||||
*/
|
||||
|
||||
drop trigger if exists deleteRbacRulesForUnixUser_Trigger on package;
|
||||
create trigger deleteRbacRulesForUnixUser_Trigger
|
||||
before delete
|
||||
on UnixUser
|
||||
for each row
|
||||
execute procedure deleteRbacRulesForUnixUser();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-unixuser-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a view to the UnixUser main table which maps the identifying name
|
||||
(in this case, actually the column `name`) to the objectUuid.
|
||||
*/
|
||||
drop view if exists UnixUser_iv;
|
||||
create or replace view UnixUser_iv as
|
||||
select distinct target.uuid, target.name as idName
|
||||
from UnixUser as target;
|
||||
-- TODO: Is it ok that everybody has access to this information?
|
||||
grant all privileges on UnixUser_iv to restricted;
|
||||
|
||||
/*
|
||||
Returns the objectUuid for a given identifying name (in this case, actually the column `name`).
|
||||
*/
|
||||
create or replace function unixUserUuidByIdName(idName varchar)
|
||||
returns uuid
|
||||
language sql
|
||||
strict as $$
|
||||
select uuid from UnixUser_iv iv where iv.idName = unixUserUuidByIdName.idName;
|
||||
$$;
|
||||
|
||||
/*
|
||||
Returns the identifying name for a given objectUuid (in this case the name).
|
||||
*/
|
||||
create or replace function unixUserIdNameByUuid(uuid uuid)
|
||||
returns varchar
|
||||
stable leakproof
|
||||
language sql
|
||||
strict as $$
|
||||
select idName from UnixUser_iv iv where iv.uuid = unixUserIdNameByUuid.uuid;
|
||||
$$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a view to the customer main table which maps the identifying name
|
||||
(in this case, the prefix) to the objectUuid.
|
||||
*/
|
||||
drop view if exists unixuser_rv;
|
||||
create or replace view unixuser_rv as
|
||||
select target.*
|
||||
from unixuser as target
|
||||
where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'unixuser', currentSubjectIds()));
|
||||
grant all privileges on unixuser_rv to restricted;
|
||||
--//
|
@ -0,0 +1,62 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-unixuser-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates test data for the package main table.
|
||||
*/
|
||||
create or replace procedure createUnixUserTestData(
|
||||
minCustomerReference integer, -- skip customers with reference below this
|
||||
unixUserPerPackage integer, -- create this many unix users for each package
|
||||
doCommitAfterEach boolean -- only for mass data creation outside of Liquibase
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
pac record;
|
||||
pacAdmin varchar;
|
||||
currentTask varchar;
|
||||
begin
|
||||
set hsadminng.currentUser to '';
|
||||
|
||||
for pac in
|
||||
(select p.uuid, p.name
|
||||
from package p
|
||||
join customer c on p.customeruuid = c.uuid
|
||||
where c.reference >= minCustomerReference)
|
||||
loop
|
||||
|
||||
for t in 0..(unixUserPerPackage-1)
|
||||
loop
|
||||
currentTask = 'creating RBAC test unixuser #' || t || ' for package ' || pac.name || ' #' || pac.uuid;
|
||||
raise notice 'task: %', currentTask;
|
||||
pacAdmin = 'admin@' || pac.name || '.example.com';
|
||||
set local hsadminng.currentUser to 'mike@hostsharing.net'; -- TODO: use a package-admin
|
||||
set local hsadminng.assumedRoles = '';
|
||||
set local hsadminng.currentTask to currentTask;
|
||||
|
||||
insert
|
||||
into unixuser (name, packageUuid)
|
||||
values (pac.name || '-' || intToVarChar(t, 4), pac.uuid);
|
||||
|
||||
if doCommitAfterEach then
|
||||
commit;
|
||||
end if;
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-unixuser-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createUnixUserTestData(0, 2, false);
|
||||
end;
|
||||
$$;
|
||||
--//
|
@ -1,159 +0,0 @@
|
||||
-- ========================================================
|
||||
-- UnixUser example with RBAC
|
||||
-- --------------------------------------------------------
|
||||
|
||||
set session session authorization default;
|
||||
|
||||
create table if not exists UnixUser
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid),
|
||||
name character varying(32),
|
||||
comment character varying(96),
|
||||
packageUuid uuid references package (uuid)
|
||||
);
|
||||
|
||||
create or replace function unixUserOwner(uu UnixUser)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return roleDescriptor('unixuser', uu.uuid, 'owner');
|
||||
end; $$;
|
||||
|
||||
create or replace function unixUserAdmin(uu UnixUser)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return roleDescriptor('unixuser', uu.uuid, 'admin');
|
||||
end; $$;
|
||||
|
||||
create or replace function unixUserTenant(uu UnixUser)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return roleDescriptor('unixuser', uu.uuid, 'tenant');
|
||||
end; $$;
|
||||
|
||||
create or replace function createUnixUserTenantRoleIfNotExists(unixUser UnixUser)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
unixUserTenantRoleDesc RbacRoleDescriptor;
|
||||
unixUserTenantRoleUuid uuid;
|
||||
begin
|
||||
unixUserTenantRoleDesc = unixUserTenant(unixUser);
|
||||
unixUserTenantRoleUuid = findRoleId(unixUserTenantRoleDesc);
|
||||
if unixUserTenantRoleUuid is not null then
|
||||
return unixUserTenantRoleUuid;
|
||||
end if;
|
||||
|
||||
return createRole(
|
||||
unixUserTenantRoleDesc,
|
||||
grantingPermissions(forObjectUuid => unixUser.uuid, permitOps => array ['view']),
|
||||
beneathRole(unixUserAdmin(unixUser))
|
||||
);
|
||||
end; $$;
|
||||
|
||||
|
||||
drop trigger if exists createRbacObjectForUnixUser_Trigger on UnixUser;
|
||||
create trigger createRbacObjectForUnixUser_Trigger
|
||||
before insert
|
||||
on UnixUser
|
||||
for each row
|
||||
execute procedure createRbacObject();
|
||||
|
||||
create or replace function createRbacRulesForUnixUser()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
parentPackage package;
|
||||
unixuserOwnerRoleId uuid;
|
||||
unixuserAdminRoleId uuid;
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
select * from package where uuid = NEW.packageUuid into parentPackage;
|
||||
|
||||
-- an owner role is created and assigned to the package's admin group
|
||||
unixuserOwnerRoleId = createRole(
|
||||
unixUserOwner(NEW),
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']),
|
||||
beneathRole(packageAdmin(parentPackage))
|
||||
);
|
||||
|
||||
-- and a unixuser admin role is created and assigned to the unixuser owner as well
|
||||
unixuserAdminRoleId = createRole(
|
||||
unixUserAdmin(NEW),
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['edit']),
|
||||
beneathRole(unixuserOwnerRoleId),
|
||||
beingItselfA(packageTenant(parentPackage))
|
||||
);
|
||||
|
||||
-- a tenent role is only created on demand
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
drop trigger if exists createRbacRulesForUnixUser_Trigger on UnixUser;
|
||||
create trigger createRbacRulesForUnixUser_Trigger
|
||||
after insert
|
||||
on UnixUser
|
||||
for each row
|
||||
execute procedure createRbacRulesForUnixUser();
|
||||
|
||||
-- TODO: CREATE OR REPLACE FUNCTION deleteRbacRulesForUnixUser()
|
||||
|
||||
|
||||
-- create RBAC-restricted view
|
||||
set session session authorization default;
|
||||
-- ALTER TABLE unixuser ENABLE ROW LEVEL SECURITY;
|
||||
drop view if exists unixuser_rv;
|
||||
create or replace view unixuser_rv as
|
||||
select target.*
|
||||
from unixuser as target
|
||||
where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'unixuser', currentSubjectIds()));
|
||||
grant all privileges on unixuser_rv to restricted;
|
||||
|
||||
|
||||
-- generate UnixUser test data
|
||||
|
||||
do language plpgsql $$
|
||||
declare
|
||||
pac record;
|
||||
pacAdmin varchar;
|
||||
currentTask varchar;
|
||||
begin
|
||||
set hsadminng.currentUser to '';
|
||||
|
||||
for pac in (select p.uuid, p.name
|
||||
from package p
|
||||
join customer c on p.customeruuid = c.uuid
|
||||
-- WHERE c.reference >= 18000
|
||||
)
|
||||
loop
|
||||
|
||||
for t in 0..9
|
||||
loop
|
||||
currentTask = 'creating RBAC test unixuser #' || t || ' for package ' || pac.name || ' #' || pac.uuid;
|
||||
raise notice 'task: %', currentTask;
|
||||
pacAdmin = 'admin@' || pac.name || '.example.com';
|
||||
set local hsadminng.currentUser to 'mike@hostsharing.net'; -- TODO: use a package-admin
|
||||
set local hsadminng.assumedRoles = '';
|
||||
set local hsadminng.currentTask to currentTask;
|
||||
|
||||
insert
|
||||
into unixuser (name, packageUuid)
|
||||
values (pac.name || '-' || intToVarChar(t, 4), pac.uuid);
|
||||
|
||||
commit;
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
end;
|
||||
$$;
|
@ -30,6 +30,12 @@ databaseChangeLog:
|
||||
- include:
|
||||
file: db/changelog/2022-07-29-070-hs-package-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/2022-07-29-070-hs-package-test-data.sql
|
||||
file: db/changelog/2022-07-29-070-hs-package-test-data.sql
|
||||
- include:
|
||||
file: db/changelog/2022-08-14-080-hs-unixuser.sql
|
||||
- include:
|
||||
file: db/changelog/2022-08-14-081-hs-unixuser-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/2022-08-14-082-hs-unixuser-test-data.sql
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user