## 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 implemented in `cartography/intel/keycloak/inheritance.py` and run after all realms are synced.

### 1. Group Membership Inheritance

**Description**: Propagates user memberships to parent groups when a user is a member of a subgroup.

**Query**:
```cypher
MATCH (u:KeycloakUser)-[:MEMBER_OF|INHERITED_MEMBER_OF]->(g:KeycloakGroup)-[:MEMBER_OF|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**:

```mermaid
graph LR
    U(KeycloakUser) -- MEMBER_OF --> SG(KeycloakGroup)
    SG -- MEMBER_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**:
```cypher
MATCH (u:KeycloakUser)-[:MEMBER_OF|INHERITED_MEMBER_OF]->(g:KeycloakGroup)-[:GRANTS|HAS_ROLE]->(r:KeycloakRole)
MERGE (u)-[r0:HAS_ROLE]->(r)
ON CREATE SET r0.firstseen = $UPDATE_TAG
SET r0.lastupdated = $UPDATE_TAG
```

**Configuration**: Non-iterative

**Graph result**:

```mermaid
graph LR
    U(KeycloakUser) -- MEMBER_OF --> G[KeycloakGroup]
    G -- HAS_ROLE --> R(KeycloakRole)
    U == HAS_ROLE ==> R
```

### 3. Composite Role Grants Propagation

**Description**: Propagates scope permissions from included roles to composite roles.

**Query**:
```cypher
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**:

```mermaid
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**:
```cypher
MATCH (u:KeycloakUser)-[:HAS_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**:

```mermaid
graph LR
    U(KeycloakUser) -- HAS_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.

```{info}
This analysis reflect the following Keycloak statement:
If there is no role scope mapping defined, each user is permitted to use this client scope. If there are role scope mappings defined, the user must be a member of at least one of the roles.
```

**Query**:
```cypher
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**:

```mermaid
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
```
