diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java
new file mode 100644
index 00000000..7a0c3864
--- /dev/null
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java
@@ -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();
+    }
+
+}
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java
new file mode 100644
index 00000000..0b343d8c
--- /dev/null
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java
@@ -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;
+}
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepository.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepository.java
new file mode 100644
index 00000000..1df718fb
--- /dev/null
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepository.java
@@ -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);
+
+}
+
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleType.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleType.java
new file mode 100644
index 00000000..51d58bc6
--- /dev/null
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleType.java
@@ -0,0 +1,5 @@
+package net.hostsharing.hsadminng.rbac.rbacrole;
+
+public enum RbacRoleType {
+    owner, admin, tenant
+}
diff --git a/src/main/resources/db/changelog/2022-07-28-005-rbac-base.sql b/src/main/resources/db/changelog/2022-07-28-005-rbac-base.sql
index 2929adec..3666b4b6 100644
--- a/src/main/resources/db/changelog/2022-07-28-005-rbac-base.sql
+++ b/src/main/resources/db/changelog/2022-07-28-005-rbac-base.sql
@@ -151,13 +151,11 @@ create type RbacRoleDescriptor as
 create or replace function roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType)
     returns RbacRoleDescriptor
     returns null on null input
-    -- STABLE LEAKPROOF
+    stable leakproof
     language sql as $$
 select objectTable, objectUuid, roleType::RbacRoleType;
 $$;
 
-
-
 create or replace function createRole(roleDescriptor RbacRoleDescriptor)
     returns uuid
     returns null on null input
@@ -347,6 +345,22 @@ select granteeId = grantedId or granteeId in (with recursive grants as (select d
                                                   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)
     returns BOOL
     stable leakproof
@@ -607,6 +621,7 @@ begin
     return regexp_replace(rawIdentifier, '\W+', '');
 end; $$;
 
+-- TODO: rename to findObjectUuidByIdName
 create or replace function findUuidByIdName(objectTable varchar, objectIdName varchar)
     returns uuid
     returns null on null input
@@ -628,18 +643,38 @@ begin
     return uuid;
 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()
     returns varchar(63)[]
     stable leakproof
     language plpgsql as $$
 declare
-    assumedRoles  varchar(63)[];
+    assumedRoles varchar(63)[];
 begin
     assumedRoles := assumedRoles();
     if array_length(assumedRoles(), 1) > 0 then
         return assumedRoles();
     else
-        return array[currentUser()]::varchar(63)[];
+        return array [currentUser()]::varchar(63)[];
     end if;
 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;
+--//
diff --git a/src/main/resources/db/changelog/2022-07-29-050-hs-base.sql b/src/main/resources/db/changelog/2022-07-29-050-hs-base.sql
index f8edf9a5..82cd5fe4 100644
--- a/src/main/resources/db/changelog/2022-07-29-050-hs-base.sql
+++ b/src/main/resources/db/changelog/2022-07-29-050-hs-base.sql
@@ -58,7 +58,7 @@ select target.uuid, target.name as idName
 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)
     returns uuid
@@ -66,6 +66,16 @@ create or replace function globalUuidByIdName(idName varchar)
     strict as $$
 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;
+$$;
 --//
 
 -- ============================================================================
diff --git a/src/main/resources/db/changelog/2022-07-29-061-hs-customer-rbac.sql b/src/main/resources/db/changelog/2022-07-29-061-hs-customer-rbac.sql
index 8524edab..5afa8dfb 100644
--- a/src/main/resources/db/changelog/2022-07-29-061-hs-customer-rbac.sql
+++ b/src/main/resources/db/changelog/2022-07-29-061-hs-customer-rbac.sql
@@ -163,6 +163,16 @@ create or replace function customerUuidByIdName(idName varchar)
     strict as $$
 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:--//
 -- ----------------------------------------------------------------------------
 /*
-    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.
  */
 set session session authorization default;
diff --git a/src/main/resources/db/changelog/2022-07-29-070-hs-package-rbac.sql b/src/main/resources/db/changelog/2022-07-29-070-hs-package-rbac.sql
index ea54d12a..f5b8263d 100644
--- a/src/main/resources/db/changelog/2022-07-29-070-hs-package-rbac.sql
+++ b/src/main/resources/db/changelog/2022-07-29-070-hs-package-rbac.sql
@@ -162,6 +162,16 @@ create or replace function packageUuidByIdName(idName varchar)
     strict as $$
 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;
+$$;
 --//