关于 implementing-sigstore-for-software-signing
面向软件供应链安全团队的 Sigstore 与 Cosign 实践指南,介绍如何使用 OIDC 身份签署和验证软件制品,并涵盖 CI/CD、Rekor 审计及策略执行。
主要功能
- 01基于 OIDC 的无密钥签名
- 02容器与文件验证
- 03查询 Rekor 透明日志
- 04CI/CD 签名工作流
- 05制品证明附加
适用场景
- 01签署 CI 构建的容器镜像
- 02验证制品签署者身份
- 03审计 Rekor 中的签名事件
- 04执行已签名镜像部署策略
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill implementing-sigstore-for-software-signing安装后在 Claude Code 中输入/implementing-sigstore-for-software-signing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdscripts/agent.py详细介绍
为软件签名实施 Sigstore
何时使用
- 在不管理长期加密密钥的情况下对容器镜像和软件制品进行签名
- 使用 OIDC 身份绑定,为 CI/CD 流水线中的构建输出建立可验证的来源
- 查询 Rekor 透明度日志,以审计制品在何时被何人签名
- 验证从镜像仓库拉取的容器镜像是否由已授权的身份和颁发者签名
- 将 Sigstore 验证集成到 Kubernetes 准入控制器中,以强制执行已签名镜像策略
不要使用于需要对制品进行签名且要求气隙或离线签名工作流、无法使用 OIDC 认证的场景;无法访问公共 Sigstore 基础设施(Fulcio、Rekor)且未部署私有实例的环境;或在法规合规要求特定密钥管理流程的情况下替代传统 PGP/GPG 签名。
前置条件
- 已安装 Cosign CLI v2.4+(
go install github.com/sigstore/cosign/v2/cmd/cosign@latest或二进制发行版) - 可访问 Fulcio 支持的 OIDC 身份提供商(Google、GitHub、Microsoft 或自定义 OIDC 颁发者)
- 容器镜像仓库凭据(用于签名容器镜像),并具有推送权限以存储签名对象
- Python 3.9+,并为自动化 Agent 安装
sigstore、requests和cryptography包 - 可访问
fulcio.sigstore.dev、rekor.sigstore.dev和tuf-repo-cdn.sigstore.dev(或私有 Sigstore 实例 URL)
工作流
步骤 1:安装并配置 Cosign
安装 Cosign 并验证其可以访问 Sigstore 基础设施:
- 从二进制发行版安装:从 Cosign GitHub releases 页面下载相应的二进制文件并验证其校验和。在 Linux 上:
curl -LO https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 && chmod +x cosign-linux-amd64 && sudo mv cosign-linux-amd64 /usr/local/bin/cosign - 验证安装:运行
cosign version以确认版本,并使用cosign initialize检查与 Sigstore 服务的连接,该命令会获取 TUF 信任根 - 配置自定义基础设施(可选):如果运行私有 Sigstore 堆栈,请设置
--fulcio-url、--rekor-url和--oidc-issuer标志,或使用环境变量COSIGN_REKOR_URL和COSIGN_FULCIO_URL
步骤 2:使用 Cosign 和 Fulcio 进行无密钥签名
执行基于身份的签名,其中 Fulcio 颁发绑定到你的 OIDC 身份的短期证书:
- 签名容器镜像:运行
cosign sign <IMAGE_DIGEST>,这会触发 OIDC 认证流程。Cosign 生成临时密钥对,从 Fulcio 获取将公钥绑定到 OIDC 身份的短期证书,对镜像摘要进行签名,并在 Rekor 中记录签名事件。私钥在签名后立即销毁。 - 签名 blob(文件):运行
cosign sign-blob <file> --bundle artifact.sigstore.json来签名任意文件。该 bundle 包含签名、证书、时间戳和 Rekor 包含证明。 - 在 CI 中进行非交互式签名:将
SIGSTORE_ID_TOKEN环境变量设置为有效的 OIDC token(例如来自 GitHub Actions OIDC 或 GCP workload identity),以跳过基于浏览器的认证流程:export SIGSTORE_ID_TOKEN=$(curl -sH "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \ "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sigstore" | jq -r '.value') cosign sign $IMAGE_DIGEST - 支持的 OIDC 提供商:Google(
https://accounts.google.com)、GitHub(https://github.com/login/oauth)、Microsoft(https://login.microsoftonline.com)、GitLab(https://gitlab.com),以及注册到私有 Fulcio 实例的自定义提供商
步骤 3:验证已签名产物
验证产物是否由预期 OIDC 颁发者的预期身份签名:
- 验证容器镜像:运行
cosign verify <IMAGE_URI> [email protected] --certificate-oidc-issuer=https://accounts.google.com以确认该镜像由指定身份签名。Cosign 会验证证书链、检查 Rekor 包含证明,并验证签名与当前镜像摘要匹配。 - 验证已签名 blob:运行
cosign verify-blob <file> --bundle artifact.sigstore.json [email protected] --certificate-oidc-issuer=https://accounts.google.com - 对 CI 身份进行正则匹配:使用
--certificate-identity-regexp匹配 CI 工作流身份:cosign verify $IMAGE --certificate-identity-regexp="https://github.com/myorg/myrepo/.*" \ --certificate-oidc-issuer=https://token.actions.githubusercontent.com - 验证失败模式:Cosign 在失败时返回非零退出码。常见失败包括证书身份不匹配、证书已过期且没有有效的 Rekor 时间戳、缺少 Rekor 条目,以及镜像摘要不匹配(镜像在签名后被修改)。
步骤 4:查询 Rekor 透明日志
搜索并验证 Rekor 透明日志中的条目,以审计签名事件:
- 按电子邮件身份搜索:使用
rekor-cli search --email [email protected]查找某个身份的所有签名事件 - 按产物哈希搜索:使用
rekor-cli search --sha sha256:<hash>查找特定产物的签名事件 - 检索并验证条目:使用
rekor-cli get --uuid <entry_uuid>检索完整条目详情,包括证书、签名和产物哈希 - 验证日志包含性:使用
rekor-cli verify --entry-uuid <uuid>根据已签名树头验证该条目的包含证明,确认该条目存在于仅追加日志中且未被篡改 - REST API 查询:向
https://rekor.sigstore.dev/api/v1/index/retrieve发送 POST 请求体{"hash": "sha256:<hash>"}以检索条目 UUID,然后从/api/v1/log/entries/<uuid>获取完整条目 - 监控一致性:使用 rekor-monitor 工具或 Omniwitness 持续验证日志保持仅追加,且条目从不被修改或删除
步骤 5:集成到 CI/CD 流水线
将签名和验证嵌入构建与部署流水线:
- GitHub Actions:使用
sigstore/cosign-installeraction 安装 Cosign,然后使用 GitHub OIDC token 作为身份对镜像进行签名。签名身份将是工作流 URL(例如https://github.com/org/repo/.github/workflows/build.yml@refs/heads/main)。 - Kubernetes 准入强制执行:部署 Sigstore Policy Controller 或 Kyverno 并配置 Cosign 验证策略,在准入时拒绝未签名或签名不正确的镜像
- 供应链元数据:使用
cosign attest将 in-toto 证明(SLSA 来源、SBOM、漏洞扫描结果)附加到镜像,并使用相同的无密钥流程签名,使使用者能够同时验证产物及其构建元数据
关键概念
| 术语 | 定义 |
|---|---|
| 无密钥签名 | 基于身份的签名,使用 Fulcio 签发并与 OIDC 身份绑定的短期证书,而非长期加密密钥,从而消除密钥管理开销 |
| Fulcio | Sigstore 的证书颁发机构,在验证 OIDC 令牌后签发短期 X.509 证书,将临时公钥绑定到已验证的身份 |
| Rekor | Sigstore 的不可变、仅追加的透明日志,记录带有时间戳的签名事件,使审计人员能够验证制品何时由谁签名 |
| Cosign | 使用 Sigstore 基础设施(Fulcio + Rekor)对容器镜像和 blob 进行签名和验证的主要命令行工具 |
| TUF 信任根 | The Update Framework 的分发机制,用于分发 Sigstore 的根 CA 证书和 Rekor 公钥,确保客户端信任正确的 Sigstore 基础设施 |
| OIDC 身份绑定 | Fulcio 通过 OpenID Connect 令牌验证用户身份并将其绑定到短期签名证书的过程 |
| 包含证明 | 来自 Rekor 的加密证明,表明某条签名事件条目存在于透明日志的 Merkle 树中 |
工具与系统
- Cosign:用于签名容器和 blob、验证签名以及附加证明的命令行工具,支持 Sigstore 无密钥签名或传统的基于密钥的签名
- Fulcio:免费的根证书颁发机构,基于 OIDC 身份验证签发代码签名证书,有效期约为 10 分钟
- Rekor:透明日志服务器,提供签名元数据的防篡改存储,可按身份、制品哈希或公钥进行搜索
- Sigstore Policy Controller:Kubernetes 准入 webhook,通过在允许创建 Pod 之前验证 Cosign 签名和证明来强制执行镜像签名策略
- rekor-cli:用于查询、上传和验证 Rekor 透明日志中条目的命令行客户端
常见场景
场景:使用无密钥签名保护容器镜像构建流水线
背景:一个 DevOps 团队在 GitHub Actions 中构建容器镜像并部署到 Kubernetes 集群。他们需要确保只有由其 CI 流水线构建的镜像才能被部署,从而防止来自受损镜像仓库或未授权推送的供应链攻击。
方法:
- 将
sigstore/cosign-installer@v3添加到 GitHub Actions 工作流,并通过id-token: write启用 OIDC 令牌权限 - 在构建并推送镜像后,使用 GitHub Actions OIDC 身份自动通过
cosign sign $IMAGE_DIGEST对其进行签名 - 将 Sigstore Policy Controller 部署到 Kubernetes 集群,并配置 ClusterImagePolicy,要求签名来自
--certificate-identity-regexp=https://github.com/myorg/myrepo/.*和--certificate-oidc-issuer=https://token.actions.githubusercontent.com - 通过使用镜像摘要哈希查询,验证签名条目出现在 Rekor 中,以确认透明日志记录了该事件
- 通过尝试部署未签名的镜像并确认其因策略违规错误而被拒绝,来测试准入控制器
陷阱:
- 对镜像标签而非摘要进行签名(
cosign sign myimage:latest与cosign sign myimage@sha256:abc...)意味着当标签更新为指向不同摘要时,验证会失败 - 在验证期间未固定
--certificate-oidc-issuer会允许来自任何 OIDC 提供商的签名通过,从而使身份绑定的目的失效 - 忘记在 GitHub Actions 中设置
id-token: write权限会导致 OIDC 令牌获取失败和签名错误 - 在生产验证策略中使用
--certificate-identity-regexp=.*实际上禁用了身份验证
输出格式
## Sigstore Signing Verification Report
**Artifact**: ghcr.io/myorg/myapp@sha256:a1b2c3d4...
**Verification Status**: PASSED
**Certificate Details**:
Subject: https://github.com/myorg/myapp/.github/workflows/build.yml@refs/heads/main
Issuer: https://token.actions.githubusercontent.com
Valid From: 2026-03-19T10:00:00Z
Valid To: 2026-03-19T10:10:00Z
**Rekor Entry**:
UUID: 24296fb24b8ad77a8d52...
Log Index: 89234567
Integrated Time: 2026-03-19T10:00:05Z
Inclusion Proof: VERIFIED (tree size: 92000000, root hash: e4f5a6...)
**Policy Check**: Image signed by authorized CI workflow identity
评论
支持 Markdown