作者:易立
2011 年,互联网技术先驱 Marc Andreessen 声称,软件正在吞噬世界(Software is eating the world)。由软件驱动的行业翻新正在颠覆着传统业务模式,推动着寰球经济实现数字化连贯。随着互联网的疾速倒退,数字化转型曾经成为每一个企业的要害策略。然而古代软件开发波及到多方合作,大量利用依赖开源代码或者三方组件。在上游开源软件的平安问题会传递到上游利用方并被放大,有可能给企业造成重大的平安危险和业务损失。
软件生产的过程与传统制造业在很多方面是类似的。软件制造商将自研业务代码和第三方组件组合成残缺的软件,构建流程会将这些组件打包成为可部署的软件制品,而后被企业客户部署到生产环境中。这个过程被形象地称为“软件供应链”。而软件供应链平安的指标是保软件从开发到部署的整个生命周期的平安、可信赖。
在 Sonatypes’s 2021 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 基础设施的安全性。
更多内容能够浏览:
https://go.dev/blog/supply-chain
对于已编译的利用二进制文件,咱们能够通过 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 Storage ORAS 我的项目也应运而生,为多样化的利用制品提供对立的治理、散发能力。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,理解阿里云云原生交付链治理和镜像平安更多详情。