一、前言
最近几年容器化技术快速发展,各大互联网厂商也都开始使用容器化技术,而如何保证容器安全便是撰写本文的目的之一。Anchore Engine的功能之一是可以基于CVE数据来对容器镜像进行漏洞扫描,从而发现是否存在安全漏洞和策略问题。本文将从两个部分来讲解Anchore Engine的使用:
基于Anchore-cli客户端的使用 与Jenkins结合完善DevSecOps
二、Anchore Engine的安装
使用Docker Compose进行安装
Anchore Engine支持docker-compose或者helm来进行安装,在此我们使用最简单的docker-compose来进行安装测试。
1.命令如下:
代码语言:javascript复制# curl https://docs.anchore.com/current/docs/engine/quickstart/docker-compose.yaml > docker-compose.yaml
# docker-compose up -d
2.查看部署是否成功:
代码语言:javascript复制# docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------
root_analyzer_1 /docker-entrypoint.sh anch ... Up 8228/tcp
root_api_1 /docker-entrypoint.sh anch ... Up 0.0.0.0:8228->8228/tcp
root_catalog_1 /docker-entrypoint.sh anch ... Up 8228/tcp
root_db_1 docker-entrypoint.sh postgres Up 5432/tcp
root_policy-engine_1 /docker-entrypoint.sh anch ... Up 8228/tcp
root_queue_1 /docker-entrypoint.sh anch ... Up 8228/tcp
# docker-compose exec api anchore-cli system status
Service analyzer (anchore-quickstart, http://analyzer:8228): up
Service simplequeue (anchore-quickstart, http://queue:8228): up
Service apiext (anchore-quickstart, http://api:8228): up
Service policy_engine (anchore-quickstart, http://policy-engine:8228): up
Service catalog (anchore-quickstart, http://catalog:8228): up
Engine DB Version: 0.0.13
Engine Code Version: 0.7.1
3.等待漏洞库更新完毕,这里需要注意的是因为漏洞库在国外,所以更新过程需要很长时间,几个小时甚至一天都是有可能的,请耐心等待。当RecordCount列的值都不是None的时候,漏洞库就算更新完毕了。
代码语言:javascript复制# docker-compose exec api anchore-cli system wait
Starting checks to wait for anchore-engine to be available timeout=-1.0 interval=5.0
API availability: Checking anchore-engine URL (http://localhost:8228)...
API availability: Success.
Service availability: Checking for service set (catalog,apiext,policy_engine,simplequeue,analyzer)...
Service availability: Success.
Feed sync: Checking sync completion for feed set (vulnerabilities)...
Feed sync: Checking sync completion for feed set (vulnerabilities)...
Feed sync: Checking sync completion for feed set (vulnerabilities)...
Feed sync: Checking sync completion for feed set (vulnerabilities)...
Feed sync: Checking sync completion for feed set (vulnerabilities)...
Feed sync: Checking sync completion for feed set (vulnerabilities)...
Feed sync: Checking sync completion for feed set (vulnerabilities)...
# docker-compose exec api anchore-cli system feeds list //查看更新情况,状态是pending代表等待更新
Feed Group LastSync RecordCount
github github:composer pending None
github github:gem pending None
github github:java pending None
github github:npm pending None
github github:nuget pending None
github github:python pending None
nvdv2 nvdv2:cves pending None
vulnerabilities alpine:3.10 2020-06-22T03:08:25.647466 1725
vulnerabilities alpine:3.11 2020-06-22T03:08:44.098248 1904
vulnerabilities alpine:3.3 2020-06-22T03:09:03.977480 457
vulnerabilities alpine:3.4 2020-06-22T03:09:09.253906 681
vulnerabilities alpine:3.5 2020-06-22T03:09:16.594355 875
vulnerabilities alpine:3.6 pending 1000
vulnerabilities alpine:3.7 pending None
三、基于Anchore-cli客户端的使用
扫描指定镜像
1.添加镜像到anchore
代码语言:javascript复制# docker-compose exec api anchore-cli image add docker.io/library/ubuntu:20.04
Image Digest: sha256:93fd0705706e5bdda6cc450b384d8d5afb18fecc19e054fe3d7a2c8c2aeb2c83
Parent Digest: sha256:52259450119427dab05c0c455121c48d7b04cee2d61b5dbdde1219b2163af572
Analysis Status: not_analyzed
Image Type: docker
Analyzed At: None
Image ID: 74435f89ab7825e19cf8c92c7b5c5ebd73ae2d0a2be16f49b3fb81c9062ab303
Dockerfile Mode: None
Distro: None
Distro Version: None
Size: None
Architecture: None
Layer Count: None
Full Tag: docker.io/library/ubuntu:20.04
Tag Detected At: 2020-06-22T07:19:18Z
2.查看扫描状态,Analysis Status为analyzed代表扫描结束
代码语言:javascript复制# docker-compose exec api anchore-cli image list
Full Tag Image Digest Analysis Status
docker.io/library/ubuntu:20.04 sha256:93fd0705706e5bdda6cc450b384d8d5afb18fecc19e054fe3d7a2c8c2aeb2c83 analyzed
3.接着查看扫描结果
代码语言:javascript复制# docker-compose exec api anchore-cli image vuln docker.io/library/ubuntu:20.04 all
Vulnerability ID Package Severity Fix CVE Refs Vulnerability URL Type Feed Group Package Path
CVE-2013-4235 login-1:4.8.1-1ubuntu5 Low None CVE-2013-4235 http://people.ubuntu.com/~ubuntu-security/cve/CVE-2013-4235 dpkg ubuntu:20.04 pkgdb
CVE-2013-4235 passwd-1:4.8.1-1ubuntu5 Low None CVE-2013-4235 http://people.ubuntu.com/~ubuntu-security/cve/CVE-2013-4235 dpkg ubuntu:20.04 pkgdb
CVE-2016-2781 coreutils-8.30-3ubuntu2 Low None CVE-2016-2781 http://people.ubuntu.com/~ubuntu-security/cve/CVE-2016-2781 dpkg ubuntu:20.04 pkgdb
CVE-2018-7169 login-1:4.8.1-1ubuntu5 Low None CVE-2018-7169 http://people.ubuntu.com/~ubuntu-security/cve/CVE-2018-7169 dpkg ubuntu:20.04 pkgdb
CVE-2018-7169 passwd-1:4.8.1-1ubuntu5 Low None CVE-2018-7169 http://people.ubuntu.com/~ubuntu-security/cve/CVE-2018-7169 dpkg ubuntu:20.04 pkgdb
CVE-2019-12904 libgcrypt20-1.8.5-5ubuntu1 Low None CVE-2019-12904 http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-12904 dpkg ubuntu:20.04 pkgdb
CVE-2019-13050 gpgv-2.2.19-3ubuntu2 Low None CVE-2019-13050 http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-13050 dpkg ubuntu:20.04 pkgdb
CVE-2019-18276 bash-5.0-6ubuntu1 Low None CVE-2019-18276 http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-18276 dpkg ubuntu:20.04 pkgdb
这就是最简单的扫描镜像方法:把镜像添加到扫描引擎,等待扫描结束然后查看扫描结果。但是这种方式基本不适用实际的工作场景,所以文章的下一部分将阐述如何把Anchore Engine应用到实际工作中。
四、与Jenkins结合应用到DevSecOps中
在传统的开发流程中,安全工作通常是作为最后一步进行。这就导致了一旦发现问题,修复的人力、时间等成本都会很高,而且通常安全问题影响的可能不仅仅是开发,甚至会改变需求和架构。而将“安全左移”,其目的就是为了降低修复问题的成本。
目前容器化技术快速发展,导致很多厂商改变了传统的部署方式,转而使用类似K8S jenkins harbor的组合。先看下这套经典组合的架构:
1.开发人员提交代码到gitlab等代码仓库 2.通过手动执行jenkins构建(或者配置webhook触发jenkins执行构建),下载代码仓库里的最新代码 3.通过mvn编译生成jar包,并进行一系列的静态分析、单元测试等工作 4.测试成功后开始通过docker build命令把jar包构建成镜像 5.把生成的镜像push到harbor镜像仓库中 6.通过k8s拉取harbor上的镜像进行创建容器和服务,最终发布完成
按照DevSecOps里安全左移的原则,我们选择在第五步构建镜像后进行镜像扫描。下面笔者将用一个示例来展示如何使用jenkins anchore实现自动化镜像扫描。
安装插件
从Jenkins主菜单中选择Manage Plugins。
单击【可选插件】然后在过滤框里输入【anchore】,选中【Anchore Container Image Scanner】后点击【直接安装】。
配置anchore插件
点击【Manage Jenkins】->【configure system】,找到【Anchore Container Image Scanner】,输入anchore engine的详细信息:
Engine URL:anchore engine的url地址(默认都是http://your_anchore_engine_IP:8228/v1) Engine Username:用户名(默认admin) Engine Password:密码(默认foobar)
添加docker仓库帐号
点击凭据->系统->全局凭据->添加凭证,添加一个hub.docker.com的帐号,id随便填写,这里填写hub.docker.com。点击【确定】完成添加
在流水线中添加扫描镜像
在这个示例中,我们将使用pipeline进行构建:
在jenkins中新建一个任务并选择pipe line,在【流水线】里输入以下脚本后点击保存
代码语言:javascript复制pipeline {
environment {
registry = "zj1244/demo" //仓库地址,用于把镜像push到镜像仓库。按照实际情况修改
registryCredential = 'hub.docker.com' //用于登陆镜像仓库的凭证,按照实际情况修改
}
agent any
stages {
//jenkins从代码仓库里下载代码
stage('Cloning Git') {
steps {
git 'https://github.com/zj1244/docker-dvwa.git'
}
}
//构建镜像
stage('Build Image') {
steps {
script {
app = docker.build(registry ":$BUILD_NUMBER")
}
}
}
//把镜像推送到仓库
stage('Push Image') {
steps {
script {
docker.withRegistry('', registryCredential ) {
app.push()
}
}
}
}
//镜像扫描
stage('Container Security Scan') {
steps {
sh 'echo "' registry ':$BUILD_NUMBER `pwd`/Dockerfile" > anchore_images'
anchore engineRetries: "240", name: 'anchore_images'
}
}
stage('Cleanup') {
steps {
sh script: "docker rmi " registry ":$BUILD_NUMBER"
}
}
}
}
最后点击【立即构建】开始进行构建
查看结果
构建结束后,点击【Anchore Report (FAIL)】查看扫描报告
报告会给出扫描结果是FAIL还是PASS,默认情况下存在漏洞将导致构建失败
整合结果
在实际工作中经常会出现一天发版几十次的情况,这种频率下在jenkins上查看扫描结果显然很不方便,所以有个图形界面来进行统计就很有必要了。anchore企业版倒是提供了UI界面,但是企业版是需要收费的,所以笔者简单做了个UI界面对扫描结果进行了整合
总结
本文介绍了Anchore Engine的一些基本用法,包括如何和jenkins结合,欢迎大家批评指正。也希望借此抛砖引玉,有好的建议大家一起交流共同进步。最后给出anchore ui的github地址,有需要的朋友自取
https://github.com/zj1244/anchore_ui
本文作者:zj1244, 属于FreeBuf原创奖励计划,未经许可禁止转载