最近在公司搭建CI流水线,涉及到容器镜像安全的话题,形成了一个笔记,分享与你,也希望我们都能够提高对安全的重视。
1 时代背景
根据 Anchore 发布的《Anchore 2021年软件供应链安全报告》显示容器的采用成熟度已经非常高了,65% 的受访者表示已经在重度使用容器了,而其他 35% 表示也已经开始了对容器的使用:
业界已经达成共识:云原生时代已经到来,如果说容器是云原生时代的核心,那么镜像应该就是云原生时代的灵魂。镜像的安全对于应用程序安全、系统安全乃至供应链安全都有着深刻的影响。
根据 snyk 发布的 2020年开源安全报告 中指出,在 dockerhub 上常用的热门镜像几乎都存在安全漏洞,多的有上百个,少的也有数十个。具体数据如下图所示:
2 解决方式
GitLab(极狐)建议我们:预防为主,防治结合的方式来提高镜像的安全性。
3 防的最佳实践
3.1 以安全的方式构建容器镜像
常规构建容器镜像的方式就是 docker build,这种情况需要客户端要能和 docker守护进程进行通信。对于云原生时代,容器镜像的构建是在 Kubernetes 集群内完成的,因此容器的构建也常用 dind(docker in docker)的方式来进行。
为了解决这个问题,可以使用一种更安全的方式来构建容器镜像,也就是使用 kaniko。kaniko是谷歌发布的一款根据 Dockerfile 来构建容器镜像的工具。kaniko 无须依赖 docker 守护进程即可完成镜像的构建。其和GitLab CI/CD的集成也是非常方便的,只需要在GitLab CI/CD 中嵌入即可,下面是在我司CI Pipeline中的实践:
variables: EXECUTOR_IMAGE_NAME: "gcr.io/kaniko-project/executor" EXECUTOR_IMAGE_VERSION: "debug" docker-build-job: stage: docker-build-stage image: name: "$EXECUTOR_IMAGE_NAME:$EXECUTOR_IMAGE_VERSION" entrypoint: [""] rules: - if: '$IMAGE_SOURCE_BUILD != "" &&$BUILD_DOCKER_IMAGE == "true" && $CI_PIPELINE_SOURCE !="merge_request_event"' script: - |- KANIKO_CONFIG="{\"auths\":{\"$CI_REGISTRY_IMAGE\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" echo "${KANIKO_CONFIG}" >/kaniko/.docker/config.json - mkdir release - cp -r Build/* release/ - | /kaniko/executor \ --context "${CI_PROJECT_DIR}" \ --dockerfile "Dockerfile" \ --destination"${CI_REGISTRY_IMAGE}:${BUILD_TAG}"
3.2 选择合适且可靠的基础镜像
Dockerfile 的第一句通常都是 FROM some_image,也就是基于某一个基础镜像来构建自己所需的业务镜像,基础镜像通常是应用程序运行所需的语言环境,比如.NET、Go、Java、PHP等,对于某一种语言环境,一般是有多个版本的。
点此浏览
docker pull registry.access.redhat.com/ubi8/dotnet-60-runtime:6.0-22
3.3 不安装非必要的安装包
Dockerfile 中应该尽量避免安装不必要的软件包,除非是真的要用到。比如:我们习惯了直接写 apt-get update && apt-get install xxxx。
3.4 以非root用户启动容器
因此,建议在Dockerfile中添加命令来让容器以非root用户身份启动,在我司的CI Pipeline中的实践:
...... USER 0 RUN chown -R 1001:0/opt/app-root && fix-permissions /opt/app-root # No root should run USER 1001 ENV ASPNETCORE_URLS=http://+:8080 EXPOSE 8080 CMD dotnet ${APPLICATION_DLL}
备注:上面的${APPLICATION_DLL}是在镜像打包阶段由流水线通过参数传递给Dockerfile的。
4 治的最佳实践
在CI流水线中加入容器镜像安全扫描任务。
参考资料
GitLab DevSecOps七剑下天山之容器镜像安全扫描》
云原生时代,如何保证容器镜像安全?》
周旭龙
https://edisonchou.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。