Michael Hoennig
2022-08-30 8045b663245c89a41241565c3a4cb7fd82c2974a
rename currentUserId->currentUserUuid + currentSubjectIds->currentSubjectsUuids
11 files modified
70 ■■■■ changed files
doc/adr/2022-07-18.row-level-security-mechanism.md 6 ●●●● patch | view | raw | blame | history
doc/rbac.md 4 ●●●● patch | view | raw | blame | history
sql/24-hs-domain.sql 2 ●●● patch | view | raw | blame | history
sql/25-hs-emailaddress.sql 2 ●●● patch | view | raw | blame | history
sql/rbac-view-option-experiments.sql 8 ●●●● patch | view | raw | blame | history
src/main/resources/db/changelog/051-rbac-user-grant.sql 10 ●●●● patch | view | raw | blame | history
src/main/resources/db/changelog/054-rbac-context.sql 24 ●●●● patch | view | raw | blame | history
src/main/resources/db/changelog/100-hs-base.sql 8 ●●●● patch | view | raw | blame | history
src/main/resources/db/changelog/113-hs-customer-rbac.sql 2 ●●● patch | view | raw | blame | history
src/main/resources/db/changelog/123-hs-package-rbac.sql 2 ●●● patch | view | raw | blame | history
src/main/resources/db/changelog/133-hs-unixuser-rbac.sql 2 ●●● patch | view | raw | blame | history
doc/adr/2022-07-18.row-level-security-mechanism.md
@@ -74,7 +74,7 @@
        FOR SELECT
        TO restricted
        USING (
            isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserId())
            isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserUuid())
        );
    
    SET SESSION AUTHORIZATION restricted;
@@ -101,7 +101,7 @@
    CREATE OR REPLACE RULE "_RETURN" AS
        ON SELECT TO cust_view
        DO INSTEAD
            SELECT * FROM customer WHERE isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserId());
            SELECT * FROM customer WHERE isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserUuid());
    SET SESSION AUTHORIZATION restricted;
    SET hsadminng.currentUser TO 'alex@example.com';
@@ -130,7 +130,7 @@
    CREATE OR REPLACE VIEW cust_view AS
        SELECT c.id, c.reference, c.prefix
          FROM customer AS c
          JOIN queryAllPermissionsOfSubjectId(currentUserId()) AS p
          JOIN queryAllPermissionsOfSubjectId(currentUserUuid()) AS p
               ON p.tableName='customer' AND p.rowId=c.id AND p.op='view';
    GRANT ALL PRIVILEGES ON cust_view TO restricted;
    
doc/rbac.md
@@ -591,7 +591,7 @@
         WHERE target.uuid IN (
            SELECT uuid
              FROM queryAccessibleObjectUuidsOfSubjectIds( 
                'view', 'customer', currentSubjectIds()));
                'view', 'customer', currentSubjectsUuids()));
This view should be automatically updatable.
Where, for updates, we actually have to check for 'edit' instead of 'view' operation, which makes it a bit more complicated.
@@ -609,7 +609,7 @@
        SELECT DISTINCT target.*
          FROM customer AS target
          JOIN queryAccessibleObjectUuidsOfSubjectIds( 
                'view', 'customer', currentSubjectIds()) AS allowedObjId
                'view', 'customer', currentSubjectsUuids()) AS allowedObjId
            ON target.uuid = allowedObjId;
This view cannot is not updatable automatically,
sql/24-hs-domain.sql
@@ -102,7 +102,7 @@
create or replace view domain_rv as
select target.*
    from Domain as target
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'domain', currentSubjectIds()));
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'domain', currentSubjectsUuids()));
grant all privileges on domain_rv to restricted;
sql/25-hs-emailaddress.sql
@@ -87,7 +87,7 @@
create or replace view EMailAddress_rv as
select target.*
    from EMailAddress as target
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'emailaddress', currentSubjectIds()));
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'emailaddress', currentSubjectsUuids()));
grant all privileges on EMailAddress_rv to restricted;
-- generate EMailAddress test data
sql/rbac-view-option-experiments.sql
@@ -20,7 +20,7 @@
    TO restricted
    USING (
        -- id=1000
        isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserId())
        isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserUuid())
    );
SET SESSION AUTHORIZATION restricted;
@@ -35,7 +35,7 @@
CREATE OR REPLACE RULE "_RETURN" AS
    ON SELECT TO cust_view
    DO INSTEAD
    SELECT * FROM customer WHERE isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserId());
    SELECT * FROM customer WHERE isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserUuid());
SELECT * from cust_view LIMIT 10;
select queryAllPermissionsOfSubjectId(findRbacUser('mike@hostsharing.net'));
@@ -51,7 +51,7 @@
    ON SELECT TO cust_view
    DO INSTEAD
    SELECT c.uuid, c.reference, c.prefix FROM customer AS c
      JOIN queryAllPermissionsOfSubjectId(currentUserId()) AS p
      JOIN queryAllPermissionsOfSubjectId(currentUserUuid()) AS p
           ON p.objectTable='customer' AND p.objectUuid=c.uuid AND p.op in ('*', 'view');
GRANT ALL PRIVILEGES ON cust_view TO restricted;
@@ -67,7 +67,7 @@
CREATE OR REPLACE VIEW cust_view AS
    SELECT c.uuid, c.reference, c.prefix
      FROM customer AS c
      JOIN queryAllPermissionsOfSubjectId(currentUserId()) AS p
      JOIN queryAllPermissionsOfSubjectId(currentUserUuid()) AS p
           ON p.objectUuid=c.uuid AND p.op in ('*', 'view');
GRANT ALL PRIVILEGES ON cust_view TO restricted;
src/main/resources/db/changelog/051-rbac-user-grant.sql
@@ -16,7 +16,7 @@
        raise exception '[400] Granting roles to user is only possible if exactly one role is assumed, given: %', assumedRoles();
    end if;
    currentSubjectUuids := currentSubjectIds();
    currentSubjectUuids := currentSubjectsUuids();
    return currentSubjectUuids[1];
end; $$;
@@ -42,7 +42,7 @@
    perform assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
    perform assertReferenceType('userUuid (ascendant)', userUuid, 'RbacUser');
    if NOT isGranted(currentSubjectIds(), grantedByRoleUuid) then
    if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
        raise exception '[403] Access to granted-by-role % forbidden for %', grantedByRoleUuid, currentSubjects();
    end if;
@@ -71,7 +71,7 @@
    perform assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
    perform assertReferenceType('userUuid (ascendant)', userUuid, 'RbacUser');
    if NOT isGranted(currentSubjectIds(), grantedByRoleUuid) then
    if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
        raise exception '[403] Revoking role created by % is forbidden for %.', grantedByRoleUuid, currentSubjects();
    end if;
@@ -79,8 +79,8 @@
        raise exception '[403] Revoking role % is forbidden for %.', grantedRoleUuid, currentSubjects();
    end if;
    --raise exception 'isGranted(%, %)', currentSubjectIds(), grantedByRoleUuid;
    if NOT isGranted(currentSubjectIds(), grantedByRoleUuid) then
    --raise exception 'isGranted(%, %)', currentSubjectsUuids(), grantedByRoleUuid;
    if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
        raise exception '[403] Revoking role granted by % is forbidden for %.', grantedByRoleUuid, currentSubjects();
    end if;
src/main/resources/db/changelog/054-rbac-context.sql
@@ -8,20 +8,20 @@
    Raises exception if not set.
 */
create or replace function currentUserId()
create or replace function currentUserUuid()
    returns uuid
    stable leakproof
    language plpgsql as $$
declare
    currentUser   varchar(63);
    currentUserId uuid;
    currentUserUuid uuid;
begin
    currentUser := currentUser();
    currentUserId = (select uuid from RbacUser where name = currentUser);
    if currentUserId is null then
    currentUserUuid = (select uuid from RbacUser where name = currentUser);
    if currentUserUuid is null then
        raise exception '[401] hsadminng.currentUser defined as %, but does not exists', currentUser;
    end if;
    return currentUserId;
    return currentUserUuid;
end; $$;
--//
@@ -33,12 +33,12 @@
    or, if any, ids of assumed role names as set in `hsadminng.assumedRoles`
    or empty array, if not set.
 */
create or replace function currentSubjectIds()
create or replace function currentSubjectsUuids()
    returns uuid[]
    stable leakproof
    language plpgsql as $$
declare
    currentUserId       uuid;
    currentUserUuid       uuid;
    roleNames           varchar(63)[];
    roleName            varchar(63);
    objectTableToAssume varchar(63);
@@ -48,14 +48,14 @@
    roleIdsToAssume     uuid[];
    roleUuidToAssume    uuid;
begin
    currentUserId := currentUserId();
    if currentUserId is null then
    currentUserUuid := currentUserUuid();
    if currentUserUuid is null then
        raise exception '[401] user % does not exist', currentUser();
    end if;
    roleNames := assumedRoles();
    if cardinality(roleNames) = 0 then
        return array [currentUserId];
        return array [currentUserUuid];
    end if;
    raise notice 'assuming roles: %', roleNames;
@@ -75,8 +75,8 @@
                where r.objectUuid = objectUuidToAssume
                  and r.roleType = roleTypeToAssume
                into roleUuidToAssume;
            if (not isGranted(currentUserId, roleUuidToAssume)) then
                raise exception '[403] user % (%) has no permission to assume role % (%)', currentUser(), currentUserId, roleName, roleUuidToAssume;
            if (not isGranted(currentUserUuid, roleUuidToAssume)) then
                raise exception '[403] user % (%) has no permission to assume role % (%)', currentUser(), currentUserUuid, roleName, roleUuidToAssume;
            end if;
            roleIdsToAssume := roleIdsToAssume || roleUuidToAssume;
        end loop;
src/main/resources/db/changelog/100-hs-base.sql
@@ -41,7 +41,7 @@
    -- TODO: this could to be optimized
select (select uuid from global) in
       (select queryAccessibleObjectUuidsOfSubjectIds(
                   op, 'global', currentSubjectIds()));
                   op, 'global', currentSubjectsUuids()));
$$;
--//
@@ -124,7 +124,7 @@
-- ----------------------------------------------------------------------------
/*
    Tests if currentUserId() can fetch the user from the session variable.
    Tests if currentUserUuid() can fetch the user from the session variable.
 */
do language plpgsql $$
@@ -132,13 +132,13 @@
        userName varchar;
    begin
        set local hsadminng.currentUser = 'sven@hostsharing.net';
        select userName from RbacUser where uuid = currentUserId() into userName;
        select userName from RbacUser where uuid = currentUserUuid() into userName;
        if userName <> 'sven@hostsharing.net' then
            raise exception 'setting or fetching initial currentUser failed, got: %', userName;
        end if;
        set local hsadminng.currentUser = 'mike@hostsharing.net';
        select userName from RbacUser where uuid = currentUserId() into userName;
        select userName from RbacUser where uuid = currentUserUuid() into userName;
        if userName = 'mike@hostsharing.net' then
            raise exception 'currentUser should not change in one transaction, but did change, got: %', userName;
        end if;
src/main/resources/db/changelog/113-hs-customer-rbac.sql
@@ -189,7 +189,7 @@
create or replace view customer_rv as
select target.*
    from customer as target
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'customer', currentSubjectIds()));
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'customer', currentSubjectsUuids()));
grant all privileges on customer_rv to restricted;
--//
src/main/resources/db/changelog/123-hs-package-rbac.sql
@@ -188,7 +188,7 @@
create or replace view package_rv as
select target.*
    from package as target
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'package', currentSubjectIds()))
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'package', currentSubjectsUuids()))
    order by target.name;
grant all privileges on package_rv to restricted;
--//
src/main/resources/db/changelog/133-hs-unixuser-rbac.sql
@@ -206,6 +206,6 @@
create or replace view unixuser_rv as
select target.*
    from unixuser as target
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'unixuser', currentSubjectIds()));
    where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'unixuser', currentSubjectsUuids()));
grant all privileges on unixuser_rv to restricted;
--//