一、镜像的检测

镜像中包含程序,其中也可能包含漏洞,所以我们需要检查镜像中是否存在漏洞。

首先,准备一台装有docker的设备,提前拉取nginx和redis镜像做检查。

docker pull nginx
docker pull redis

接着下载Trivy这个工具。Trivy是一个简单而全面的扫描器,用于检测容器镜像、文件系统和 Git 存储库中的漏洞,以及配置问题。 Trivy检测操作系统包(Alpine、RHEL、CentOS 等)和特定语言包(Bundler、Composer、npm、yarn 等)的漏洞。此外,Trivy扫描基础设施即代码 (IaC) 文件,例如 Terraform、Dockerfile 和 Kubernetes,以检测可能使我们的部署面临攻击风险的潜在配置问题。 Trivy易于使用。只需安装二进制文件,我们就可以开始扫描了。安装步骤具体请参考:https://aquasecurity.github.io/trivy/v0.18.3/installation/

这里以Centos宿主机为例子。将仓库设置添加到/etc/yum.repos.d

[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/
gpgcheck=0
enabled=1

安装trivy:

yum -y update
yum -y install trivy

Trivy工作的原理如下:读取互联网上CVE(Common Vulnerabilities and Exposures)库,CVE中记录了漏洞的信息。然后Trivy会下载这些信息到本地数据库中。然后当我们检测时,Trivy会读取其中的信息,并且与本地的数据库进行对比,从而判断出此程序是否存在漏洞。接下来,我们分别使用trivy检查下载的两个镜像:

首先检查nginx镜像:

trivy image nginx

部分截图,可以看到其中存在83个low risk漏洞,6个medium risk,6个high risk和4个critical的漏洞:

检查redis镜像:

trivy image redis

高危的漏洞不多,主要是56个low risk的漏洞。那么可以看到,redis相对于nginx,漏洞会少一些。

我们后续可以根据检测的结果,决定哪些漏洞需要进行修补。

二、DockerFile的优化

DcokerFileke可以帮助我们在原始镜像上进行自定义修改或者更新原有镜像。DockerFile的原理和语法请参考:官网文档https://docs.docker.com/develop/develop-images/dockerfile_best-practices/或总结的笔记https://blog.csdn.net/tushanpeipei/article/details/115837183

DockerFile的优化原则:越小越好、提高安全性。具体的方式有:

1.减少层数:
尽量减少镜像中的层数以确保它们的性能非常重要。添加了以下功能以减少此限制:只有指令RUN, COPY,ADD创建层。其他指令会创建临时中间镜像,并且不会增加构建的大小,也就是说多个命令放在一个RUN 里写,比多个RUN要小。

2.清理无用数据:
清理缓存可以有效减少镜像的大小。例如我们可以可以构建镜像是加上如下命令:

yum clean all && rm -rf /var/cache/yum/*

3.多阶段构建:
多阶段构建能够帮助我们大幅减少最终镜像的大小,而无需费力减少中间层和文件的数量。因为镜像是在构建过程的最后阶段构建的,所以我们可以通过利用构建缓存来最小化镜像层。例如,如果我们的构建包含多个层,可以将它们从更改较不频繁(以确保构建缓存可重用)到更改较频繁的排序:

  1. 安装构建应用程序所需的工具;
  2. 安装或更新库依赖项;
  3. 生成我们的应用程序。

Go 应用程序的 Dockerfile 可能如下所示:

# syntax=docker/dockerfile:1
FROM golang:1.16-alpine AS build# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep# List project dependencies with Gopkg.toml and Gopkg.lock
# These layers are only re-built when Gopkg files are updated
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# Install library dependencies
RUN dep ensure -vendor-only# Copy the entire project and build it
# This layer is rebuilt when a file changes in the project directory
COPY . /go/src/project/
RUN go build -o /bin/project# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]

其中涉及到2个镜像的构建。我们将第一个临时镜像命名为build。最终镜像使用–from=build,从第一个临时的镜像中拷贝信息到本地目录。那么最终镜像其实就这由COPY创建的一层镜像。构建完成后,我们只需要删除第一个临时镜像即可。

4.利用构建缓存:
构建镜像时,Docker 会逐步执行 Dockerfile 中的指令,并按照指定的顺序执行每个指令。在检查每条指令时,Docker 会在其缓存中查找可以重用的现有镜像,而不是创建新的(重复)镜像。

对于 ADD 和 COPY 指令,检查镜像中文件的内容并计算每个文件的校验和。这些校验和不考虑文件的最后修改和最后访问时间。在缓存查找期间,校验和与现有镜像中的校验和进行比较。如果文件中的任何内容(例如内容和元数据)发生了更改,则缓存将失效。

除了 ADD 和 COPY 命令之外,缓存检查不会查看容器中的文件来确定缓存匹配。例如,在处理 RUN apt-get -y update 命令时,不会检查容器中更新的文件以确定是否存在缓存命中。在这种情况下,仅使用命令字符串本身来查找匹配项。

5.尽量避免使用root登录
保证容器运行所使用的权限不要超过其需要使用的需要。因此,我们需要创建一个新的用户,然后赋予它有限的权限。在构建镜像时,我们可以还有USER XXX指定默认使用什么用户。

6.不要安装多余的包
了减少复杂性、依赖性、文件大小和构建时间,避免安装额外或不必要的包。例如,我们不需要在数据库镜像中包含文本编辑器。

7.对多行参数进行排序
只要有可能,通过按字母数字顺序对多行参数进行排序来简化以后的更改。这有助于避免包重复并使列表更易于更新。这也使 PR 更易于阅读和审查。在反斜杠 (\) 前添加一个空格也有帮助。以下是来自 buildpack-deps 镜像的示例:

RUN apt-get update && apt-get install -y \bzr \cvs \git \mercurial \subversion \&& rm -rf /var/lib/apt/lists/*

三、yaml文件安全

很多时候我们都以最简单的方式来应用yaml文件,而忽略了yaml文件中存在的很多安全设置,例如securityContext等。那么,如何检查我们的yaml文件是否安全?可以使用kubsec这个工具来帮助我们完成这个任务。下载地址:https://github.com/controlplaneio/kubesec/releases

下载适合自己的版本即可。我这里下载的是kubesec_linux_amd64.tar。在master设备上解压后,扫描如下的pod2.yaml文件:

apiVersion: v1
kind: Pod
metadata:creationTimestamp: nulllabels:run: pod2name: pod2
spec:containers:- image: nginximagePullPolicy: IfNotPresentname: pod2resources: {}env:- name: aavalue: xxx- name: bbvalue: '999'dnsPolicy: ClusterFirstrestartPolicy: Always
status: {}

扫描的命令:

./kubesec scan pod2.yaml

扫描结果:结果中给我们了很多相关的修改建议,例如在spec下添加ServiceAccountName字段可以严格控制kubernets API的访问。

我们可以按照它给的提示和实际的需求修改我们的yaml文件。

四、使用Secret拉取镜像

很多私有镜像仓库,都必须要求客户端登陆后才能拉取镜像,无法匿名拉取。所以在K8s中我们可以设置一个Secret,保存镜像仓库的账号和密码,例如:

kubectl create secret docker-registry mysec1(secret名称) --docker-server=x.x.x.x(仓库地址) --docker-username=yyy(仓库用户名) --docker-password=zzz(仓库密码)

然后再创建pod的yaml文件中使用此secret即可,例如:

root@vms71:~/yaml_sec# cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:creationTimestamp: nulllabels:run: pod1name: pod1
spec:terminationGracePeriodSeconds: 0imagePullSecrets:- name: mysec1containers:- image: x.x.x.x/nginximagePullPolicy: IfNotPresentname: pod1resources: {}dnsPolicy: ClusterFirstrestartPolicy: Always
status: {}

仅需在原始的yaml文件中,与containers对其,添加如下参数即可:

  imagePullSecrets:- name: mysec1 # secret名称

这样设置的话,当我们使用此yaml文件创建pod时,如果pod本地不存在,则会使用secret中的账号密码登录到我们的私人仓库拉取镜像了。

整理资料来源:
《老段CKS课程》
trivy github:https://github.com/aquasecurity/trivy
DockerFile:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

三十一、K8s供应链安全2 - 镜像的检测及优化与yaml文件安全相关推荐

  1. 【k8s】三、k8s集群的初始化

    目录 前言 环境规划 kubeadm kubelet kubectl 安装kubeadm master节点初始化 node节点初始化加入集群 集群网络初始化之flannel 报错 kubeadm in ...

  2. 《深入剖析Kubernetes》-张磊——白话容器基础(三):深入理解容器镜像

    <深入剖析Kubernetes>-张磊 白话容器基础(三):深入理解容器镜像 写在前面: 张磊的极客时间课程<深入剖析Kubernetes>,是我见过讲docker和k8s最好 ...

  3. 【正点原子Linux连载】第三十一章 U-Boot顶层Makefile详解 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  4. (三)k8s资源清单

    一.k8s中的资源 K8s中所有的内容都抽象为资源,资源实例化之后,叫做对象,那么这些资源不能在同一空间下重名 名称空间级别(namespace) 工作负载型资源( workload):Pod. Re ...

  5. 【FastDev4Android框架开发】RecyclerView完全解析之下拉刷新与上拉加载SwipeRefreshLayout(三十一)...

    转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49992269 本文出自:[江清清的博客] (一).前言: [好消息] ...

  6. Python编程基础:第三十一节 文件读取Read a File

    第三十一节 文件读取Read a File 前言 实践 前言 当我们检测到文件之后就可以读取其中的内容,读取所用到的函数是read(). 实践 我们依然以上一节的lyric.txt为例展示如何读取文件 ...

  7. OpenCV学习笔记(三十一)——让demo在他人电脑跑起来 OpenCV学习笔记(三十二)——制作静态库的demo,没有dll也能hold住 OpenCV学习笔记(三十三)——用haar特征训练自己

    OpenCV学习笔记(三十一)--让demo在他人电脑跑起来 这一节的内容感觉比较土鳖.这从来就是一个老生常谈的问题.学MFC的时候就知道这个事情了,那时候记得老师强调多次,如果写的demo想在人家那 ...

  8. 三十一、Java多线程编程(下篇)

    @Author:Runsen @Date:2019/11/07 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘课严重,专业 ...

  9. FreeSql (三十一)分区分表

    分区 分区就是把一个数据表的文件和索引分散存储在不同的物理文件中.把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,数据库不同实现方式有所不同. 与分表不同,一张大表进行 ...

  10. docker pull 下载一半_Docker三个重要的基本操作,镜像,容量,仓库

    前言 Docker的功能和特性有很多,各种运行命令.参数等也都要学习和练习. 比如:如何管理数据.如何管理网络.如何互相配合工作.如何编写更专业的Dockerfile等. 本文讲讲Docker镜像,容 ...

最新文章

  1. 四年级计算机考试反思,考试后的反思四年级作文
  2. linux 文件 加密传输,服务端和客户端之文件加密传输
  3. 本地提交到yarn_Flink on Yarn三部曲之三:提交Flink任务
  4. It's my life
  5. android按钮切换颜色,togglebutton
  6. 2020-08-17每日一句
  7. redis报错: redis.exceptions.ResponseError: value is not an integer or out of range
  8. 汇编跳转指令(转载)
  9. 分享一个自己写的QT小游戏-玛丽奥医生
  10. 日文简历 模板
  11. 有什么方法可以将WMV格式转换成MP4格式
  12. win10计算机语言超清壁纸,适合win10励志超清壁纸欣赏
  13. python分号怎么用_go、java已经python中分号的使用
  14. 人体手脚部位与内脏的对应关系图
  15. 06 基于v5-resources在macos系统搭建a8服务
  16. C++解决《无重复字符的最长子串》问题(滑动窗口(unordered_set),string)
  17. java memorystream 包_C#到Java:Base64String,MemoryStream,GZipStream
  18. “很抱歉,出现错误,Word不能启动(2)。”解决方法(转载),2023-3-3
  19. pta 试试手气 C语言
  20. python字符宽度_使用vars或\uyu dict的Python固定宽度字符串格式__

热门文章

  1. CCFTF17(上海):认知计算产业化如何落地(知识图谱、智能问答等)
  2. 【python】读取json文件
  3. 《统计学习方法》——感知机
  4. 量子时代已来,与时代接轨,从这本书开始
  5. 名企面试官精讲典型编程题之数据结构数组篇
  6. 第三:启发式搜索:A* 算法
  7. python staticmethod
  8. Python机器学习基础教程(一):简介
  9. HTML样式- CSS
  10. create方法 eslint关闭_详解create-react-app 自定义 eslint 配置