探索容器镜像安全管理之道

邓宇星,Rancher 中国软件架构师,7 年云原生领域经验,参与 Rancher 1.x 到 Rancher 2.x 版本迭代变化,目前负责 Rancher for openEuler(RFO)项目开发。

最近 Rancher v2.7.4 发布了,作为一个安全更新版本,也让大家对软件供应链安全多了一份思考。本文将围绕其中比较流行的容器镜像安全管理进行探讨和实践。

运行环境介绍

软件/操作系统版本
Rancherv2.7.4
Host OS: openEuler22.03-LTS-SP1
K8s: RFOv1.26.5+rfor1
cosignv2.0.2
Harborv2.8.2
Client OS: MacOS13.4
Kubewardenv1.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/cosign@latest 的方式安装。
  • 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 TypePublicKey

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_DIGEST=`docker inspect --format='{{index .RepoDigests 1}}' yuxing-test.cnrancher.com/test/alpine:3.18.0`
# sign image with key stored in k8s, --tlog-upload=false is aim to not upload transparency log to sigstore server.
cosign sign --key k8s://cosign/imagekey --tlog-upload=false ${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 证书管理服务,但大部分场景下企业需要有自己的证书管理工具与流程,这些流程本身就不利于证书的利用。
  • 对签名密钥的生命周期管理一直都是证书管理领域的大问题,这个问题在容器镜像签名中被放大。对何时需要对证书进行轮换,以及证书轮换时的影响与调整方案,都需要更深入的研究。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/51631.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【bar堆叠图形绘制】

绘制条形图示例 在数据可视化中,条形图是一种常用的图表类型,用于比较不同类别的数据值。Python的matplotlib库为我们提供了方便易用的功能来绘制条形图。 1. 基本条形图 首先,我们展示如何绘制基本的条形图。假设我们有一个包含十个类别的…

ElasticSearch 7.x

前言 elastic表示可伸缩,search表示查询。所以es的核心即为查询。通常情况下,我们的数据可以分为三类:结构化数据、非结构化数据、半结构化数据。 结构化数据:一般会用特定的结构来组织和管理数据,表现为二维表结构。…

【Android常见问题(五)】- Flutter项目性能优化

文章目录 知识回顾前言源码分析1. 渲染过程2. 分析工具3. 优化方法合理使用const关键词合理使用组件管理着色器编译垃圾 知识回顾 前言 项目迭代开发一定程度后,性能优化是重中之重,其中包括了包体积,UI 渲染、交互等多个方面。 通过 Flutt…

码农该如何延长周末体验感

码农该如何延长周末体验感 码农该如何延长周末体验感 码农该如何延长周末体验感1.制定合理的工作计划:2.实践工作与生活的平衡:3.学习新技术或扩展知识领域4.参与开源项目或个人项目:5.与同事或朋友组织活动:6.自己写博客或者总结…

百万数据快速导入导出

百万数据快速导入 pom <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.0</version></dependency>Resourceprivate SalariesListener salariesListener;private ExecutorService…

求解方程x^2=a的根,不使用库函数直接求解(不动点迭代法)

首先可以将方程两边同时加上x&#xff0c;&#xff0c;这时候两边同时再除以1x&#xff0c;就得到了&#xff0c;变形为。&#xff08;变性后的迭代式不唯一&#xff0c;这里随便选取一个&#xff09; 当x是准确值的时候&#xff0c;两边应该是相等的&#xff0c;如果x是近似值…

【Git】分支管理之创建、切换、合并、删除分支以及冲突处理

目录 一、理解分支 二、创建、切换、合并分支 三、删除分支 四、冲突处理 五、合并模式 六、合并策略 七、Bug分支处理 八、强制删除分支 一、理解分支 master其实就是一个指针 &#xff0c;他指向的是主分支最近一次commit。我们可以创建新的分支&#xff0c;在新的分…

Arcgis之 KML/KMZ文件转shp

一般我们在Goole Earth上勾画的区域导出后都为KML或者KMZ格式的&#xff0c;但无法在arcgis等软件上直接应用&#xff0c;故需进行一定的转换 1.打开ArcMap&#xff0c;选择ArcToolbox->Conversion Tools->From KML->KML To Layer 得到如下结果&#xff08;由于本KML…

请问学JavaScript 前要学html 和css 吗?

前言 html和css可以理解为是一个网站的骨架和皮肤&#xff0c;这两部分做好后整个网站的外观展示的完成度基本就有了个90%左右&#xff0c;所以在学习js前是需要学习html和css 的&#xff0c;这两部分不用花特别多的时间&#xff08;虽然css如果想做一些非常炫酷的效果个人认为…

什么是SVM算法?硬间隔和软间隔的分类问题

SVM全称是supported vector machine(支持向量机)&#xff0c;即寻找到一个超平面使样本分成两类&#xff0c;并且间隔最大。 SVM能够执行线性或⾮线性分类、回归&#xff0c;甚至是异常值检测任务。它是机器学习领域最受欢迎的模型之一。SVM特别适用于中小型复杂数据集的分类。…

MobaXterm通过SSH访问Ubuntu服务器遇到的一个问题

在Windows下的MobaXterm界面配置完ubuntuIP以后显示access denied&#xff0c;排查发现是因为在ubuntu那边忘记安装了SSH Serve&#xff0c;安装过程如下&#xff1a; 第一步&#xff1a;安装所需包 让我们从打开终端输入一些必要命令开始。 注意&#xff0c;在安装新的包或…

SpringBoot统一异常处理和统一返回格式

上篇博客我们讲解了使用AOP来进行统一的用户登录判断&#xff0c;其实像这种功能统一且使用较多的地方&#xff0c;都可以用AOP来处理&#xff0c;除了统⼀的⽤户登录判断之外&#xff0c;AOP 还可以实现&#xff1a; 统⼀⽇志记录统⼀⽅法执⾏时间统计&#xff08;在性能优化…

机器学习:混合高斯聚类GMM(求聚类标签)+PCA降维(3维降2维)习题

使用混合高斯模型 GMM&#xff0c;计算如下数据点的聚类过程&#xff1a; Datanp.array([1,2,6,7]) 均值初值为: μ1,μ21,5 权重初值为: w1,w20.5,0.5 方差: std1,std21,1 K2 10 次迭代后数据的聚类标签是多少&#xff1f; 采用python代码实现&#xff1a; from scipy import…

人工智能-Dlib+Python实现人脸识别(人脸识别篇)

人脸识别流程 人脸检测,人脸数据提取:首先是检测到人脸保存人脸数据:可以保存到mysql数据库中mysql数据库连接mysql数据库安装mysql数据库操作设置人脸数据标签:(人脸名字),保存到数据库打开摄像头,检测到人脸,提取人脸数据:人脸数据与数据库中的数据对比,1、人脸检…

【图论】Prim算法

一.介绍 Prim算法是一种用于解决最小生成树问题的贪心算法。最小生成树问题是指在一个连通无向图中找到一个生成树&#xff0c;使得树中所有边的权重之和最小。 Prim算法的基本思想是从一个起始顶点开始&#xff0c;逐步扩展生成树&#xff0c;直到覆盖所有顶点。具体步骤如下…

用合成数据训练托盘检测模型【机器学习】

想象一下&#xff0c;你是一名机器人或机器学习 (ML) 工程师&#xff0c;负责开发一个模型来检测托盘&#xff0c;以便叉车可以操纵它们。 ‌你熟悉传统的深度学习流程&#xff0c;已经整理了手动标注的数据集&#xff0c;并且已经训练了成功的模型。 推荐&#xff1a;用 NSDT设…

【业务功能篇60】Springboot + Spring Security 权限管理 【终篇】

4.4.7 权限校验扩展 4.4.7.1 PreAuthorize注解中的其他方法 hasAuthority&#xff1a;检查调用者是否具有指定的权限&#xff1b; RequestMapping("/hello")PreAuthorize("hasAuthority(system:user:list)")public String hello(){return "hello Sp…

深度学习入门教程(1):用神经网络预测糖尿病病例Predict Diabetes Cases with Neural Networks

本深度学习入门教程是在polyu HPCStudio 启发以及资源支持下进行的&#xff0c;在此也感谢polyu以及提供支持的老师。 大纲&#xff08;what will you learn from this project&#xff09; 1&#xff1a;What are neural networks&#xff1f; 2&#xff1a;Why use neural …

3D 渲染技巧-如何创建高质量写实渲染?

掌握创建高质量建筑渲染和任何 3D 渲染的艺术是一项复杂且需要技巧的工作&#xff0c;通常需要多年的经验和实践。实现逼真的结果需要仔细考虑众多因素&#xff0c;并避免可能导致缺乏真实性的假渲染效果的常见错误。 避免常见错误 - 提升渲染游戏的技巧 在追求创建真正逼真的…

从零开始学习CTF——CTF是什么

引言&#xff1a; 从2019年10月开始接触CTF&#xff0c;学习了sql注入、文件包含等web知识点&#xff0c;但都是只知道知识点却实用不上&#xff0c;后来在刷CTF题才发现知识点的使用方法&#xff0c;知道在哪里使用&#xff0c;哪里容易出漏洞&#xff0c;可是在挖src漏洞中还…