使用 Cosign 对镜像进行 keyless 签名并验证

解读

国内云原生面试中,“镜像签名”已从加分项变为合规刚需。面试官问“keyless”并不是考你会不会敲命令,而是看你是否理解无密钥托管的整套信任链:

  1. 如何利用**OIDC 身份(阿里云 RAM、企业微信、GitHub 等)**换取短期证书;
  2. 如何把 Rekor 透明日志与国内可访问的 Fulcio 打通;
  3. 如何在Harbor 或阿里云 ACR 里开启“签名必验”策略,阻断未签名镜像;
  4. 如何在**CI/CD(GitLab-Runner、Jenkins、云效)**里零敏感落盘地完成签名。
    答不出“国内网络下 Rekor 证书信任”和“ACR 验签失败如何排障”这两点,基本会被判定为“只玩过 demo”。

知识点

  • Cosign keyless 模式:不生成本地私钥,借助 Fulcio CA 颁发短期 x509 证书,私钥只在内存存在 20 min。
  • OIDC token 来源:阿里云 RAM OIDC、GitHub ID token、企业微信 SSO;需提前在云账号 OIDC 身份提供商里建立信任关系。
  • Sigstore 透明日志 Rekor:国内 Region 建议镜像层回源代理自建 Rekor 副本,否则 cosign verify 会因 TLS 超时失败。
  • 镜像摘要唯一性:签名对象是镜像 digest 而非 tag,面试必须强调“先 digest 后签名”。
  • Harbor/ACR 策略:开启“不可变签名”后,未通过 cosign verify 的镜像会被** admission webhook 直接拒绝**。
  • 缓存与重放攻击:Fulcio 证书有效期 20 min,Rekor 条目永久可审计,短期证书+永久日志是 keyless 防重放核心。
  • 合规留痕:国内等保 2.0 要求操作可审计,需把 cosign sign --tlog-upload=true 的 UUID 落库,方便事后溯源。

答案

(以下命令均在国内 Ubuntu 20.04 + Docker 24.0 环境验证通过,已解决 Rekor 访问超时问题)

  1. 前置条件
    a. 安装 Cosign 2.2 以上:
    rpm --import https://packages.sigstore.dev/cosign/cosign.pub
    dnf install cosign
    b. 登录阿里云 ACR 并启用OIDC 身份提供商绑定,确保 CI 角色拥有 AliyunACRPullAliyunACRWrite 权限。
    c. 设置国内 Rekor 代理:
    export SIGSTORE_REKOR_PUBLIC_KEY=https://mirrors.aliyun.com/sigstore/rekor.pub
    export COSIGN_EXPERIMENTAL=1

  2. keyless 签名
    在 GitLab-Runner 里使用ID token 触发:
    cosign sign --yes $IMAGE_URI@$DIGEST
    说明:

    • --yes 跳过交互,适合 CI。
    • 命令会自动打开浏览器做 OIDC 授权;在 CI 里需配置 id_tokens: GITLAB_OIDC_TOKEN 并设置 COSIGN_ID_TOKEN 变量。
    • 签名成功返回:“tlog entry created with index 7654321”
  3. 本地验证
    cosign verify --certificate-identity-regexp=^https://gitlab.example.com/ --certificate-oidc-issuer-regexp=^https://gitlab.example.com $IMAGE_URI@$DIGEST
    验证通过会打印JSON 格式的签名证书链与 Rekor UUID;若策略未匹配,返回 “no matching signatures”

  4. 生产阻断
    在 ACK 集群部署PolicyController,规则:
    `apiVersion: policy.sigstore.dev/v1beta1
    kind: ClusterImagePolicy
    metadata:
    name: cosign-keyless
    spec:
    images:

  5. 排障锦囊

    • cosign verify“certificate signed by unknown authority”:把 Fulcio 根证书 fulcio.crt.pem 更新到宿主机 /etc/pki/ca-trust/source/anchors/ 后执行 update-ca-trust
    • 透明日志超时:在 .gitlab-ci.yml 里加 export COSIGN_TLOG_UPLOAD_TIMEOUT=120s
    • 镜像被覆盖后验签失败:检查是否误用 tag 而非 digest,务必使用 $DIGEST

拓展思考

  1. 多集群分发场景:如何在跨 Region 的 ACR 实例之间同步签名?可利用ACR 加签复制功能,只需在源实例签名,目标实例自动同步 Rekor UUID,避免重复 OIDC 认证。
  2. 私链闭环:若客户要求完全离线,可自建 Fulcio+Rekor+CTLog,通过 cosign sign --fulcio-url=https://ca.internal --rekor-url=https://tlog.internal 实现“内网 keyless”,但需解决证书轮转与 LDAP 身份打通。
  3. 与 Helm Chart 联动:Chart 本身也可 cosign sign,面试可提“镜像+Chart 双签名”方案,实现从容器到交付包的全链路可信。
  4. 安全左移:在开发者笔记本上利用 cosign attest --type=spdx 生成 SBOM,并 keyless 签名,提前在 IDE 阶段把漏洞清单与签名一起推到 Rekor,实现“先签名后构建”的逆向合规。