本文共 1k 字,预计阅读时间 3 分钟。
本文是对 Clair 开源客户端 Clair scanner 源码分析,而非对 Clair 本身(Server 端)进行分析。关于 Clair 本身我推荐看看这个。
利用 docker-compose 可以快速构建 Clair 服务端,而 Clair scanner 则是一个简单易用的客户端,我们可以基于此开发一系列自己需要的功能。这里本文 Clair scanner 源码结构进行简单分析,介绍一些编译过程中可能会遇到的小问题,但是出于工作内容原因不会给出二次开发的案例。
源码编译
二次开发自然需要从源码编译,然而源码年久失修并且并未考虑到一些报错,文章开头我们给出一些解决方案。毕竟至少先要跑起来!
移除 clair/api/v1 依赖
clair.go
中有一个名为 github.com/coreos/clair/api/v1
的包被引用,然而这个包非常难以下载和配置。经过研究这个包中只有一些简单地 struct 定义,所以不妨手写一下,移除依赖。
新建文件 api.go
如下:
1 | package main |
然后对 clair.go
做出以下修改,这里给一个 git diff 截图:
之后正常通过 go get -v
下载依赖之后应该可以正常编译了,然而别急,大概率是跑不了的。
Docker API 版本修正
大概率跑起来之后会出现一个 Could not create a Docker client
的错误,这是因为 Docker API 版本过高造成的。实际使用中我没有发现各版本的差别(除了会报错),因为我们可以简单地在终端里执行:
1 | export DOCKER_API_VERSION="1.39" |
如果依旧报错,改为 1.38 版本完全可以。
也可以选择在 docker.go
中作如下修改。注意,这样的修改在 zsh 中可以正常工作,但是 bash 不可以。bash 中请继续每次使用 export。
IP 配置
Clair scanner 的 -c (--clair)
和 --ip
两个 IP 地址需要选择。这里做一个简单的解释 。
如果你的 Clair 服务端跑在本地,这里保持 localhost 就行,不用使用这两个选项。
如果你的 Clair 服务端跑在 http://A.A.A.A:6060,clair-scanner 所处 IP 为 B.B.B.B,那么你的配置应该如下:
1 | -c "http://A.A.A.A:6060" --ip "B.B.B.B" |
这里要求服务端可以通过 B.B.B.B 访问到 clair-scanner 所处位置,所以我们推荐将客户端跑在本地虚拟机中而非 VPS,因为这样没有公网 IP 的我们会无法使用。我们稍后对此解释。
交互流程
因为 Clair 服务端需要通过 Clair scanner 启动的 Web 服务来获取 Layer 文件,所以要保证 Clair scanner 所位于的 IP 是可(内网或外网)访问的。这就是为什么我们为什么推荐在虚拟机而不是 VPS 启动服务端的原因。
主要函数模块
docker.go
createDockerClient
新建 Docker 通信会话saveDockerImage
保存 Docker 镜像到本地,并解压出 tar 包readManifestFile
获取镜像的 ManifestgetImageLayerIds
通过 Manifest 获取每个 Layer 的 ID
server.go
- 在 9279 端口启动一个 Web 文件服务
chair.go
analyzeLayer
提交一个 Layer 分析请求analyzeLayers
调用上面的函数,提交多个请求fetchLayerVulnerabilities
提交一个获取 Layer 扫描结果的请求getVulnerabilities
调用上面的函数,获取最后一层的结果,因为最后一层包含前面全部层次的漏洞
scanner.go
scan
扫描镜像【可在这里对整体流程就行修改,添加多镜像扫描等】- 剩余模块可以自行跟进
scan
函数【最低可在 Layer 粒度处理数据】
reporter.go
- 主要是一些报告输出模块【二次开发后可以自定义输出结果】