Keycloak Built-In Analysis¶
Cartography includes several automatic analyses for Keycloak that help identify inheritance relationships and derived permissions in a Keycloak realm. These analyses are defined in cartography/data/jobs/analysis/keycloak_inheritance.json
.
1. Group Membership Inheritance¶
Description: Propagates user memberships to parent groups when a user is a member of a subgroup.
Query:
MATCH (u:KeycloakUser)-[:MEMBER_OF|INHERITED_MEMBER_OF]->(g:KeycloakGroup)-[:SUBGROUP_OF]->(pg:KeycloakGroup)
MERGE (u)-[r:INHERITED_MEMBER_OF]->(pg)
ON CREATE SET r.firstseen = $UPDATE_TAG
SET r.lastupdated = $UPDATE_TAG
Configuration: Iterative (iteration size: 100)
Graph result:
graph LR U(KeycloakUser) -- MEMBER_OF --> SG(KeycloakGroup) SG -- SUBGROUP_OF --> PG(KeycloakGroup) U == INHERITED_MEMBER_OF ==> PG
2. Group-Based Role Assignment¶
Description: Automatically assigns roles to users based on their group membership (direct or inherited).
Query:
MATCH (u:KeycloakUser)-[:MEMBER_OF|INHERITED_MEMBER_OF]->(g:KeycloakGroup)-[:GRANTS]->(r:KeycloakRole)
MERGE (u)-[r0:ASSUME_ROLE]->(r)
ON CREATE SET r0.firstseen = $UPDATE_TAG
SET r0.lastupdated = $UPDATE_TAG
Configuration: Non-iterative
Graph result:
graph LR U(KeycloakUser) -- MEMBER_OF --> G[KeycloakGroup] G -- GRANTS --> R(KeycloakRole) U == ASSUME_ROLE ==> R
3. Composite Role Grants Propagation¶
Description: Propagates scope permissions from included roles to composite roles.
Query:
MATCH (r:KeycloakRole)-[:INCLUDES]->(c:KeycloakRole)-[:GRANTS|INDIRECT_GRANTS]->(s:KeycloakScope)
MERGE (r)-[r0:INDIRECT_GRANTS]->(s)
ON CREATE SET r0.firstseen = $UPDATE_TAG
SET r0.lastupdated = $UPDATE_TAG
Configuration: Iterative (iteration size: 100)
Graph result:
graph LR R(KeycloakRole) -- INCLUDES --> CR(KeycloakRole) CR -- GRANTS --> S(KeycloakScope) R == INDIRECT_GRANTS ==> S
4. Legitimate User Scope Assignment¶
Description: Identifies all scopes that a user can legitimately use based on the roles they assume.
Query:
MATCH (u:KeycloakUser)-[:ASSUME_ROLE]->(:KeycloakRole)-[:GRANTS|INDIRECT_GRANTS]->(s:KeycloakScope)
MERGE (u)-[r:ASSUME_SCOPE]->(s)
ON CREATE SET r.firstseen = $UPDATE_TAG
SET r.lastupdated = $UPDATE_TAG
Configuration: Non-iterative
Graph result:
graph LR U(KeycloakUser) -- ASSUME_ROLE --> R(KeycloakRole) R -- GRANTS --> S(KeycloakScope) U == ASSUME_SCOPE ==> S
5. Orphan Scope Assignment¶
Description: Automatically assigns “orphan” scopes (not granted by any role) to all users in the realm.
Query:
MATCH (s:KeycloakScope)<-[:RESOURCE]-(r:KeycloakRealm)
MATCH (u:KeycloakUser)<-[:RESOURCE]-(r)
WHERE NOT (s)<-[:GRANTS|INDIRECT_GRANTS]-(:KeycloakRole)
MERGE (u)-[r0:ASSUME_SCOPE]->(s)
SET r0.firstseen = $UPDATE_TAG
SET r0.lastupdated = $UPDATE_TAG
Configuration: Non-iterative
Graph result:
graph LR R(KeycloakRealm) -- RESOURCE --> U(KeycloakUser) R -- RESOURCE --> S(KeycloakScope) R -- RESOURCE --> ROLE(KeycloakRole) subgraph "No relationship" S ROLE end U == ASSUME_SCOPE ==> S