作者:易立

2011 年,互联网技能前驱 Marc Andreessen 声称,软件正在吞噬世界(Software is eating the world)。由软件驱动的职业创新正在颠覆着传统事务形式,推进着全球经济完成数字化衔接。跟着互联网的快速开展,数字化转型现已成为每一个企业的要害战略。可是现代软件开发涉及到多方协作,大量运用依靠开源代码或许三方组件。在上游开源软件的安全问题会传递到下流运用方并被扩大,有可能给企业造成重大的安全危险和事务丢失。

软件出产的进程与传统制造业在很多方面是类似的。软件制造商将自研事务代码和第三方组件组合成完好的软件,构建流程会将这些组件打包成为可布置的软件制品,然后被企业客户布置到出产环境中。这个进程被形象地称为“软件供给链”。而软件供给链安全的目标是保软件从开发到布置的整个生命周期的安全、可信赖。

谈谈我对云原生与软件供应链安全的思考

谈谈我对云原生与软件供应链安全的思考

在 Sonatypes’s2021 State of the Software Supply Chain 调查陈述中,2021 年软件供给链进犯事情增长了 650%。

目前,软件供给链安全现已得到职业的高度重视。现已有很多国家出台了相关的政策法规来指导本国的供给链安全办理,以进步供给链安全韧性。2021 年 4 月,美国网络安全与根底设施安全局(CISA)和美国国家标准与技能院(NIST)联合发布《防御软件供给链进犯》陈述,首次对软件供给链进行界定,并给出与软件供给链进犯相关的信息、关联危险以及缓解办法。

谷歌也提出了Supply chain Levels for Software Artifacts- 软件制品的供给链等级,简称为 SLSA。SLSA 是 Google 内部施行的多年的安全流程的开源版别,供给了一个安全结构和一组最佳实践,来预防由于源代码篡改、三方组件缝隙、制品库房侵略产生的安全威胁。

谈谈我对云原生与软件供应链安全的思考

SBOM-提升软件构成透明度

软件供给链安全的根底便是透明性。只要理解了运用是怎么从代码和依靠组件构建而成,咱们才能够对运用的安全危险进行有用的治理。在美国 2021 年颁布的《关于改善国家网络安全的行政指令》行政令中,特别要求政府软件应包括机器可读的软件物料清单(Software Bill Of Materials, SBOM)。SBOM 是包括构建软件运用的各种组件的详细信息和供给链联系的正式记录。

美国国家电信和信息办理局(NITA)在 14028 号政令的要求下,在 2021 年 7 月 12 日发布了《SBOM 的最低要素》,该文档为各开发东西的安排和厂商供给了 SBOM 数据格式的参阅。在新一代软件开发东西中,越来越多的软件供给了对 SBOM 的支撑。

运用的 SBOM 信息

下面咱们以一个 Golang 的 HTTP Server 示例运用为例,了解一下 SBOM 的的概念和运用办法。

$ git clone https://github.com/denverdino/secure-supply-chain-sample
$ cd secure-supply-chain-sample
$ go build .

了解 Go 语言的开发者一定对 go 模块概念十分了解。运用所依靠的模块,都经过 go.mod 文件声明。go mod tidy 指令能够用来更新 go.mod 文件,并”确定“所依靠的模块和版别信息,这大大提升了构建的确定性、可重现性和可验证性。为了保证第三方无法篡改所依靠的模块版别, 在 go.sum 文件记录了每个模块依靠的加密哈希值。当使用go指令将模块代码下载到本地时,就会核算其哈希值,如果核算结果与 go.sum 记录的数据不符就意味着存在篡改的危险。更近一步,Google 运营着一个 Go 模块校验数据库服务,它记录了 go 模块版别的加密哈希值,进一步提升了 Go 根底设施的安全性。

更多内容能够阅览:

go.dev/blog/supply…

对于已编译的运用二进制文件,咱们能够经过 go version -m 指令查看运用的构建信息,包括其软件来历,依靠模块,构建参数等等。

$ go version -m secure-supply-chain-sample
secure-supply-chain-sample: go1.18.3
    path    github.com/denverdino/secure-supply-chain-sample
    mod    github.com/denverdino/secure-supply-chain-sample    (devel)
    dep    github.com/sirupsen/logrus    v1.8.1    h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
    dep    golang.org/x/sys    v0.0.0-20220702020025-31831981b65f    h1:xdsejrW/0Wf2diT5CPp3XmKUNbr7Xvw8kYilQ+6qjRY=
    build    -compiler=gc
    build    CGO_ENABLED=1
    build    CGO_CFLAGS=
    build    CGO_CPPFLAGS=
    build    CGO_CXXFLAGS=
    build    CGO_LDFLAGS=
    build    GOARCH=amd64
    build    GOOS=darwin
    build    GOAMD64=v1
    build    vcs=git
    build    vcs.revision=c630057157df402b658ab97139895337633b5bbc
    build    vcs.time=2022-07-04T01:33:01Z
    build    vcs.modified=false

容器镜像的 SBOM 支撑

容器技能重塑了整个软件供给链。容器镜像将运用及其所有依靠项打包,从而使运用能够在不同的核算环境之间快速、可靠地运转。容器镜像现已成为了运用分发的标准,而 Kubernetes 成为了分布式资源调度和编列的事实标准。那么怎么保证容器镜像在构建、分发和运转时的完好性、安全性呢?

咱们继续以上面的 Golang 运用为例,介绍一下现容器化软件供给链安全的最新实践和东西链。

Ko是 Google 开源的一个简略、快速的 Go 运用程序容器镜像构建器。今日咱们只聚集于 Ko 在软件供给链的一些设计,咱们能够触类旁通,运用在自己的语言和项目中。

无需编写 Dockerfile,使用 Ko build 咱们能够将一个 Golang 项目构建成为一个 Docker 镜像。

$ cat .ko.yaml
defaultBaseImage: knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/distroless/static:nonroot
$ export KO_DOCKER_REPO=knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino
$ ko build -B .
2022/07/02 21:05:33 Using base knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/distroless/static:nonroot@sha256:66cd130e90992bebb68b8735a72f8ad154d0cd4a6f3a8b76f1e372467818d1b4 for github.com/denverdino/secure-supply-chain-sample
2022/07/02 21:05:33 Building github.com/denverdino/secure-supply-chain-sample for linux/amd64
2022/07/02 21:05:34 Publishing knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample:latest
2022/07/02 21:05:35 existing blob: sha256:64ef75a9b8ab92a78ea225f1e707dfee0434dcf7cb0e0b5a8b5020e6b737b791
2022/07/02 21:05:35 existing blob: sha256:3f99978937439fa8ef418c3f36e755f10d175ba218dda5f42846a52b8dca002d
2022/07/02 21:05:35 knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample:sha256-cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3.sbom: digest: sha256:0500ec91074135a2774c87fe86833c0267713be9e78cc4ea86b86cc42701fd0a size: 368
2022/07/02 21:05:35 Published SBOM knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample:sha256-cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3.sbom
2022/07/02 21:05:36 existing blob: sha256:7d883a3eb1c556752c73dedf88da2c0d3943b9f5c3f763cdd7a813ca766f5486
2022/07/02 21:05:36 existing blob: sha256:250c06f7c38e52dc77e5c7586c3e40280dc7ff9bb9007c396e06d96736cf8542
2022/07/02 21:05:36 existing blob: sha256:1759dab52bf113b8a23d818934e0fb48d6f4528df4d614b6edc1d7dba05a01b3
2022/07/02 21:05:36 existing blob: sha256:70e4c71b62aef82e9650deb85d30f3402b435e07665d775a3f3b700e9e7300cb
2022/07/02 21:05:36 knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample:latest: digest: sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3 size: 751
2022/07/02 21:05:36 Published knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample@sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3
knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample@sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3

为什么镜像的创立时间变成了 ”1970/1/1“ ? 这是由于 Ko 的一个设计目标便是支撑Reproducible Builds – 可重现的构建。Reproducible Builds 是一组开发实践,当源码与构建环境装备一模一样时,在不同机器上编译出来的目标二进制文件会在比特层面上做到完全相同。这样的优点是允许独立的第三方能够对从源代码到二进制文件编译进程中进行验证,保证没有引入缝隙或后门。常见的 docker build 指令构建出的容器镜像会在镜像的 manifest 文件中包括构建时间戳,而镜像的 HASH 核算会包括 manifest 文件。这样导致即使是运用相同的代码和 Dockerfile,也无法保证构建出的镜像 HASH 是相同的。

Ko 经过固定运用代码和镜像构建的时间戳,保证了在任何环境构建出的镜像 HASH 保持不变。所以咱们能够经过比较镜像的 HASH 值来快速判别两个镜像中的内容是否一致。一个开放性的问题,Reproducible Build 是否是一个最佳实践?是否适合于您的事务场景?

此外,为了更好支撑软件供给链安全。Ko 自动为运用容器镜像生成了相应的 SBOM 信息,并且作为一个运用制品推送到镜像库房中。能够经过 URL 路径进行访问:{KO_DOCKER_REPO}/{IMAGE_NAME}:sha256-{HASH}.sbom

怎么取得容器镜像的 SBOM 信息呢?咱们有两个办法:

榜首,如果在镜像库房中没有保存容器镜像的 SBOM 信息,咱们能够使用 docker sbom 指令剖析生成运用镜像的 SBOM 信息。

$ docker sbom knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample@sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3
Syft v0.43.0
 ✔ Loaded image
 ✔ Parsed image
 ✔ Cataloged packages      [6 packages]
NAME                                              VERSION                             TYPE
base-files                                        11.1+deb11u3                        deb
github.com/denverdino/secure-supply-chain-sample                                      go-module
github.com/sirupsen/logrus                        v1.8.1                              go-module
golang.org/x/sys                                  v0.0.0-20220702020025-31831981b65f  go-module
netbase                                           6.3                                 deb
tzdata                                            2021a-1+deb11u4                     deb

第二,如果在镜像库房中现已存储了容器镜像的 SBOM 信息,比方 Ko 所发布的 SBOM 信息。咱们能够使用 Sigstore 项目中的cosign东西直接取得镜像的 SBOM 内容。

$ cosign download sbom knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample@sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3
Found SBOM of media type: text/spdx
SPDXVersion: SPDX-2.2
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: github.com/denverdino/secure-supply-chain-sample
DocumentNamespace: http://spdx.org/spdxpackages/github.com/denverdino/secure-supply-chain-sample
Creator: Tool: ko 0.11.2
Created: 1970-01-01T00:00:00Z
##### Package representing github.com/denverdino/secure-supply-chain-sample
PackageName: github.com/denverdino/secure-supply-chain-sample
SPDXID: SPDXRef-Package-github.com.denverdino.secure-supply-chain-sample
PackageSupplier: Organization: github.com/denverdino/secure-supply-chain-sample
PackageDownloadLocation: https://github.com/denverdino/secure-supply-chain-sample
FilesAnalyzed: false
PackageHomePage: https://github.com/denverdino/secure-supply-chain-sample
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageLicenseComments: NOASSERTION
PackageComment: NOASSERTION
Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package-github.com.denverdino.secure-supply-chain-sample
Relationship: SPDXRef-Package-github.com.denverdino.secure-supply-chain-sample DEPENDS_ON SPDXRef-Package-github.com.sirupsen.logrus-v1.8.1
##### Package representing github.com/sirupsen/logrus
PackageName: github.com/sirupsen/logrus
SPDXID: SPDXRef-Package-github.com.sirupsen.logrus-v1.8.1
PackageVersion: v1.8.1
PackageSupplier: Organization: github.com/sirupsen/logrus
PackageDownloadLocation: https://proxy.golang.org/github.com/sirupsen/logrus/@v/v1.8.1.zip
FilesAnalyzed: false
PackageChecksum: SHA256: 7492ae1e0aa4d4d35096aa00e814e533559ff43387dcd063432bb487df806591
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageLicenseComments: NOASSERTION
PackageComment: NOASSERTION
Relationship: SPDXRef-Package-github.com.denverdino.secure-supply-chain-sample DEPENDS_ON SPDXRef-Package-golang.org.x.sys-v0.0.0-20220702020025-31831981b65f
##### Package representing golang.org/x/sys
PackageName: golang.org/x/sys
SPDXID: SPDXRef-Package-golang.org.x.sys-v0.0.0-20220702020025-31831981b65f
PackageVersion: v0.0.0-20220702020025-31831981b65f
PackageSupplier: Organization: golang.org/x/sys
PackageDownloadLocation: https://proxy.golang.org/golang.org/x/sys/@v/v0.0.0-20220702020025-31831981b65f.zip
FilesAnalyzed: false
PackageChecksum: SHA256: c5db1e8eb5bfd167f67624f908fa775e629435bafb5efc3c9188a543eeaa8d16
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageLicenseComments: NOASSERTION
PackageComment: NOASSERTION

新一代镜像签名技能-Keyless

众所周知,咱们能够用镜像签名的办法来保证镜像的可追溯性。一般来说,开发者使用私钥对镜像加签,在布置运用时,能够经过 OPA/Gatekeeper 阻拦恳求,对镜像进行验签。开发者能够界说安全策略来自动化安全流程。比方咱们能够界说一个策略,不允许存在高危险缝隙的镜像布置到出产体系。在镜像构建阶段,咱们能够对经过镜像扫描且不包括高危险缝隙的镜像进行签名,而在 K8s 出产集群中,经过安全策略来来校验镜像签名。

谈谈我对云原生与软件供应链安全的思考

由于曩昔镜像加签/验签的东西易用性不好,并没有得到企业广泛的运用。阿里云镜像服务 ACR,ACK 在供给了集成、简化的镜像安全体会,极大降低了镜像安全的技能门槛。

咱们今日给咱们介绍一个新的技能思路。Sigstore 是由红帽、谷歌联合几所美国高校主导开发保护的供给链安全开源项目,旨在供给一个新的软件加签、验签和防护的标准。经过 Sigstore,咱们能够自动对云原生下的各类开源制品进行数字签名并校验,帮助构建一个更安全、可追溯的供给监控链。

其中 Sigstore 的无密钥签名 Keyless Signatures形式是这个项目最大的亮点之一。无密钥签名,支撑自动化的密钥办理才能,运用者无需办理保护私钥,极大简化的镜像加签验签的体会。

咱们首先经过 cosign sign 指令对镜像进行加签:

$ COSIGN_EXPERIMENTAL=true cosign sign knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample@sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3
Generating ephemeral keys...
Retrieving signed certificate...
        Note that there may be personally identifiable information associated with this signed artifact.
        This may include the email address associated with the account with which you authenticate.
        This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
        By typing 'y', you attest that you grant (or have permission to grant) and agree to have this information stored permanently in transparency logs.
Are you sure you want to continue? (y/[N]): y
Your browser will now be opened to:
https://oauth2.sigstore.dev/auth/auth?access_type=online&client_id=sigstore&code_challenge=Zj3B13VeqlwO1OEs_cc_gVly21ZWdotsB_ipAG1KUD0&code_challenge_method=S256&nonce=2BPd2p6uHg1e916zBz3MoEoH8FR&redirect_uri=http%3A%2F%2Flocalhost%3A55455%2Fauth%2Fcallback&response_type=code&scope=openid+email&state=2BPd2uo32VlgXKC9NY0rDOJlfmA
Successfully verified SCT...
tlog entry created with index: 2824482
Pushing signature to: knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample

在 Keyless 形式中,终端会自动翻开浏览器,由用户选择 OAuth 身份服务商进行认证,流程完成后。cosign 会对镜像进行签名,并将镜像签名保存在镜像库房中,其 URL 路径为:{IMAGE_REPO}/{IMAGE_NAME}:sha256-{HASH}.sig

谈谈我对云原生与软件供应链安全的思考

在这个进程中 cosign 使用 fulcio 的根证书,创立了一个暂时秘钥和证书,对镜像进行加签。签名也会记录在 Rekor 的透明化日志中,为镜像签名供给远程证明。

咱们能够使用 cosign verify 指令对镜像签名进行校验。

COSIGN_EXPERIMENTAL=true cosign verify knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample@sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3
Verification for knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample@sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3 --
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
  - Any certificates were verified against the Fulcio roots.
[{"critical":{"identity":{"docker-reference":"knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample"},"image":{"docker-manifest-digest":"sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3"},"type":"cosign container image signature"},"optional":{"Bundle":{"SignedEntryTimestamp":"MEQCIB1YeNP8suFn6xm7hn0qkAJBiID/gcOP//tsm7u2Z/FIAiBqiw0Zl1CvgVfcGhOWKUEkZKB2XdFm3FPaxq9E+Jsmyg==","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoicmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI2MDRiZWI5M2Q0OGVhYzA4ZmE3OTQzNWNhNTVlZmQyNTE4ODhlN2NmZmMzODJlZTE0MmRjMzZkZDExMzhkYzFjIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNhNXhYd25pR1J6ckRlamtHRHFCSFNTdlMvdUVCeUJkVUV0cFBiRVRxZUVBSWdGY0hWOW9RWkYxYk4xYmtxMWY3UFdWOUpCY00vZlhyZXZTa0orT0tWSDJrPSIsImZvcm1hdCI6Ing1MDkiLCJwdWJsaWNLZXkiOnsiY29udGVudCI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVU52ZWtORFFXbHBaMEYzU1VKQlowbFZTSHByZFVSeVprODJWamxqVUhsSlkyZ3JOVXBFUlc4NVRtcHpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BKZDA1NlFYbE5WRTB3VFdwSk1sZG9ZMDVOYWtsM1RucEJlVTFVVFRGTmFra3lWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWQ016UkNhRGRPZWtRMFRqaEVWVWxyWW5WWVkxWTVUMEZEV1d4MlpGcFNiMkkzVmt3S1RIaE9SMnhOSzNrMmIycGhUR05EZHpaNVlsaHNaak5RVFU0clduaERUVmROTUVreVkyWjFPRUpZZFhNelUzaFVka3RQUTBGVlkzZG5aMFpFVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWUFExUm5DakZMV1dKbFZFRlpWVmxvZUZwVU1HeDJja0YzU0RaWmQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQwbG5XVVJXVWpCU1FWRklMMEpDWjNkR2IwVlZXa2RXZFdSdFZubGFSMngxWWpCQ2JtSlhSbkJpUXpWcVlqSXdkMHhCV1V0TGQxbENRa0ZIUkFwMmVrRkNRVkZSWldGSVVqQmpTRTAyVEhrNWJtRllVbTlrVjBsMVdUSTVkRXd5ZUhaYU1teDFUREk1YUdSWVVtOU5TVWRLUW1kdmNrSm5SVVZCWkZvMUNrRm5VVU5DU0hORlpWRkNNMEZJVlVGRFIwTlRPRU5vVXk4eWFFWXdaRVp5U2pSVFkxSlhZMWx5UWxrNWQzcHFVMkpsWVRoSloxa3lZak5KUVVGQlIwSUtkbmxZT0d0blFVRkNRVTFCVW1wQ1JVRnBRazVFYjBkNE16STNaMGRDZWxWeWRIaEZVVFZ6ZEZSRFF6Z3haRWMwY1dsU2VrMHZTMHR2Y3pGMU5IZEpad3BMVDIxTVNXdENXVzF6V21ZeFZIQTNNRXhaWkRCbGIwaFVVV3AyV1dFdldrbFdaVFEzWTBwMUwwaFpkME5uV1VsTGIxcEplbW93UlVGM1RVUmhVVUYzQ2xwblNYaEJTemREVFRkQ1NFMW1UWE5GY0hwa1lXbHlVRFIzUkZFeUwxUnZibEUxYTBack5FbEZWamRvY1dScFJWbDJVMEpEVVhoSU0xQjRjV2RGU1dJS2RVdEhiWEozU1hoQlR6VmlRamMyUVRSaE5qWXpUSGRFYVVkalYyUlpkVEZrY0Rabk1ubDRkREpyY0ZObFprcGlVMHBQT1dOWFJEVldOM1JUY1d0WmVRcGFSbkJSUmsxUlowdDNQVDBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0=","integratedTime":1656769347,"logIndex":2822273,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}},"Issuer":"https://github.com/login/oauth","Subject":"denverdino@gmail.com"}},{"critical":{"identity":{"docker-reference":"knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample"},"image":{"docker-manifest-digest":"sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3"},"type":"cosign container image signature"},"optional":{"Bundle":{"SignedEntryTimestamp":"MEYCIQDdn2/IzVRCAuS+8s5Zz1F2+Gp3/MXzFP2whryasTa3GQIhAJKWFtb7jGnL8krnR4CwVYr/jbtZuHtlX7TpNPtEP67R","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoicmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI2MDRiZWI5M2Q0OGVhYzA4ZmE3OTQzNWNhNTVlZmQyNTE4ODhlN2NmZmMzODJlZTE0MmRjMzZkZDExMzhkYzFjIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUURVVUdHOEJOZnRoeDBrZGxzWGpvZzZQaFRENmFsNUo4Y3F0WnFFOFJQY3BBSWdMYlFRd2pLT2I0VU9OS05DZ2hvNnlENDNSNHl4TVU2QldtYllBQmVTQXhnPSIsImZvcm1hdCI6Ing1MDkiLCJwdWJsaWNLZXkiOnsiY29udGVudCI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVU53UkVORFFXbHRaMEYzU1VKQlowbFZTVmhtYW5nME1sTnNhQzl5TW5CTlNYUjFRMVJHVjNWVGNUTnJkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BKZDA1NlFYcE5SRVY1VFVSVk5GZG9ZMDVOYWtsM1RucEJlazFFUlhwTlJGVTBWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVVMk9HWkZabkJqWVZSaE1XUjRlVXQxU0RsbGVIcFJSM2MyWWtaelRDOTJVelkxZENzS01WWnNaSEJFZFRWaVMwcFJjbVozVjA1SFEzZ3Zia3RzYUVaS09VZDZhV1JpTUZkYWJtZFJTVUpsU25GcVRtMTVjVFpQUTBGVlozZG5aMFpGVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWTlRTdG9Da1ZsVDBGUkszaEpTUzlxVVZvMWJrbE5ObEpaWWxadmQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQwbG5XVVJXVWpCU1FWRklMMEpDWjNkR2IwVlZXa2RXZFdSdFZubGFSMngxWWpCQ2JtSlhSbkJpUXpWcVlqSXdkMHhCV1V0TGQxbENRa0ZIUkFwMmVrRkNRVkZSWldGSVVqQmpTRTAyVEhrNWJtRllVbTlrVjBsMVdUSTVkRXd5ZUhaYU1teDFUREk1YUdSWVVtOU5TVWRMUW1kdmNrSm5SVVZCWkZvMUNrRm5VVU5DU0hkRlpXZENORUZJV1VGRFIwTlRPRU5vVXk4eWFFWXdaRVp5U2pSVFkxSlhZMWx5UWxrNWQzcHFVMkpsWVRoSloxa3lZak5KUVVGQlIwSUtkMkZYUlVGM1FVRkNRVTFCVW5wQ1JrRnBRazVLWVVKMVJqUk1OVFJsUnpGRlFYVlJTMHh3WTNFNGNtdFlSbXB5TlRoeE1EZHpNazE1ZVVOcFJXZEphQXBCU1hCc1luZHpNVFZLV21KbmVGRTNXRGRTYlRocU5uSjBPV1pWVGxSWlJtMXdhVFJJYzBGcVNIQnRkVTFCYjBkRFEzRkhVMDAwT1VKQlRVUkJNbXRCQ2sxSFdVTk5VVU4zWWtSUVFqQXJWVUZHWkhkcWJVeHJUVEZ4VEhsbGFucGFNbEpWYURKRVEyMHdZbE5rZURSQmQwaDNkV2Q2UmsxaFlsZHpOaTlqVURFS2MxWjZOWHBTTkVOTlVVUTJaR2RVYm0wNWNIUnhVa3BTVlVkWFRGTm1lVzlqZFZoeVRqaFllR1JhU1VsMWJuQjBTek01WW1ZNVYweFdZVFJRYTFObFR3cGhUeXRzSzJvMGRHUmtWVDBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0=","integratedTime":1656811260,"logIndex":2824453,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}},"Issuer":"https://github.com/login/oauth","Subject":"denverdino@gmail.com"}},{"critical":{"identity":{"docker-reference":"knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample"},"image":{"docker-manifest-digest":"sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3"},"type":"cosign container image signature"},"optional":{"Bundle":{"SignedEntryTimestamp":"MEUCIBe/RXXYBuyDXJVvCwFV/vcjfiUXnNqjS7HR2TpyB6WeAiEA+4MdLCkXW1zFqo4M0cdkNcPpEQe5ZfLw5mv266ib1oE=","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI2MDRiZWI5M2Q0OGVhYzA4ZmE3OTQzNWNhNTVlZmQyNTE4ODhlN2NmZmMzODJlZTE0MmRjMzZkZDExMzhkYzFjIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNwN3BUckFUMk04M3hYaFJGc1IyNERnc2dEL3dJOHFCdW1TYUdaSXhiTHVBSWdETUpCb3hNWmU0M2ZtMjJBaHR2SE5BVEFwazhteWN0Y3huaC9oUG13QmxBPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTnZla05EUVdseFowRjNTVUpCWjBsVlZHWkJRM0ZXTWtKWmJ6UjNUVEpDY2pCVU4yMW5OVWcxVjFrd2QwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcEpkMDU2UVhwTlJFVjVUa1JWTTFkb1kwNU5ha2wzVG5wQmVrMUVSWHBPUkZVelYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZxVTNSR1dtcFljbXh2U0dwaGRTOXZRMWxwWVZSVmNUbFRWMk5wWVVzd2RrSnlaMGNLVmt4WlNYbzVVbmR3UnpnM1RuTjNhV3BIZFhac1QySnlXbUkzUTFad2JtRXlSMGwyVUhSNVRFdzNaWFp5VWxOQmJtRlBRMEZWYTNkblowWkdUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlV3TUc5ekNtcFRlRnAzYmtwRWVFeDVVREl2WXl0SEwyZFNUMmR2ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBsbldVUldVakJTUVZGSUwwSkNaM2RHYjBWVldrZFdkV1J0Vm5sYVIyeDFZakJDYm1KWFJuQmlRelZxWWpJd2QweEJXVXRMZDFsQ1FrRkhSQXAyZWtGQ1FWRlJaV0ZJVWpCalNFMDJUSGs1Ym1GWVVtOWtWMGwxV1RJNWRFd3llSFphTW14MVRESTVhR1JZVW05TlNVZE1RbWR2Y2tKblJVVkJaRm8xQ2tGblVVTkNTREJGWlhkQ05VRklZMEZEUjBOVE9FTm9VeTh5YUVZd1pFWnlTalJUWTFKWFkxbHlRbGs1ZDNwcVUySmxZVGhKWjFreVlqTkpRVUZCUjBJS2QyRnJiakZuUVVGQ1FVMUJVMFJDUjBGcFJVRm9TR3RCV21abGRWWnVNREpMUlhoU1FsSnNNVGt2Y0VsWUx5OXNMelptZFd3ekwxazNSRE5yYjNGblF3cEpVVVJHSzBWSGRFaEViMUZNT1VseWVWQnNVbk5oUlVOa1FrbGpibVphWldKWE9HMW1RMmgxVFV4dVdtRlVRVXRDWjJkeGFHdHFUMUJSVVVSQmQwNXVDa0ZFUW10QmFrRXJaV1pJTlhjMlUyMVNObnBvVFM5TmQwSkJXVUY1Um10bWRVdEVOMWQwVldadlFUUTVabUUyY205MFZ6WnNjV1UwWm04eVFtbFJTVTRLUjBwYWFVcHJPRU5OU0ZGNkwwdE9aa3d5VjA4eFNFVlNVSFJWTUdoRVlYcFBORkYxUkhkSlJtdDZabFJRYlZaMFJub3JRakIxYjI1TlR5OVhVWHBuVWdwd016Vm1RVXhyWVVKQlBUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0ifX19fQ==","integratedTime":1656811517,"logIndex":2824482,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}},"Issuer":"https://github.com/login/oauth","Subject":"denverdino@gmail.com"}}]

Sigstore 的cosign-gatekeeper-provider项目供给了 Cosign 与 OPA/Gatekeeper 的集成,能够在 Kubernetes 集群中 对镜像进行验签。可是目前这个版别还不支撑 Keyless 签名办法。我 fork 了一个版别,支撑了 Keyless 签名。

安装装备 Gatekeeper 支撑 external data 特性:

$ helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
$ helm install gatekeeper/gatekeeper  \
    --name-template=gatekeeper \
    --namespace gatekeeper-system --create-namespace \
    --set enableExternalData=true \
    --set controllerManager.dnsPolicy=ClusterFirst,audit.dnsPolicy=ClusterFirst

安装 cosign-gatekeeper-provider,装备 OPA 策略,拒绝不包括合法签名的镜像。

$ git clone https://github.com/denverdino/cosign-gatekeeper-provider
$ cd cosign-gatekeeper-provider
$ kubectl apply -f manifest
$ kubectl apply -f policy/template.yaml
$ kubectl apply -f policy/constraint.yaml

咱们能够验证一下,如果 Deployment 包括正确签名的镜像能够被成功布置。

$ cat deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
  labels:
    app: sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample
  template:
    metadata:
      labels:
        app: sample
    spec:
      containers:
        - name: sample
          image: knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample@sha256:cd1ac13d65aa8983f6c10317a09b994cd66fa46aceb1ba1eaf2cab4ee2038ec3
          ports:
            - containerPort: 8080
$ kubectl apply -f deploy.yaml
deployment.apps/sample-deployment created

如果镜像没有签名,Deployment 的布置将被阻断:

$ cat deploy-unsigned.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment-unsigned
  labels:
    app: sample-unsigned
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-unsigned
  template:
    metadata:
      labels:
        app: sample-unsigned
    spec:
      containers:
        - name: sample
          image: knative-dev-registry.cn-hangzhou.cr.aliyuncs.com/denverdino/secure-supply-chain-sample:unsigned
          ports:
            - containerPort: 8080
$ kubectl apply -f deploy-unsigned.yaml
Error from server (Forbidden): error when creating "deploy-unsigned.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [cosign-gatekeeper-provider] invalid response: {"errors": [], "responses": [], "status_code": 200, "system_error": "VerifyImageSignatures: no matching signatures:\n"}

社区与展望

完成真实的端到端的软件供给链安全需求整个职业的尽力,近期众多开源社区加大了相关技能的投入和协作。

跟着容器技能的遍及,越来越多的软件制品经过 OCI 库房进行办理,比方 AI 模型,Helm Charts。社区的OCI Registry As StorageORAS 项目也应运而生,为多样化的运用制品供给一致的办理、分发才能。Cosign 等软件供给链安全才能,也能够无缝运用于这些软件制品。Kubernetes 社区也在大力推进本身项目的安全根底才能建造。从 1.21 版别开始,所有发布的组件将包括相关 SBOM 信息。KEP-3031也在推进软件制品的签名机制,防止中间人进犯,保证组件的完好性与可信度。

除了容器镜像,Sonatype 也宣告在其 Maven Central 与 Sigstore 打开协作,来提升 Java 开发流程的供给链安全。

曩昔阻止软件供给链运用的最大阻力在于其用户体会,无论是秘钥办理仍是镜像 SBOM、签名等元数据办理都十分复杂,需求多个体系相互协同。Sigstore/Cosign 在简化用户体会方面有了长足的进展。然而 Cosign 目前基于约好办法,如将 sha256-{IMAGE_HASH}.sig 作为镜像签名的 tag。这样的设计十分简略,可是缺少灵活性和扩展才能。OCI – Open Container Initiative 成立了Reference Types 工作组,目标为 OCI 库房中的软件制品间的联系供给标准化的描绘和查询机制。咱们拭目以待,期待能够和 Sigstore 社区共同协作在用户体会的简略性,体系的可扩展性方面达到共识,进一步推进软件供给链安全技能的遍及。

软件供给链安全仍是一个比较新的范畴,很多最佳实践和东西链还不完善。目前 Cosign 等项目还在快速开展中,Keyless 签名机制还未达到出产可用,本文仅供咱们学习参阅相应的技能架构

阿里云容器服务 ACK、容器镜像服务 ACR 在容器安全范畴有着深厚的投入。在信通院首次 “云原生安全成熟度”评估中,阿里云取得了国内唯一全域最高等级认证。咱们也在和 OCI, Sigstore 等社区协作,继续为企业客户供给愈加可信赖、愈加易用的软件供给链安全才能。

点击此处,访问容器镜像服务 ACR,了解阿里云云原生交给链办理和镜像安全更多概况。