本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
11 種(不)被駭客攻擊的方法
Kubernetes 安全性自專案啟動以來取得了長足進步,但仍然存在一些陷阱。本文從控制平面開始,逐步介紹工作負載和網路安全,最後展望未來的安全性,提供了一系列實用技巧,以幫助加固您的叢集並提高其在受損後的恢復能力。
第一部分:控制平面
控制平面是 Kubernetes 的大腦。它全面掌握叢集中執行的每個容器和 pod,可以排程新的 pod(其中可能包含對其父節點具有 root 訪問許可權的容器),並可以讀取叢集中儲存的所有 secrets。這些寶貴的資料需要保護,防止意外洩漏和惡意意圖:在訪問時、在靜止時以及在網路傳輸時。
1. 隨處使用 TLS
應為支援 TLS 的每個元件啟用 TLS,以防止流量嗅探,驗證伺服器身份,以及(對於相互 TLS)驗證客戶端身份。
請注意,某些元件和安裝方法可能會透過 HTTP 啟用本地埠,管理員應熟悉每個元件的設定,以識別潛在不安全的流量。
Lucas Käldström 繪製的此網路圖展示了 TLS 應該理想地應用的一些地方:主節點上的每個元件之間,以及 Kubelet 和 API 伺服器之間。Kelsey Hightower 的經典之作 《Kubernetes The Hard Way》提供了詳細的手動說明,etcd 的安全模型文件也提供了類似說明。

自動擴充套件 Kubernetes 節點在歷史上一直很困難,因為每個節點都需要一個 TLS 金鑰才能連線到主節點,而將 secrets 烘焙到基礎映象中並非良好實踐。Kubelet TLS 引導提供了一種能力,允許新的 kubelet 建立證書籤名請求,以便在啟動時生成證書。

2. 啟用 RBAC 並遵循最小許可權原則,停用 ABAC,並監控日誌
基於角色的訪問控制為使用者訪問資源(例如訪問名稱空間)提供了細粒度的策略管理。

自 1.6 版本釋出以來,Kubernetes 的 ABAC(基於屬性的訪問控制)已被 RBAC 取代,不應在 API 伺服器上啟用。請改用 RBAC。
--authorization-mode=RBAC
或者在 GKE 中使用此標誌將其停用
--no-enable-legacy-authorization
有許多關於叢集服務的 RBAC 策略的良好示例,以及文件。而且,這並非終點——可以使用 audit2rbac 從審計日誌中提取細粒度的 RBAC 策略。
不正確或許可權過高的 RBAC 策略在 pod 受損時會帶來安全威脅。維護最小許可權,並持續審查和改進 RBAC 規則,應被視為團隊納入其開發生命週期的“技術債務衛生”的一部分。
審計日誌(1.10 版中的測試版)提供了可定製的 API 日誌記錄,包括有效負載(例如請求和響應)和元資料級別。日誌級別可以根據您組織的安全策略進行調整——GKE 提供了合理的預設設定供您入門。
對於讀取請求(如 get、list 和 watch),只有請求物件會儲存在審計日誌中;響應物件不會。對於涉及敏感資料(如 Secret 和 ConfigMap)的請求,只匯出元資料。對於所有其他請求,請求和響應物件都會儲存在審計日誌中。
別忘了:將這些日誌儲存在叢集記憶體在安全威脅,以防遭到破壞。這些日誌,就像所有其他安全敏感日誌一樣,應傳輸到叢集外部,以防止在發生洩露時被篡改。
3. 為 API 伺服器使用第三方身份驗證
在組織中集中身份驗證和授權(也稱為單點登入)有助於使用者的入職、離職和一致許可權管理。.
將 Kubernetes 與第三方身份驗證提供商(如 Google 或 GitHub)整合,可以利用遠端平臺的身份保障(由 2FA 等支援),並避免管理員不得不重新配置 Kubernetes API 伺服器來新增或刪除使用者。
Dex 是一個具有可插拔聯結器的 OpenID Connect 身份(OIDC)和 OAuth 2.0 提供商。Pusher 透過一些自定義工具更進一步,並且還有其他輔助工具可用於略有不同的用例。
4. 隔離並防火牆您的 etcd 叢集
etcd 儲存狀態和機密資訊,是 Kubernetes 的關鍵元件——它應與叢集的其餘部分區別對待,進行保護。
對 API 伺服器的 etcd 具有寫訪問許可權相當於獲得整個叢集的 root 許可權,即使是讀訪問許可權也可以相當容易地用於提升許可權。
Kubernetes 排程器將在 etcd 中搜索沒有節點的 Pod 定義。然後它將找到的 Pod 傳送給可用的 Kubelet 進行排程。提交的 Pod 的驗證由 API 伺服器在將其寫入 etcd 之前執行,因此直接寫入 etcd 的惡意使用者可以繞過許多安全機制——例如 PodSecurityPolicies。
etcd 應配置 對等和客戶端 TLS 證書,並部署在專用節點上。為了緩解私鑰被盜用和從工作節點使用的問題,叢集也可以透過防火牆保護到 API 伺服器。
5. 輪換加密金鑰
安全最佳實踐是定期輪換加密金鑰和證書,以限制金鑰洩露的“爆炸半徑”。
Kubernetes 會自動輪換某些證書(特別是 kubelet 客戶端和伺服器證書),方法是在現有憑據過期時建立新的 CSR。
然而,API 伺服器用於加密 etcd 值的對稱加密金鑰不會自動輪換——它們必須手動輪換。這需要主節點訪問許可權,因此託管服務(如 GKE 或 AKS)將此問題抽象化,無需操作員干預。
第二部分:工作負載
控制平面上有了最低限度的安全保障,叢集就能安全執行。但是,就像一艘載有潛在危險貨物的船一樣,船上的集裝箱必須受到保護,以在發生意外事故或違規時容納這些貨物。Kubernetes 工作負載(pod、部署、作業、集合等)也是如此——它們在部署時可能受到信任,但如果它們面向網際網路,則總存在後續被利用的風險。以最小許可權執行工作負載並加固其執行時配置有助於降低此風險。
6. 使用 Linux 安全特性和 PodSecurityPolicies
Linux 核心具有許多重疊的安全擴充套件(功能、SELinux、AppArmor、seccomp-bpf),可以配置為嚮應用程式提供最小許可權。.
像 bane 這樣的工具可以幫助生成 AppArmor 配置檔案,而 docker-slim 可以生成 seccomp 配置檔案,但請注意——在驗證應用這些策略的副作用時,需要一套全面的測試套件來執行應用程式中的所有程式碼路徑。
PodSecurityPolicies 可以用於強制使用安全擴充套件和其他 Kubernetes 安全指令。它們提供了一個 pod 必須滿足才能提交到 API 伺服器的最低契約——包括安全配置檔案、特權標誌以及主機網路、程序或 IPC 名稱空間的共享。
這些指令很重要,因為它們有助於防止容器化程序逃逸其隔離邊界,而 Tim Allclair 的PodSecurityPolicy 示例是一個全面的資源,您可以根據自己的用例進行定製。
7. 靜態分析 YAML
在 PodSecurityPolicies 拒絕訪問 API 伺服器的情況下,靜態分析也可用於開發工作流,以模擬組織的合規性要求或風險承受能力。
敏感資訊不應儲存在 pod 型別 YAML 資源(部署、pod、集合等)中,敏感的配置對映和秘密應使用 vault(透過 CoreOS 的操作器)、git-crypt、sealed secrets 或 雲提供商 KMS 等工具進行加密。
YAML 配置的靜態分析可用於建立執行時安全基線。kubesec 為資源生成風險評分。
{
"score": -30,
"scoring": {
"critical": [{
"selector": "containers[] .securityContext .privileged == true",
"reason": "Privileged containers can allow almost completely unrestricted host access"
}],
"advise": [{
"selector": "containers[] .securityContext .runAsNonRoot == true",
"reason": "Force the running image to run as a non-root user to ensure least privilege"
}, {
"selector": "containers[] .securityContext .capabilities .drop",
"reason": "Reducing kernel capabilities available to a container limits its attack surface",
"href": "/docs/tasks/configure-pod-container/security-context/"
}]
}
}
而 kubetest 是一個用於 Kubernetes 配置的單元測試框架。
#// vim: set ft=python:
def test_for_team_label():
if spec["kind"] == "Deployment":
labels = spec["spec"]["template"]["metadata"]["labels"]
assert_contains(labels, "team", "should indicate which team owns the deployment")
test_for_team_label()
這些工具“左移”(將檢查和驗證提前到開發週期)。在開發階段進行安全測試可以為使用者提供關於可能被後續手動或自動化檢查拒絕的程式碼和配置的快速反饋,並可以減少引入更安全實踐的阻力。
8. 以非 root 使用者執行容器
作為 root 執行的容器通常擁有比其工作負載所需的許可權多得多的許可權,這在受到攻擊時可能有助於攻擊者進一步攻擊。
容器仍然依賴傳統的 Unix 安全模型(稱為自主訪問控制或 DAC)——一切都是檔案,許可權授予使用者和組。
Kubernetes 中未啟用使用者名稱空間。這意味著容器的使用者 ID 表對映到主機的使用者表,並且在容器內部以 root 使用者執行程序會將其作為主機的 root 執行。儘管我們有分層安全機制來防止容器逃逸,但仍不建議在容器內部以 root 身份執行。
許多容器映象使用 root 使用者執行 PID 1——如果該程序受到攻擊,攻擊者將在容器中獲得 root 許可權,並且任何錯誤配置都更容易被利用。
Bitnami 做了大量工作,將其容器映象遷移到非 root 使用者(特別是因為 OpenShift 預設要求這樣做),這可能有助於遷移到非 root 容器映象。
此 PodSecurityPolicy 片段可防止在容器內部以 root 身份執行程序,並防止許可權提升至 root。
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
runAsUser:
# Require the container to run without root privileges.
rule: 'MustRunAsNonRoot'
非 root 容器不能繫結到 1024 以下的特權埠(這由 CAP_NET_BIND_SERVICE 核心能力控制),但可以使用服務來掩蓋這一事實。在此示例中,虛構的 MyApp 應用程式在其容器中繫結到埠 8443,但服務透過將請求代理到 targetPort 來將其公開在 443 埠。
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 443
targetPort: 8443
在使用者名稱空間可用之前,或者在無 root 執行容器的持續工作在容器執行時中實現之前,以非 root 使用者身份執行工作負載的情況不會改變。
9. 使用網路策略
預設情況下,Kubernetes 網路允許所有 Pod 到 Pod 的流量;這可以使用網路策略進行限制。

傳統服務受到防火牆的限制,防火牆對每個服務使用靜態 IP 和埠範圍。由於這些 IP 很少更改,因此歷史上一直被用作一種身份形式。容器很少有靜態 IP——它們旨在快速失敗、快速重新排程,並使用服務發現而不是靜態 IP 地址。這些特性意味著防火牆的配置和審查變得更加困難。
由於 Kubernetes 將其所有系統狀態儲存在 etcd 中,因此如果 CNI 網路外掛支援,它可以配置動態防火牆。Calico、Cilium、kube-router、Romana 和 Weave Net 都支援網路策略。
需要注意的是,這些策略是故障關閉的,因此此處缺少 podSelector 預設為萬用字元。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector:
這是一個網路策略示例,它拒絕除 UDP 53(DNS)之外的所有出口流量,這也阻止了傳入應用程式的連線。網路策略是有狀態的,因此對出站請求的回覆仍然會到達應用程式。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: myapp-deny-external-egress
spec:
podSelector:
matchLabels:
app: myapp
policyTypes:
- Egress
egress:
- ports:
- port: 53
protocol: UDP
- to:
- namespaceSelector: {}
Kubernetes 網路策略不能應用於 DNS 名稱。這是因為 DNS 可以輪詢解析為多個 IP,或根據呼叫 IP 動態解析,因此網路策略只能應用於固定 IP 或 podSelector(用於動態 Kubernetes IP)。
最佳實踐是首先拒絕名稱空間的所有流量,然後逐步新增路由以允許應用程式透過其驗收測試套件。這可能變得複雜,因此 ControlPlane 團隊合力開發了 netassert——用於 DevSecOps 工作流的網路安全測試,具有高度並行化的 nmap。
k8s: # used for Kubernetes pods
deployment: # only deployments currently supported
test-frontend: # pod name, defaults to `default` namespace
test-microservice: 80 # `test-microservice` is the DNS name of the target service
test-database: -80 # `test-frontend` should not be able to access test-database’s port 80
169.254.169.254: -80, -443 # AWS metadata API
metadata.google.internal: -80, -443 # GCP metadata API
new-namespace:test-microservice: # `new-namespace` is the namespace name
test-database.new-namespace: 80 # longer DNS names can be used for other namespaces
test-frontend.default: 80
169.254.169.254: -80, -443 # AWS metadata API
metadata.google.internal: -80, -443 # GCP metadata API
雲提供商元資料 API 是許可權提升的持續來源(正如最近的 Shopify 漏洞賞金所證明的),因此專門的測試以確認 API 在容器網路上被阻止有助於防範意外的錯誤配置。
10. 掃描映象並執行 IDS
Web 伺服器向其所連線的網路提供攻擊面:掃描映象的已安裝檔案可確保不存在攻擊者可能利用的已知漏洞,從而獲得對容器的遠端訪問。IDS(入侵檢測系統)會在發生攻擊時檢測到它們。
Kubernetes 允許 Pod 透過一系列准入控制器門進入叢集,這些門應用於 Pod 和其他資源(如部署)。這些門可以驗證每個 Pod 的准入或更改其內容,現在它們支援後端 webhook。

這些 webhook 可以被容器映象掃描工具用來在映象部署到叢集之前驗證映象。未透過檢查的映象可以被拒絕准入。
掃描容器映象是否存在已知漏洞可以縮短攻擊者利用已披露 CVE 的時間視窗。CoreOS 的 Clair 和 Aqua 的 Micro Scanner 等免費工具應在部署管道中使用,以防止部署具有嚴重可利用漏洞的映象。
像 Grafeas 這樣的工具可以儲存映象元資料,以便針對容器的唯一簽名(內容可定址雜湊)進行持續的合規性和漏洞檢查。這意味著使用該雜湊掃描容器映象與掃描生產環境中部署的映象相同,並且可以在不訪問生產環境的情況下持續進行。
未知的零日漏洞將始終存在,因此應在 Kubernetes 中部署諸如 Twistlock、Aqua 和 Sysdig Secure 之類的入侵檢測工具。IDS 檢測容器中的異常行為並暫停或終止它——Sysdig 的 Falco 是一個開源規則引擎,也是這個生態系統的入口點。
第三部分:未來
安全“雲原生演進”的下一階段似乎是服務網格,儘管其普及可能需要時間——遷移涉及將複雜性從應用程式轉移到網格基礎設施,組織將熱切希望瞭解最佳實踐。

11. 執行服務網格
服務網格是加密的持久連線網路,透過高效能的“邊車”代理伺服器(如 Envoy 和 Linkerd)建立。它增加了流量管理、監控和策略——所有這些都無需更改微服務。
將微服務安全和網路程式碼解除安裝到一套共享的、經過實戰檢驗的庫中,這在使用 Linkerd 時已經可能實現,而 Google、IBM 和 Lyft 引入的 Istio 為這一領域提供了另一種選擇。隨著 SPIFFE 提供每個 Pod 的加密身份以及眾多其他功能的加入,Istio 可以簡化下一代網路安全的部署。
在“零信任”網路中,可能不需要傳統的防火牆或 Kubernetes 網路策略,因為每次互動都透過 mTLS(相互 TLS)進行,確保雙方不僅安全通訊,而且知道兩個服務的身份。
這種從傳統網路到雲原生安全原則的轉變對於那些具有傳統安全思維的人來說並非易事,強烈推薦閱讀 SPIFFE 的Evan Gilman撰寫的《零信任網路》一書,作為進入這個勇敢新世界的入門。
Istio 0.8 LTS 已經發布,專案正迅速接近 1.0 版本。其穩定性版本控制與 Kubernetes 模型相同:穩定的核心,各個 API 在各自的 alpha/beta 穩定性名稱空間下標識自己。預計未來幾個月 Istio 的採用率將有所上升。
結論
雲原生應用程式擁有一套更細粒度、輕量級的安全原語來鎖定工作負載和基礎設施。這些工具的強大和靈活性既是福也是禍——在自動化不足的情況下,更容易暴露不安全的工作負載,從而允許從容器或其隔離模型中進行突破。
可用的防禦工具比以往任何時候都多,但必須謹慎行事,以減少攻擊面和錯誤配置的可能性。
然而,如果安全阻礙了組織的功能交付速度,那麼它永遠不會成為一流公民。將持續交付原則應用於軟體供應鏈,可以使組織在不影響業務底線的情況下實現合規性、持續審計和強制治理。
在全面的測試套件支援下,快速迭代安全性最容易實現。這透過持續安全來實現——持續安全是傳統滲透測試的替代方案,透過持續的管道驗證確保組織的攻擊面是已知的,並且風險得到持續理解和管理。
這是 ControlPlane 的工作方式:如果我們可以幫助您啟動持續安全規範、提供 Kubernetes 安全和運營培訓,或與您共同實施安全的雲原生演進,請聯絡我們。
Andrew Martin 是 @controlplaneio 的聯合創始人,並在 @sublimino 釋出有關雲原生安全的推文。