Dockerfile静态扫描

发布时间 2023-07-12 15:06:16作者: 北方姆Q
我们的产物都是基于同一Dockerfile生成,因此我们需要保证这个底层Dockerfile的安全性
Dockerfile的写法有很多,我一般会采用最简单的方式,即Dockerfile什么都不处理直接RUN
# 主要是时区跟源的问题,我们需要重封一次
[root@jenkins-bj-ali-ql1 conf.d]# cat Dockerfile
FROM alpine:latest
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
    && apk add --no-cache tzdata tini \
    && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime  \
    && echo Asia/Shanghai > /etc/timezone \
    && apk del tzdata
[root@jenkins-bj-ali-ql1 conf.d]# docker build -t golang:base .
[root@jenkins-bj-ali-ql1 conf.d]# cat goDockerfile
FROM golang:base

WORKDIR /app
COPY main .
COPY configs/ configs/
COPY templates/ templates/
ENTRYPOINT ["/sbin/tini", "--"]
CMD /app/main ${GO_OPTIONS}
alpine与distroless是推荐的两个最底层镜像,他们很精简,distroless2M,alpine5.57M,不过distroless是不包含任何bash的,没放处理意外情况,为了职业生涯,建议用alpine;如果是为了技术,建议用distroless

Checkov安装

heckov 不仅可以扫描dockfile, 也可以扫描 Cloudformation、AWS SAM、Kubernetes、Helm charts、Kustomize 、镜像checkov 不仅可以扫描dockfile, 也可以扫描 Cloudformation、AWS SAM、Kubernetes、Helm charts、Kustomize 、镜像

需要先安装python3.7以上版本

curl -O https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz
tar -zxvf Python-3.9.0.tgz
cd Python-3.9.0 && ./configure prefix=/usr/local/python3
make && make install
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
python3 --version

使用pip3直接安装checkov,大概需要半小时...

pip3 install --upgrade pip
pip3 install checkov -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
checkov -h

真的是支持巨多的扫描,这也是我们选用它的原因,后续的安全扫描我们直接复用checkov即可
image
还支持cyclonedx_json的输出,那看来在sbom扫描处我们也可以用他替换syft生成清单
image

扫描一下刚才的Dockerfile跟goDockerfile,只列出问题内容

[root@jenkins-bj-ali-ql1 conf.d]# checkov -f Dockerfile --framework dockerfile --quiet --compact --skip-results-upload
dockerfile scan results:

Passed checks: 19, Failed checks: 3, Skipped checks: 0

Check: CKV_DOCKER_7: "Ensure the base image uses a non latest version tag"
	FAILED for resource: Dockerfile.FROM
	File: Dockerfile:1-1
	Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/docker-policies/docker-policy-index/ensure-the-base-image-uses-a-non-latest-version-tag.html
Check: CKV_DOCKER_3: "Ensure that a user for the container has been created"
	FAILED for resource: Dockerfile.
	File: Dockerfile:1-6
	Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/docker-policies/docker-policy-index/ensure-that-a-user-for-the-container-has-been-created.html
Check: CKV_DOCKER_2: "Ensure that HEALTHCHECK instructions have been added to container images"
	FAILED for resource: Dockerfile.
	File: Dockerfile:1-6
	Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/docker-policies/docker-policy-index/ensure-that-healthcheck-instructions-have-been-added-to-container-images.html
[root@jenkins-bj-ali-ql1 cmd]# checkov -f Dockerfile --quiet --compact --skip-results-upload --framework dockerfile
dockerfile scan results:

Passed checks: 3, Failed checks: 2, Skipped checks: 0

Check: CKV_DOCKER_3: "Ensure that a user for the container has been created"
	FAILED for resource: Dockerfile.
	File: Dockerfile:1-8
	Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/docker-policies/docker-policy-index/ensure-that-a-user-for-the-container-has-been-created.html
Check: CKV_DOCKER_2: "Ensure that HEALTHCHECK instructions have been added to container images"
	FAILED for resource: Dockerfile.
	File: Dockerfile:1-8
	Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/docker-policies/docker-policy-index/ensure-that-healthcheck-instructions-have-been-added-to-container-images.html
  1. 不让用tag为latest的镜像作为基础镜像
  2. 需要设定一个运行用户
  3. 需要设定健康检查

修改goDockerfile内容,毕竟我们真实打包制品用的是它

[root@jenkins-bj-ali-ql1 cmd]# cat Dockerfile
FROM golang:base

WORKDIR /app
COPY main .
COPY configs/ configs/
COPY templates/ templates/
USER work 								# 加了这里
HEALTHCHECK NONE						# 加了这里
ENTRYPOINT ["/sbin/tini", "--"]
CMD /app/main ${GO_OPTIONS}
[root@jenkins-bj-ali-ql1 cmd]# checkov -f Dockerfile --quiet --compact --skip-results-upload --framework dockerfile
dockerfile scan results:

Passed checks: 6, Failed checks: 0, Skipped checks: 0

集成jenkins pipeline

本次Checkov用来扫描Dockerfile,而Dockerfile是固定的,因此实际情况中应当在编写好用于后续封装制品Dockerfile后扫描后根据报告修改问题即可,理论上不需要在pipeline中每次都再次扫描,不过为了整体完整性,依然会加入到pipeline Package中作为前置条件

		stage('Package') {
            steps {
                script {
                    sh "/bin/cp -rpf /var/lib/jenkins/workspace/conf.d/goDockerfile Dockerfile"
                    def dcfstatus = sh(script: "checkov -f Dockerfile --quiet --compact --skip-results-upload --framework dockerfile", returnStatus: true)
                    if (dcfstatus != 0) {
                        error "Dockerfile insecure"
                    }
                    sh "docker build -t ${JOB_NAME}:${BUILD_NUMBER} ."
                }
            }
        }

其他Dockerfile扫描工具
Checkov
docker scan