基于Cosign容器镜像签名/验证工具能力,实现Pod可信验证

腾讯云TKE集群,在23年5月,上线了一特性: Cerberus 组件支持对签名镜像进行可信验证

支持在Kubernetes集群中只部署可信授权方签名的容器镜像,降低在容器环境中的镜像安全风险。

因此,cosign-webhook, 功能上类似腾讯Cerberus. 为了实现一套多云可用,并支持Docker hubHarborQuay镜像仓库 签名sig 存储的通用解决方案

背景:Cosign 工具

[Cosign](https://github.com/sigstore/cosign) 是 谷歌开源容器镜像的签名和验证工具。 此二进制工具支持 容器镜像 签名与验证。并继承到谷歌内部容器基础设施distroless中。

Cosign 除了提供给用户可以方便的对镜像签名和验证,还提供免费 OIDC PKI (Fucio) 和内置二进制透明度和时间戳服务 Rekor, 来托管签名和验证过程中的公钥和私钥

cosign基本使用

1. 签名:cosign keyless模式,签名证书托管在googleapi open OIDC PKI

Dockerhub上的dongjiang1989/node-metrics:latest镜像为例:

因为,是keyless模式,直接行cosign sign <image>@sha256:<digest>

dongjiang@MacBook Pro:~ $  cosign sign dongjiang1989/node-metrics@sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282
Generating ephemeral keys...
Retrieving signed certificate...

	The sigstore service, hosted by sigstore a Series of LF Projects, LLC, is provided pursuant to the Hosted Project Tools Terms of Use, available at https://lfprojects.org/policies/hosted-project-tools-terms-of-use/.
	Note that if your submission includes personal data associated with this signed artifact, it will be part of an immutable record.
	This may include the email address associated with the account with which you authenticate your contractual Agreement.
	This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later, and is subject to the Immutable Record notice at https://lfprojects.org/policies/hosted-project-tools-immutable-records/.

By typing 'y', you attest that (1) you are not submitting the personal data of any other person; and (2) you understand and agree to the statement and the Agreement terms at the URLs listed above.
Are you sure you would like to continue? [y/N] y
error opening browser: exec: "xdg-open": executable file not found in $PATH
Go to the following link in a browser:

	 https://oauth2.sigstore.dev/auth/auth?access_type=online&client_id=sigstore&code_challenge=L_clEcpY7BXtgaJ0W5qZJq74ovXNnznXpwYluzCUPEQ&code_challenge_method=S256&nonce=2TSKHjXGVJMxbj4TgFNe6wtXXKg&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&scope=openid+email&state=2TSKHg5tyauZ3PaaVJHyNfRAf1D
Enter verification code: yql4si3wqdvkzrm25ohncuk45

Successfully verified SCT...
tlog entry created with index: 29886419
Pushing signature to: index.docker.io/dongjiang1989/node-metrics

执行期间会跳转到到 https://oauth2.sigstore.dev/auth/auth?xxx 连接 需要用github 或者 google 或者 microsoft 统一登入,验证邮箱, 并在平台上保留公钥和私钥.

完成验证后,会将signature文件,提交到镜像仓库

cosign signature

2. 验证:cosign keyless模式

keyless模式,直接通过:

cosign verify --certificate-identity <keyless邮箱地址> --certificate-oidc-issuer <认证平台地址> <image>@sha256:<digest>

其中,认证平台地址根据sign in平台,不通进行设置

dongjiang@MacBook Pro:~ $ cosign verify --certificate-identity dongjiang1989@126.com --certificate-oidc-issuer https://github.com/login/oauth dongjiang1989/node-metrics@sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282

Verification for index.docker.io/dongjiang1989/node-metrics@sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The code-signing certificate was verified using trusted certificate authority certificates

[{"critical":{"identity":{"docker-reference":"index.docker.io/dongjiang1989/node-metrics"},"image":{"docker-manifest-digest":"sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282"},"type":"cosign container image signature"},"optional":{"1.3.6.1.4.1.57264.1.1":"https://github.com/login/oauth","Bundle":{"SignedEntryTimestamp":"xxxxxxxxx","Payload":{"body":"xxxxxxxxxxxx=","integratedTime":1691030975,"logIndex":29886419,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}},"Issuer":"https://github.com/login/oauth","Subject":"dongjiang1989@126.com"}}]

3. 本地key方式签名和验证

a. 先创建创建密钥对

dongjiang@MacBook Pro:~ $ cosign generate-key-pair
Enter password for private key: 
Enter password for private key again: 
Private key written to cosign.key
Public key written to cosign.pub
dongjiang@MacBook Pro:~ $ ls
aaa  cosign.key  cosign.pub  go  src  tools

b. 通过cosign.key, 镜行容器镜行签名 cosign sign --key cosign.key <image>@sha256:<digest>

dongjiang@MacBook Pro:~ $ cosign sign --key cosign.key dongjiang1989/node-metrics:sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282
Enter password for private key: 
Error: signing [dongjiang1989/node-metrics:sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282]: parsing reference: could not parse reference: dongjiang1989/node-metrics:sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282
main.go:74: error during command execution: signing [dongjiang1989/node-metrics:sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282]: parsing reference: could not parse reference: dongjiang1989/node-metrics:sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282
[root@VM-0-5-centos ~]# cosign sign --key cosign.key dongjiang1989/node-metrics@sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282
Enter password for private key: 

	The sigstore service, hosted by sigstore a Series of LF Projects, LLC, is provided pursuant to the Hosted Project Tools Terms of Use, available at https://lfprojects.org/policies/hosted-project-tools-terms-of-use/.
	Note that if your submission includes personal data associated with this signed artifact, it will be part of an immutable record.
	This may include the email address associated with the account with which you authenticate your contractual Agreement.
	This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later, and is subject to the Immutable Record notice at https://lfprojects.org/policies/hosted-project-tools-immutable-records/.

By typing 'y', you attest that (1) you are not submitting the personal data of any other person; and (2) you understand and agree to the statement and the Agreement terms at the URLs listed above.
Are you sure you would like to continue? [y/N] y
tlog entry created with index: 29887689
Pushing signature to: index.docker.io/dongjiang1989/node-metrics

c. 通过cosign.pub, 镜行容器镜行验证 cosign verify --key cosign.pub <image>@sha256:<digest>

[root@VM-0-5-centos ~]# cosign verify --key cosign.pub dongjiang1989/node-metrics@sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282

Verification for index.docker.io/dongjiang1989/node-metrics@sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The signatures were verified against the specified public key

[{"critical":{"identity":{"docker-reference":"index.docker.io/dongjiang1989/node-metrics"},"image":{"docker-manifest-digest":"sha256:c1aa0f2861d2eb744efb8f82a1d7d5f1b74919d1cc6501e799daeac1991fc282"},"type":"cosign container image signature"},"optional":{"Bundle":{"SignedEntryTimestamp":"xxxxxxxxxx","Payload":{"body":"xxxxxxxxxx=","integratedTime":1691032440,"logIndex":29887689,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}}}}]

由于国内对国外google,github访问限制,使用本地签名方式更有利于与私有化 和 跨云验证

具体实现方式

先通过 CRD 描述 namespaceCosignKey 扩展限制

设计如下:

apiVersion: cosignkey.kubeservice.cn/v1
kind: CustomCosignKey
metadata:
  name: test-cosignkey
  namespace: xxxxx
spec:
  authorities:
    key:
    - |
          -----BEGIN PUBLIC KEY-----
          ......
          -----END PUBLIC KEY-----          

namespace 可以是添加label设置 cosignkey.kubernetes.io/verify : disabled, 可支持 ignore namespace下Cosign验证

注意

  1. 只有 namespace 添加label设置 cosignkey.kubernetes.io/verify : enablednamespace CustomCosignKey被定义, 才生效
  2. 同一个namespace CRD 只能背定义一次,重复定义出错;
  3. 会对pod中的 initContainer、Container 都会进行验证;

1.为什么CRD需要说明支持多个key? 一个namespace(属于1个租户),他部署的pod中的容器,可能有几个来源。 这几个来源的public key可能不通,支持轮训检查 2.配置namespace label flag 作用? 用于 功能上线,持续替换 或者 特殊场景下排ta处理

周边生态

  1. Harbor 直接镜像同步 支持 cosign 签名和验证:https://github.com/goharbor/harbor/releases/tag/v2.5.0
  2. Skopeo 镜像迁移工具 支持 cosign 镜像迁移: https://github.com/containers/skopeo/pull/1849
  3. KMS: aws、google 和 azure kms都支持 cosign 容器验证

source

https://github.com/kubeservice-stack/cosign-webhook

其他

  1. 安装cosign :https://docs.sigstore.dev/cosign/installation/
  2. 签名和认证:https://docs.sigstore.dev/cosign/signing_with_containers/