GitHub Actions 实战:五分钟配置 Cosign Keyless 无密钥镜像签名
2
0
0
0
在软件供应链攻击频发的今天,为容器镜像进行签名已成为生产环境的标配。传统的签名方式通常需要开发者手动管理私钥(如存储在 GitHub Secrets 中),这不仅存在泄露风险,还带来了密钥轮转的运维负担。
Sigstore 项目下的 Cosign 提供的 Keyless(无密钥)模式彻底改变了这一现状。它利用 GitHub Actions 提供的 OIDC 身份令牌,结合 Sigstore 的 Fulcio(CA 服务)和 Rekor(透明日志),实现了“无需管理密钥即可完成签名”的优雅流程。
本文将手把手带你快速在 GitHub Actions 中集成这一方案。
一、 核心原理简述
在 Keyless 模式下:
- GitHub Actions 为运行的工作流生成一个短效的 OIDC ID Token。
- Cosign 提取该 Token 并发送给 Sigstore 的 Fulcio。
- Fulcio 验证身份后,签发一个有效期仅几分钟的短效证书。
- Cosign 使用该证书签署镜像,并将记录上传到 Rekor 公开透明账本。
- 验证者只需通过 Rekor 即可核实该镜像确实是由特定的 GitHub Repository 生成的。
二、 前置要求
- 一个托管在 GitHub 的项目。
- 使用 GitHub Container Registry (ghcr.io) 或 Docker Hub 存储镜像。
- 工作流文件位于
.github/workflows/目录下。
三、 实战配置步骤
以下是一个完整的 GitHub Actions YAML 示例。
1. 设置权限 (核心步骤)
要实现 Keyless 签名,GitHub 工作流必须具备获取 id-token 的权限,否则 Cosign 无法向 Fulcio 申请证书。
permissions:
contents: read
packages: write
id-token: write # 必须:用于获取 OIDC 令牌
2. 编写完整工作流
name: Docker Image CI & Sign
on:
push:
tags: [ 'v*.*.*' ]
jobs:
build-and-sign:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
# 安装 Cosign 工具
- name: Install Cosign
uses: sigstore/cosign-installer@v3.5.0
# 登录到 GitHub Container Registry
- name: Log into registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# 构建并推送镜像
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}/my-app:latest
# 使用 Cosign 进行 Keyless 签名
- name: Sign the published Docker image
env:
DIGEST: ${{ steps.build-and-push.outputs.digest }}
TAGS: ghcr.io/${{ github.repository }}/my-app:latest
run: |
cosign sign --yes "${TAGS}@${DIGEST}"
四、 关键点解析
cosign-installer: 官方提供的 Action,用于在 Runner 中快速安装 cosign 环境。cosign sign --yes: 在非交互模式下,--yes参数会自动处理 Keyless 流程。它会自动探测当前环境是否在 GitHub Actions 中,并自动请求 OIDC 令牌。- 不可篡改性: 建议使用
DIGEST(镜像摘要)而不是TAG来进行签名,这能防止在签名过程中镜像被篡改或覆盖。
五、 如何验证签名?
签名完成后,任何人都可以验证该镜像的真实性,且不需要你的公钥。
使用以下命令验证:
cosign verify ghcr.io/your-username/your-repo/my-app:latest \
--certificate-identity-regexp https://github.com/your-username/your-repo/.github/workflows/ \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
验证逻辑:
--certificate-identity: 检查证书中的身份是否匹配指定的 GitHub 工作流路径。--certificate-oidc-issuer: 确保证书是由 GitHub 的 OIDC 发行版签发的。
六、 常见问题排查
- Permission Denied: 检查你的
permissions部分。如果漏掉了id-token: write,Cosign 会提示无法获取 credential。 - Private Repo: 默认情况下,Keyless 签名的元数据会上传到 Sigstore 的公共 Rekor 服务器。如果你是私有商业项目,且不想公开任何构建元数据,请考虑部署私有的 Sigstore 实例。
- Docker Hub 支持: 如果你推送到 Docker Hub,Cosign 的操作完全一致,只需更换
login-action的地址即可。
总结
通过 GitHub Actions 结合 Cosign Keyless 模式,我们可以在不接触任何密钥的情况下,为镜像建立起强大的信任链。这不仅简化了 CI/CD 的维护工作,更显著提升了项目分发的安全性。建议所有开源项目的维护者都尽早开启此功能。