在线制作视频网站,花生壳做网站需要备案,动感十足的网站,网站突然打不开邓宇星#xff0c;Rancher 中国软件架构师#xff0c;7 年云原生领域经验#xff0c;参与 Rancher 1.x 到 Rancher 2.x 版本迭代变化#xff0c;目前负责 Rancher for openEuler(RFO)项目开发。 最近 Rancher v2.7.4 发布了#xff0c;作为一个安全更新版本#xff0c;也… 邓宇星Rancher 中国软件架构师7 年云原生领域经验参与 Rancher 1.x 到 Rancher 2.x 版本迭代变化目前负责 Rancher for openEuler(RFO)项目开发。 最近 Rancher v2.7.4 发布了作为一个安全更新版本也让大家对软件供应链安全多了一份思考。本文将围绕其中比较流行的容器镜像安全管理进行探讨和实践。
运行环境介绍
软件/操作系统版本Rancherv2.7.4Host OS: openEuler22.03-LTS-SP1K8s: RFOv1.26.5rfor1cosignv2.0.2Harborv2.8.2Client OS: MacOS13.4Kubewardenv1.6.0
本次实践将使用最新版 Rancher v2.7.4 作为 K8s 集群管理工具。在此之上可安装 Kubewarden UI 作为可视策略管理工具。整体运行架构以及流程如下 arch 使用 RFO 分发版作为本次下游 K8s 集群RFO 为 Rancher for openEuler 的简称是一个基于 openEuler 基础镜像的 RKE2 分发版。同时我们使用 openEuler 作为本次 K8s 的 Host OS与 RFO 适配性更佳。 RFO 介绍与 Quick Start 请点击https://gitee.com/openeuler/community/tree/master/sig/sig-rfo 本次使用 Harbor cosign Kubewarden 的组合对容器镜像进行存储/签名/验证操作cosign 与 harbor v2.5.0版本有较好的兼容性能直接在 harbor UI 上看到 cosign 证书配置。经测试 Harbor v2.1.1 版本也可使用 cosign 进行签名只是 Harbor UI 上显示不太直观。
环境准备
Harbor 安装请参考官网文档请尽量使用 https 方式让 Harbor 对外提供服务并使用可信的证书减少配置步骤。在本次实践当中我们使用一个免费可信证书来规避此问题。cosign 安装参考官方文档本次使用的是 go install github.com/sigstore/cosign/v2/cmd/cosignlatest 的方式安装。RFO 参考上文的 quick 地址本次准备环境使用 1 master 1 worker 的集群机器规格都是 4c8g确保有足够的资源运行所需组件。Rancher 使用 Docker run 方式启动并将 RFO 集群使用 import 方式纳管到 Rancher 中。
Kubewarden 安装
Kubewarden 是一个开源项目它是针对 Kubernetes 平台的策略引擎。它的目标是通过策略即代码的方式为 Kubernetes 集群提供强大的安全性和策略控制功能。Kubewarden 可以帮助管理员和开发人员定义和实施各种策略以确保应用程序和基础设施的安全性和合规性。
首先我们需要在 Rancher 开启 extension 以及安装 Kubewarden 插件从左侧菜单进入 Configuration - Extensions extension 开启 Extensions 后在 Available 选项卡中找到 Kubewarden 进行安装 kubewarden PS安装时如果是国内的环境容易出现安装插件失败的情况可以使用以下操作进行修复 进入 local 集群的 workload 页面编辑 cattle-ui-plugin-system 命名空间下 ui-plugin-operator 工作负载配置 在 Pod 选项卡中修改 Networking 配置添加 Host Aliases配置185.199.110.133 raw.githubusercontent.com并保存这样能减少国内 Github 相关域名被 DNS 污染的问题。 安装成功后刷新页面并进入下游 RFO 集群管理页面左侧菜单出现 Kubewarden 管理页面。 rfo-kubewarden 并根据 Kubewarden 安装指引安装 Kubewarden这个过程需要安装 cert-manager将 Kubewarden 的 charts repo 添加到 Rancher 中并在集群中安装 Kubewarden APP。安装成功后集群中 Kubewarden 页面如下 kubewarden-installed 根据提示安装 default-policy-server这个默认 policy-server 将会使用 validatingwebhookconfigurations 以及 mutatingwebhookconfigurations 进行策略应用。 default-policy-server 镜像构建推送并验证
整个镜像推送验证的环节包括
使用 cosign 创建镜像签名密钥在 Kubewarden 界面中创建镜像签名验证策略构建镜像并推送到镜像仓库中对镜像使用 cosign 签名并推送在集群中部署镜像
cosign 创建签名密钥
参考文档这次我们使用 k8s secret 作为 cosign 的 kms provider使用以下命令创建密钥
# 创建 cosign namespace
kubectl create ns cosign
# 使用cosign 创建 key并存储在 k8s secret中通过 COSIGN_PASSWORD 指定证书密码此处为了简化操作使用了空密码请在应用时使用密码加强管理
COSIGN_PASSWORD cosign generate-key-pair k8s://cosign/imagekey
# 通过kubectl 查看secret是否创建成功
kubectl get secret -n cosign imagekey
# NAME TYPE DATA AGE
# imagekey Opaque 3 2m46s正常情况下公钥会同时保存在运行目录下的 cosign.pub 文件中。
在 Kubewarden 中创建策略
进入集群下的 Kubewarden 菜单下 ClusterAdmissionPolicy 页面点击 Create 进入创建页面查找 Verify Image Signatures create-policy PS: 在第一次进入时可能无法看到 artifacthub 中 kubewarden 策略可以根据页面提示添加 artifacthub.io 到访问白名单即可查询到配置。 选择 Verify Image Signatures 策略之后在 General 中填写 Name image-validate然后切换到 Settings 配置页面中修改 Signature Type 为 PublicKey signature-type 在 Public Key 下点击 Add 之后出现 image 输入框此处需要输入镜像匹配名称本次填写为 yuxing-test.cnrancher.com/test/*其中 yuxing-test.cnrancher.com 是本次测试使用的 Harbor 域名test 为镜像所在项目。
在 Public Keys 下添加我们的证书公钥内容可以在cosign 创建签名密钥 中找到。输入完成后点击 Finish 创建完成。
创建完成后回到 ClusterAdmissionPolicies 列表页面我们可以看到刚创建的 policy 状态 policy-list 等待 Policy 状态为 Active 后生效过程中 default-policy-server 会重启进行重新配置。若规则配置有问题可以通过 kubectl get po -n cattle-kubewarden-system 找到 policy-server 并查看日志确认问题。
构建镜像并推送到镜像仓库中
本次简化构建镜像过程使用 alpine:3.18.0 作为测试目标。
# pull alpine image
docker pull alpine:3.18.0
# retag it to our registry
docker tag $DIGEST yuxing-test.cnrancher.com/test/alpine:3.18.0
# push to registry
docker push yuxing-test.cnrancher.com/test/alpine:3.18.0使用 cosign 对镜像进行签名
# get the digest of alpine image, it should be only to diegst for this image and the one we need should be index to 1
IMAGE_DIGESTdocker inspect --format{{index .RepoDigests 1}} yuxing-test.cnrancher.com/test/alpine:3.18.0
# sign image with key stored in k8s, --tlog-uploadfalse is aim to not upload transparency log to sigstore server.
cosign sign --key k8s://cosign/imagekey --tlog-uploadfalse ${IMAGE_DIGEST}
# Pushing signature to: yuxing-test.cnrancher.com/test/alpine签名完成后可以登录到 Harbor查看该镜像的签名情况 harbor-alpine 同时我们推送 alpine:3.17.0 镜像到镜像仓库中但不进行 cosign 签名。
docker pull alpine:3.17.0
docker tag alpine:3.17.0 yuxing-test.cnrancher.com/test/alpine:3.17.0
docker push yuxing-test.cnrancher.com/test/alpine:3.17.0在集群中部署镜像
我们在 Rancher UI 上进入集群管理页面使用 yuxing-test.cnrancher.com/test/alpine:3.18.0 镜像创建 deployment create-ok 点击创建后成功部署并注意到镜像名称被修改为只用 digest 的格式。
然后我们使用没有签名的 alpine:3.17.0 镜像创建 deployment在创建后会提示由于无签名而无法创建 pod create-fail 如果我们对 Verify Image Signatures 规则进行调整/升级并应用到 Deployment/StatefulSet/DaemonSet 等类型上则会在创建该类型资源时提示错误。
至此我们完成了整个镜像的构建、签名和部署。
总结与思考
镜像签名的场景可以应用在容器供应链安全的保障上增强镜像来源的可信程度在以下场景能发挥巨大的作用
使用镜像签名对生产环境进行保护只部署已签名的镜像减少镜像从其他环境误操作导致进入生产环境的问题。对引入的开源镜像进行可信扫描并签名进行镜像准入核查。使用签名结合 SBOM(Software Bill of Materials)文档增强对镜像中的软件进行溯源和审计的能力。
在引入签名的同时也会带来额外的管理成本
使用 self-generated 证书固然很方便但不利于分发和管理对于大型的开发团队来说并不是一个好的选择。引入 CA(certificate authority) 管理机构或使用公开可信的 CA 机构签发的证书进行签名。 使用公网中可信 CA 的证书进行签名需要 CI 环境有互联网访问的能力并不利于私有环境的场景。cosign 本身也提供基于 sigstore 的 CA 机构Fulcio 签发证书对镜像进行签名的操作。虽然公有云中有提供私有 CA 证书管理服务但大部分场景下企业需要有自己的证书管理工具与流程这些流程本身就不利于证书的利用。 对签名密钥的生命周期管理一直都是证书管理领域的大问题这个问题在容器镜像签名中被放大。对何时需要对证书进行轮换以及证书轮换时的影响与调整方案都需要更深入的研究。