Harbor 复制端点 CA 证书配置:per-endpoint 自定义 CA 校验与连接测试全解析
【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor
导读
在 Harbor 的跨实例复制(Replication)场景中,远端 Registry 若使用自签名或私有 CA 签发的 HTTPS 证书,传统做法是关闭「Verify Remote Cert」校验,但这会牺牲传输安全。Harbor 为每个复制端点(endpoint)提供了独立的CA Certificate配置字段,允许管理员按端点粘贴 PEM 格式的 CA 证书,在保持证书校验开启的前提下建立可信连接。本文将结合 Harbor 官方测试用例与仓库源码,完整讲解 per-endpoint CA 证书的配置方法、底层 TLS 校验机制、连接测试的判定逻辑,以及常见坑点。
测试用例背景:验证什么、需要什么环境
本主题对应仓库中的系统测试用例 7-16-Endpoints-per-endpoint-ca-certificate.md,该用例的验证目标是:
确认管理员可以为使用自签名(或其他不受信任)证书的 Registry 端点配置 per-endpoint CA 证书,并且 Harbor 会使用该证书校验连接,而不是必须关闭「Verify Remote Cert」。
用例对环境的要求是:
- 至少两个 Harbor 实例处于运行且可访问状态;
- 远端实例以HTTPS + 自签名证书提供服务。
这说明该特性面向的是真实的跨 Harbor 复制场景——两个 Harbor 之间互为主备或数据同步时,远端 Harbor 的 HTTPS 证书往往由企业内部 CA 签发或为自签名,此时为端点单独配置信任证书是保证复制安全性的关键手段。
核心配置字段:insecure与ca_certificate
在 Harbor 的注册表(Registry)端点模型中,与 TLS 校验相关的两个核心字段定义在 src/pkg/reg/model/registry.go:
type Registry struct { ID int64 `json:"id"` Name string `json:"name"` Description string `json:"description"` Type string `json:"type"` URL string `json:"url"` // TokenServiceURL is only used for local harbor instance to // avoid the requests passing through the external proxy for now TokenServiceURL string `json:"token_service_url"` Credential *Credential `json:"credential"` Insecure bool `json:"insecure"` CACertificate string `json:"ca_certificate,omitempty"` Status string `json:"status"` CreationTime time.Time `json:"creation_time"` UpdateTime time.Time `json:"update_time"` }两个字段的语义:
| 字段 | 类型 | 含义 | 对应 UI 控件 |
|---|---|---|---|
Insecure | bool | 是否跳过对远端证书的校验(即 UI 上的Verify Remote Cert复选框,勾选=校验=true) | Verify Remote Cert 复选框 |
CACertificate | string | PEM 编码的 CA 证书内容,用于校验该端点证书的替代信任源 | CA Certificate 文本框 |
注意 UI 上Verify Remote Cert勾选时对应Insecure=false;该复选框取消勾选时Insecure=true(跳过校验)。两者配合关系在 OpenAPI 规范中有明确描述,见 api/v2.0/swagger.yaml:
insecure:Whether or not the certificate will be verified when Harbor tries to access the server.ca_certificate:The PEM-encoded CA certificate for this registry endpoint. If provided, this CA will be used to verify the registry's certificateinstead of the system CA pool.
后者的关键点是:一旦填写了自定义 CA,Harbor 将优先使用该 CA 替代系统 CA 池来校验该端点的服务端证书。
底层实现:TLS Transport 的选择优先级
Harbor 的所有 Registry 适配器在构建 HTTP 客户端时,都会把端点的Insecure与CACertificate透传给统一的传输层构造函数GetHTTPTransport,例如:
- 原生 Docker Registry 适配器 src/pkg/reg/adapter/native/adapter.go:
adapter.Client = registry.NewClientWithCACert(reg.URL, username, password, reg.Insecure, reg.CACertificate)- Harbor 对 Harbor 适配器 src/pkg/reg/adapter/harbor/base/adapter.go 同样透传两个配置项。
传输层的核心判定逻辑位于 src/common/http/transport.go:
func GetHTTPTransport(opts ...TransportOption) http.RoundTripper { cfg := &TransportConfig{} for _, opt := range opts { opt(cfg) } if cfg.CACertificate != "" { return NewTransport( WithCustomCACert(cfg.CACertificate), ) } if cfg.Insecure { return insecureHTTPTransport } return secureHTTPTransport }由此可以归纳出三档优先级(源码注释中亦明确列出):
- 自定义 CA 证书优先:只要
CACertificate非空,就基于该证书新建 TLS Transport(WithCustomCACert),使用自定义 CA 验证远端证书; - Insecure 模式:未填 CA 但
Insecure=true时,使用全局共享的跳过校验 Transport(insecureHTTPTransport); - 默认模式:两者皆空时,使用系统 CA 池的共享 Transport(
secureHTTPTransport)。
这正是测试用例所验证行为的代码级证据:在「填写匹配的 CA 且Verify Remote Cert保持开启」的情况下,请求走的是第 1 档——自定义 CA 校验,而不是被降级为跳过校验。
对应地,TransportOption的两个构造函数定义在同文件 src/common/http/transport.go:
// WithInsecure returns a TransportOption that configures the transport to skip verification of the server's certificate func WithInsecure(skipVerify bool) TransportOption { return func(cfg *TransportConfig) { cfg.Insecure = skipVerify } } // WithCACert returns a TransportOption that configures custom CA certificate func WithCACert(caCert string) TransportOption { return func(cfg *TransportConfig) { cfg.CACertificate = caCert } }该逻辑还配套了针对性的单元测试,覆盖有效 CA、无效 CA、空 CA、Insecure 与 CA 组合等场景,见 src/common/http/transport_test.go,可作为理解传输层行为的参考。
连接测试(Test Connection)如何判定成功
测试用例中的关键步骤是「点击 Test Connection」。该动作在源码层面最终调用的是原生适配器的HealthCheck(或Ping)方法:
- src/pkg/reg/adapter/native/adapter.go:
HealthCheck依据端点是否配置了凭据,分别走PingSimple(无凭据,仅校验连通性与证书)或Ping(带凭据); - src/pkg/reg/adapter/native/adapter.go:
PingSimple只关心连通性与 TLS 证书校验是否通过,401/403 等鉴权错误不算失败。
因此,连接测试成功与否直接取决于 TLS 握手阶段的证书校验结果:
- 当粘贴的 CA 与远端端点证书匹配时,TLS 校验通过 →
HealthCheck返回Healthy→ UI 显示连接成功、可保存端点; - 当粘贴的 CA 与远端端点证书不匹配(或用错 CA)时,TLS 握手在证书校验处失败(典型错误如
x509: certificate signed by unknown authority)→ 测试失败 → 端点无法保存。
这与测试用例的 Expected Outcome 完全一致:
- Step 2:提供匹配的 CA,Test Connection 成功,端点保存;
- Step 3:替换为不匹配的 CA,Test Connection 失败。
完整操作步骤(UI 实操)
以下操作路径对应测试用例 7-16,适用于至少两台 Harbor 实例、远端为 HTTPS 自签名证书的环境:
Step 1:准备远端 CA 证书
在运行远端 Harbor 的机器上导出其 HTTPS 证书签发者(自签名证书则导出其自身)的 PEM 内容。如果远端证书由内部 CA 签发,则需要该 CA 的根证书;证书链中间证书可一并放入同一字段(Go 的x509会按 PEM 块依次解析,支持多证书链)。
Step 2:新增端点并配置 CA(用例 Step 2)
- 使用 admin 账号登录 Harbor UI;
- 进入
Administration -> Registries页面; - 点击New Endpoint,填写:
- 端点 URL:远端 Harbor 的 HTTPS 地址(如
https://remote-harbor.example.com); - 访问凭证:用户名 / 密码;
- 保持
Verify Remote Cert复选框为勾选状态(即不关闭证书校验); - 在
CA Certificate文本框中粘贴与远端证书匹配的 PEM 格式 CA 证书;
- 端点 URL:远端 Harbor 的 HTTPS 地址(如
- 点击Test Connection,预期结果为连接成功;
- 保存端点。
Step 3:验证不匹配 CA 的拦截(用例 Step 3)
- 在
Administration -> Registries中编辑刚保存的端点; - 将
CA Certificate替换为一张与远端端点证书不匹配的 CA 证书; - 保持
Verify Remote Cert勾选; - 再次点击Test Connection,预期结果为连接失败——这正是自定义 CA 生效、证书校验未被绕过的直接证明。
可选:结合 API 验证
Endpoint 创建/更新对应的 REST API 也暴露了insecure与ca_certificate字段(见 api/v2.0/swagger.yaml 的RegistryUpdate定义),可通过 Harbor API 以 JSON 形式设置与查询这两个字段,方便在自动化脚本中复现上述步骤。
常见问题与避坑指南
- CA 与 Insecure 的优先级:一旦填写了
CA Certificate,即使Insecure被置为 false(校验开启),传输层也会优先使用自定义 CA(见上文GetHTTPTransport的分支顺序)。反之,若只勾选不校验而不填 CA,则完全跳过证书校验,安全性最弱。 - 自签名证书与 IP SAN:在 Harbor 内部(
CORE_URL与本机一致)的本地端点场景,源码注释提到会遇到x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs类问题,因此本地端点会被强制使用 insecure transport 并忽略 CA 证书,参见 src/pkg/reg/adapter/harbor/base/adapter.go。该行为仅适用于「本 Harbor 检测到目标 URL 与自身一致」的特殊情形,普通远端端点不受影响。 - 多证书链:CA 字段支持粘贴完整 PEM 链(根 CA + 中间 CA),测试
GetHTTPTransport的多证书场景可见 src/common/http/transport_test.go。 - 证书更换后重新测试:编辑端点替换 CA 后务必重新点击 Test Connection,Harbor 会在保存前用新的传输配置发起一次真实 TLS 握手,不匹配的 CA 会在该阶段即被拒绝。
小结
Harbor 的 per-endpoint CA 证书能力,让复制端点在「保持证书校验开启」的前提下,通过自定义 CA 信任自签名/私有 CA 的远端 Registry,避免了为兼容自签名证书而整体关闭校验的安全妥协。从源码看,其实现机制是传输层GetHTTPTransport对「自定义 CA > Insecure > 系统 CA 池」的三级优先级选择,连接测试则通过适配器HealthCheck/Ping完成真实 TLS 握手验证。参考 测试用例 与 传输层实现,你可以在自己的多 Harbor 复制环境中安全地启用该配置。
【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考