Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
353 changes: 353 additions & 0 deletions proposals/new/Custom-Project-Roles
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
# Proposal: Custom Project Roles
Author: Max Graustenzel (@maxgraustenzel-create)
Discussion: #18124

## Abstract

Add support for custom project roles in Harbor, allowing system administrators to create roles with flexible permission combinations beyond the five built-in roles. This extends the existing RBAC system to enable runtime role creation without code changes, addressing long-standing community requests for role customization while maintaining full backward compatibility.

## Background

Harbor currently provides five hardcoded project roles (Project Admin, Maintainer, Developer, Guest, Limited Guest) with fixed permissions defined in `rbac_role.go`. Organizations have diverse security and workflow requirements that cannot be met by these predefined roles alone.

**Current Limitations:**
- Role permissions are hardcoded in Go source code
- Adding new roles requires code changes and Harbor releases
- Organizations cannot adapt roles to specific workflows (e.g., "DevOps Engineer" with artifact management + robot creation but no member management)
- No middle-ground between overly permissive and overly restrictive built-in roles

**Community Demand:**
- Issue #18124 and related issues (#18143, #21306, #12062, #8632, #1486) have 60+ positive reactions
- Consistent feedback requesting role customization capabilities
- Organizations work around limitations by creating multiple projects or granting excessive permissions

**Example Use Cases:**
- **DevOps Engineer:** Push/pull artifacts + manage robot accounts, but cannot manage project members
- **Security Auditor:** Read-only access + trigger vulnerability scans, but cannot modify artifacts
- **Release Manager:** Manage artifacts + set tag immutability, but cannot delete repositories

## Proposal

Extend Harbor's existing RBAC infrastructure to support custom roles by linking the existing `role` table to the `permission_policy` table through the `role_permission` table.

**Core Changes:**

1. **Database:** Move role permissions from hardcoded `rbac_role.go` to database (`role_permission` table)
2. **API:** Add role CRUD endpoints for system administrators
3. **UI:** Add role management interface in System Administration section
4. **Security:** Implement privilege escalation prevention and audit logging
5. **Caching:** Load permissions at login (session-scoped cache)

**Key Design Decisions:**

- **Reuse existing infrastructure:** `role`, `permission_policy`, `role_permission`, and `project_member` tables already exist
- **Minimal schema changes:** Only extend `role` table with metadata columns (`is_builtin`, `description`, `modified`, `created_by`, `modified_by`, timestamps)
- **Discriminator pattern:** `role_permission.role_type` distinguishes 'project-role' (users/groups) from 'robotaccount' (direct permissions)
- **System admin only:** Only system administrators can create/modify custom roles (project admins assign roles, existing workflow unchanged)
- **Built-in role protection:** Built-in roles can be modified but not deleted; modifications are tracked and reversible

**Technical Architecture:**

```
┌──────────────────────────────────────────────────────────────┐
│ Before: Hardcoded in rbac_role.go │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ users/groups │ │
│ └────────┬────────┘ │
│ ↑ │
│ │ │
│ ┌─────────────────┐ │
│ │ project_member │ │
│ └────────┬────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────┐ │
│ │ role (table) │ │
│ └────────┬────────┘ │
│ │ │
│ ↓ │
│ permissions │
│ (hardcoded in │
│ rbac_role.go) │
│ │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│ After: Database-driven │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ users/groups │ │
│ └────────┬────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ project_member │───────→│ role (table) │ │
│ └─────────────────┘ └────────┬────────┘ │
│ ↑ │
│ │ │
│ ┌─────────────────┐ │
│ │ role_permission │ │
│ │ (role_type= │ │
│ │ 'project-role') │ │
│ └────────┬────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────┐ │
│ │ permission_ │ │
│ │ policy (table) │ │
│ └─────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
```

**User Workflow:**

1. **System Admin:** Creates custom role "DevOps Engineer" with specific permissions
2. **Project Admin:** Assigns "DevOps Engineer" role to user/group (same as built-in roles)
3. **User Login:** Permissions loaded into session cache
4. **Authorization:** Permission checks use cached permissions (O(1) lookup)

## Non-Goals

**Explicitly out of scope for this proposal:**

1. **Repository-level permissions:** Permissions apply at project level (all repositories in project). Repository-level permission assignment is tracked separately in Issue #10159
2. **Global role assignments:** Custom roles are assigned per-project (user can have different roles in different projects). Global role assignment is tracked in Issue #8351
3. **Role templates/marketplace:** No predefined custom role templates in initial release
4. **Role inheritance/composition:** Roles are flat, not hierarchical
5. **Real-time permission updates:** Permission changes apply at next login (not mid-session)
6. **Robot account roles:** Robots continue using direct permission assignment (no role concept)

## Rationale

**Why extend existing RBAC vs. creating a new system:**

✅ **Advantages:**
- Leverages existing, battle-tested permission infrastructure
- Minimal code changes (extend, don't replace)
- No breaking changes to APIs or database schema
- Consistent with Harbor's architectural patterns
- Easy to understand for existing Harbor users and contributors

❌ **Alternative: New parallel permission system:**
- Would require maintaining two RBAC systems
- Breaking changes to existing code
- Higher risk of bugs and security issues
- More complex for users to understand

**Why database-driven vs. more built-in roles:**

✅ **Advantages:**
- Organizations have diverse, unpredictable needs
- Reduces Harbor maintenance burden (no code changes for role requests)
- Enables rapid adaptation to new workflows
- Doesn't clutter built-in role list

❌ **Alternative: Add more built-in roles:**
- Cannot cover all use cases
- Each new role requires code review, testing, release cycle
- Built-in role list becomes overwhelming
- Organizations still request customization

**Why system admin only for role creation:**

✅ **Advantages:**
- Centralized governance and security control
- Prevents permission sprawl
- Aligns with enterprise security models
- Simpler initial implementation

❌ **Alternative: Project admins create custom roles:**
- Higher risk of permission sprawl
- Inconsistent roles across projects
- More complex audit trail
- Can be added later if needed

**Why session-scoped caching:**

✅ **Advantages:**
- Fast permission checks (O(1) in-memory lookup)
- No database queries during requests
- Simple cache invalidation (logout = clear)
- Minimal performance impact

❌ **Alternative: Real-time permission updates:**
- Requires complex cache invalidation across sessions
- Performance overhead for permission change propagation
- Added complexity for minimal benefit (permissions rarely change mid-session)

## Compatibility

**Backward Compatibility: Fully maintained**

✅ **No breaking changes:**
- All existing APIs maintain contracts
- Built-in roles function identically
- Existing role assignments preserved
- Authentication/authorization flow unchanged
- Database migration is reversible

✅ **Migration strategy:**
- Zero-downtime migration
- Built-in role permissions migrated from `rbac_role.go` to `role_permission` table
- Existing roles automatically marked `is_builtin=true`
- All user/group assignments preserved
- Rollback: Standard Harbor rollback procedure (custom roles become inaccessible but data preserved)

**API Compatibility:**

- **New endpoints:** `/api/v2.0/roles/*` (no conflicts with existing endpoints)
- **Extended endpoint:** `/api/v2.0/permissions` (already existed for robots, now includes role permissions)
- **Unchanged endpoints:** All existing role assignment APIs work with custom roles (transparent)

**UI Compatibility:**

- New "Roles" section in System Administration (no impact on existing UI)
- Project member assignment dropdown includes custom roles (alongside built-in roles)
- No changes to existing workflows

**Performance Impact:**

- **Login:** +50-100ms (one-time permission load)
- **Requests:** No change (cached permissions)
- **Database:** Minimal load increase (one query per login)

**Version Compatibility:**

- Harbor instances without custom roles: No impact
- Harbor instances with custom roles: Rollback preserves data but makes custom roles inaccessible
- Upgrade path: Standard Harbor upgrade (no special steps)

## Implementation

**Current Status: ~60% Complete**

### Phase 1: Foundation (✅ Complete)
- Database schema design and migrations
- Core RBAC permission loading logic
- `role_permission` table integration

**Owner:** Max Graustenzel
**Timeline:** Completed

### Phase 2: API Layer (✅ Complete)
- `/api/v2.0/roles` endpoints (CRUD operations)
- `/api/v2.0/permissions` endpoint extension
- OpenAPI/Swagger specification

**Owner:** Max Graustenzel
**Timeline:** Completed

### Phase 3: UI Components (✅ Complete)
- System Administration → Roles management interface
- Role creation/edit wizard
- Permission selection interface
- Built-in vs custom role indicators

**Owner:** Max Graustenzel
**Timeline:** Completed

### Phase 4: Security Validation (🔄 In Progress - 30%)
- Privilege escalation prevention (robot creation)
- Privilege escalation prevention (member assignment)
- Audit logging for all role operations
- UI security enhancements (disable invalid permissions/roles in forms)

**Owner:** Max Graustenzel
**Timeline:** 2 weeks

### Phase 5: Testing (🔄 In Progress - 10%)
- Unit tests (role CRUD, permission validation, cache behavior)
- Integration tests (API contracts, multi-user scenarios, migrations)
- Security tests (privilege escalation attempts, unauthorized access)
- E2E tests (complete workflows via UI)

**Owner:** Max Graustenzel
**Timeline:** 2 weeks

### Phase 6: Documentation (🔄 In Progress - 30%)
- User guide (creating and managing custom roles)
- Administrator guide (installation, migration, security)
- API documentation (code examples, migration guide)
- Design documentation (architecture, trade-offs)

**Owner:** Max Graustenzel
**Timeline:** 1 week

### Phase 7: Review & Polish (⏳ Not Started)
- Performance optimization
- Security audit
- Code review addressing feedback
- Release preparation

**Owner:** Max Graustenzel + Community Reviewers
**Timeline:** 2-3 weeks

**Estimated Timeline to Production Ready:** 6-10 weeks from current state

**Repository:**
- Fork: https://github.com/maxgraustenzel-create/harbor
- Branch: `origin/18124-custom-role-feature`

## Open Issues

### 1. Permission Granularity
**Question:** Is project-level permission granularity sufficient, or should we support repository-level permissions?

**Current Decision:** Project-level only (permissions apply to entire project, not individual repositories)
**Rationale:**
- Permissions are defined system-wide in `permission_policy` table
- Applied per-project via `project_member` role assignments
- Repository-level permissions would require different scope model and significant additional complexity
- Project-level covers 70%+ of use cases
- Repository-level permissions tracked separately in Issue #10159

**Open for Discussion:** Should repository-level permission assignment be part of this proposal or remain a separate future enhancement?

### 2. Global vs. Project-Scoped Custom Roles
**Question:** Should custom roles be system-wide (reusable across projects) or per-project?

**Current Decision:** System-wide roles, assigned per-project (matches built-in role model)
**Rationale:** Consistent with existing Harbor model, easier to manage
**Open for Discussion:** Per-project custom roles could be added later if needed

### 3. Role Templates
**Question:** Should we provide predefined custom role templates (e.g., "Read-Only Auditor", "CI/CD Bot Manager")?

**Current Decision:** No templates in initial release
**Rationale:** Keep initial scope focused, templates can be added based on community usage patterns
**Open for Discussion:** Community can contribute templates as documentation/examples

### 4. Built-in Role Modification Policy
**Question:** Should built-in roles be modifiable or immutable?

**Current Decision:** Modifiable (with tracking and reset capability)
**Rationale:** Maximum flexibility, modifications are tracked, can be reset to defaults
**Alternative:** Immutable built-in roles (forces use of custom roles for any changes)
**Open for Discussion:** Security-conscious organizations may prefer immutable built-in roles

### 5. Permission Change Propagation
**Question:** Should permission changes apply immediately or at next login?

**Current Decision:** Next login (session-scoped cache invalidation)
**Rationale:** Simpler implementation, minimal real-world impact (permissions rarely change mid-session)
**Alternative:** Real-time propagation (complex cache invalidation, performance overhead)
**Open for Discussion:** Real-time propagation could be added later if needed

---

**Feedback Welcome**

This proposal is open for community discussion. Please provide feedback on:
- Architecture and design approach
- Security model and concerns
- API design and compatibility
- UI/UX and usability
- Documentation clarity
- Implementation timeline
- Open issues and alternatives

**Contact:** Max Graustenzel (@maxgraustenzel-create)