Skip to content

Roles and Permissions

Ephor uses role-based access control (RBAC). Roles are assigned based on group memberships from the identity provider.

Role Mapping

When a user authenticates, oauth2-proxy forwards their groups in the X-Forwarded-Groups header. Ephor maps these to internal roles:

GroupRole
ephor-viewersViewer
ephor-analystsAnalyst
ephor-leadsLead
ephor-adminsAdmin

If a user belongs to multiple groups, their effective role is the highest-privilege match.

Permissions by Role

Viewer

Read-only access to security data.

PermissionDescription
VIEW_VULNERABILITIESView vulnerability findings and details
VIEW_ESCALATIONSView escalations
VIEW_TRIAGEView triage status and history
VIEW_REMEDIATIONSView remediation records

Analyst

All Viewer permissions plus:

PermissionDescription
MANAGE_VULNERABILITIESUpdate vulnerability status and metadata
MANAGE_ESCALATIONSCreate and update escalations
MANAGE_TRIAGEUpdate triage status and add comments
MANAGE_REMEDIATIONSCreate and update remediation records

Lead

All Analyst permissions plus:

PermissionDescription
VIEW_ADMINAccess admin-level views and reports

Admin

All permissions including:

PermissionDescription
MANAGE_ADMINManage system configuration and all administrative functions

Group Extraction by Provider

Keycloak -- Groups are extracted from the groups claim in the JWT token. The default development configuration includes this claim automatically.

GitHub -- Groups are resolved by looking up the user's team memberships in the configured organization. The GITHUB_TOKEN must have read:org scope. The organization prefix is stripped automatically (e.g., holbein-io:ephor-analysts becomes ephor-analysts).

Custom providers -- The X-Forwarded-Groups header must contain a comma-separated list of group names matching the mappings above.

API Authorization

For developers extending the API, the @RequireAuth annotation enforces access control:

java
// Any authenticated user
@RequireAuth
@GetMapping("/resource")
public ResponseEntity<?> get() { ... }

// Specific permission required
@RequireAuth(permissions = {Permission.MANAGE_VULNERABILITIES})
@PutMapping("/vulnerabilities/{id}")
public ResponseEntity<?> update() { ... }

// Specific groups required
@RequireAuth(groups = {"ephor-admins"})
@DeleteMapping("/resource/{id}")
public ResponseEntity<?> delete() { ... }

// Multiple groups (all required)
@RequireAuth(groups = {"ephor-admins", "ephor-leads"}, requireAllGroups = true)
@PostMapping("/admin/action")
public ResponseEntity<?> adminAction() { ... }

Licensed under AGPL v3