Harbor LDAP 模式下非管理员用户多项目创建与分页功能验证指南
【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor
导读
本文档对应 Harbor 仓库中的功能验证用例 2-13-LDAP-user-push-multiple-projects.md,核心目的是验证在 LDAP/AD 认证模式下(auth_mode=ldap_auth),非管理员用户能否创建多个项目,并验证项目列表的分页与搜索功能是否正常工作。读完本文,你将掌握 LDAP 模式下多项目创建验证的完整环境准备、操作步骤与预期结果判定方法,同时理解 Harbor 底层 LDAP 认证、项目公开性与分页查询的实现原理,便于自行设计同类回归测试。
一、测试目标与适用场景
本用例归属于tests/testcases/Group2-image-management测试套件,该套件系统性地覆盖了 Harbor 镜像管理领域的核心用户场景,包括:
| 用例 | 主题 | 认证模式 |
|---|---|---|
| 2-01 | 创建项目 | DB(本地数据库) |
| 2-03 | 创建多个项目 | DB |
| 2-11 | 创建项目 | LDAP |
| 2-12 | 推送多个镜像 | LDAP |
| 2-13(本文) | 创建多个项目 | LDAP |
| 2-14 | 查看项目 | LDAP |
本用例与 2-03 的唯一区别在于用户来源:2-03 中用户由 Harbor 本地数据库管理(db_auth),而本用例中用户数据存储在 LDAP/AD 服务器中(ldap_auth)。这决定了该用例的验证重点是:LDAP 用户经 Harbor 认证"上船"(onboard)后,其身份权限模型与本地用户完全一致,应具备同等的项目创建能力。
为什么要单独验证 LDAP 模式
从 src/core/auth/ldap/ldap.go 的实现可以看到,LDAP 用户登录时与本地用户有一个关键差异:LDAP 用户通过绑定(Bind)方式在 LDAP 服务器上完成密码校验,成功后 Harbor 会在本地数据库中插入一条"虚拟"用户记录,以便将用户与项目、成员、角色等实体关联。这个流程由PostAuthenticate→OnBoardUser完成(ldap.go 中的OnBoardUser会为 LDAP 用户生成随机密码并标记Comment = "from LDAP.",密码本身不保存在本地库中)。
因此,本用例本质上是在验证这条"LDAP 校验 + 本地关联"链路在创建项目、分页浏览、关键词搜索等操作下是否稳定可靠。
二、环境准备(Environment)
依据原文档,执行本用例需要满足以下前提条件:
- Harbor 实例正在运行且可访问。
- Harbor 配置为向 LDAP/AD 服务器进行认证,即
auth_mode设置为ldap_auth,用户数据存储在 LDAP/AD 服务器中。 - 一台安装了 Docker CLI 的 Linux 主机(作为 Docker 客户端)。
- 至少一个非管理员用户(本文以"用户 A"代称,实际使用时应替换为更有意义的长名称)。
注:与原文档保持一致,LDAP 模式下该用例只要求"至少一个非管理员用户"即可完成多项目创建验证,无需像 2-11 那样准备两个用户。
2.1 认证模式常量的源码确认
在 src/common/const.go 中可找到认证模式的常量定义:
LDAPAuth = "ldap_auth"Harbor 的认证助手通过auth.Register机制注册,ldap.go 末尾的init()函数完成注册:
func init() { auth.Register(common.LDAPAuth, &Auth{ userMgr: user.New(), }) }这意味着当系统配置auth_mode=ldap_auth时,登录请求会路由到ldap.Auth实现,使用 LDAP 服务器完成身份校验。
2.2 LDAP 登录认证链路
ldap.go 中的Authenticate方法描述了完整链路,这也是本用例能执行的前提:
- 校验用户名非空;
- 加载系统 LDAP 配置并建立会话(
ldapCtl.Ctl.Session+Session.Open); - 在 LDAP 中搜索用户(
SearchUser),要求恰好命中一条记录,否则分别报Not found an entry/Multiple entries found; - 使用用户 DN 与密码向 LDAP 服务器执行 Bind 校验;
- 校验通过后,将用户名、真实姓名、邮箱写入
models.User; - 从本地数据库同步
SysAdminFlag,并附加 LDAP 用户组信息(含组管理员 DN 识别、ldap_group_search_filter配置的组成员填充); - 返回用户模型,交由后续的
PostAuthenticate完成 onboard。
值得注意的细节:attachLDAPGroup中会判断该用户所属组是否等于配置的group_admin_dn,若命中则设置AdminRoleInAuth = true——这也是 LDAP 模式下组管理员与系统管理员角色识别的关键逻辑。若 LDAP 组搜索过滤器为空则跳过组填充,不会阻塞用户登录。
三、测试步骤(Test Steps)
原文档指出"操作步骤与 2-03 相同,仅用户来自 LDAP/AD"。为便于独立执行,下面将 2-03-DB-user-push-multiple-projects.md 的完整步骤迁移到 LDAP 场景,并补充验证要点:
- 以非管理员用户 A 登录 Harbor UI(用户 A 必须来自 LDAP/AD,且通过 LDAP 认证成功 onboard)。
- 创建 16 个或更多项目,使项目列表出现多页分页。创建项目时可采用默认配置(公开性关闭,即私有项目)。
- 在多页列表间翻页浏览,并点开若干项目查看详情,验证分页控件工作正常。
- 使用关键词搜索项目,验证列表与分页是否随搜索结果同步更新。
原文提示:文中的"用户 A""项目 X/Y"等占位名称,实际执行时应替换为更长、更有辨识度的名称,避免与真实数据混淆。
3.1 步骤要点解析
步骤 2 的关键在于"量":只有项目数量超过单页容量(Harbor 项目列表 API 默认按page/page_size参数分页)才会出现多页,因此要求创建 16 个以上项目以覆盖至少两页。这一步同时验证了 LDAP 用户连续创建多个项目的权限与配额是否正常。
步骤 4 的关键在于"搜索与分页联动":输入关键词后,列表应只展示匹配项目,且分页总页数应基于过滤后的总数重新计算——这要求服务端先按关键词过滤、再分页返回,而不是在前端做简单过滤。
3.2 使用 REST API 辅助验证(可选)
除了 UI 操作,还可以通过 Harbor v2.0 API 直接验证分页与搜索行为。项目列表接口对应的服务端实现位于 src/server/v2.0/handler/project.go,其关键调用链为:
query, err := a.BuildQuery(ctx, params.Q, params.Sort, params.Page, params.PageSize) ... WithLink(a.Links(ctx, params.HTTPRequest.URL, total, query.PageNumber, query.PageSize).String()).对应可构造如下请求:
# 不带筛选,看第 1 页,每页 10 条 curl -u "<userA>:<password>" \ "https://<harbor_host>/api/v2.0/projects?page=1&page_size=10" # 按关键词过滤,同时观察分页 curl -u "<userA>:<password>" \ "https://<harbor_host>/api/v2.0/projects?q=name=~<keyword>&page=1&page_size=10"其中q参数的模糊匹配语法(name=~keyword)来自 src/lib/q/builder.go,该文件定义了完整的查询语法:精确匹配k=v、模糊匹配k=~v、区间k=[min~max]、或列表k={v1 v2 v3}、与列表k=(v1 v2 v3)。
四、预期结果(Expected Outcome)
与原文档及 2-03 一致,本用例的预期结果如下:
- 步骤 3:分页控件正常工作,LDAP 用户 A 可以在多页之间自由翻页,点开各项目详情均可正常查看;
- 步骤 4:关键词搜索后,列表与分页同步更新,仅显示匹配搜索条件的项目,且分页总数基于过滤结果正确计算。
也就是说:LDAP 模式下的非管理员用户应拥有与 DB 模式用户完全一致的多项目创建、浏览与搜索能力。
五、源码级原理:这些行为在 Harbor 中如何实现
5.1 项目创建与公开性(Publicity)
项目模型定义在 src/pkg/project/models/project.go,其中:
- 项目公开性通过元数据键
public存储,常量ProjectPublic/ProjectPrivate分别对应"public"/"private"; IsPublic()读取public元数据并判断是否为 true(字符串"true"或"1"均视为 true);FilterByPublic通过子查询SELECT project_id FROM project_metadata WHERE name = 'public' AND value = '...'实现公开项目过滤。
项目控制器 src/controller/project/controller.go 对外暴露Create、List、Count、ListRoles等操作,其中ListRoles用于查询用户在某项目中的角色,非管理员用户创建项目后会自动成为该项目管理员(项目所有者)。
5.2 分页与排序的实现
Harbor 的统一分页机制位于 src/lib/q/builder.go 的Build函数:
// Build query sting, sort and pagination information into the Query model // query string format: q=k=v,k=~v,k=[min~max],k={v1 v2 v3},k=(v1 v2 v3) func Build(q, sort string, pageNumber, pageSize int64) (*Query, error)它将查询串、排序串、页码与页大小统一封装为Query模型(含Keywords、Sorts、PageNumber、PageSize)。排序语法支持sort=k1,-k2(前缀-表示降序)。
服务端处理器通过 src/server/v2.0/handler/base.go 中的BuildQuery组装查询,并用Links方法基于总数、页码、页大小生成上一页/下一页的导航链接——这正是 UI 分页控件的数据来源:
// BuildQuery builds the query model according to the query string func (b *BaseAPI) BuildQuery(_ context.Context, query, sort *string, pageNumber, pageSize *int64) (*q.Query, error) { ... return q.Build(qs, st, pn, ps) }结合 src/server/v2.0/handler/project.go 的调用点(第 318、346 行等)可以确认:项目列表 API 先过滤(q)、再排序(sort)、后分页(page/page_size),并基于总数生成分页链接。这从底层印证了"关键词搜索后分页同步更新"的预期行为是服务端语义,而非前端实现。
5.3 LDAP 用户与本地权限模型的统一
本用例之所以能与 DB 模式用例"共用步骤",其根本原因在于:LDAP 用户登录成功后,Harbor 通过OnBoardUser在本地用户表中建立映射记录(密码为随机字符串、备注from LDAP.),后续所有权限判断(项目创建、成员关系、角色分配)均基于本地用户 ID 进行。因此从项目控制器的视角看,LDAP 用户与 DB 用户没有区别——这正是测试套件中 DB 用例与 LDAP 用例成对出现、步骤互引的设计动机。
六、常见问题与排查建议
原文档"Possible Problems"一节为空(None),但根据源码可以预判并排查以下潜在问题:
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 用户无法登录 | LDAP 配置错误、搜索命中多条记录 | 检查ldap_url、ldap_base_dn、ldap_uid配置;查看 ldap.go 中Authenticate对"多条记录"的报错 |
| 登录成功但无法创建项目 | 系统配置中限制了普通用户创建项目(如project_creation_restriction),或用户未被正确 onboard | 确认系统设置中的项目创建权限;检查用户表中是否存在Comment = "from LDAP."的映射记录 |
| 分页/搜索结果与预期不符 | 服务端q参数语法错误 | 参照 src/lib/q/builder.go 的语法规则构造查询 |
| LDAP 用户被识别为系统管理员 | 用户属于group_admin_dn配置的组,AdminRoleInAuth被置为 true | 检查attachLDAPGroup逻辑与组管理员配置 |
七、结语
本用例以极简的方式验证了一个关键的产品承诺:无论用户来自本地数据库还是 LDAP/AD,Harbor 都向非管理员用户提供一致的多项目创建、分页浏览与搜索能力。它作为 Group2 镜像管理测试套件中 LDAP 链路的一环,与 2-11(创建单个项目)、2-12(推送多个镜像)、2-14(查看项目)共同构成了 LDAP 模式下镜像管理主链路的完整回归覆盖。测试人员可将本文步骤作为模板,结合自身 LDAP 目录结构扩展更多项目数量与搜索关键词,以覆盖边界场景。
【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考