Harbor 内容信任实战:Docker 客户端拉取已签名镜像(DB 模式)完整指南
2026/9/10 2:58:12 网站建设 项目流程

Harbor 内容信任实战:Docker 客户端拉取已签名镜像(DB 模式)完整指南

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

导读

本文以 Harbor 官方内容信任(Content Trust)测试用例 9-03-DB-user-pull-signed-images.md 为骨架,系统讲解在本地数据库(DB 模式)认证环境下,普通用户如何通过 Docker 客户端启用 Docker Content Trust(DCT)并成功拉取已签名镜像的完整流程。读者将掌握DOCKER_CONTENT_TRUSTDOCKER_CONTENT_TRUST_SERVER环境变量的正确配置、自签名证书环境下 Notary 服务的信任配置、签名镜像在 Harbor Web 界面的识别方法,以及 Harbor 服务端在拉取链路上执行内容信任校验的底层原理。

背景:为什么需要"内容信任"与 Notary

Harbor 是一个开源的云原生制品仓库,支持制品的存储、签名与扫描。内容信任(Content Trust)基于 Docker 的 Notary 项目实现:当客户端启用 DCT 后,推送镜像时会同时生成签名元数据并上传至 Notary 服务(Harbor 中该服务默认监听4443端口);拉取镜像时,Docker 客户端会先向 Notary 校验镜像的签名与信任链,再决定是否拉取对应镜像内容。

在 Harbor 中,内容信任的落地分为两个层面:

  1. 客户端层面:由 Docker CLI 通过环境变量控制是否签名、是否校验签名;
  2. 服务端层面:当项目开启了"内容信任"策略后,Harbor 的 Registry 路由会在拉取镜像的请求链路上插入校验中间件,强制要求镜像存在有效签名,否则拒绝拉取。

本文聚焦第一个层面——用户主动开启 DCT 并成功拉取已签名镜像(对应测试用例 9-03)。

环境准备

依据测试用例的Environment一节,执行本流程需要满足:

  • 一个正在运行且可访问的 Harbor 实例(本地数据库认证模式,即 DB 模式);
  • 一台安装了 Docker CLI(Docker 客户端)的 Linux 机器;
  • 一个已经存在的 Harbor 项目(文中以 project X 代指)。

补充说明:DB 模式意味着用户数据存放在 Harbor 内置的本地数据库中,与之相对的是 LDAP/AD 等外部认证模式。本测试用例 9-03 针对 DB 模式设计;对应的 LDAP 版本见 9-13-LDAP-user-pull-signed-images.md,管理员版本见 9-23-admin-pull-signed-images.md。

测试步骤详解

第 1 步:登录 Harbor Web UI

在浏览器中访问 Harbor 门户,使用具有目标项目访问权限的普通用户账号登录 UI。确保目标项目 X 已存在(可通过 9-01-DB-user-push-signed-images.md 中的流程创建项目并推送已签名镜像作为前置准备)。

第 2 步:在 Docker 客户端启用内容信任并登录

在 Docker 客户端主机上执行以下环境变量设置:

export DOCKER_CONTENT_TRUST=1 export DOCKER_CONTENT_TRUST_SERVER=https://<harbor_ip>:4443
  • DOCKER_CONTENT_TRUST=1:通知 Docker CLI 启用内容信任模式。此模式下,docker pull在拉取镜像前会先向信任服务器查询该镜像的签名元数据,只有签名有效时才继续拉取镜像内容。
  • DOCKER_CONTENT_TRUST_SERVER=https://<harbor_ip>:4443:显式指定信任服务器地址。Harbor 部署的 Notary 服务默认暴露在 4443 端口(HTTPS)。不设置此变量时,Docker 会按https://<registry_host>:4443的默认约定推断,但在 Harbor 场景下显式指定更稳妥。

设置完成后,登录 Harbor:

docker login <harbor_ip>

按提示输入用户名与密码。若目标 Harbor 使用了非默认端口,需在<harbor_ip>后附带端口号。

自签名证书注意事项:如果 Harbor 使用自签名证书,Docker 客户端默认不会信任该证书,必须将 CA 根证书复制到以下两个位置(来自测试用例的 NOTE 说明):

# Registry 访问信任 /etc/docker/certs.d/<harbor_ip>/ # Notary 信任服务器访问信任(端口 4443) $HOME/.docker/tls/<harbor_ip>:4443/

完成证书放置后重启 Docker 守护进程使其生效。这一步骤缺失时,docker login或后续的信任校验会因 TLS 证书不受信任而失败。

第 3 步:拉取已签名镜像

从项目 X 中拉取一个已签名镜像:

docker pull <harbor_ip>/project_x/signed-image:tag

其中project_x应替换为实际项目名,signed-image:tag替换为实际镜像名与标签。

预期结果

根据测试用例Expected Outcome

镜像可以被成功拉取。

docker pull命令成功完成,本地出现该镜像。这表明:在DOCKER_CONTENT_TRUST=1下,Docker 客户端成功向 Harbor 的 Notary 服务(4443 端口)验证了镜像签名,随后从 Registry 拉取了镜像内容。

服务端原理:Harbor 如何配合签名拉取

虽然测试用例 9-03 主要验证"客户端开启 DCT 后能拉到签名镜像",但理解 Harbor 服务端的处理逻辑有助于排查问题。从源码看,Harbor 在 Registry 的 manifest 拉取链路上挂了内容信任中间件。

在 src/server/registry/route.go 中,GETHEAD两种/*/manifests/:reference请求都挂载了contenttrust.ContentTrust()中间件:

root.NewRoute(). Method(http.MethodGet). Path("/*/manifests/:reference"). Middleware(metric.InjectOpIDMiddleware(metric.ManifestOperationID)). Middleware(repoproxy.ManifestMiddleware()). Middleware(contenttrust.ContentTrust()). Middleware(vulnerable.Middleware()). HandlerFunc(getManifest)

中间件实现位于 src/server/middleware/contenttrust/contentrust.go:它根据请求中的ArtifactInfo找到对应项目,若项目开启了内容信任策略(ContentTrustEnabled()ContentTrustCosignEnabled()),则进一步调用signatureChecking检查制品是否带有对应类型的签名 accessory;若无签名,则返回PROJECTPOLICYVIOLATION错误,拒绝拉取。

项目级策略通过项目元数据(metadata)实现,键定义在 src/pkg/project/models/pro_meta.go:

  • enable_content_trust(对应ProMetaEnableContentTrust):是否要求镜像具备 Notation 签名;
  • enable_content_trust_cosign(对应ProMetaEnableContentTrustCosign):是否要求镜像具备 Cosign 签名。

对应的布尔判断实现在 src/pkg/project/models/project.go。

需要强调的是:9-03 场景下项目未必开启了上述项目级策略,拉取成功的关键在于 Docker 客户端自身开启 DCT 并成功完成签名校验。项目级策略是另一道服务端强制门禁,对应测试 9-30-Project-level-content-trust.md(启用策略后,未签名镜像将无法拉取,而签名镜像可以拉取)。

关联场景:签名镜像的完整生命周期

9-03 属于 Group9-Content-trust 测试组中"DB 模式普通用户"的子集,将其放入整个测试矩阵可以更清楚地理解内容信任的完整闭环:

测试用例操作关键预期
9-01开启 DCT 后推送镜像镜像被签名并推送成功,UI 显示绿色对勾
9-02关闭 DCT 推送镜像推送成功但无签名
9-03开启 DCT 拉取已签名镜像拉取成功
9-04开启 DCT 拉取未签名镜像拉取被拒绝
9-05删除已签名镜像删除成功

从 9-01 的Expected Outcome可以看到,签名镜像在 Harbor UI 中会以"绿色对勾"标识呈现,这是确认镜像已被签名的最直观方式。在 9-04 中,当DOCKER_CONTENT_TRUST=1时拉取未签名镜像会失败——这正是 Docker 客户端侧 DCT 校验拦截的结果,与 9-03 形成对照。

常见问题与排查思路

测试用例中Possible Problems为 None,但在真实环境中仍可能遇到以下情况:

  1. TLS 证书错误(x509: certificate signed by unknown authority:自签名证书未按上文复制到/etc/docker/certs.d/<harbor_ip>/$HOME/.docker/tls/<harbor_ip>:4443/,或复制后未重启 Docker 守护进程。
  2. 拉取被拒(could not find signed tag/no valid trust data:目标镜像本身未签名(未在 DCT 开启状态下推送),请先通过 9-01 流程准备签名镜像,或在 UI 中确认镜像带绿色对勾标识。
  3. 项目级内容信任策略拦截:若项目在配置页面开启了"内容信任"或"Cosign 内容信任",未签名镜像即使客户端开启 DCT 也会被 Harbor 服务端中间件拒绝(返回PROJECTPOLICYVIOLATION,错误信息为 "The image is not signed by notation/cosign")。此时需使用签名镜像,或按 9-30 的流程验证策略行为。
  4. 信任服务器端口不通:确认 Harbor 的 Notary 服务(4443 端口)对外可达,且DOCKER_CONTENT_TRUST_SERVER中的 IP/FQDN 与证书中的主机名匹配。

小结

本测试用例验证了 Harbor 内容信任体系中最基础也最关键的一环:DB 模式下的普通用户能够在启用DOCKER_CONTENT_TRUST后成功拉取已签名镜像。整个过程同时涉及 Docker 客户端侧(环境变量、信任服务器、TLS 证书)与 Harbor 服务端侧(Notary 4443 端口、manifest 拉取链路中间件、项目元数据策略)。掌握 9-03 的操作流程,再配合 9-01(签名推送)、9-04(未签名拦截)与 9-30(项目级强制策略)等关联用例,即可完整落地 Harbor 的镜像签名信任体系。

相关文件索引:

  • 测试用例:9-03-DB-user-pull-signed-images.md、9-01-DB-user-push-signed-images.md、9-04-DB-user-pull-unsigned-images.md、9-30-Project-level-content-trust.md
  • 服务端中间件:src/server/middleware/contenttrust/contentrust.go
  • 路由挂载点:src/server/registry/route.go
  • 项目元数据键定义:src/pkg/project/models/pro_meta.go
  • 项目策略判断:src/pkg/project/models/project.go

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

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

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

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

立即咨询