news 2026/9/10 0:03:36

Harbor RBAC 实战:db_auth 模式下非管理员用户管理项目成员的完整验证与权限模型解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Harbor RBAC 实战:db_auth 模式下非管理员用户管理项目成员的完整验证与权限模型解析

Harbor RBAC 实战:db_auth 模式下非管理员用户管理项目成员的完整验证与权限模型解析

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

本文基于 Harbor 仓库自带的 RBAC 测试用例(tests/testcases/Group3-RBAC/3-01-DB-user-manage-project-members.md),完整还原"非系统管理员在本地数据库认证(db_auth)模式下管理项目成员"的验证流程:读者可以掌握 Harbor 项目角色体系(projectAdmin/maintainer/developer/guest/limitedGuest)的权限边界、成员增删改对各操作的实际生效点,以及 pull/push 权限与 UI 成员列表的一致性,并能对照源码理解这些行为背后的策略定义。

测试目的与适用前提

该用例的核心目的是:在 Harbor 使用本地数据库管理用户(auth_modedb_auth)时,验证一个非系统管理员用户能否按预期为项目添加不同角色的成员,以及各角色能做什么、不能做什么

原文档声明的环境前提如下,执行前必须逐项确认:

  • 一个可用、正在运行的 Harbor 实例;
  • Harbor 认证方式为本地数据库,即auth_mode配置为db_auth,用户数据存于本地数据库;
  • 一台安装了 Docker CLI 的 Linux 主机作为客户端;
  • Harbor 中至少存在三个非管理员用户(下文记为 User A、B、C)。

db_auth是 Harbor 的默认认证模式,这一点可以在源码中确认:metadatalist.go 中auth_mode元数据的DefaultValue"db_auth",其描述为The auth mode of current system, such as "db_auth", "ldap_auth", "oidc_auth";userconfig.go 在读取不到认证模式配置时同样回退返回"db_auth"db_auth与其他认证模式(ldap_authuaa_authoidc_auth等)的常量定义见 const.go。同组测试用例中还有 LDAP 模式下的对应用例 3-04-LDAP-user-manage-project-members.md,两者验证的是同一套 RBAC 模型在不同认证源下的表现。

执行测试时的三条硬性注意事项(原文档 NOTE 部分):

  1. 测试中的 User A、B、C 和项目 X 应替换为更长的、有实际含义的名称,避免与真实数据混淆;
  2. 必须同时使用两种浏览器(如 Chrome 与 Firefox)保证两个用户会话相互独立;
  3. 不要在同一浏览器的不同窗口/标签页中同时登录两个用户,否则 session 会互相覆盖,导致"User A 的会话在线"这一前提失效。

项目角色体系:测试中 guest → developer → projectAdmin 的升级路径

用例第 11、17、22 步中,User A 依次把 User B 设为 guest、developer、project admin,这正是 Harbor 项目级 RBAC 的三个典型角色。从源码 const.go 可以看到项目角色的数字常量定义:

常量说明
RoleProjectAdmin1项目管理员
RoleDeveloper2开发者
RoleGuest3访客
RoleMaintainer4维护者
RoleLimitedGuest5受限访客

这些角色与策略的映射集中定义在 rbac_role.go 的rolePoliciesMap中。与本文测试步骤直接相关的权限差异如下(完整的resource + action清单以源码为准):

  • guestRepository资源仅有Read/List/Pull三项动作,没有Push;对Member资源仅有Read/List——这解释了为什么 guest 只能拉取、不能推送,且不能管理成员;
  • developer:在 guest 基础上为Repository增加了Create/Update/Push,因此 developer 可以推送镜像,但仍然只能Read/List成员,不能添加或修改成员;
  • projectAdmin:额外拥有Member资源的Create/Update/Delete动作(以及Self资源的Read/Update/Delete),是唯一能在项目内增删改成员的角色。

projectRBACRole.GetPolicies()会按roleID解析出角色名(projectAdmin/maintainer/developer/guest/limitedGuest),再结合NewNamespace(projectID)把策略限定在该项目的命名空间内返回。也就是说,角色的每一条策略都只在其所属项目内生效,这是"成员权限随项目隔离"的底层保证。

完整测试步骤(30 步)

以下步骤完整继承自原用例文档,按"初始状态验证 → guest 授权 → developer 升级 → projectAdmin 升级 → 移除成员"五个阶段组织。

阶段一:无成员权限时的基线验证(步骤 1–10)

  1. 以 User A(非管理员)登录 Harbor UI。
  2. 创建新项目 X,publicity 保持关闭(默认 private)。
  3. 验证 User A 无法修改自己在项目 X 中的角色。
  4. 在 Docker 客户端主机上,以 User A 执行docker login <harbor_host>登录。
  5. 向项目 X 推送一个镜像。
  6. 在客户端退出 User A,登录 User B。
  7. User B 执行docker pull拉取项目 X 的镜像——应当失败
  8. User B 执行docker push向项目 X 推送镜像——应当失败
  9. 保持 User A 的 UI 会话在线,在另一台浏览器的独立会话中登录 User B。
  10. User B 查看 "My Projects"——不应看到项目 X

阶段二:加入为 guest(步骤 11–16)

  1. 在 User A 的 UI 中,将 User B 以guest角色加入项目 X。
  2. 在 User B 的 UI 中确认项目 X 出现在 "My Projects",可查看成员列表和镜像列表。
  3. 验证 User B 无法修改项目 X 中其他成员的角色。
  4. 验证 User B 无法向项目 X 添加新成员。
  5. 在客户端,User B 再次执行docker pull拉取项目 X 的镜像——应当成功
  6. User B 执行docker push向项目 X 推送镜像——应当失败

阶段三:升级为 developer(步骤 17–21)

  1. 在 User A 的 UI 中,将 User B 更新为项目 X 的developer角色。
  2. 在 User B 的 UI 中确认项目 X 在 "My Projects",可查看成员和镜像。
  3. 验证 User B 仍无法修改其他成员的角色。
  4. 验证 User B 仍无法添加新成员。
  5. 在客户端,User B 向项目 X 推送一个新镜像——应当成功

阶段四:升级为 project admin 并授权第三个用户(步骤 22–26)

  1. 在 User A 的 UI 中,将 User B 更新为项目 X 的project admin角色。
  2. 在 User B 的 UI 中确认项目 X 在 "My Projects",可查看成员和镜像。
  3. 验证 User B 现在可以添加新用户 User C 到项目 X。
  4. 验证 User B可以修改 User C 在项目 X 中的角色。
  5. 在客户端,User B 再次向项目 X 推送一个新镜像——成功。

阶段五:移除成员后验证权限即时回收(步骤 27–30)

  1. 在 User A 的 UI 中,将 User B 从项目 X 中移除。
  2. 在客户端,User B 拉取项目 X 的镜像——应当失败
  3. 在客户端退出 User B,登录 User C。
  4. User C 拉取项目 X 的镜像——应当成功(因为 User C 是步骤 24 中被加入的成员)。

预期结果逐条对照

原文档 "Expected Outcome" 部分的完整断言:

  • 步骤 3:User A 不能修改自己的角色,也不能把自己从项目 X 移除;
  • 步骤 7:User B 未加入项目前,拉取镜像失败;
  • 步骤 8:同上,推送镜像失败;
  • 步骤 9:必须确保以另一浏览器登录 User B 时 User A 的会话仍在线;
  • 步骤 10:User B 看不到项目 X;
  • 步骤 12–14:按描述,guest 可查看项目、不能改成员角色、不能加新成员;
  • 步骤 15:User B 加入为 guest 后可以拉取镜像;
  • 步骤 16:User B 作为 guest 不能推送镜像;
  • 步骤 18–20:developer 同样不能改成员角色、不能加新成员;
  • 步骤 21:developer 推送镜像成功;
  • 步骤 23–25:project admin 可以添加 User C、可以修改 User C 的角色;
  • 步骤 28:User B 被移除后拉取失败,说明权限随成员关系即时回收;
  • 步骤 30:User C 拉取成功。

源码层面的佐证与延伸

  • 成员权限的来源:guest/developer/projectAdmin 对member资源分别只有Read/List或完整的Create/Update/Delete(见 rbac_role.go),与步骤 13/14(guest 不能管理成员)、19/20(developer 不能管理成员)、24/25(projectAdmin 可以管理成员)的预期结果一一对应。
  • pull/push 权限的来源Repository资源上的Pull/Push动作是 Registry v2 认证链路的判定依据,guest 没有Push,因此步骤 8/16 推送失败、步骤 15/21/26 依角色变化而结果不同;项目范围之外的完整资源-动作清单定义在 rbac/const.go 的ScopeProject策略集中。
  • "不能修改自己角色/不能移除自己"(步骤 3)projectAdmin角色持有SelfRead/Update/Delete策略,而 guest/developer 只有Self: Read;从源码结构看,对"自己"这一子资源的操作限制是在成员管理接口的服务层结合请求者身份进一步判定的,测试用例以行为断言方式覆盖了这一边界。
  • 认证模式与用户来源db_auth表示用户账号直接存于 Harbor 的 PostgreSQL 数据库,因此测试中才能由 A 直接在 UI 里把 B、C(同为本地用户)加入项目;在 LDAP 等外部认证源下,对应用例(见 3-04-LDAP-user-manage-project-members.md)还需要处理用户搜索与 DN 匹配等额外问题。
  • 同组用例可作对照阅读:3-02-DB-user-manage-project-publicity.md 验证项目公开性管理,3-03-DB-user-search-project-members.md 验证成员搜索,3-11-DB-admin-user-manage-project-members.md 则是系统管理员执行相同成员管理操作的版本——两者对比即可看出系统管理员与项目内 projectAdmin 在成员管理上的权限差异。

小结

这个用例的价值在于它用 30 个可复现的步骤把"成员关系变化 → 角色策略变化 → pull/push 与 UI 可见性变化"的因果链完整钉死:guest 能拉不能推、developer 能推不能管人、projectAdmin 才能增删改成员,且权限随加入/移除即时生效。执行该用例时,重点检查项是步骤 7/8/10(加入前基线)、15/16(guest 边界)、21(developer 边界)、24/25(projectAdmin 边界)和 28/30(移除后的权限回收),任何一步与预期不符,都应优先对照 rbac_role.go 中对应角色的策略清单定位是权限定义问题还是会话/登录态问题(原文档 Possible Problems 一节标注为 None,说明按上述独立会话要求执行时不应出现环境问题)。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 0:02:33

ThinkPHP与Laravel双框架实战:儿童性教育网站构建解析

接手这个项目的时候&#xff0c;我第一反应是有点意外&#xff1a;ThinkPHP 和 Laravel 这两个框架&#xff0c;平时大家总是习惯二选一&#xff0c;怎么会在同一个项目里出现&#xff1f;仔细一看需求才明白&#xff0c;这不是技术选型出了问题&#xff0c;而是这个儿童性教育…

作者头像 李华
网站建设 2026/9/9 23:59:30

从断点到容器查询:媒体查询完整实战指南

我做了快十年的前端&#xff0c;有一件事特别能说明媒体查询&#xff08;Media Query&#xff09;在网页设计里的地位&#xff1a;好几个项目&#xff0c;开发阶段看着一切正常&#xff0c;设计稿还原度也高&#xff0c;结果客户拿自己的手机一打开&#xff0c;页面就乱得没法看…

作者头像 李华
网站建设 2026/9/9 23:57:05

Ruffle Flash 模拟器完整指南:从打开第一个 SWF 到调好渲染模式

Ruffle Flash 模拟器完整指南&#xff1a;从打开第一个 SWF 到调好渲染模式 【免费下载链接】ruffle A Flash Player emulator written in Rust 项目地址: https://gitcode.com/GitHub_Trending/ru/ruffle Flash Player 已经退役&#xff0c;但你硬盘里的 .swf 游戏文件…

作者头像 李华
网站建设 2026/9/9 23:52:57

1D信号数据增强实战:从时域变换到深度生成模型

1. 这个题目到底在解决什么问题先把这个话题聊透。做1D信号处理的人&#xff0c;手里几乎都有一个说不出口的痛&#xff1a;数据不够。不是不够用&#xff0c;是根本不够训模型。拿工业故障诊断来说&#xff0c;正常工况的样本一抓一大把&#xff0c;但故障样本尤其是早期故障、…

作者头像 李华
网站建设 2026/9/9 23:52:53

C++虚函数详解:构造函数不能虚,析构函数必须虚

1. 题目拆解&#xff1a;这到底在考什么不管你是准备C面试&#xff0c;还是写了好几年业务代码突然被同事问住&#xff0c;这个问题出现的频率都相当高。表面上看它只是一个“是或否”的判断题&#xff0c;但背后牵扯到虚函数机制、对象内存布局、构造和析构顺序、多态行为的边…

作者头像 李华