# How to Set Up Role-Based Access Control (RBAC) in Harbor: A Complete Implementation Guide

> Implement role-based access control RBAC in Harbor. This guide details setting up user and robot account permissions for secure resource management within your projects.

- Repository: [Harbor/harbor](https://github.com/goharbor/harbor)
- Tags: how-to-guide
- Published: 2026-04-09

---

**Harbor implements role-based access control (RBAC) by mapping users and robot accounts to predefined roles that grant specific resource-action permissions within project namespaces, enforced through the `RequireProjectAccess` and `RequireSystemAccess` methods in the API handlers.**

Harbor, the open-source container and artifact registry, provides a sophisticated RBAC system to secure your container images and helm charts. Understanding how to set up role-based access control (RBAC) in Harbor is essential for managing multi-team environments and ensuring least-privilege access to your projects. This guide explains the architecture based on the goharbor/harbor source code and provides practical steps to configure permissions.

## Understanding Harbor's RBAC Architecture

Harbor's RBAC model uses a classic design where **roles** represent collections of **policies** (resource-action pairs) evaluated against user identities within specific project namespaces. The implementation distinguishes between **System** scope (admin-level) and **Project** scope (per-project access).

### Core RBAC Components

The foundational definitions reside in [`src/common/rbac/const.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/const.go). This file establishes:

- **Scope**: Either `System` for administrative functions or `Project` for repository-specific access (lines 88-91)
- **Action**: REST-like verbs including `create`, `read`, `update`, `delete`, `list`, `pull`, and `push` (lines 21-38)
- **Resource**: Logical objects such as `project`, `repository`, `artifact`, and `robot` (lines 40-84)
- **Policy**: A resource-action-effect triple (defaulting to `allow`), stored in the `PoliciesMap` for both system and project scopes (lines 163-214)

### Role Definitions and Mappings

Project-level roles are defined in [`src/common/rbac/project/rbac_role.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/project/rbac_role.go). The `rolePoliciesMap` associates five standard roles with specific policy sets:

- `projectAdmin` (ID: 1)
- `maintainer` (ID: 2)
- `developer` (ID: 3)
- `guest` (ID: 4)
- `limitedGuest` (ID: 5)

Each role implements the `RBACRole` interface through the `projectRBACRole` struct, which builds a **namespace** for the target project using `NewNamespace(projectID)` and prefixes policies with that namespace (`resource := namespace.Resource(policy.Resource)`) as implemented in lines 40-47.

### Namespace Resolution

Resource isolation depends on namespace encoding implemented in [`src/common/rbac/project/namespace.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/project/namespace.go) (lines 54-57). A project namespace encodes the project ID into the resource path (e.g., `/project/123/repository`), ensuring policies apply only to specific projects. System-wide resources use the namespace implementation in [`src/common/rbac/system/namespace.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/system/namespace.go).

## Configuring RBAC in Harbor

Setting up role-based access control involves creating projects, assigning members to roles, and optionally configuring robot accounts with scoped permissions.

### Step 1: Create a Project

First, establish a project namespace to contain your repositories:

```bash
curl -u admin:Admin123 -X POST "https://harbor.example.com/api/v2.0/projects" \
     -H "Content-Type: application/json" \
     -d '{"project_name":"myproj","public":false}'

```

This creates a private project that serves as the boundary for your RBAC policies.

### Step 2: Assign Members to Roles

Add users to the project with specific role IDs defined in [`src/common/role/role.go`](https://github.com/goharbor/harbor/blob/main/src/common/role/role.go). The API expects integer IDs: `1` for projectAdmin, `2` for maintainer, `3` for developer, `4` for guest, and `5` for limitedGuest.

To assign developer permissions (ID: 3) to user ID 42:

```bash
curl -u admin:Admin123 -X POST "https://harbor.example.com/api/v2.0/projects/1/members" \
     -H "Content-Type: application/json" \
     -d '{
           "role_id": 3,
           "member_user": {"user_id": 42}
         }'

```

The handlers in [`src/server/v2.0/handler/project.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/project.go) process these requests, while [`src/server/v2.0/handler/base.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/base.go) provides `RequireProjectAccess` (lines 102-109 and 126-136) to validate the requesting user holds the necessary role permissions.

### Step 3: Configure Robot Accounts with Scoped Permissions

For CI/CD pipelines, create robot accounts with granular permissions. Robot accounts can receive system-level policies appended through providers like `NolimitProvider`, as referenced in [`src/common/rbac/const.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/const.go) (lines 119-128).

Create a robot account with pull and push access to project 1:

```bash
curl -u admin:Admin123 -X POST "https://harbor.example.com/api/v2.0/projects/1/robots" \
     -H "Content-Type: application/json" \
     -d '{
           "name": "ci-bot",
           "access": [
             {"resource": "/project/1/repository", "action": "pull"},
             {"resource": "/project/1/repository", "action": "push"}
           ]
         }'

```

### Step 4: Validate Access Controls

Verify your RBAC configuration by attempting operations that require specific permissions. The enforcement occurs in [`src/server/v2.0/handler/base.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/base.go) through methods like `RequireProjectAccess`, which builds the full resource path via the namespace and delegates to the security context (`secCtx.Can`).

A `403 Forbidden` response indicates the user lacks the required policy in their role, while successful execution confirms proper RBAC setup.

## Programmatic RBAC Management

For automated workflows, Harbor's Go SDK provides type-safe access to the RBAC APIs.

### Adding Project Members via Go SDK

The following example demonstrates adding a developer role using the Harbor Go client:

```go
import (
    "github.com/go-openapi/runtime/client"
    "github.com/goharbor/harbor/src/server/v2.0/client/project"
    "github.com/goharbor/harbor/src/server/v2.0/client/operations"
)

// Authenticate to Harbor
auth := client.BasicAuth("admin", "Admin123")
transport := client.New("harbor.example.com", "/api/v2.0", []string{"https"})
transport.DefaultAuthentication = auth

// Add developer role (3) for user ID 42 to project 1
payload := &project.AddProjectMemberParams{
    ProjectID: 1,
    Member: &models.Member{
        RoleID:    3,
        MemberUser: &models.User{UserID: 42},
    },
}
_, err := operations.NewAddProjectMember(transport, nil).AddProjectMember(payload)
if err != nil { log.Fatalf("add member failed: %v", err) }

```

### Internal Policy Lookup

Internally, Harbor evaluates permissions by retrieving policies for a given role and prefixing them with the project namespace:

```go
// role := &projectRBACRole{projectID: 1, roleID: common.RoleDeveloper}
// policies := role.GetPolicies() 
// Returns []*types.Policy with namespace-prefixed resources like "/project/1/repository"

```

The `GetPolicies` method defined in [`src/common/rbac/project/rbac_role.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/project/rbac_role.go) (lines 24-46) returns the policy set associated with the role ID, enabling the RBAC evaluator to check against the requested resource and action.

## Key Source Files for RBAC Implementation

Understanding these files from the goharbor/harbor repository clarifies the complete authorization flow:

- [`src/common/rbac/const.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/const.go) — Defines `Action`, `Resource`, scopes, and the built-in `PoliciesMap` for system and project scopes
- [`src/common/rbac/project/rbac_role.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/project/rbac_role.go) — Maps role names to policy sets and implements the `RBACRole` interface
- [`src/common/rbac/project/namespace.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/project/namespace.go) — Encodes project ID into resource paths
- [`src/server/v2.0/handler/base.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/base.go) — Contains `RequireProjectAccess` and `RequireSystemAccess` for API enforcement
- [`src/server/v2.0/handler/project.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/project.go) — Exposes project member management endpoints
- [`src/pkg/rbac/model/model.go`](https://github.com/goharbor/harbor/blob/main/src/pkg/rbac/model/model.go) — Database entities (`RolePermission`, `PermissionPolicy`) for persisting RBAC policies

## Summary

- **Harbor RBAC** operates on a scope-based model distinguishing between System and Project levels, defined in [`src/common/rbac/const.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/const.go)
- **Five standard project roles** (projectAdmin, maintainer, developer, guest, limitedGuest) map to specific policy sets in [`src/common/rbac/project/rbac_role.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/project/rbac_role.go)
- **Namespace isolation** ensures policies apply only to specific projects through path encoding in [`src/common/rbac/project/namespace.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/project/namespace.go)
- **API enforcement** occurs via `RequireProjectAccess` in [`src/server/v2.0/handler/base.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/base.go), which evaluates the security context against namespace-prefixed resources
- **Role IDs** for API calls correspond to: 1 (projectAdmin), 2 (maintainer), 3 (developer), 4 (guest), and 5 (limitedGuest)
- **Robot accounts** support granular, scoped permissions for automated systems without human user accounts

## Frequently Asked Questions

### What are the default role IDs in Harbor's RBAC system?

Harbor assigns integer IDs to project roles as defined in [`src/common/role/role.go`](https://github.com/goharbor/harbor/blob/main/src/common/role/role.go): **1** for projectAdmin, **2** for maintainer, **3** for developer, **4** for guest, and **5** for limitedGuest. When using the API to add members, you must specify these numeric IDs rather than string names.

### How does Harbor isolate resources between projects?

Harbor uses **namespaces** to scope resources, implemented in [`src/common/rbac/project/namespace.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/project/namespace.go). The system encodes the project ID into the resource path (e.g., `/project/123/repository`), ensuring that policies granted to a user in project 123 cannot access resources in project 456. The `projectRBACRole` struct automatically prefixes all policies with the project namespace before evaluation.

### Where does Harbor enforce RBAC checks in the API layer?

API handlers invoke `RequireProjectAccess` or `RequireSystemAccess` from [`src/server/v2.0/handler/base.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/base.go) (lines 102-109 and 126-136). These methods build the fully qualified resource using the namespace helper, then delegate to the security context's `Can` method to verify the user possesses a role containing the required policy.

### Can robot accounts have different permissions than human users?

Yes, robot accounts support scoped permissions through the robot permission provider system. According to [`src/common/rbac/const.go`](https://github.com/goharbor/harbor/blob/main/src/common/rbac/const.go), robot accounts can receive additional system-level policies (lines 119-128). When creating a robot account via the API, you specify explicit resource-action pairs (such as `pull` and `push` on specific repositories), allowing more granular access than standard human roles.