4、IDP中的签名链路架构:从代码提交到制品部署的完整签名链
在内部开发者平台(IDP)中,制品签名不是孤立的单点操作,而是一条贯穿软件交付全生命周期的信任链。从开发者提交代码开始,到最终制品部署到生产环境,每一个环节都需要对产物进行数字签名,形成一条可追溯、不可篡改的签名链路。本章将详细解析这条链路的架构设计、各环节签名策略以及它们在Backstage中的映射方式。
4.1 完整签名链的总体架构
IDP制品签名链路遵循“左移安全”原则,将签名操作嵌入到CI/CD管道的每个关键节点。整条链路包含四个核心环节:代码提交、构建、仓库存储和部署。每个环节的签名都使用独立的密钥对,并生成对应的签名凭证,最终形成一条从源码到运行时的信任链。
4.2 各环节签名策略详解
每个签名环节都有其特定的技术实现和策略要求。下表对比了四个环节的核心差异:
| 签名环节 | 签名对象 | 签名工具/标准 | 密钥类型 | 验证时机 |
|---|---|---|---|---|
| 提交签名 | Git Commit | GPG / SSH / S/MIME | 非对称密钥(4096位RSA或Ed25519) | 代码推送时(pre-receive hook) |
| 构建签名 | 构建产物(容器镜像、JAR包、WAR包等) | Cosign / JWT / Sigstore | 短期密钥对(由OIDC动态签发) | 构建完成后立即执行 |
| 仓库签名 | OCI制品(镜像、Helm Chart、SBOM) | Notation / OCI Reference | 长期证书(X.509或PKI) | 制品推送至仓库时 |
| 部署签名 | 部署清单(K8s YAML、ArgoCD Application) | K8s Admission Webhook / Kyverno | 集群级证书 | 部署前准入控制 |
4.3 提交签名策略
提交签名是整个信任链的起点。开发者使用GPG或SSH密钥对每次提交进行签名,确保代码的来源可信且未被篡改。
提交签名的核心流程:
- 开发者使用
git commit -S对提交进行签名 - Git服务器(如GitHub、GitLab)通过pre-receive hook验证签名
- 验证通过后,提交被标记为“已验证”(Verified)
- Backstage通过API获取提交签名状态,并在组件页面展示
# 开发者本地配置GPG签名
gpg --full-generate-key
git config --global user.signingkey <KEY_ID>
git config --global commit.gpgsign true
# 提交时自动签名
git commit -m "feat: add signing chain support"
# 输出示例:
# [main 1a2b3c4] feat: add signing chain support
# 1 file changed, 42 insertions(+)
# signature: 1a2b3c4d5e6f7g8h9i0j... (GPG)
4.4 构建签名策略
构建签名是链路中最关键的环节。CI/CD管道在构建完成后,立即对制品进行签名。推荐使用Sigstore生态的Cosign工具,结合OIDC(OpenID Connect)实现无密钥签名(Keyless Signing)。
构建签名的关键步骤:
- 生成SBOM:在构建过程中同步生成软件物料清单(SBOM)
- 签名制品:使用Cosign对容器镜像和SBOM进行签名
- 附加元数据:将构建流水线ID、提交哈希、构建时间等元数据写入签名负载
- 上传签名:将签名结果以OCI Reference形式上传至镜像仓库
# 使用Cosign进行Keyless签名
cosign sign \
--oidc-issuer "https://.actions.githubusercontent.com" \
--oidc-client-id "sigstore" \
registry.example.com/my-app:v1.0.0
# 验证签名
cosign verify \
--certificate-identity "https://github.com/my-org/my-repo/.github/workflows/build.yml@refs/heads/main" \
--certificate-oidc-issuer "https://.actions.githubusercontent.com" \
registry.example.com/my-app:v1.0.0
4.5 仓库签名策略
制品推送至镜像仓库后,仓库签名环节使用Notation工具对OCI制品进行签名。与构建签名不同,仓库签名使用基于PKI的长期证书,由组织的证书颁发机构(CA)签发。
仓库签名的核心特点:
| 特性 | 说明 |
|---|---|
| 签名格式 | Notation使用COSign v1.1标准,签名存储在OCI Reference中 |
| 证书管理 | 证书由组织CA签发,有效期通常为1-2年,支持CRL和OCSP吊销 |
| 信任策略 | 仓库端配置信任策略,只接受由指定CA签发的签名 |
| 审计追溯 | 每次签名操作记录在仓库的审计日志中,包含签名者身份和签名时间 |
# 使用Notation对镜像签名
notation sign \
--key "myorg-signing-key" \
--plugin "myorg-plugin" \
registry.example.com/my-app:v1.0.0
# 验证仓库签名
notation verify \
--trust-policy "myorg-trust-policy.json" \
registry.example.com/my-app:v1.0.0
4.6 部署签名策略
部署签名是信任链的最后一环。在Kubernetes集群中,通过Admission Webhook或策略引擎(如Kyverno、OPA)在部署前验证制品的签名链完整性。
部署签名的验证策略:
- 强制验证:所有部署到生产环境的镜像必须经过完整签名链验证
- 策略分级:开发环境允许跳过签名验证,预发环境验证仓库签名,生产环境验证全链路
- 失败处理:验证失败时,Admission Webhook拒绝部署请求,并返回详细的失败原因
- 审计记录:所有验证结果写入K8s事件和审计日志,Backstage通过插件实时展示
# Kyverno策略示例:验证镜像签名
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signature
spec:
validationFailureAction: Enforce
rules:
- name: check-signature-chain
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "registry.example.com/*"
attestors:
- count: 1
entries:
- keyless:
subject: "https://github.com/my-org/my-repo/.github/workflows/build.yml@refs/heads/main"
issuer: "https://.actions.githubusercontent.com"
mutateDigest: true
required: true
4.7 签名链在Backstage中的可视化
Backstage通过自定义插件将整条签名链的状态集中展示。开发者无需跳转到多个系统,即可在一个界面中查看从代码提交到部署的完整签名状态。
4.8 签名链的移植适配要点
将签名链路移植到Backstage IDP时,需要关注以下适配要点:
- 凭证管理:将各环节的签名密钥/证书统一托管在Backstage的Secrets Store中
- 管道集成:在Backstage的CI/CD模板中嵌入签名步骤,确保新项目自动继承签名策略
- 状态同步:通过Webhook或轮询机制,将各系统的签名状态实时同步到Backstage
- 策略配置:在Backstage中提供签名策略的可视化配置界面,支持按环境、团队、项目级别定制
- 审计合规:所有签名操作和验证结果统一写入Backstage的审计日志,满足合规要求