【翻译】如何用Cosign和Distroless图像来保证容器的安全

原文为InfraCloud高级SRE Jeswin Ninan在InfraCloud的博客上发表的客座文章

容器技术和 "容器镜像 "这个词对许多开发人员、SRE和DevOps工程师来说并不陌生。但是,为生产部署提供安全的容器镜像是我们现在真正需要的东西。我们已经看到了最近通过插入后门对SolarWinds商业应用程序的软件供应链攻击。当客户从SolarWinds应用程序中下载木马安装包时,攻击者可以访问那些正在运行SolarWinds产品的系统。在这篇文章中,我们将讨论协同签名和无分布式容器映像,它们可以帮助实现您的应用程序容器在生产中更安全地部署和运行。

什么是无分布式容器图像?

无分布式容器镜像是 "以语言为中心的Docker镜像,减去操作系统"。这意味着它只包含你的应用程序及其运行时的依赖,而不包含其他通常的操作系统包管理器、Linux外壳或任何我们通常在标准Linux发行版中期望的程序。无发行版的基本镜像比其对应的软件包要少。这减少了攻击面,因为有可能受到攻击的组件较少,因此提高了安全性。

来源:https://github.com/GoogleContainerTools/distroless

无发行版容器镜像的好处。
  • 提高了容器的安全性。
  • 减少了容器的大小。
  • 减少合规范围。
  • 提高容器分发性能。
  • 通过利用更少的资源来提高成本效益。

为我们的应用程序提供的无分布式容器图像,以及Cosign验证

Cosign是谷歌与Linux基金会项目合作开发的一个工具,名为sigstore,用于简化容器镜像的签名和验证。谷歌宣布,无发行版图像现在由Cosign签署。因此,这意味着无发行版的所有用户可以在启动镜像构建之前,验证他们确实在使用他们打算使用的基础镜像,使无发行版的镜像更加值得信赖。

一般的Cosign工作流程
Diagram showing Cosign workflow
为什么我们需要 Cosign 和无发行版容器镜像?

之所以需要Cosign,是因为即使是无发行版的镜像,也有可能面临一些安全威胁,比如错别字攻击,或者收到恶意的镜像。如果无发行版的构建过程被破坏,就会使用户容易意外地使用恶意镜像而不是实际的无发行版镜像。

Typosquatting是一种社会工程攻击,攻击者将恶意软件包发布到注册表上,希望用相似的软件包或注册表/域的名称来欺骗用户安装它们。

如何用Cosign和无发行版图像构建应用容器图像?

Diagram showing building application process with Cosign
用Cosign验证来验证无发行版容器基础镜像。

用发布者谷歌共享的Cosign公钥验证无发行版镜像gcr.io/distroless/static。这应该是镜像构建过程中的第一步。

$ cosign verify -key publisher-shared-cosign-pub.key gcr.io/distroless/static 验证 gcr.io/distroless/static --对每个签名都进行了以下检查。- 签名已被验证 - 签名已根据指定的公钥被验证 - 任何证书已根据Fulcio的根进行验证。io/distroless/static"},"image":{"docker-manifest-digest":"sha256:c9320b754c2fa2cd2dea50993195f104a24f4c7ebe6e0297c6ddb40ce3679e7d"},"type":"cosign   container image signature"},"optional":null}
用经过Cosign验证的无发行版基础镜像构建应用容器镜像

有几种方法可以构建应用程序镜像作为无发行版容器镜像。

  • 使用各自的构建工具,从源代码构建应用程序。之后,通过使用Docker指令COPY或ADD来构建带有复制或添加的构建工件的Docker镜像。
  • 多阶段的Docker构建。

我在这里遵循多个场景,为我的Hello-World Go网络应用构建Docker容器镜像,你可以在这里找到静态无发行版镜像和标准基础镜像

  1. 在多阶段构建过程中,用gcr.io/distroless/static作为基础镜像构建的应用程序镜像。
FROM golang:1.15 as builder COPY ./usr/local WORKDIR /usr/local/ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o cmd/app FROM gcr.io/distroless/static USER nonroot:nonroot COPY --from=builder --chown=nonroot:nonroot /usr/local/cmd/app /bin/app ENTRYPOINT ["/bin/app"]
  1. 在单阶段构建过程中,用golang:1.15构建的应用程序图像。
FROM golang:1.15 as builder COPY ./usr/local WORKDIR /usr/local/ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /bin/app ENTRYPOINT ["/bin/app" ]
  1. 以ubuntu:21.04为基础镜像,在一个多阶段的构建过程中构建的应用程序镜像。
FROM golang:1.15 as builderstage COPY ./usr/local WORKDIR /usr/local/ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o cmd/app FROM ubuntu:21.04 COPY --from=builderstage /usr/local/cmd/app /bin/app ENTRYPOINT ["/bin/app" ]

你可以在下一个主题中找到Docker扫描报告的细节,它确定了为你的应用程序使用无发行版基础镜像的意义。

容器镜像扫描:无发行版容器镜像与标准容器镜像的对比

我使用了名为Synk的Docker原生扫描工具,该工具现在在较新版本的Docker包中可用。你可以通过使用docker命令来使用这个工具。"docker scan image_name"。

图像扫描报告
静态无分布式基础镜像 作为 Alpine 标准基础镜像 作为Ubuntu的标准基础映像
$ docker scan local-distroless:v1

测试 local-distroless:v1...

Organization: jeswinjkn
Package manager: deb
Project name: docker-image|local-distroless
Docker image: local-distroless:v1
Platform: linux/amd64
Licenses: enabled

✔ Tested 3 dependencies for known issues, no vulnerable paths found.
$ docker scan local-standard:v1

测试 local-standard:v1...

Organization: jeswinjkn
Package manager: deb
Project name: docker-image|local-standard
Docker image: local-standard:v1
Platform: linux/amd64
Licenses: enabled

针对已知问题测试了200个依赖项,发现169项问题。
$ docker scan local-ubuntu:v1

测试 local-ubuntu:v1...

Organization: jeswinjkn
Package manager: deb
Project name: docker-image|local-ubuntu
Docker image: local-ubuntu:v1
Platform: linux/amd64
Licenses: enabled

Test 103 dependencies for known issues, found 12 issues.

注意:你可以从参考文献中找到Synk扫描的完整报告。

使用Cosign构建的无发行版应用容器镜像进行签名。
生成cosign密钥对
$ cosign generate-key-pair 输入私钥的密码。 
再次输入。 
私钥写到cosign.key 公钥写到cosign.pub

我们需要用注册表的细节来标记本地构建的容器镜像,并推送到远程注册表。用生成的私钥签署远程容器镜像。

$ cosign sign -key cosign.key jeswinkninan/distroless:v1 输入私钥的密码。 
Pushing signature to: index.docker.io/jeswinkninan/distroless:sha256-41fd2ec0997d91c5df7c7d58d0a2433a5744119d79a803123541cdd2b0e93f08.sig
使用生成的 Cosign 公钥验证应用程序容器镜像
$ cosign verify -key cosign.pub jeswinkninan/distroless:v1 验证 jeswinkninan/distroless:v1 -- 对每个签名进行了以下检查: --验证了cosign声明 --根据指定的公钥验证了签名 --根据Fulcio根验证了任何证书。
{"critical":{"identity":{"docker-reference":"index.docker.io/jeswinkninan/distroless"},"image":{"docker-manifest-     digest":"sha256:41fd2ec0997d91c5df7c7d58d0a2433a5744119d79a803123541cdd2b0e93f08"},"type":"cosign container image signature"},"optional":null}

关键点

  • 无区块链是以语言为中心的Docker镜像,减去了操作系统。
  • 软件包越少,出现漏洞的可能性就越小。无Distroless镜像将只拥有必要的软件包。
  • 无Distroless镜像现在是Cosigned。
  • 在每次构建之前,用Cosign公钥验证每个无发行版的镜像。
  • 容器镜像扫描是你的CICD构建系统中必须具备的。
  • 在生产中使用无发行版镜像之前,请对从无发行版镜像构建的内部应用镜像进行Cosign,并进行验证,以确保镜像的可靠性。

我们希望你喜欢阅读这篇博文。如果你喜欢听我们说话,请通过TwitterLinkedin与我们联系。

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值