本文已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
11 種(避免)被駭客入侵的方法
自 Kubernetes 專案啟動以來,安全性已取得了長足的進步,但仍然存在一些陷阱。從控制平面開始,逐步建立工作負載和網路安全性,並展望安全性的未來,以下列出了一些實用技巧,可協助您強化叢集,並在叢集遭到入侵時提高其復原能力。
第一部分:控制平面
控制平面是 Kubernetes 的大腦。它可以全面檢視叢集上運行的每個容器和 Pod,可以排程新的 Pod(其中可能包含對其父節點具有 Root 存取權的容器),並且可以讀取叢集中儲存的所有密鑰。這種寶貴的貨物需要保護,以防止意外洩漏和惡意意圖:無論是在存取時、靜止時,還是在網路上傳輸時。
1. 全面採用 TLS
應為每個支援 TLS 的組件啟用 TLS,以防止流量監聽、驗證伺服器的身分,以及(對於相互 TLS)驗證用戶端的身份。
請注意,某些組件和安裝方法可能會透過 HTTP 啟用本機連接埠,管理員應熟悉每個組件的設定,以識別潛在的不安全流量。
Lucas Käldström 的這張網路圖表 Lucas Käldström 展示了 TLS 理想情況下應用的某些位置:主節點上每個組件之間,以及 Kubelet 和 API 伺服器之間。Kelsey Hightower 的權威指南 Kubernetes The Hard Way 提供了詳細的手動說明,etcd 的安全性模型 文件也提供了詳細說明。

Kubernetes 節點的自動擴展在過去一直很困難,因為每個節點都需要 TLS 金鑰才能連接到主節點,並且將密鑰烘焙到基礎映像檔中並不是好的做法。Kubelet TLS 啟動引導 提供了新 Kubelet 建立憑證簽署請求的能力,以便在啟動時產生憑證。

2. 啟用具有最小權限的 RBAC、停用 ABAC,並監控日誌
基於角色的存取控制 (RBAC) 為使用者存取命名空間等資源提供細緻的政策管理。

Kubernetes 的 ABAC(基於屬性的存取控制)自 1.6 版本起已被 RBAC 取代,不應在 API 伺服器上啟用。請改用 RBAC
--authorization-mode=RBAC
或者使用此標誌在 GKE 中停用它
--no-enable-legacy-authorization
關於 如何在 Kubernetes 叢集中設定 RBAC 以及 叢集服務的 RBAC 政策,以及文件中,有很多良好範例。而且它不只於此 - 可以使用 audit2rbac 從稽核日誌中提取細緻的 RBAC 政策。
不正確或過於寬鬆的 RBAC 政策在 Pod 遭到入侵的情況下是一種安全威脅。維護最小權限,以及持續審查和改進 RBAC 規則,應被視為團隊建置到其開發生命週期中的「技術債衛生」的一部分。
稽核日誌記錄(在 1.10 版本中為 Beta 版)在酬載(例如請求和回應)以及元數據級別提供可自訂的 API 日誌記錄。日誌級別可以根據您組織的安全性政策進行調整 - GKE 提供了合理的預設值,可讓您入門。
對於諸如 get、list 和 watch 之類的讀取請求,稽核日誌中僅儲存請求物件;回應物件不儲存。對於涉及敏感資料(例如 Secret 和 ConfigMap)的請求,僅匯出元數據。對於所有其他請求,請求和回應物件都會儲存在稽核日誌中。
別忘了:將這些日誌保留在叢集內部在發生入侵時是一種安全威脅。這些日誌應與所有其他安全性敏感的日誌一樣,傳輸到叢集外部,以防止在發生違規事件時遭到竄改。
3. 為 API 伺服器使用第三方驗證
在整個組織中集中身份驗證和授權(也稱為單一登入)有助於使用者入門、離職和一致的權限.
將 Kubernetes 與第三方驗證提供者(如 Google 或 GitHub)整合,使用遠端平台的身份保證(由 2FA 等功能支援),並防止管理員必須重新設定 Kubernetes API 伺服器以新增或移除使用者。
Dex 是具有可插拔連接器的 OpenID Connect Identity (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 將透過在其現有憑證到期時建立新的 CSR,自動輪換某些憑證(特別是 Kubelet 用戶端和伺服器憑證)。
但是,API 伺服器用於加密 etcd 值的 對稱加密金鑰 不會自動輪換 - 必須手動輪換。需要主節點存取權才能執行此操作,因此受管服務(例如 GKE 或 AKS)會從運營商的角度抽象化此問題。
第二部分:工作負載
透過控制平面上的最低限度可行安全性,叢集能夠安全地運行。但是,就像一艘運載潛在危險貨物的船隻一樣,必須保護船隻的容器,以便在發生意外事故或違規事件時容納貨物。Kubernetes 工作負載(Pod、Deployment、Job、Set 等)也是如此 - 它們在部署時可能是受信任的,但如果它們面向網際網路,則始終存在稍後被利用的風險。以最小權限運行工作負載並強化其運行時組態可以幫助減輕這種風險。
6. 使用 Linux 安全性功能和 PodSecurityPolicies
Linux 核心具有許多重疊的安全性擴充功能(capabilities、SELinux、AppArmor、seccomp-bpf),可以將其設定為向應用程式提供最小權限.
諸如 bane 之類的工具可以幫助產生 AppArmor 設定檔,而 docker-slim 則用於 seccomp 設定檔,但請注意 - 在驗證應用這些政策的副作用時,需要全面的測試套件來執行應用程式中的所有程式碼路徑。
PodSecurityPolicies 可用於強制使用安全性擴充功能和其他 Kubernetes 安全性指令。它們提供 Pod 必須滿足的最低合約才能提交到 API 伺服器 - 包括安全性設定檔、特權標誌以及主機網路、進程或 IPC 命名空間的共用。
這些指令非常重要,因為它們有助於防止容器化進程逃脫其隔離邊界,並且 Tim Allclair 的 PodSecurityPolicy 範例 是一個全面的資源,您可以根據您的使用案例進行自訂。
7. 靜態分析 YAML
在 PodSecurityPolicies 拒絕存取 API 伺服器的地方,靜態分析也可以在開發工作流程中使用,以模擬組織的合規性要求或風險承受能力。
敏感資訊不應儲存在 Pod 類型 YAML 資源(Deployment、Pod、Set 等)中,並且應使用諸如 Vault(搭配 CoreOS 的運營商)、git-crypt、Sealed Secrets 或 雲端供應商 KMS 等工具加密敏感 ConfigMap 和密鑰。
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. 運行服務網格
服務網格是由高效能「Sidecar」代理伺服器(如 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 上發布關於雲原生安全性的推文