1. 程式人生 > >Harbor倉庫鏡像掃描原理

Harbor倉庫鏡像掃描原理

格式 設置 有一個 存儲系統 ken mod 存在 出了 www.

初次聽說鏡像掃描的人肯定有很多疑惑,總會想原理是什麽呢?我們可以先思考下,windows控制面板、包括一些第三方軟件比如三六零等,它們都能獲取系統安裝的軟件以及版本,當然綠色解壓版他們就無法識別,獲取軟件版本之後,他們就能提供一些升級的版本、以及當前軟件版本的漏洞列舉出來,由此可見,系統安裝了哪些版本的軟件,第三方都可以通過系統相關文件獲取,那麽Linux系統也一樣。

Harbor倉庫中的鏡像掃描這個功能,看似很高大上,其實等你了解了它的底層原理與流程,你就會發現就是做了那麽一件事而已,用通俗的一句話概括,就是找到每個鏡像文件系統中已經安裝的軟件包與版本,然後跟官方系統公布的信息比對,官方已經給出了在哪個系統版本上哪個軟件版本有哪些漏洞,比如Debian 7系統上,nginx 1.12.1有哪些CVE漏洞,通過對逐個安裝的軟件包比對,就能知道當前這個鏡像一共有多少CVE。下面就Harbor的具體流程進行簡單介紹,讓你對這個功能了如指掌。

Harbor倉庫中的鏡像掃描功能是擴展功能,如果需要,只需啟動的時候帶上參數./prepare --with-clair && ./install.sh --with-clair。Harbor鏡像掃描功能依賴的第三方項目是coreos旗下的clair,項目地址:https://github.com/coreos/clair ,簡單介紹下clair系統中幾個核心功能結構。

技術分享圖片

API是clair對外提供的http api,harbor請求鏡像掃描則是請求clair提供的http接口之一。

notifier用來調用外部系統的webhook,當軟件包的CVE被更新或者刪除的時候,調用webhook通知第三方系統,消息中只有一個id。

updater是clair中的定時任務,定期從各開源社區獲取CVE數據,由於各開源社區維護的CEV結構各自不同,clair的每個fetcher只能fetch一個CVE數據源,然後調用對應的parser解析CVE數據,然後統一格式化,最後存入postgresql數據庫中。clair系統中很多模塊都是可以擴展的,提供了擴展接口,比如數據源、解析器等。

在了解鏡像掃描之前,這裏先簡單說下鏡像的概念,鏡像就是由許多Layer層組成的文件系統,重要的是每個鏡像有一個manifest,這個東西跟springboot中的manifest是同一個概念,就是文件清單的意思。一個鏡像是由許多Layer組成,總需要這個manifest文件來記錄下到底由哪些Layer層聯合組成的。要掃描分析一個鏡像,首先你就必須獲取到這個鏡像的manifest文件,通過manifest文件獲取到鏡像所有Layer層的地址digest,digest在docker鏡像存儲系統中代表的是一個地址,類似操作系統中的一個內存地址概念,通過這個地址,可以找到當前Layer層文件的內容,這種通過digest可尋址的設計是harbor v2版本的重大改變。在docker hub儲存系統中,所有文件都是有地址的,這個digest就是由某種高效的sha算法通過對文件內容計算出來的,類似在linux上的md5sum命令,執行md5sum xx.txt,即可得到一個摘要。

技術分享圖片

上圖中,左邊是harbor系統,右邊是clair系統,左邊的harbor只給出了與鏡像掃描有交互的模塊,並不是完整的功能結構,如需了解harbor的完整功能結構請參考另一篇文章 部署Harbor鏡像倉庫服務 。在harbor系統中有幾個鏡像掃描的觸發點,當然根據參數設置,可以關閉系統觸發掃描。

1、每天定時全量掃描

2、docker client執行docker push推送鏡像成功之後,registry發送event通知harbor,harbor對當前的推送成功的鏡像進行掃描

3、系統啟動的時候全量掃描

4、http api請求掃描指定的鏡像

下面以用戶調用harbor的http api觸發鏡像掃描為例,詳解流程原理,先說harbor這一側流程,後面再說clair接收到掃描請求的流程。

a、用戶請求harbor的/api/repositories/nginx/tags/1.12.1/scan接口,發起對版本為1.12.1的nginx進行鏡像掃描。

b、UI模塊對用戶操作權限認證通過之後,發起對Jobservice的post請求。

c、Jobservice調用Registry校驗該鏡像的manifest成功之後,獲取該manifest的digest,然後在數據庫中生成一個初始狀態的掃描job記錄,同時把這個job加入到定時調度器中。

d、Jobservice用digest為唯一鍵,在image_scan_overview表中插入一條存放記錄,待獲取到掃描結果之後更新對應的掃描結果字段,Jobservice將job狀態修改為Running,狀態機模式開始處理。

e、Jobservice調用UI模塊生成請求registry的token令牌,該token中包括對該鏡像的一個操作權限(push、pull),同時根據digest調用Registry獲取鏡像的manifest文件內容,解析manifest。

f、構造請求掃描系統Clair的請求參數,將鏡像的每一層參數封裝成ClairLayer結構。

l := models.ClairLayer{
            Name:    fmt.Sprintf("%x", sha256.Sum256([]byte(shaChain))),
            Headers: tokenHeader,
            Format:  "Docker",
            Path:    utils.BuildBlobURL(registryEndpoint, iz.Context.Repository, string(d.Digest)),
        }
        if len(iz.Context.layers) > 0 {
            l.ParentName = iz.Context.layers[len(iz.Context.layers)-1].Name
        }

通過相應的算法sha256.Sum256計算Name,保證鏡像的每一層Layer在Clair系統中都具備唯一標誌,Headers則包含了clair請求Registry必備的請求頭信息,最重要的是上一步生成的token令牌,Path則是鏡像的每一層在Registry中的下載地址,除了鏡像的基礎層,其他每一層都維護著父子關系,參數demo如下

Name:    sha256:7d99455a045a6c89c0dbee6e1fe659eb83bd3a19e171606bc0fd10eb0e34a7dc
Headers: tokenHeader,
Format:  "Docker",
Path:    http://registry:5000/v2/nginx/blobs/7d99455a045a6c89c0dbee6e1fe659eb83bd3a19e171606bc0fd10eb0e34a7dc
ParentName: a55bba68cd4925f13c34562c891c8c0b5d446c7e3d65bf06a360e81b993902e1

這裏的Name並不是Layer的digest,每一層的Name都是它的digest與它所有的直接父級以及間接父級digest拼接起來,再通過sha256.Sum256生成的。所有的參數準備完畢之後,循環每一個layer,逐層調用Clair的http接口請求掃描,每個請求都是同步等待結果,只要有一個Layer請求返回失敗,則馬上退出狀態機,同時更新該job的狀態為error,所有Layer請求都成功只後,則開始用最後一層的Name請求Clair獲取掃描結果,Clair會返回該Name對應的所有parent的掃描結果信息,獲取掃描結果之後,Jobservice退出狀態機,同時更新job狀態為success,掃描結果表image_scan_overview,Harbor的頁面則可以直接從自身數據庫獲取掃描結果了。

Clair掃描詳細流程

1、clair接收harbor發起的http post鏡像掃描請求,同時進行基本的參數校驗。

2、clair利用請求參數中的token headers,直接對Registry的path發起請求,下載鏡像層文件,然後解析鏡像文件內容,得到一個filesMap。

3、探測鏡像操作系統

遍歷解壓後的文件目錄,探測操作系統文件路徑。 首先要了解各Linux發行版的一些基礎文件,比如系統版本、安裝的軟件包版本記錄等文件,比如centos

centos:etc/os-release,usr/lib/os-release

查看文件/etc/os-release文件內容

NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

clair利用針對centos的解析器逐行解析該文件,提取ID以及VERSION_ID字段,最終把centos:7作為clair中的一個namespace概念。

4、探測已安裝的軟件包

上一步已經探測到了操作系統,自然可以知道系統的軟件管理包是rpm還是dpkg。

debian, ubuntu : dpkg
centos, rhel, fedora, amzn, ol, oracle : rpm

centos系統的軟件管理包是rpm,而debain系統的軟件管理是dpkg,獲取軟件管理工具之後,則可以在操作系統對應的路徑下獲取當前系統已安裝了哪些包。

rpm:var/lib/rpm/Packages
dpkg:var/lib/dpkg/status
apk:lib/apk/db/installed

比如debian系統,從文件/var/lib/dpkg/status文件則可以探測到當前系統安裝了哪些版本的軟件,安裝文件清單內容格式如下,由於篇幅有限,只截取了兩個安裝包展示。

Package: sed
Essential: yes
Status: install ok installed
Priority: required
Section: utils
Installed-Size: 799
Maintainer: Clint Adams <[email protected]>
Architecture: amd64
Multi-Arch: foreign
Version: 4.4-1
Pre-Depends: libc6 (>= 2.14), libselinux1 (>= 1.32)
Description: GNU stream editor for filtering/transforming text
 sed reads the specified files or the standard input if no
 files are specified, makes editing changes according to a
 list of commands, and writes the results to the standard
 output.
Homepage: https://www.gnu.org/software/sed/

Package: libsmartcols1
Status: install ok installed
Priority: required
Section: libs
Installed-Size: 257
Maintainer: Debian util-linux Maintainers <[email protected]>
Architecture: amd64
Multi-Arch: same
Source: util-linux
Version: 2.29.2-1+deb9u1
Depends: libc6 (>= 2.17)
Description: smart column output alignment library
 This smart column output alignment library is used by fdisk utilities.

Clair又采取指定的解析器,對該文件逐行解析,提取Package以及Version字段,最終獲取 libsmartcols1 2.29-1+deb9u1以及sed 4.4-1等重要屬性信息。

5、持久化

把上面探測到的系統版本、以及系統上安裝的各種軟件包版本都存入數據庫。Clair系統已經獲取了各linux版本操作系統軟件版本,以及對應軟件版本存在的CVE。官方公布了某個軟件在某個版本修復了哪個CVE,Clair只需要將當前鏡像中的軟件的版本與官方公布的版本進行比較。比如官方維護的CVE信息中公布了nginx 1.13.1修復了漏洞CVE-2015-10203,那麽當前鏡像中包含的版本為1.12.1的nginx必然存在漏洞CVE-2015-10203,這些版本比較都是基於同一個版本的操作系統之上比較的。

harbor頁面具體的漏洞詳細數據展示,還是通過UI系統調用Clair系統實時查詢。

技術分享圖片

綜上,我們可以完全擴展一下clair,並不局限於只掃描鏡像,它掃描鏡像的原理無非是提取了操作系統的安裝清單,然後進行信息比對。

Harbor倉庫鏡像掃描原理