使用 Cosign 对镜像进行 keyless 签名并验证
解读
国内云原生面试中,“镜像签名”已从加分项变为合规刚需。面试官问“keyless”并不是考你会不会敲命令,而是看你是否理解无密钥托管的整套信任链:
- 如何利用**OIDC 身份(阿里云 RAM、企业微信、GitHub 等)**换取短期证书;
- 如何把 Rekor 透明日志与国内可访问的 Fulcio 打通;
- 如何在Harbor 或阿里云 ACR 里开启“签名必验”策略,阻断未签名镜像;
- 如何在**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 访问超时问题)
-
前置条件
a. 安装 Cosign 2.2 以上:
rpm --import https://packages.sigstore.dev/cosign/cosign.pub
dnf install cosign
b. 登录阿里云 ACR 并启用OIDC 身份提供商绑定,确保 CI 角色拥有AliyunACRPull与AliyunACRWrite权限。
c. 设置国内 Rekor 代理:
export SIGSTORE_REKOR_PUBLIC_KEY=https://mirrors.aliyun.com/sigstore/rekor.pub
export COSIGN_EXPERIMENTAL=1 -
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”。
-
本地验证
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”。 -
生产阻断
在 ACK 集群部署PolicyController,规则:
`apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: cosign-keyless
spec:
images:- glob: "registry.cn-hangzhou.aliyuncs.com/yourapp/**"
authorities: - keyless:
identities:- issuer: https://gitlab.example.com
subjectRegExp: ^https://gitlab.example.com/your-group/your-project`
未签名镜像会被AdmissionWebhook 直接拒绝,Pod 事件显示 “signature verification failed”。
- issuer: https://gitlab.example.com
- glob: "registry.cn-hangzhou.aliyuncs.com/yourapp/**"
-
排障锦囊
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。
拓展思考
- 多集群分发场景:如何在跨 Region 的 ACR 实例之间同步签名?可利用ACR 加签复制功能,只需在源实例签名,目标实例自动同步 Rekor UUID,避免重复 OIDC 认证。
- 私链闭环:若客户要求完全离线,可自建 Fulcio+Rekor+CTLog,通过
cosign sign --fulcio-url=https://ca.internal --rekor-url=https://tlog.internal实现“内网 keyless”,但需解决证书轮转与 LDAP 身份打通。 - 与 Helm Chart 联动:Chart 本身也可
cosign sign,面试可提“镜像+Chart 双签名”方案,实现从容器到交付包的全链路可信。 - 安全左移:在开发者笔记本上利用
cosign attest --type=spdx生成 SBOM,并 keyless 签名,提前在 IDE 阶段把漏洞清单与签名一起推到 Rekor,实现“先签名后构建”的逆向合规。