# Existing Permission Model Analysis

This document describes the current role-based access control (RBAC) implementation in Fides/Fidesplus and identifies architectural limitations that constrain fine-grained access control.

## Overview

The current permission system has two independent mechanisms:

1. **Role-based scopes** - Broad permissions granted to all resources of a type
2. **System Manager assignments** - Narrow write permissions to specific systems

These two mechanisms do not integrate well, creating gaps in access control capabilities.

---

## Role-Based Permissions

### Available Roles

| Role | Description | Scope Coverage |
|------|-------------|----------------|
| `owner` | Full administrator | All scopes in `SCOPE_REGISTRY` |
| `contributor` | Standard user | All scopes except storage, messaging, connector registration |
| `viewer` | Read-only access | Read scopes only |
| `viewer_and_approver` | Viewer + privacy request approval | Viewer scopes + approval scopes |
| `approver` | Privacy request approval only | Limited to privacy request operations |
| `respondent` | Internal manual step responder | `PRIVACY_REQUEST_MANUAL_STEPS_RESPOND` only |
| `external_respondent` | External manual step responder | `PRIVACY_REQUEST_MANUAL_STEPS_RESPOND` only |

### Key Characteristic: All-or-Nothing Access

Roles grant permissions **globally across all resources** of a given type. For example:

- `SYSTEM_READ` scope allows reading **all** systems
- `SYSTEM_CREATE` scope allows creating **any** system
- `PRIVACY_ASSESSMENT_CREATE` scope allows creating assessments for **all** systems

There is no mechanism to scope a role to a subset of resources.

**Code Reference:** `fides/src/fides/api/oauth/roles.py:152-160`
```python
ROLES_TO_SCOPES_MAPPING: Dict[str, List] = {
    OWNER: sorted(SCOPE_REGISTRY),  # All scopes
    VIEWER: sorted(viewer_scopes),
    # ...
}
```

---

## System Manager Mechanism

### Purpose

System Manager is a separate permission mechanism that grants **specific write permissions** to **specific systems**. It exists to allow users without broad role-based write access to manage systems they are responsible for.

### Implementation

- Many-to-many relationship: `FidesUser.systems` ↔ `System.data_stewards`
- Stored in `systemmanager` join table
- System IDs are embedded in the user's JWT token (`JWE_PAYLOAD_SYSTEMS`)

**Code Reference:** `fides/src/fides/api/models/system_manager.py`

### System Manager Scopes

System managers receive a **fixed, limited set of scopes** for their assigned systems:

```python
SYSTEM_MANAGER_SCOPES = [
    SYSTEM_UPDATE,
    SYSTEM_DELETE,
    CONNECTION_CREATE_OR_UPDATE,
    CONNECTION_READ,
    CONNECTION_DELETE,
]
```

**Code Reference:** `fides/src/fides/api/oauth/system_manager.py:11-17`

Fidesplus extends this with:
```python
SYSTEM_MANAGER_SCOPES.extend([
    CUSTOM_FIELD_CREATE,
    CUSTOM_FIELD_UPDATE,
    CUSTOM_FIELD_DELETE,
])
```

**Code Reference:** `fidesplus/src/fidesplus/api/system_manager_oauth_util.py:24-27`

### Permission Check Flow

For endpoints that support system manager permissions (e.g., `PUT /system`, `DELETE /system/{fides_key}`):

```
1. Check if user has required scope via ROLE (model-level permissions)
   → If yes: ALLOW (access to ALL systems)

2. If no role-based permission, check if user is SYSTEM MANAGER of specific system
   → If yes AND required scope is in SYSTEM_MANAGER_SCOPES: ALLOW (this system only)

3. Otherwise: DENY
```

**Code Reference:** `fides/src/fides/api/oauth/system_manager_oauth_util.py:126-154`

---

## Architectural Limitations

### 1. No Resource-Scoped Roles

**Problem:** Roles cannot be scoped to specific resources.

A user is either:
- An `owner` of **everything**, or
- A `viewer` of **everything**, or
- A system manager with **very limited** write permissions on specific systems

**Impact:** Cannot create a "System Owner" who has full control over systems A and B but no access to systems C and D.

**Example Scenario:**
- Organization has 50 systems across 5 departments
- Department head should own their 10 systems completely (create assessments, manage connections, etc.)
- Current model: Department head must be global `owner` (sees all 50 systems) or `system_manager` (can only update/delete, cannot create assessments)

### 2. Fixed System Manager Scope Set

**Problem:** The scopes granted to system managers are hardcoded and cannot be customized.

System managers can only perform these operations on their systems:
- Update system metadata
- Delete system
- Manage connections

System managers **cannot**:
- Create privacy assessments for their systems
- Manage privacy notices for their systems
- Access discovery/classification features for their systems
- Any other operation not in `SYSTEM_MANAGER_SCOPES`

**Impact:** New features (like Privacy Assessments) require either:
1. Adding scopes to `SYSTEM_MANAGER_SCOPES` globally (affects all system managers)
2. Requiring users to have global role-based permissions (defeats purpose of system-level access control)

### 3. Inconsistent Permission Patterns Across Endpoints

**Problem:** Different endpoints handle system-level permissions differently.

| Endpoint | Permission Check | System Filtering |
|----------|-----------------|------------------|
| `GET /system` | `SYSTEM_READ` scope | None - returns all systems |
| `POST /system` | `SYSTEM_CREATE` scope | None - can create any system |
| `PUT /system` | `SYSTEM_UPDATE` scope OR system manager | System manager limited to their systems |
| `DELETE /system/{key}` | `SYSTEM_DELETE` scope OR system manager | System manager limited to their systems |
| `GET /datamap` | `DATAMAP_READ` scope | None - includes all systems |
| `POST /privacy-assessments` | `PRIVACY_ASSESSMENT_CREATE` scope | None - generates for all systems |

**Impact:** Users expect consistent behavior. If a user is assigned to specific systems, they may expect all operations to be scoped to those systems.

### 4. No Hierarchical or Group-Based Permissions

**Problem:** No way to grant permissions to groups of systems or inherit permissions.

- System Groups exist but have no permission implications
- Cannot say "users in Group X can manage all systems in System Group Y"
- Each user-to-system assignment must be made individually

**Impact:** Administrative overhead scales linearly with users × systems.

### 5. Role Assignment is Binary

**Problem:** A user either has a role or doesn't. Cannot have different roles for different contexts.

**Example:** A user cannot be:
- `owner` for Department A's systems
- `viewer` for Department B's systems
- No access to Department C's systems

They must pick one role that applies globally.

### 6. Token-Based System Manager Verification

**Problem:** System manager assignments are embedded in JWT tokens at login time.

```python
assigned_systems: List[str] = token_data.get(JWE_PAYLOAD_SYSTEMS, [])
```

**Impact:**
- Changes to system manager assignments require re-authentication
- Token size grows with number of assigned systems
- No real-time permission changes

---

## Current Workarounds

### Workaround 1: Grant Global Owner Role

**Approach:** Give users who need full system control the `owner` role.

**Drawbacks:**
- User can access/modify ALL systems, not just their assigned ones
- Violates principle of least privilege
- Audit/compliance concerns

### Workaround 2: Accept Limited System Manager Capabilities

**Approach:** Use system manager for what it supports, accept that some operations require elevated roles.

**Drawbacks:**
- Poor user experience (user can update system but not create assessment for it)
- Confusing mental model
- Requires documentation/training

### Workaround 3: Custom Middleware/Endpoint Overrides

**Approach:** Override specific endpoints to add custom permission logic.

**Drawbacks:**
- Maintenance burden
- Inconsistent with base Fides behavior
- Must be repeated for each endpoint

---

## Recommendations for Future RBAC Improvements

1. **Resource-Scoped Roles:** Allow roles to be assigned with a resource scope (e.g., "owner of systems X, Y, Z")

2. **Configurable System Manager Scopes:** Allow organizations to configure which scopes system managers receive

3. **Permission Groups:** Create permission groups that can be assigned to users and linked to resource groups

4. **Consistent System Filtering:** Apply system-based filtering consistently across all endpoints for users with system-level assignments

5. **Real-Time Permission Evaluation:** Move away from token-embedded permissions to real-time database lookups for permission changes

6. **Hierarchical Permissions:** Support permission inheritance through system groups or organizational hierarchy

---

## Appendix: Scope to Role Mapping

### Owner Role (All Scopes)
The owner role receives every scope in `SCOPE_REGISTRY`, which includes all base Fides scopes plus all Fidesplus scopes.

### Contributor Role
All scopes except:
- `CONNECTOR_TEMPLATE_REGISTER`
- `STORAGE_CREATE_OR_UPDATE`
- `STORAGE_DELETE`
- `MESSAGING_CREATE_OR_UPDATE`
- `MESSAGING_DELETE`
- `PRIVACY_REQUEST_NOTIFICATIONS_CREATE_OR_UPDATE`
- `PRIVACY_REQUEST_EMAIL_INTEGRATIONS_SEND`
- `USER_PERMISSION_ASSIGN_OWNERS`
- `HEAP_DUMP_EXEC`

### Viewer Role
Read-only scopes:
- `*_READ` scopes for most resources
- `MASKING_EXEC`, `MASKING_READ`
- No write/create/delete scopes

### System Manager (Not a Role)
Fixed scopes for assigned systems only:
- `SYSTEM_UPDATE`
- `SYSTEM_DELETE`
- `CONNECTION_CREATE_OR_UPDATE`
- `CONNECTION_READ`
- `CONNECTION_DELETE`
- `CUSTOM_FIELD_CREATE` (Fidesplus)
- `CUSTOM_FIELD_UPDATE` (Fidesplus)
- `CUSTOM_FIELD_DELETE` (Fidesplus)

---

## References

- Role definitions: `fides/src/fides/api/oauth/roles.py`
- System manager scopes: `fides/src/fides/api/oauth/system_manager.py`
- System manager OAuth util: `fides/src/fides/api/oauth/system_manager_oauth_util.py`
- Fidesplus scope extensions: `fidesplus/src/fidesplus/api/plus_scope_registry.py`
- Fidesplus system manager extensions: `fidesplus/src/fidesplus/api/system_manager_oauth_util.py`
