當前位置:
首頁 > 最新 > Kubernetes管理員的11條安全軍規

Kubernetes管理員的11條安全軍規

自從Kubernetes項目開天闢地以來, 其安全性已經取得了長足的發展, 但它目前依然還有些要點值得注意。 本文列舉了11條軍規來幫助讓你的集群在穩定運行時加固安全,以及在受到危害時對抗衝擊。這些軍規涵蓋了對控制面板的配置, 對工作負載的防護, 乃至對未來的展望。

第一部分:控制面板

作為Kubernetes的核心大腦, 控制面板全面展示了在集群中所有容器和Pod的運行情況。 它可以直接調度新的Pod(可能包含對宿主節點有root許可權的容器), 還可以用來讀取集群中所有的secret。 控制面板中展示的內容非常重要, 需要好好的保護起來以免發生意外泄漏和惡意訪問——無論這些內容是被訪問時, 在存儲狀態, 又或者是在網路中傳輸時。

1. 全面啟用TLS

應該在所有組件上都使用TLS, 以防止網路嗅探, 驗證伺服器端的身份,以及在啟動雙向TLS認證時驗證客戶端的身份。

需要注意的是, 一些組件在安裝時可能會有默認設置啟用http埠。管理員需要熟悉每個組件的設置從而識別出這種潛在會產生不安全流量的情況。

這份來自Lucas K?ldstr?m[1]的網路圖展示了幾處應該配置TLS的地方, 包括組件與主節點的交互, 以及Kubelet與API Server的交互。 Kelsey Hightower的大作Kubernetes The Hard Way[2]中對此提供了詳細的手工操作指導。 etcd的安全模型文檔[3]里也有細緻描述。

自動伸縮Kubernetes的節點在過去是非常困難的操作, 因為每個節點都需要一個TLS的密鑰來連接主節點, 而將密鑰打包放進基礎鏡像又不是一個好的實踐方式。 現在Kubelet的TLS引導程序提供了讓新的kubelet在啟動時生成證書籤名申請的能力。

2. 以最小特權原則設置RBAC, 關閉ABAC, 以及監控日誌

RBAC提供了細粒度的規則管理功能, 以限制用戶對資源(比如namespace)的訪問。

ABAC於Kubernetes的1.6版開始為RBAC所取代,已不建議啟用。 在普通的Kubernetes集群中通過設置以下啟動參數在API Server中啟用RBAC:

而在GKE中通過另一個參數來禁用ABAC:

網上有很多不錯的例子和文檔描述了如何在集群中使用RBAC策略[4]。 除此之外, 管理員還可以通過audit2rbac[5]生成的審計日誌來分析調優RBAC規則。

如果將RBAC規則設置得過大或者不正確, 一旦集群中出現有問題的Pod會對整個集群產生安全威脅。 RBAC規則應該基於最小特權原則進行維護, 並持續地加之以審閱和改善。 這應被團隊視為技術負債的清除手段被整合進開發流程之中。

審計日誌功能(1.10中為beta階段)提供了可定製化地對集群各組件的訪問流量內容(例如請求和響應)及元數據(例如發起用戶和時間戳)記錄日誌的功能。 日誌等級可以根據組織內的安全策略進行調整。 在GKE上也有相應的設置來配置這個功能。

對於讀取類請求(比如get, list和watch) ,只有請求內容會被記錄在審計日誌中, 響應內容不會保存。 對於涉及到敏感數據(比如Configmap和Secret)的請求, 只有元數據會被記錄。 對於其他類型的請求, 請求和相應對象都會被記錄。

切記:如果將審計日誌保留在集群內部, 在集群已被入侵時會有安全威脅。 像這樣的所有安全相關的日誌都應轉移到集群之外, 以避免出現安全漏洞時被篡改。

3. 為API Server啟用第三方認證

在一個組織內部通過集中化的手段管理認證和授權(又被稱為單點登錄)有助於管理用戶的添加, 刪除以及一致的許可權控制。

通過將Kubernetes與第三方的身份驗證服務(比如Google和GitHub)整合,這樣可以使用第三方平台的身份保證機制(包括雙因子驗證等機制), 以避免管理員不得不重新配置API Server來添加或刪除用戶。

Dex[6]是個OpenID Connect(OIDC)和OAuth2.0的身份服務組件。 它帶有可插拔的連接器。 Pusher公司通過這個機制將Dex作為認證鏈的中間件將Kubernetes與其他第三方認證服務關聯。 除此之外還有其他工具可以達成類似目的。

4. 將etcd集群隔離出來並加上防火牆控制

etcd中存儲了集群的狀態和secret, 對Kubernetes而言是至關重要的組件。 它的防護措施應該與集群的其他部分區別處理。

對API Server的etcd擁有寫許可權相當於獲取了整個集群的root許可權。 甚至僅通過對etcd的讀取操作都可以相當簡單地自行提權。

Kubernetes的調度器會搜索etcd找出那些已定義但還沒被調度到節點上的Pod, 然後把這樣的Pod發送到空閑的Kubelet節點進行部署。 在Pod信息被寫進etcd之前, API Server會檢查提交的Pod定義。 因此一些有惡意使用者會直接把Pod定義寫入etcd, 以跳過許多諸如PodSecurityPolicy這樣的安全機制。

無論是etcd集群的節點與節點, 還是節點與API Server, 他們的通信都應該配置TLS證書, 並且etcd集群應部署在專屬的節點之上。 etcd集群與Kubernetes集群間也應該設置防火牆, 以避免由於私鑰被盜而被從工作節點上發起攻擊。

5. 定期替換密鑰

定期替換密鑰和證書是一條安全方面的最佳實踐。 這樣能減小當密鑰被盜時所遭受的損害範圍。

Kubernetes會在某些現有證書過期時創建新的證書籤名申請來自動替換Kubelet的客戶端和伺服器端證書。

但是API Server用來加密etcd數據的對稱密鑰是無法自動替換的。 它只能手工替換。 這樣的操作需要有對主節點操作的許可權, 因此託管Kubernetes服務(比如谷歌的GKE和微軟的AKS)會自行解決這個問題而無需管理員操心。

第二部分:工作負載

通過對控制面板實施最小化可用安全策略,可以使集群工作得更安全。 但這樣還不夠。 打個比方, 對於一艘裝運了危險貨物的船,船上的集裝箱也必須加以防護,這樣在出現意外事故或破壞時集裝箱還能承載貨物。對於Kubernetes的工作負載對象(Pod, Deployment,Job和Set等)也是一樣。 它們在部署時還是可信的,然而當面對外網流量時總還是會有被攻破的風險。 要減輕此類風險,除了針對工作負載對象實施最小特權原則外,還需要加固它們運行時的配置。

6. 使用Linux的安全功能以及Kubernetes的Pod安全規則

Linux內核提供了許多互相有功能重疊的安全擴展(capabilities, SELinux, AppArmor, seccomp-bpf)。 他們可被配置用來為應用提供最小特權。

像bane[7]這樣的工具可以用來生成AppArmor的配置文件和seccomp的docker-slim配置文件。 然而用戶需要詳細測試自己應用的所有路徑, 驗證這些配置對應用是否會造成副作用。

而Pod安全規則可以用來授權使用Kubernetes的安全擴展和其他安全指令。 這些規則描述了一個Pod提交到API Server後所必須遵守的最小安全契約。 這些契約包括了安全配置,提權標誌,以及共享主機網路,進程或進程間通信的命名空間。

這些安全規則相當重要, 因為他們有助於防止容器內的進程超越其隔離邊界。 Tim Allclair提供的PodSecurityPolicy範例[8]相當詳盡。 你可以自定義這個範例, 將其用在自己的使用場景里。

7. 靜態分析YAML文件

在使用Pod安全規則來控制Pod訪問API Server的同時, 也可以在開發工作流中使用靜態文件分析來構築組織的合規需求或滿足風險偏好。

在Pod類型(比如Deployment, Pod, Set等)的YAML文件中不應該存放敏感數據, 而包含敏感數據的Configmap和Secret應該由諸如vault(通過CoreOS提供的operator), git-crypt, sealed secret或者雲廠商提供的密鑰管理服務來進行加密處理。

靜態分析YAML配置可以對運行時的安全情況構建一條基準線。 以下是kubesec工具為某個資源生成風險評分的例子:

而kubetest工具是個針對Kubernetes的YAML文件的單元測試框架。 代碼例子如下:

以上這些工具都通過將檢查和驗證工作在軟體開發周期中提前(shift left])到更早的開發階段的方式, 使開發人員能更早地獲得對於代碼和配置的反饋, 以避免提交在之後的人工或自動檢查中被退回。這樣也可以減少引入更多安全實踐的障礙。

8. 使用非root的用戶運行容器

運行在root用戶下的容器大多擁有了大大超過其所承載的服務需要的許可權。 當集群被侵入時,這樣的容器會讓攻擊者有能力執行更進一步的破壞。

容器技術依然基於傳統的Unix安全模型, 叫做自主訪問控制(簡稱DAC)。在這個模型之下,所有東西都是文件, 而許可權是可以被賦予用戶或用戶組。

用戶命名空間在Kubernetes下並沒有啟用, 這意味著容器中的用戶表會被映射到宿主機的用戶表中, 而在容器里由root身份運行的進程相當於在宿主機上也是以root身份運行。 儘管說我們有層級安全機制來防範容器發生問題, 但在容器中用root身份運行進程依然是不推薦的做法。

許多容器鏡像使用root用戶運行一號進程。 如果這個進程被攻破, 那麼攻擊者在容器中就有了root的許可權, 從而會輕易放大由於集群誤配置造成的安全漏洞。

Bitnami公司在將容器鏡像遷移到非root用戶這方面做了很多工作[9](主要由於OpenShift平台默認要求非root身份運行容器)。參考他們提供的文檔可以降低管理員實施類似遷移的難度。

下列Pod安全規則的代碼片段給出了防止容器中的進程以root身份運行, 以及防止進程提權到root身份的方法:

非root的容器無法綁定小於1024的埠(可以通過配置內核參數CAP_NET_BIND_SERVICE來啟用), 但使用service的特性可以使對外埠配置為1024以下。 在以下例子中,MyApp這個應用在容器中綁定了8443埠,而service將相關流量代理到443這個埠中對外暴露應用:

在用戶命名空間在Kubernetes中可用之前,或者非root功能在容器運行時組件中獲得直接支持之前, 使用非root用戶運行容器依然是推薦的做法。

9. 使用網路規則

默認狀態下, Kubernetes中Pod與Pod之間的網路是互通的。 可以通過使用網路規則來對此加以限制。

傳統的服務一般給每個應用配置靜態IP和埠範圍。 這樣的靜態IP一般很少會改變,從而會被當作服務的一種標識來對待。 因此傳統服務可以通過防火牆來加以限制和保護。 容器為了能快速失敗快速重新調度,一般很少使用固定IP,而是通過使用服務發現的機制來替代。 容器這樣的特性使得防火牆會更難配置和審查。

由於Kubernetes將所有系統狀態都存儲在etcd里, 只要CNI網路插件支持網路規則, 藉助etcd中的數據就可以配置動態防火牆。 當前Calico, Cilium, kube-router, Romana和Weave Net這些插件都能支持網路規則。

值得注意的是,這些網路規則是失效關閉的(fail-closed), 因此在下列YAML中缺少podSelector配置意味著這個規則會應用到所有容器:

下列的網路規則的例子描述了如何關閉除了UDP 53(DNS埠)之外的所有對外流量。 這樣也防止了進入應用的連接——這是因為網路規則是有狀態面向連接的, 同一個網路連接中應用對外請求的響應也依舊會返回到應用中。

Kubernetes的網路規則並不能被應用到DNS名字上。 這是因為一個DNS名字會可能被輪詢調度解析到許多個IP地址,或者依據調用IP動態被解析到不同的目標IP地址, 而網路規則只能被應用到靜態的IP或podSelector(也就是Kubernetes的動態IP機制)上。

安全上有一條最佳實踐建議一開始對Kubernetes的namespace先拒絕所有流量, 然後再逐漸添加路由允許應用能通過測試場景。 這樣做是非常複雜的, 可以通過下列ControlPlane公司出品的netassert這個開源工具來幫助達成最佳實踐。 netassert[10]是一個安全運維工作流方面的網路安全工具, 通過高度並發運用nmap來掃描和嗅探網路:

雲廠商的元數據API一般也會是被攻擊的源頭之一(參見最近發生的Shopify受攻擊的案例[11]), 因此也需要有專門的測試來確定這一類API在容器網路中被關閉, 以避免誤配置的可能。

10. 掃描容器鏡像和運行IDS(入侵檢測系統)

Web伺服器作為它所部署的網路上的一個可被攻擊的切入口,它鏡像上的文件系統需要被完全掃描,以避免存在已知的漏洞被攻擊者利用來取得遠程控制容器的許可權。使用IDS可以檢測已知漏洞。

Kubernetes通過一系列的Admission Controller來控制Pod類型的資源(如Deployment等)是否能被部署進集群。 Admission controller會檢驗每個被提交進來的Pod的定義,或者有時會修改Pod定義的內容。 現在已經支持後台webhook掛載外部應用。

Webhook功能可以和容器鏡像掃描工具結合起來。 在容器被部署進集群之前掃描鏡像內容。 一旦未通過掃描檢查, 容器便會被Admission Controller拒絕部署。

使用工具掃描容器鏡像中是否包含已有的漏洞, 這樣能減小攻擊者利用公開漏洞(CVE, Common Vulnerabilities & Exposures)的時間窗口。 像CoreOS出品的Clair和Aqua出品的Micro Scanner都應該被整合到部署管道中, 以避免部署的容器中包含致命漏洞。

像Grafeas這樣的工具可以存儲鏡像的元數據, 用來針對容器的特有簽名(基於內容定址的散列哈希)進行持續的合規與漏洞檢查。 通過這個簽名來掃描本地容器鏡像等同於掃描部署在生產環境的容器, 這樣就可以持續地做本地檢查而不需要連接到生產環境中。

而未知的瞬時攻擊漏洞(Zero Day)永遠會存在。 為了應對這樣的威脅, 需要在集群中部署一些諸如Twistlock,Aqua和Sysdig Security這樣的工具。而另外一些IDS會檢測出容器中發生的不尋常的行為, 暫停或者終止這樣的容器。 典型的工具有Sysdig出品的開源規則引擎Falco[12]。

第三部分: 展望未來

目前看來服務網格當屬安全在「雲原生進化(cloud native evolution)」發展中的下一階段形態。 當然真正應用服務網格尚需時日。 遷移工作涉及到將應用層中含有的相關複雜邏輯轉移為依賴服務網格的基礎構件, 而企業也會很想詳細理解遷移和運用服務網格相關的最佳實踐。

11. 使用服務網格

服務網格是通過類似Envoy和Linkerd這樣的高性能邊車(sidecar)代理伺服器在集群中組建應用間加密網路的基礎設施。 它提供了流量管理, 監控和規則控制的能力而無需微服務為此修改代碼。

服務網格意味著微服務中的安全與網路管理相關的代碼可以被去除, 而這部分責任將被轉移到經過實戰驗證的公共組件中。 之前通過Linkerd就已經可以達成這樣的功能。 如今由Google, IBM和Lyft聯合推出了Istio在服務網格領域也可以作為一個可選方案。 Istio通過基於SPIFFE規範的Pod間相互進行身份識別的能力以及其他一系列的功能, 來簡化服務網格這個下一代網路安全的部署。 在「永不信任,始終驗證」(Zero Trust)的網路模型中, 每次交互都應在互信TLS(mTLS, mutual TLS)下發生, 以保證交互雙方不僅鏈路安全,而且身份已知。 這樣的話或許就沒有必要使用傳統的防火牆或者Kubernetes的網路規則了。

Istio 0.8 LTS版本已經推出。 這個項目正快速接近1.0版本的發布(譯者:Istio 1.0版已於2018年7月31號發布)。 其版本編號習慣會與Kubernetes遵循的模型相同:核心版本穩定增長, 每個API都會通過自己版本中的alpha/beta來描述其穩定性。 可以期待Istio在之後幾個月的採用率會有上升。

結語

雲原生應用擁有一系列帶有細粒度配置能力的輕量級安全組件來控制工作負載與基礎架構。 這些工具的威力和靈活性對管理員來說既是祝福又是詛咒。 如果自動化安全能力不足, 這些工具很容易會暴露不安全的網路流量,導致容器或隔離結構爆發問題。

防護工具層出不窮, 但管理員仍需警惕誤配置的潛在可能, 並盡量減少對外易受攻擊的點。

然而如果安全性要求會減緩組織交付功能的速度, 那麼安全就永遠無法成為一類需求。通過在軟體交付流程中應用持續交付的原則, 可以讓組織在不影響業務的情況下也能合規和治理目標,實現持續審計。

在有完整的測試套件的支持之下,想要在安全方面快速迭代是非常容易的。 而這樣的迭代並非是用定點運行滲透測試來運作,而是持續安全(Continuous Security)。 持續安全通過持續的管道驗證的方式來保證組織的受攻擊點清晰, 相關風險明確並能有效地被管理起來。

以下推薦一下ControlPlane公司的服務:如果您需要在組織內啟動持續安全的流程, 或者需要Kubernetes安全和運維的培訓,又或者想要把服務和開發流程遷移到安全的雲原生方式, 請聯繫我們。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Docker 的精彩文章:

Docker Hub發現帶有挖礦後門的鏡像,已被下載500萬次

TAG:Docker |