add RbacRole...

This commit is contained in:
Michael Hoennig 2022-08-03 06:12:16 +02:00
parent bb05eb4ac4
commit ece36209a5
8 changed files with 222 additions and 7 deletions

View File

@ -0,0 +1,34 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
import net.hostsharing.hsadminng.context.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import javax.transaction.Transactional;
@RestController
public class RbacRoleController {
@Autowired
private Context context;
@Autowired
private RbacRoleRepository rbacRoleRepository;
@GetMapping(value = "/api/rbacroles")
@Transactional
public Iterable<RbacRoleEntity> listCustomers(
@RequestHeader(value = "current-user") String userName,
@RequestHeader(value = "assumed-roles", required = false) String assumedRoles
) {
context.setCurrentUser(userName);
if (assumedRoles != null && !assumedRoles.isBlank()) {
context.assumeRoles(assumedRoles);
}
return rbacRoleRepository.findAll();
}
}

View File

@ -0,0 +1,36 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Immutable;
import javax.persistence.*;
import java.util.UUID;
@Entity
@Table(name = "rbacrole_rv")
@Getter
@Setter
@Immutable
@NoArgsConstructor
@AllArgsConstructor
public class RbacRoleEntity {
@Id
private UUID uuid;
@Column(name="objectuuid")
private UUID objectUuid;
@Column(name="roletype")
@Enumerated(EnumType.STRING)
private RbacRoleType roleType;
@Column(name="objecttable")
private String objectTable;
@Column(name="objectidname")
private String objectIdName;
}

View File

@ -0,0 +1,58 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public interface RbacRoleRepository extends Repository<RbacRoleEntity, UUID> {
/**
* Retrieves an entity by its id.
*
* @param id must not be {@literal null}.
* @return the entity with the given id or {@literal Optional#empty()} if none found.
* @throws IllegalArgumentException if {@literal id} is {@literal null}.
*/
Optional<RbacRoleEntity> findByUuid(UUID id);
/**
* Returns whether an entity with the given id exists.
*
* @param id must not be {@literal null}.
* @return {@literal true} if an entity with the given id exists, {@literal false} otherwise.
* @throws IllegalArgumentException if {@literal id} is {@literal null}.
*/
boolean existsByUuid(RbacRoleEntity id);
/**
* Returns all instances of the type.
*
* @return all entities
*/
Iterable<RbacRoleEntity> findAll();
/**
* Returns all entities sorted by the given options.
*
* @param sort the {@link Sort} specification to sort the results by, can be {@link Sort#unsorted()}, must not be
* {@literal null}.
* @return all entities sorted by the given options
*/
List<RbacRoleEntity> findAll(Sort sort);
/**
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@link Pageable} object.
*
* @param pageable the pageable to request a paged result, can be {@link Pageable#unpaged()}, must not be
* {@literal null}.
* @return a page of entities
*/
Page<RbacRoleEntity> findAll(Pageable pageable);
}

View File

@ -0,0 +1,5 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
public enum RbacRoleType {
owner, admin, tenant
}

View File

@ -151,13 +151,11 @@ create type RbacRoleDescriptor as
create or replace function roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType) create or replace function roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType)
returns RbacRoleDescriptor returns RbacRoleDescriptor
returns null on null input returns null on null input
-- STABLE LEAKPROOF stable leakproof
language sql as $$ language sql as $$
select objectTable, objectUuid, roleType::RbacRoleType; select objectTable, objectUuid, roleType::RbacRoleType;
$$; $$;
create or replace function createRole(roleDescriptor RbacRoleDescriptor) create or replace function createRole(roleDescriptor RbacRoleDescriptor)
returns uuid returns uuid
returns null on null input returns null on null input
@ -347,6 +345,22 @@ select granteeId = grantedId or granteeId in (with recursive grants as (select d
from grants); from grants);
$$; $$;
create or replace function isGranted(granteeIds uuid[], grantedId uuid)
returns bool
returns null on null input
language plpgsql as $$
declare
granteeId uuid;
begin
-- TODO: needs optimization
foreach granteeId in array granteeIds loop
if isGranted(granteeId, grantedId) then
return true;
end if;
end loop;
return false;
end; $$;
create or replace function isPermissionGrantedToSubject(permissionId uuid, subjectId uuid) create or replace function isPermissionGrantedToSubject(permissionId uuid, subjectId uuid)
returns BOOL returns BOOL
stable leakproof stable leakproof
@ -607,6 +621,7 @@ begin
return regexp_replace(rawIdentifier, '\W+', ''); return regexp_replace(rawIdentifier, '\W+', '');
end; $$; end; $$;
-- TODO: rename to findObjectUuidByIdName
create or replace function findUuidByIdName(objectTable varchar, objectIdName varchar) create or replace function findUuidByIdName(objectTable varchar, objectIdName varchar)
returns uuid returns uuid
returns null on null input returns null on null input
@ -628,18 +643,38 @@ begin
return uuid; return uuid;
end ; $$; end ; $$;
create or replace function findIdNameByObjectUuid(objectTable varchar, objectUuid uuid)
returns varchar
returns null on null input
language plpgsql as $$
declare
sql varchar;
idName varchar;
begin
objectTable := pureIdentifier(objectTable);
sql := format('select * from %sIdNameByUuid(%L::uuid);', objectTable, objectUuid);
begin
raise notice 'sql: %', sql;
execute sql into idName;
exception
when others then
raise exception 'function %IdNameByUuid(...) not found, add identity view support for table %', objectTable, objectTable;
end;
return idName;
end ; $$;
create or replace function currentSubjects() create or replace function currentSubjects()
returns varchar(63)[] returns varchar(63)[]
stable leakproof stable leakproof
language plpgsql as $$ language plpgsql as $$
declare declare
assumedRoles varchar(63)[]; assumedRoles varchar(63)[];
begin begin
assumedRoles := assumedRoles(); assumedRoles := assumedRoles();
if array_length(assumedRoles(), 1) > 0 then if array_length(assumedRoles(), 1) > 0 then
return assumedRoles(); return assumedRoles();
else else
return array[currentUser()]::varchar(63)[]; return array [currentUser()]::varchar(63)[];
end if; end if;
end; $$; end; $$;
@ -708,3 +743,20 @@ grant all privileges on all tables in schema public to restricted;
--// --//
-- ============================================================================
--changeset rbac-base-ROLE-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a view to the role table with row-level limitation
based on the grants of the current user or assumed roles.
*/
drop view if exists rbacrole_rv;
create or replace view rbacrole_rv as
select r.*, o.objectTable,
findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
from rbacrole as r
join rbacobject as o on o.uuid=r.objectuuid
where isGranted(currentSubjectIds(), r.uuid);
grant all privileges on rbacrole_rv to restricted;
--//

View File

@ -58,7 +58,7 @@ select target.uuid, target.name as idName
grant all privileges on global_iv to restricted; grant all privileges on global_iv to restricted;
/* /*
Returns the objectUuid for a given identifying name (in this case the prefix). Returns the objectUuid for a given identifying name (in this case the idName).
*/ */
create or replace function globalUuidByIdName(idName varchar) create or replace function globalUuidByIdName(idName varchar)
returns uuid returns uuid
@ -66,6 +66,16 @@ create or replace function globalUuidByIdName(idName varchar)
strict as $$ strict as $$
select uuid from global_iv iv where iv.idName = globalUuidByIdName.idName; select uuid from global_iv iv where iv.idName = globalUuidByIdName.idName;
$$; $$;
/*
Returns the identifying name for a given objectUuid (in this case the idName).
*/
create or replace function globalIdNameByUuid(uuid uuid)
returns varchar
language sql
strict as $$
select idName from global_iv iv where iv.uuid = globalIdNameByUuid.uuid;
$$;
--// --//
-- ============================================================================ -- ============================================================================

View File

@ -163,6 +163,16 @@ create or replace function customerUuidByIdName(idName varchar)
strict as $$ strict as $$
select uuid from customer_iv iv where iv.idName = customerUuidByIdName.idName; select uuid from customer_iv iv where iv.idName = customerUuidByIdName.idName;
$$; $$;
/*
Returns the identifying name for a given objectUuid (in this case the prefix).
*/
create or replace function customerIdNameByUuid(uuid uuid)
returns varchar
language sql
strict as $$
select idName from customer_iv iv where iv.uuid = customerIdNameByUuid.uuid;
$$;
--// --//
@ -170,7 +180,7 @@ $$;
--changeset hs-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
/* /*
Creates a view to the customer main table with row-level limitatation Creates a view to the customer main table with row-level limitation
based on the 'view' permission of the current user or assumed roles. based on the 'view' permission of the current user or assumed roles.
*/ */
set session session authorization default; set session session authorization default;

View File

@ -162,6 +162,16 @@ create or replace function packageUuidByIdName(idName varchar)
strict as $$ strict as $$
select uuid from package_iv iv where iv.idName = packageUuidByIdName.idName; select uuid from package_iv iv where iv.idName = packageUuidByIdName.idName;
$$; $$;
/*
Returns the identifying name for a given objectUuid (in this case the name).
*/
create or replace function packageIdNameByUuid(uuid uuid)
returns varchar
language sql
strict as $$
select idName from package_iv iv where iv.uuid = packageIdNameByUuid.uuid;
$$;
--// --//