153 lines
4.7 KiB
PL/PgSQL
153 lines
4.7 KiB
PL/PgSQL
|
|
-- ========================================================
|
|
-- 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 DISTINCT 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;
|
|
$$;
|