Harbor 项目创建权限管控:从配置文件到 API 校验的完整实践
2026/9/11 21:05:51 网站建设 项目流程

Harbor 项目创建权限管控:从配置文件到 API 校验的完整实践

【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor

导读

Harbor 作为开源的云原生制品仓库,其「项目创建权限」(Project Creation Restriction)开关决定了普通用户能否自助创建项目。本文以 Harbor 官方测试用例 tests/testcases/Group8-Configuration/8-02-Authentication-edit-project-creation-restriction.md 为主线,完整还原"管理员修改项目创建限制 → 普通用户创建项目被拒"的验证流程,并结合仓库源码(配置元数据、参数校验、API 权限拦截)讲解该功能的底层实现。读完本文,你将掌握该开关的两种取值、配置入口、默认行为、后端校验逻辑以及自动化回归验证方法。


一、测试用例背景:验证什么

该测试用例属于Group8-Configuration(配置类测试组),其标题为Test 8-02 - Update-project-restrict,核心目的(Purpose)是:

To verify that an admin user can update project restrict. 验证管理员用户能够更新「项目创建限制」配置。

这是一个黑盒功能验证用例,覆盖的操作链路为:

  1. 管理员在 UI 配置页将项目创建限制从everyone改为admin only
  2. 登出管理员;
  3. 使用非管理员账号登录;
  4. 尝试新建项目;
  5. 断言:非管理员看不到"新建项目"按钮(即创建入口被隐藏,后端同时返回 403)。

从源码角度,这一系列行为背后对应的是 Harbor 的全局配置项project_creation_restriction,它由系统级配置框架统一管理,并最终在项目创建 API 处强制执行。


二、核心配置项:project_creation_restriction

2.1 两种取值与默认值

在 src/common/const.go 中定义了该配置项仅有的两种合法取值:

常量取值含义
ProCrtRestrEveryoneeveryone任何已登录用户(含普通用户)均可创建项目(默认值)
ProCrtRestrAdmOnlyadminonly仅系统管理员可创建项目

配置项的元数据定义在 src/lib/config/metadata/metadatalist.go:

{Name: common.ProjectCreationRestriction, Scope: UserScope, Group: BasicGroup, EnvKey: "PROJECT_CREATION_RESTRICTION", DefaultValue: common.ProCrtRestrEveryone, // 默认 "everyone" ItemType: &ProjectCreationRestrictionType{}, Editable: false, Description: `Indicate who can create projects, it could be ''adminonly'' or ''everyone''.`},

要点说明:

  • 默认值为everyone,即默认情况下普通用户登录后即可自助创建项目;
  • 该项属于UserScope用户级配置(而非部署期 system 级配置),意味着它不通过harbor.yml或环境变量在部署时固定,而是运行时通过 UI / API 修改并持久化到数据库;
  • Editable: false表示该配置项不能通过 API 随意修改,仅能由管理员通过 UI 或在部署配置中设置(见下文 API 说明)。

2.2 取值合法性校验

配置值的合法性由 src/lib/config/metadata/type.go 中的ProjectCreationRestrictionType.validate保证:

func (t *ProjectCreationRestrictionType) validate(str string) error { if !(str == common.ProCrtRestrAdmOnly || str == common.ProCrtRestrEveryone) { return fmt.Errorf("invalid %s, should be %s or %s", common.ProjectCreationRestriction, common.ProCrtRestrAdmOnly, common.ProCrtRestrEveryone) } return nil }

即配置值只接受adminonlyeveryone二选一,写入其他值会被配置管理器直接拒绝。这也解释了为什么测试用例与 API 测试中始终使用这两个精确字符串。

2.3 读取逻辑

src/lib/config/userconfig.go 提供了业务侧读取入口:

// OnlyAdminCreateProject returns the flag to restrict that only sys admin can create project func OnlyAdminCreateProject(ctx context.Context) (bool, error) { err := DefaultMgr().Load(ctx) if err != nil { return true, err } return DefaultMgr().Get(ctx, common.ProjectCreationRestriction).GetString() == common.ProCrtRestrAdmOnly, nil }
  • 每次调用先从配置管理器Load最新配置(支持内存 / DB / REST 等多种配置驱动,见 src/common/const.go 中DBCfgManagerInMemoryCfgManagerRestCfgManager);
  • 返回值true表示"仅管理员可创建项目";加载失败时出于安全考虑默认返回 true(收紧权限),避免配置异常导致权限失控。

三、后端强制校验:CreateProject API 的权限拦截

测试用例期望"非管理员无法创建项目",这一约束不仅仅依赖 UI 隐藏按钮,还在服务端强制实施。项目创建入口在 src/server/v2.0/handler/project.go 的CreateProject中完成两层拦截:

func (a *projectAPI) CreateProject(ctx context.Context, params operation.CreateProjectParams) middleware.Responder { if err := a.RequireAuthenticated(ctx); err != nil { return a.SendError(ctx, err) } onlyAdmin, err := config.OnlyAdminCreateProject(ctx) if err != nil { return a.SendError(ctx, fmt.Errorf("failed to determine whether only admin can create projects: %v", err)) } secCtx, _ := security.FromContext(ctx) if r, ok := secCtx.(*robotSec.SecurityContext); ok && !r.User().IsSysLevel() { log.Errorf("Only system level robot can create project") return a.SendError(ctx, errors.ForbiddenError(nil).WithMessage("Only system level robot can create project")) } if onlyAdmin && !(a.isSysAdmin(ctx, rbac.ActionCreate) || secCtx.IsSolutionUser()) { log.Errorf("Only sys admin can create project") return a.SendError(ctx, errors.ForbiddenError(nil).WithMessage("Only system admin can create project")) } ... }

拦截流程可概括为:

  1. 认证RequireAuthenticated确保请求来自已登录用户;
  2. 读取全局配置:调用config.OnlyAdminCreateProject(ctx)判断当前是否为"仅管理员可建项目"模式;
  3. Robot 账号限制:非系统级的 robot 账号一律禁止创建项目(返回Only system level robot can create project);
  4. 管理员校验:当onlyAdmin == true且当前用户既不是系统管理员、也不是 Solution User 时,返回403 Forbidden,错误信息为Only system admin can create project—— 这正是 API 自动化测试断言的服务端错误体。

也就是说,即使绕过 UI 直接调用 REST API,普通用户也无法创建项目,权限边界在服务端是闭环的。


四、UI 侧表现:普通用户看不到"新建项目"按钮

测试用例的期望结果是:

In step5, non-admin user will not see the add project button.

Harbor 前端根据系统配置动态渲染项目列表页。相关逻辑位于 src/portal/src/app/base/left-side-nav/projects/list-project/list-project.component.ts,它读取系统配置中的project_creation_restriction,当其值为adminonly时,仅向系统管理员展示"新建项目"入口;普通用户的项目列表页则不渲染该按钮。配置的获取与传递在 src/portal/src/app/services/app-config.ts 与 src/portal/src/app/base/left-side-nav/config/config.ts 中定义,与后端返回的配置项一一对应。

因此该功能存在双重防线:UI 层面隐藏入口(提升体验),服务端 API 层面强制拒绝(保证安全)。


五、管理员修改配置的两种途径

5.1 通过 UI 配置页

管理员登录后,进入配置管理(Administration)→ 系统设置 / Configuration页面,找到「项目创建限制」(Project Creation Restriction)项,在EveryoneAdmin Only之间切换并保存。该页面由 src/portal/src/app/base/left-side-nav/config/system/system-settings.component.ts 实现,其中project_creation_restriction是其处理的配置属性之一。

5.2 通过 REST API

自动化测试使用 Harbor 的 v2.0 配置 API 完成切换。API 客户端封装见 tests/apitests/python/library/configurations.py:

def set_configurations_of_project_creation_restriction(self, project_creation_restriction, expect_status_code = 200, **kwargs): client = self._get_client(**kwargs) config=dict(project_creation_restriction=project_creation_restriction) set_configurations(client, expect_status_code = expect_status_code, **config)

对应的 REST 调用为PUT /api/v2.0/configurations,请求体示例:

{ "project_creation_restriction": "adminonly" }

读取配置则使用GET /api/v2.0/configurations,返回体中的project_creation_restriction.value即为当前取值(见get_configurations实现)。注意:普通用户无权调用配置 API,该接口仅系统管理员可访问,这也是测试中必须先用ADMIN_CLIENT修改配置的原因。

部署层面的补充:虽然该项为运行时配置,但 Harbor 也提供了PROJECT_CREATION_RESTRICTION环境变量作为初始化值(见元数据EnvKey),可在首次部署时由harbor.yml/ 环境注入,随后可在 UI 中再调整。


六、完整的端到端回归验证

6.1 UI 手工验证步骤(对应原测试用例)

前置环境:

  • 一个运行中的 Harbor 实例;
  • 一台装有 Docker CLI(Docker 客户端)的 Linux 主机;
  • 拥有系统管理员账号与一个普通用户账号。

执行步骤:

  1. 以管理员身份登录 Harbor UI;
  2. 进入配置管理 → 系统设置,将「项目创建限制」从Everyone改为Admin Only并保存;
  3. 登出管理员账号;
  4. 以普通用户身份登录;
  5. 尝试新建项目。

预期结果:

  • 步骤 5 中,普通用户页面不会出现"新建项目"按钮;即使手工构造 API 请求,也会收到403 Forbidden,错误体为Only system admin can create project

6.2 API 自动化测试:test_edit_project_creation.py

仓库中已提供与手工用例等价的 Python 自动化用例 tests/apitests/python/test_edit_project_creation.py,其核心步骤(与 tests/apitests/python/library/project.py 的项目封装配合使用):

  1. 管理员创建一个新用户(密码Aa123456);
  2. 以管理员身份调用配置 API,将project_creation_restriction设为adminonly
  3. 用新用户调用创建项目 API,断言返回 403,并精确校验响应体:
self.project.create_project( metadata = {"public": "false"}, expect_status_code = 403, expect_response_body = "{\"errors\":[{\"code\":\"FORBIDDEN\",\"message\":\"Only system admin can create project\"}]}", **TestProjects.USER_edit_project_creation_CLIENT)
  1. 以管理员身份将配置改回everyone
  2. 再次用新用户创建项目,断言创建成功(得到项目 ID);
  3. 清理:删除项目与用户(tearDown)。

该用例形成完整的"限制开启 → 拒绝 → 限制关闭 → 放行"闭环,既能验证配置写入/读取的正确性,也能验证后端权限拦截的准确性,可作为 CI 中配置类回归测试的参考模板(相关 CI 运行入口见 tests/ci/api_run.sh)。


七、常见问题与注意事项

现象 / 疑问说明
修改后普通用户仍显示"新建项目"按钮检查配置是否保存成功、浏览器缓存;或通过GET /api/v2.0/configurations确认真实值
直接调用 API 创建项目返回 403属预期行为:adminonly模式下服务端强制拦截(src/server/v2.0/handler/project.go)
robot 账号创建项目被拒非系统级 robot 一律禁止创建项目,与project_creation_restriction无关(见同文件 L114-L117)
配置值写不进去该配置项仅接受everyone/adminonly,其他值会被元数据校验拒绝(src/lib/config/metadata/type.go)
配置管理器加载失败OnlyAdminCreateProject出于安全默认返回true(收紧为仅管理员),避免误放行(src/lib/config/userconfig.go)

八、总结

project_creation_restriction是 Harbor 多租户权限模型中一个简单但关键的系统配置:

  • 配置层:取值限定everyone(默认)/adminonly,由元数据框架统一管理、校验与持久化(src/lib/config/metadata/metadatalist.go);
  • 服务端:项目创建 API 通过OnlyAdminCreateProject读取配置并强制拦截非管理员请求(src/server/v2.0/handler/project.go);
  • 客户端:UI 根据配置动态隐藏/显示"新建项目"入口;
  • 验证:既有 UI 手工用例 8-02-Authentication-edit-project-creation-restriction.md,也有等价的 API 自动化用例 test_edit_project_creation.py 可长期回归。

对于多团队共享的 Harbor 实例,建议在生产环境将该项设为adminonly,由管理员统一审批项目创建,从而避免命名空间混乱与资源滥用;在开发/测试环境可保持默认的everyone以降低协作门槛。

【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询