4. Harbor 中的签名机制:架构、存储与镜像关系
Harbor 的镜像签名机制基于 Notary 项目(Docker Content Trust 的后端实现),为镜像提供端到端的完整性验证。签名机制的核心在于:镜像在被推送到 Harbor 时,由客户端(Docker 或 Helm)对镜像摘要进行数字签名,并将签名元数据存储在独立的 Notary 服务中;Harbor 本身不直接存储签名数据,而是通过 Notary 的 API 查询签名状态,并在镜像拉取或部署时进行校验。
4.1 Harbor 签名架构
Harbor 的签名架构采用“镜像仓库 + 签名仓库”分离的设计模式。镜像层数据存储在 Harbor 的 Registry(基于 Distribution)中,而签名元数据存储在 Notary Server 的数据库(通常为 MySQL 或 PostgreSQL)中。两者通过统一的认证网关(Harbor Core)进行关联。
架构要点:
- Notary Server:负责接收、存储和查询签名数据,提供 TUF(The Update Framework)元数据服务。
- Notary Signer:负责对签名进行私钥管理和签名操作,通常与 Notary Server 分离部署。
- Harbor Core:作为统一入口,在镜像推送/拉取时调用 Notary API 检查签名状态。
- 客户端(Docker/Helm):在推送镜像前使用
docker trust sign或helm push配合 Notary 客户端完成签名。
4.2 签名存储位置
签名数据并不存储在 Harbor 的镜像仓库(Registry)中,而是存储在独立的 Notary 数据库中。这种分离设计带来了安全性和可扩展性的优势:即使 Registry 被攻破,攻击者也无法篡改签名数据;同时,签名查询不会影响镜像拉取的性能。
| 存储组件 | 存储内容 | 存储位置 | 访问方式 |
|---|---|---|---|
| Registry | 镜像层(Blob)、镜像清单(Manifest) | 文件系统 / S3 / GCS 等对象存储 | Docker Registry API |
| Notary Server | TUF 元数据(root.json、targets.json、snapshot.json、timestamp.json) | Notary 数据库(MySQL/PostgreSQL) | Notary API(/v2/_trust/tuf/) |
| Notary Signer | 签名私钥(加密存储) | Notary 数据库或 HSM(硬件安全模块) | gRPC 内部接口 |
| Harbor Core | 签名策略配置、项目级别的签名要求 | Harbor 数据库(PostgreSQL) | Harbor API |
存储路径示例: 在 Notary 数据库中,签名元数据按
docker.io/library/nginx 这样的镜像全名组织。每个镜像仓库对应一组 TUF 元数据文件,其中 targets.json 记录了所有已签名的镜像摘要(digest)及其签名信息。
4.3 签名与镜像的关系
签名与镜像之间是 多对一 的关系:一个镜像可以拥有多个签名(来自不同签名者或不同密钥),但每个签名只对应一个特定的镜像摘要(digest)。签名并不绑定到镜像标签(tag),而是绑定到镜像的 内容哈希,这确保了签名的不可篡改性。
4.4 签名验证流程
当客户端拉取镜像时,Harbor 的准入控制机制会触发签名验证。验证流程分为以下步骤:
- 客户端请求拉取镜像:Docker 客户端向 Harbor Core 发起
GET /v2/<project>/<repo>/manifests/<tag>请求。 - Harbor Core 查询签名策略:检查项目配置是否要求镜像必须签名。
- Harbor Core 调用 Notary API:向 Notary Server 查询该镜像摘要对应的签名元数据。
- Notary Server 返回签名状态:返回
targets.json中记录的签名信息,包括签名者、签名时间、使用的密钥 ID。 - Harbor Core 执行策略判定:如果项目要求签名但未找到有效签名,则拒绝拉取请求;否则允许拉取。
- 客户端验证签名:Docker 客户端使用本地信任根(root.json)验证签名的完整性和可信度。
重要注意事项:
- 签名验证的 最终责任在客户端:Harbor 的准入控制只能确保镜像在仓库层面有签名,但客户端仍需通过
DOCKER_CONTENT_TRUST=1环境变量启用本地验证。 - 签名与标签的 解耦:如果镜像标签被更新(指向新的摘要),旧的签名不会自动迁移到新摘要上,需要重新签名。
- 多签名者场景:在大型企业中,一个镜像可能需要经过开发、测试、安全三个角色的签名才能部署,Harbor 支持配置“最少签名数量”策略。
4.5 签名元数据内容
Notary 存储的 TUF 元数据是签名机制的核心。以下是一个简化的 targets.json 示例,展示了签名与镜像摘要的绑定关系:
{
"signed": {
"_type": "Targets",
"expires": "2026-01-01T00:00:00Z",
"targets": {
"nginx:latest": {
"hashes": {
"sha256": "abc123def456..."
},
"length": 1234567,
"custom": {
"harbor-signature": {
"signer": "developer-a",
"timestamp": "2025-03-15T10:30:00Z",
"key-id": "a1b2c3d4e5f6..."
}
}
}
},
"version": 1
},
"signatures": [
{
"keyid": "a1b2c3d4e5f6...",
"method": "ecdsa",
"sig": "3045022100..."
}
]
}
关键字段说明:
targets:键为镜像标签,值为对应的摘要哈希和自定义签名信息。custom.harbor-signature:Harbor 扩展字段,记录签名者身份和时间戳。signatures:使用 ECDSA 算法对 targets 元数据本身的签名,确保元数据完整性。