使用此开源工具签名和验证容器镜像

sigstore 项目旨在保护供应链技术。
39 位读者喜欢这篇文章。
Parts, modules, containers for software

Opensource.com

许多开源软件项目每天都在软件构建中使用,这对于几乎每个组织都至关重要。开源软件带来了许多好处,并帮助软件开发人员专注于创新和效率,而不是重复造轮子。

有时,您无法识别和验证第三方软件的完整性,持续进行验证可能会为供应链攻击打开大门。因此,sigstore 项目应运而生。sigstore 项目旨在保护供应链技术,并最终保护开源软件本身的安全。

sigstore 项目由其保护伞下的几个开源组件组成:

  • Fulcio(代码签名的根 CA)
  • Rekor(用于记录签名元数据的不可变防篡改账本)
  • Cosign(容器签名、验证和存储在符合 OCI 标准的注册表中)

在本文中,我将着眼于项目中的 cosign 部分,以及如何使用它来签名和验证容器镜像(以及其他受支持的对象)。cosign 的理念是使签名和验证过程成为开发人员的 不可变基础设施

安装和构建 cosign

在本示例中,我将在基于 macOS 的系统上安装 cosign。首先,确保系统已安装并运行 Docker,以便管理容器镜像。

使用 brew,我安装 cosign

$ brew install sigstore/tap/cosign

==> Installing sigstore/tap/cosign
?  /usr/local/Cellar/cosign/1.3.1: 3 files, 82.5MB, built in 2 seconds

接下来,我确保已登录到目标注册表,在本示例中为 docker.io。

$ docker login docker.io

Login Succeeded

签名和验证容器镜像

在我可以签名和验证任何镜像之前,我需要生成公钥和私钥对。然后,我使用此私钥对对象进行签名,并在以后使用相应的公钥对其进行验证。我还应该使用强密码来保护密钥对。理想情况下,此密码应存储在保险库中以用于安全和审计目的。

$ cosign generate-key-pair
Enter password for private key:
Enter again:
Private key written to cosign.key
Public key written to cosign.pub

既然我已经有了开始签名所需的密钥,我将对之前推送到注册表的测试镜像进行签名。

$ cosign sign --key cosign.key docker.io/mzali/test:latest
Enter password for private key:

使用 triangulate 选项,我可以从注册表中找到 cosign 镜像引用。

$ cosign triangulate docker.io/mzali/test:latest
index.docker.io/mzali/test:sha256-25ca0d9c2f4e70ce3bfba7891065dfef09760d2cbace7a2d21fb13c569902133.sig

现在,这是我要根据公钥验证镜像并验证签名真实性的部分。使用公钥,我可以验证镜像签名密钥签名。

$ cosign verify --key cosign.pub docker.io/mzali/test:latest

Verification for index.docker.io/mzali/test:latest --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
  - Any certificates were verified against the Fulcio roots.

[{"critical":{"identity":{"docker-reference":"index.docker.io/mzali/test"},"image":{"docker-manifest-digest":"sha256:25ca0d9c2f4e70ce3bfba7891065dfef09760d2cbace7a2d21fb13c569902133"},"type":"cosign container image signature"},"optional":null}]

对 SBOM 执行相同的操作

接下来,我还想 签名 SBOM。在本示例中,我使用 alpine:latest 镜像来展示如何执行此操作。

alpine 容器镜像已经推送到注册表。我首先需要从镜像生成 SBOM,我使用 syft 项目 中的 syft 二进制文件。由于我在基于 macOS 的系统上进行测试,因此我将使用 brew 来安装它。

$ brew tap anchore/syft
$ brew install syft

我检查以查看注册表中的 alpine 容器镜像中包含哪些软件包,使用 syft

$ syft packages mzali/alpine        
 ✔ Loaded image            
 ✔ Parsed image            
 ✔ Cataloged packages      [14 packages]

NAME                    VERSION      TYPE 
alpine-baselayout       3.2.0-r16    apk   
alpine-keys             2.4-r0       apk   
apk-tools               2.12.7-r0    apk   
busybox                 1.33.1-r6    apk   
ca-certificates-bundle  20191127-r5  apk   
libc-utils              0.7.2-r3     apk   
libcrypto1.1            1.1.1l-r0    apk   
libretls                3.3.3p1-r2   apk   
libssl1.1               1.1.1l-r0    apk   
musl                    1.2.2-r3     apk   
musl-utils              1.2.2-r3     apk   
scanelf                 1.3.2-r0     apk   
ssl_client              1.33.1-r6    apk   
zlib                    1.2.11-r3    apk

现在我将要签名此 SBOM。我希望 SBOM 采用 SPDX 2.2 标签值格式(或另一种受支持的格式,在本示例中,我选择 SPDX 格式),然后将其附加到镜像。

$ syft packages mzali/alpine -o spdx  > latest.spdx
 ✔ Loaded image            
 ✔ Parsed image            
 ✔ Cataloged packages      [14 packages]

$  ls -lrt latest.spdx 
-rw-r--r--  1 yanked  yanked  10058 Nov 17 15:52 latest.spdx

$ cosign attach sbom --sbom latest.spdx mzali/alpine 
Uploading SBOM file for [index.docker.io/mzali/alpine:latest] to [index.docker.io/mzali/alpine:sha256-5e604d3358ab7b6b734402ce2e19ddd822a354dc14843f34d36c603521dbb4f9.sbom] with mediaType [text/spdx].

使用上述摘要输出,我在注册表中签名 SBOM 并对其进行验证。

$ cosign sign --key cosign.key docker.io/mzali/alpine:sha256-5e604d3358ab7b6b734402ce2e19ddd822a354dc14843f34d36c603521dbb4f9.sbom 
Enter password for private key: %     

$ cosign verify --key cosign.pub docker.io/mzali/alpine:sha256-5e604d3358ab7b6b734402ce2e19ddd822a354dc14843f34d36c603521dbb4f9.sbom 

Verification for index.docker.io/mzali/alpine:sha256-5e604d3358ab7b6b734402ce2e19ddd822a354dc14843f34d36c603521dbb4f9.sbom --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
  - Any certificates were verified against the Fulcio roots.

[{"critical":{"identity":{"docker-reference":"index.docker.io/mzali/alpine"},"image":{"docker-manifest-digest":"sha256:00a101b8d193c294e2c9b3099b42a7bc594b950fbf535d98304d4c61fad5491b"},"type":"cosign container image signature"},"optional":null}]

下一步是什么?

使用 cosign 最简单的方法是将其包含到您的 SDLC 管道中,例如 Jenkins 或 Tekton 工具。使用 cosign,我可以将其包含到构建过程中,以签名和验证我的软件。如果您正在使用 Kubernetes,则有一个 Kubernetes cosigned 准入控制器,它可以查看您的镜像签名并将其与指定的公钥进行比较。如果镜像未签名或使用未知密钥,则准入控制器会因违规而阻止它。

$ kubectl apply -f unsigned-deployment.yaml
Error from server (BadRequest): error when creating "unsigned-deployment.yaml": admission webhook "cosigned.sigstore.dev" denied the request: validation failed: invalid image signature: spec.template.spec.containers[0].image

再次强调,cosign 只是整个 sigstore 项目的冰山一角。这些组件是协作的、集成的,并提供防篡改性、强大的验证点,并使用相同的标准更轻松地保护软件!

接下来阅读什么
User profile image.
Muhammad(也称为 Din)在 IT 行业工作了近 15 年,曾在 PCI-DSS 安全托管公司、系统集成商、托管服务组织和主要供应商等组织工作。他对新兴技术,特别是容器和安全领域有着浓厚的兴趣。

评论已关闭。

© . All rights reserved.