做者:Pawan Shankar翻譯:Bach(才雲)正則表達式
如今不少團隊面臨着這麼一個挑戰:如何在不減慢應用交付速度的狀況下,管理好安全風險。有種方法能夠解決該問題,就是採用安全的 DevOps 工做流程。ubuntu
安全的 DevOps(也稱爲 DevSecOps)會在從開發到生產的整個應用程序生命週期中提供安全性以及監控功能,幫助咱們交付安全、穩定和高性能的應用程序。若是咱們把該工做流程插入現有的工具鏈中,能夠爲 DevOps、開發人員和安全團隊最大程度地提升效率。後端
DevSecOps 五個基本工做流程包括鏡像掃描、運行安全、合規性、Kubernetes 和容器的監控以及應用程序和雲服務監控。緩存
鏡像掃描是嵌入到 DevSecOps 工做流程中的一項關鍵功能。做爲第一道防線,它能夠幫助咱們在漏洞被利用以前檢測到漏洞並阻止,另外,它還易於實現並可自動化。本文將介紹多個鏡像掃描的最佳實踐和技巧,幫助你們採用有效的容器鏡像掃描策略。安全
K8sMeetup服務器
什麼是容器鏡像掃描架構
鏡像掃描是指分析容器鏡像的內容和構建過程,以檢測安全問題、漏洞或錯誤實踐。併發
咱們能夠從多個 Feed(NVD、Alpine、Canonical 等)中收集「通用漏洞披露(CVE)」信息,以檢查鏡像是否容易受到攻擊,其中有些還提供了開箱即用的掃描規則,以查找最多見的安全問題和錯誤實踐。less
鏡像掃描能夠輕鬆被集成到 DevSecOps 工做流程的多個步驟中,例如集成到 CI/CD 管道中,阻止漏洞到達註冊表;集成在註冊表中,防止第三方鏡像中的漏洞;也能夠在運行時集成,防止新發現的 CVE。
當咱們遵循並執行最佳實踐時,鏡像掃描可確保團隊不會因部署應用程序而致使交付速度變慢。如今讓咱們深刻了解這 12 種鏡像掃描最佳實踐。
K8sMeetup
12 種鏡像掃描最佳實踐
1.將鏡像掃描嵌入到 CI/CD 管道中
構建容器鏡像時,咱們應格外當心,並在鏡像發佈以前對其進行掃描。咱們能夠在 DevOps 工做流程中使用已經構建好的 CI/CD 管道,並增長鏡像掃描的步驟。
CI/CD 管道上鏡像掃描的架構以下:
測試和構建鏡像後,咱們沒必要將鏡像推送到生產庫,能夠先推送到暫存庫,而後運行鏡像掃描工具。這些工具一般會返回一份報告,列出發現的問題,併爲每一個問題分配不一樣級別的嚴重性。在 CI/CD 管道中,咱們能夠檢查這些鏡像掃描結果,並在出現任何嚴重問題時中止構建。
有一點要記住,自動化是最關鍵的,這是 DevOps 的核心概念,也適用於保護 DevOps。經過自動化 CI/CD 管道中的安全性檢查,咱們能夠在漏洞進入註冊表以前就將其捕獲,這樣就不會給漏洞任何機會。
2.採用 inline 掃描以保護隱私
在上一步中,咱們看到了 CI/CD 管道中的鏡像掃描與臨時註冊表的關係,但若是鏡像包含一些錯誤憑證該怎麼辦?它們可能會出現錯誤,最終致使數據泄漏。因此更進一步,咱們能夠實施 inline 鏡像掃描,不使用暫存庫,直接從 CI/CD 管道掃描鏡像。
使用 inline 鏡像掃描,它會僅掃描發送到掃描工具的元數據,從而幫助保護隱私。
使用 inline 鏡像掃描,能夠在 CI/CD 管道內掃描鏡像。代碼推送後,在不離開 CI/CD 管道的狀況下便可構建並掃描鏡像。鏡像元數據會被髮送到鏡像掃描器,而後結果會發送回 CI/CD 管道。若是該鏡像遵循安全策略,那它將被推送到生產鏡像存儲庫。
3.在註冊表中執行鏡像掃描
開始實施鏡像掃描時,要將其嵌入到註冊表中,這是第一步。
一般,咱們會有一個用於發佈鏡像的專用存儲庫,還有一些用於從第三方下載鏡像的公共存儲庫。咱們須要掃描這兩個儲存庫的鏡像。
咱們部署的全部鏡像都將從註冊表中提取。經過在那裏掃描鏡像,咱們至少能夠確保它們在運行以前已經被掃描過了。
4.使用 Kubernetes 准入控制器
若是想在使用鏡像以前先對其進行檢查,以防止將未掃描或易受攻擊的鏡像部署到集羣上,咱們可使用准入控制器。
Kubernetes 准入控制器是強大的 Kubernetes 原生功能,能夠幫助咱們自定義在集羣上容許運行的內容。在對請求進行身份驗證和受權以後,在對象持久化存儲 etcd 以前,准入控制器能夠攔截並處理對 Kubernetes API 的請求。
將 Deployment 的建立請求發送到 Kuberenetes 後,准入控制器將調用 Webhook 併發送鏡像元數據。鏡像掃描器會將掃描結果發回准入控制器,准入控制器在掃描經過後纔會保留 Deployment。
掃描工具一般會提供一個驗證 Webhook,該 Webhook 能夠按需觸發鏡像掃描,而後返回驗證決策。
准入控制器能夠在調度鏡像以前調用此 Webhook。Webhook 返回的安全性驗證決策將傳回 API 服務器,該服務器會回覆原始請求者,而且僅在鏡像經過檢查後纔將對象持久保存在 etcd 數據庫中。不過,該決定是由鏡像掃描器作出的,並無任何集羣中有關狀況的上下文(context),這裏咱們可使用 OPA 改進。
Open Policy Agent(OPA)是一種開放源代碼通用策略引擎,它是一種叫 Rego 的高級聲明性語言編寫的。OPA 關鍵思想之一是將決策與政策執行脫鉤。
使用 OPA,咱們能夠在 Kubernetes 集羣而不是鏡像掃描器中作出准入決定,這樣就能夠在決策過程當中使用集羣信息,例如命名空間、Pod 元數據等。
5.固定的鏡像版本
有時,咱們掃描的鏡像與在 Kubernetes 集羣中部署的鏡像不一樣,例如在使用可變標籤(好比「latest」或「staging」)時,就可能會發生這種狀況。此類標籤會不斷更新版本,從而使得咱們很難知道最新的掃描結果是否仍然有效。
標籤「:latest」會指向鏡像的最新版本,除了最後一個版本外,其餘全部版本均會被掃描。
使用可變標籤可能會致使使用同一個鏡像卻部署了不一樣版本容器的狀況。除了掃描結果帶來的安全問題外,這可能還會致使難以調試。
爲了代替 ubuntu:focal,咱們應該儘量使用不可變標籤,例如 ubuntu:focal-20200423。
這裏要記住,version 標籤(對於某些鏡像)每每會進行較小的、不間斷的更新,所以確保可重複性惟一的選擇就是使用實際鏡像 ID:
ubuntu:@sha256:d5a6519d9f048100123c568eb83f7ef5bfcad69b01424f420f17c932b00dea76
這裏可能有點超出鏡像掃描最佳實踐的範圍,但咱們要知道,這些不只會影響 Dockerfiles 中的 FROM 命令,還會影響 Kubernetes Deployment 文件以及幾乎全部放置鏡像名稱的地方。
從鏡像掃描的角度來看,咱們能作什麼?咱們能夠經過結合使用 Kubernetes 准入控制器、鏡像掃描器和 OPA 引擎來實施此策略。
6.掃描操做系統漏洞
做爲通常的鏡像掃描最佳實踐,請牢記這一點:「鏡像越輕越好。」 越輕的鏡像意味着更快的構建、更快的掃描以及更少的潛在漏洞依賴性。
新的 Docker 鏡像一般是在現有基礎鏡像的基礎上構建的,或在現有基礎鏡像之上添加一層。該基礎鏡像是由 Dockerfile 鏡像中的 FROM 語句定義的,這樣分層的體系結構設計,能夠在最多見的任務中節省大量時間。例如,在鏡像掃描時,咱們只須要掃描一次基礎鏡像。若是父鏡像易受攻擊,那麼在該父鏡像之上構建的任何其餘鏡像也是易受攻擊的。
WordPress 和 PHP 鏡像基於 Apache,而 Apache 基於 Ubuntu 鏡像。若是 Apache 上存在漏洞,那麼 WordPress 和 PHP 鏡像都將容易受到攻擊。
即便咱們沒有在鏡像中引入新漏洞,但基礎鏡像中的漏洞也很容易讓咱們受到攻擊。這就是爲何掃描工具應主動跟蹤已知漏洞文件的漏洞源,並在咱們使用其中的漏洞時進行通知。
7.使用 distroless 鏡像
distroless 鏡像僅容許咱們將應用程序及其依賴項打包在輕量級容器鏡像中。將運行時容器中的內容嚴格限制爲必需內容能夠最大程度地減小攻擊面。另外,它還能夠改善掃描器的信噪比(例如 CVE),並根據須要減輕負擔。
如下示例顯示了用於「Hello world」應用程序的 Dockerfile,該應用程序在 Ubuntu 和 Distroless 上運行。
FROM ubuntu:focal
`COPY main /`ENTRYPOINT ["/main"]
對其進行掃描後,咱們發現了 24 個操做系統漏洞,其中兩個嚴重程度爲中。這樣一個簡單的應用程序,鏡像大小竟然有 77.98MB 這麼大。
如今,基於 distroless 鏡像的同一應用程序:
FROM gcr.io/distroless/static-debian10
`COPY main /`ENTRYPOINT ["/main"]
如今,咱們只發現了兩個能夠忽略不計的漏洞。此外,鏡像大小減少到只有 6.93MB,這更適合此應用程序。
這代表,distroless 容器沒有任何沒必要要的程序包,這些程序包可能致使更多的漏洞而被利用。
8.掃描第三方庫中的漏洞
應用程序使用了大量的庫,以致於這些庫最終提供的代碼行比團隊編寫的實際代碼還多。這意味着咱們不只須要知道代碼中的漏洞,還須要知道其全部依賴項中的漏洞。
不過掃描器檢測操做系統漏洞的相同漏洞源,會跟蹤這些漏洞,但並不是全部工具都能像掃描鏡像中的庫同樣深刻,所以請確保鏡像掃描器已深刻挖掘並向咱們警告這些漏洞。
9.優化鏡像層順序
謹慎使用 Dockerfile 中的 RUN 命令能夠進一步優化鏡像。RUN 命令的順序可能會對最終鏡像產生重大影響,由於它決定了鏡像層的順序。
咱們能夠首先放置較大的層(一般是不變的),最後放置變化最大的文件(例如已編譯的應用程序)來優化 Docker 緩存的使用。這將有利於現有層的使用,加快構建鏡像的速度,並間接加快鏡像掃描的速度。
10.掃描 Dockerfile 中的配置錯誤
如咱們所見,Docker 鏡像構建過程遵循 Dockerfile 指令清單。
咱們能夠遵循如下幾種 Dockerfile 最佳實踐來檢測常見的安全性錯誤配置:
在這樣的 Dockerfile 中:
FROM ubuntu:focal-20200423
`USER rootRUN curl http://my.service/?auth=ABD54F0356FA0054
EXPOSE 80/tcpEXPOSE 22/tcp
ENTRYPOINT ["/main"]`
咱們的鏡像掃描能夠自動檢測到如下問題:
USER root
咱們以 root 身份運行:
EXPOSE 22/tcp
在這裏,咱們將暴露一般用於 ssh 的 22 端口,這是容器不該該包含的工具。另外,咱們還將公開 90 端口,但這個沒問題,這就像 HTTP 服務器的通用端口同樣。
RUN curl http://my.service/auth=ABD54F0356FA005432D45D0056AF5400
此命令使用一個 auth 密鑰,任何人均可以使用它來給咱們形成危險,所以咱們應該改用某種變量。這樣的密鑰不只能夠在 Dockerfile 上,還能夠在鏡像中存在的任何文件中使用正則表達式進行檢測。做爲一項額外措施,咱們還能夠檢查已知可存儲憑證的文件名。
11.快速標記 Kubernetes Deployment 中的漏洞
經過掃描的鏡像並非絕對安全的。若是在掃描後,咱們部署了鏡像,但此時發現了一個新漏洞,雖然咱們能夠當即增強安全策略,可是那些已經運行的鏡像會怎麼樣?
生產中部署的易受攻擊鏡像的時間軸:
所以咱們要連續掃描鏡像以達到如下目標:
固然,實施運行時掃描能夠幫助咱們減小這些漏洞的影響。以 CVE-2019-14287 爲例, 咱們能夠編寫一些 Falco 規則來檢測該漏洞是否已被利用,但爲每一個漏洞編寫特定規則是一項耗時的工做,應將其做爲最後一道防線。所以,咱們要連續掃描集羣中正在運行的鏡像。
安全工具會使用不一樣的策略進行存檔,最簡單的方法是每隔幾個小時從新掃描一次全部鏡像。理想狀況下,咱們但願在漏洞列表更新後當即從新掃描受影響的鏡像。不過某些工具可以存儲鏡像元數據,無需徹底從新掃描便可檢測新漏洞。
一旦在運行中的容器中發現漏洞,咱們就應儘快修復。這裏的關鍵是有效的漏洞報告,這樣每一個人均可以專一於有關的信息。
實現此目標的一種方法是使用可查詢的漏洞數據庫,該數據庫讓 DevOps 安全團隊能夠在其龐大的鏡像、程序包和 CVE 目錄中進行一些排序。他們將搜索諸如 CVE age、是否有可用的修復程序、軟件版本等參數。最後,若是能夠下載這些報告並與漏洞管理團隊、CISO 共享,那麼將很是有用。
讓咱們用一個例子來講明,如今有一個查詢包含了如下內容:全部的漏洞在 prod 命名空間,嚴重性爲高,CVE>30 天,修復可用。
藉助這種漏洞報告功能,團隊能夠輕鬆地識別出他們能夠實際修復的易受攻擊鏡像,並在漏洞被利用以前開始着手解決方案。
12.選擇基於 SaaS 的掃描解決方案
在本地解決方案上選擇基於 SaaS 的掃描服務有不少好處:
K8sMeetup
結論
鏡像掃描是 DevSecOps 工做流程中的第一道防線。經過使其自動化,咱們能夠最大程度地發揮其潛力,並在問題有機會變大以前發現問題。遵循鏡像掃描最佳實踐將幫助你們將安全性嵌入其中,而且交付速度不會所以下降。
最後,要記住鏡像掃描不應僅用一次,而要在工做流程中連續檢查,包括在構建時、在註冊表上、在部署以前以及容器已經運行時。