資料分類別與安全架構設計
在考慮資料分類別時,我發現問自己「最壞的情況會是什麼?」然後從那裡往往回推是很有幫助的。如圖所示,程式碼會嘗試逃離其容器,可能攻擊叢集並可能危及帳戶。不要將高價值資料放在可能被低價值資料系統入侵的地方。
叢集應該根據資料分類別和入侵影響進行隔離。極端情況下,這意味著每個租戶一個叢集,這很昂貴與為 SRE 和安全團隊創造了管理開銷。劃分叢集的藝術是安全性和可維護性之間的平衡。
擁有彼此隔離的多個叢集執行成本高與浪費大量閒置計算資源,但這對於敏感工作負載有時是必要的。每個叢集必須應用一致的策略,分層名稱空間控制器提供了推出類別似設定的途徑。
分層名稱空間與策略傳播
統一設定需要將 Kubernetes 資源同步到下屬叢集,並應用一致的准入控制和網路策略。我們可以看到策略物件如何在名稱空間之間傳播,以提供統一執行安全需求,如 RBAC、網路策略和團隊特定的 Secret。
這種分層設計允許組織在保持安全隔離的同時,實作更高效的資源管理和策略一致性。
叢集支援服務與工具環境的安全風險
連線到不同敏感度叢集的分享工具環境可能為攻擊者提供在環境之間橫向移動或收集洩漏資料的機會。
工具環境的安全風險
工具環境是攻擊的主要目標,特別是登入檔和內部包的供應鏈,以及日誌和可觀察性系統。
例如,CVE-2019-11250 是一個側通道訊息洩露漏洞,洩露 HTTP 身份驗證標頭。這些敏感資料預設被執行 client-go 函式庫的 Kubernetes 元件記錄。標頭和環境變數的過度記錄在任何系統中都是一個常見問題,並強調了敏感系統中分離的必要性。
能夠將流量路由回其客戶端叢集的工具環境可能夠使用 CI/CD 系統的憑證存取管理介面和資料儲存。或者,即使沒有直接網路存取,攻擊者也可能:
- 汙染容器映像
- 入侵原始碼
- 掠奪監控系統
- 存取安全和掃描服務
- 植入後門
安全監控與可見性
大型組織執行安全營運中心(SOC)和安全訊息和事件管理(SIEM)技術以支援合規性、威脅檢測和安全管理。叢集會發出事件、稽核、日誌和可觀察性資料到這些系統,在那裡它們被監控和回應。
用資料超載這些系統、超過速率限制或增加事件延遲(為稽核、事件或容器日誌增加延遲)可能會壓倒 SOC 或 SIEM 的回應能力。
由於無狀態應用程式傾向於將其資料儲存在別人的資料函式庫中,從 Kubernetes 可存取的雲資料儲存是主要目標。可以讀取或寫入這些資料的工作負載非常吸引人,服務帳戶憑證和工作負載身份很容易用來收集資料。
在我的安全實踐中,發現 SOC 和 SIEM 應該將雲事件與其呼叫的 Kubernetes 工作負載身份相關聯,以瞭解系統的使用方式。這種相關性分析能夠提供更全面的安全視角,幫助識別異常活動和潛在的安全威脅。
Kubernetes 安全實踐的關鍵建議
根據以上分析,我建議採取以下安全措施來強化 Kubernetes 環境:
控制面保護:嚴格限制對控制面元件的存取,特別是 API 伺服器和雲控制器管理器。
節點限制實施:確保 NodeRestriction 准入控制器已啟用,防止節點自我重新標記攻擊。
叢集隔離策略:根據資料敏感度和業務需求實施適當的叢集隔離策略。
工具環境隔離:將工具環境與生產環境隔離,防止攻擊者利用工具環境進行橫向移動。
監控與可見性:實施全面的安全監控,將 Kubernetes 事件與雲端活動相關聯,以識別異常行為。
分層名稱空間管理:利用分層名稱空間控制器實作一致的策略管理和資源隔離。
最小許可權原則:為所有服務帳號和使用者實施最小許可權原則,限制潛在攻擊的影響範圍。
安全是一個持續的過程,需要不斷評估和調整。透過實施這些安全措施,組織可以顯著提高其 Kubernetes 環境的安全性,減少潛在攻擊的影響範圍,並更有效地保護敏感資料和關鍵業務功能。
在容器化世界中,安全不再是單一邊界的概念,而是多層次防禦機制的組合。理解這些安全層如何相互配合,是建立強大 Kubernetes 安全架構的關鍵。透過適當的控制面和資料面防護策略,組織可以在享受容器化靈活性的同時,維持必要的安全控制。
Kubernetes安全政策:構建堅固的防護體系
在多租戶Kubernetes環境中,安全政策是維護系統完整性的關鍵要素。就像建造海上堡壘防禦海盜只是戰鬥的一半,接下來還需要在瞭望塔上佈署守衛並時刻保持防禦狀態。安全政策就像是給堡壘守衛的命令,定義了叢集中允許的行為範圍。
工作負載隔離是Kubernetes安全的根本,但這需要投入大量精力進行測試與驗證。在本文中,玄貓將帶您探索Kubernetes安全政策的多個層面,包括如何管理不同型別的政策、身份驗證與授權機制,以及如何使用現代政策引擎保護您的叢集。
工作負載隔離:多租戶環境的安全挑戰
工作負載隔離是一項艱巨的任務,需要大量投入來測試自己的安全設定。玄貓建議透過靜態分析驗證設定檔案,並在執行時重新驗證叢集,確保它們仍然正確設定。
API伺服器和etcd是Kubernetes的大腦和記憶體,必須與潛在的惡意租戶隔離。某些多租戶選項在更大的Kubernetes叢集中執行多個控制平面,以增強隔離性。
階層名稱空間控制器(Hierarchical Namespace Controller)為多叢集政策帶來了分散式管理能力,使大型組織能更有效地管理複雜的名稱空間結構。
政策型別:技術、組織與法規
在實際生產環境中執行工作負載時,我們需要考慮不同型別的政策:
技術政策
技術政策通常容易理解與直接實施。例如,執行時政策或網路通訊政策。在實施這些政策時,玄貓發現許多組織往往過於關注個別控制點,而忽視了整體安全架構。技術政策應該是一個完整的安全矩陣的一部分,而不是孤立的控制措施。
組織政策
組織政策的制定可能具有挑戰性,取決於組織的結構和文化。例如,“開發人員只能佈署到測試和開發環境"這樣的政策,雖然看似簡單,但在實際執行中可能面臨各種挑戰,特別是在DevOps文化盛行的組織中。
監管政策
監管政策取決於工作負載執行的行業,根據合規級別不同,可能需要大量時間和精力來實施。例如,支付卡行業資料安全標準(PCI DSS)要求透過開放、公共網路傳輸的持卡人資料必須加密。
在本文中,我們主要關注如何定義和實施可以明確表述的政策。而在實際執行中,儘管有所有政策的保障,人類使用者作為安全鏈中最薄弱的環節,往往會為攻擊者提供入侵角度。
Kubernetes的預設安全設定
政策對於保持Kubernetes安全至關重要,但預設情況下啟用的安全功能相當有限。大多數軟體的設定會隨著新功能的推出而變化;設定錯誤是常見的攻擊向量,Kubernetes也不例外。
重用和擴充套件開放原始碼政策設定通常比自行開發更安全,為防止迴歸,必須在佈署前使用conftest等工具測試基礎設施和安全程式碼。
Kubernetes安全工作者Brad Geesaman曾指出預設不啟用准入控制的危險性。如果管理員疏於職守,攻擊者可能利用這些預設設定進行攻擊。
網路流量控制
NetworkPolicy資源與實施它的CNI外掛結合使用,允許我們實施限制網路流量的政策。這是建立微分段(micro-segmentation)安全模型的基礎,可以限制pod之間的通訊。
限制資源分配
在Kubernetes中,預設情況下,pod中的容器在計算資源消耗方面沒有限制。自Kubernetes 1.10起,可以使用LimitRanges在名稱空間基礎上限制容器和pod的資源分配。這種政策型別透過准入控制器實施,這意味著它不適用於已執行的pod。
假設我們想要限制dev名稱空間中容器可以使用的記憶體為2GB RAM,可以這樣定義政策:
apiVersion: v1
kind: LimitRange
metadata:
name: dev-mem-limits
spec:
limits:
- type: Container
max:
memory: 2Gi
這段YAML定義了一個LimitRange資源,名為dev-mem-limits。它指定了Container型別資源的最大記憶體限制為2Gi(2吉位元組)。這意味著在應用此LimitRange的名稱空間中,所有容器的記憶體請求不能超過2GB。這是防止單個容器消耗過多叢集資源的重要機制,特別是在分享環境中。
假設將上述YAML片段儲存在名為dev-mem-limits.yaml的檔案中,然後執行以下命令來實施限制範圍:
kubectl -n dev apply -f dev-mem-limits.yaml
如果現在嘗試建立一個容器記憶體請求超過限制的pod,將收到403 Forbidden錯誤訊息。
資源配額
在多租戶環境中,叢集由多個團隊分享,特定團隊可能使用超過其公平份額的可用資源(如工作節點提供的CPU、RAM等)。資源配額是一種允許控制這些配額的政策型別。
某些Kubernetes發行版,如OpenShift,以特定方式擴充套件了名稱空間(在OpenShift中稱為"project”),使資源配額等功能預設可用並強制執行。
此外,自Kubernetes v1.20起,還可以限制pod在每個節點基礎上可以使用的程式ID數量。這對於防止fork炸彈等拒絕服務攻擊特別重要。
執行時政策
Pod安全政策(PSP)允許定義pod建立和更新的細粒度授權。例如,可以使用PSP設定預設的seccomp和AppArmor設定檔案:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default'
apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
seccomp.security.alpha.kubernetes.io/defaultProfileName: 'runtime/default'
apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'
spec:
# ...其他規格設定
這個YAML定義了一個名為"restricted"的PodSecurityPolicy,它設定了seccomp和AppArmor的預設設定檔案。seccomp(secure computing mode)限制容器可以執行的系統呼叫,而AppArmor提供強制存取控制框架。這些安全機制協同工作,大減少容器的攻擊面。
然而,值得注意的是,PSP正在被棄用。越來越多的組織正在考慮OPA Constraints Framework作為PSP的替代品。好訊息是PSP的替代品已經存在:在上游,它們被Pod安全標準(PSS)所取代,或者也可以使用後文討論的通用政策框架。
身份驗證與授權:安全的根本
在授予特權之前,我們如何證明工作負載的身份?這個問題引出了Kubernetes中身份驗證和授權的重要性。
Kubernetes提供了強大的根據角色的存取控制(RBAC)系統,允許細粒度地定義誰可以對哪些資源執行哪些操作。RBAC是防止未授權存取的關鍵機制,但必須正確設定才能有效。
在實施RBAC時,玄貓建議遵循最小特權原則,只授予完成任務所需的最小許可權。這減少了潛在攻擊面,限制了惡意行為者可能造成的損害。
通用政策引擎:超越內建功能
隨著組織安全需求的增長,內建的Kubernetes政策機制可能不足以滿足所有需求。這就是通用政策引擎如Open Policy Agent(OPA)和Kyverno發揮作用的地方。
這些工具提供了一個統一的框架,用於跨叢集和雲環境定義和執行政策。它們可以處理從准入控制到執行時安全的各種政策需求,並提供一致的執行機制。
OPA使用宣告式語言Rego來定義政策,而Kyverno則採用更接近Kubernetes原生YAML的方法。這兩種工具都能夠實施複雜的政策,如要求特定標籤、限制容器映像源或強制執行安全上下文設定。
政策同步與執行:跨環境一致性
政策必須在叢集和雲環境中同步(准入控制器、IAM政策、安全邊車、服務網格、seccomp和AppArmor設定檔案)並強制執行。這確保了無論工作負載在何處執行,都受到相同的安全控制。
在多叢集環境中,政策同步尤為重要。不一致的政策可能導致安全漏洞,使攻擊者能夠利用設定較弱的叢集作為入口點。
玄貓在處理多叢集環境時,發現使用GitOps工作流程管理政策是一種有效的方法。將政策定義為程式碼並儲存在版本控制系統中,可以確保所有叢集應用相同的政策集,並提供稽核跟蹤和變更歷史。
稽核與合規:持續驗證
政策實施後,必須持續驗證其有效性。稽核是安全政策生命週期的關鍵部分,幫助識別違規行為並確保合規性。
Kubernetes提供稽核日誌功能,記錄對API伺服器的請求。這些日誌可以分析以識別潛在的安全問題,如未授權的存取嘗試或異常行為。
除了內建稽核功能外,還可以使用第三方工具進行更深入的合規性檢查。這些工具可以驗證叢集設定是否符合行業標準和最佳實踐,如CIS Kubernetes Benchmark。
實用建議:加強Kubernetes安全政策
根據玄貓在多個Kubernetes環境中的經驗,以下是一些實用建議,可以幫助加強安全政策:
從預設拒絕開始 - 採用白名單方法,只允許明確許可的行為,而不是嘗試列出所有禁止的行為。
實施深度防禦 - 不要依賴單一安全控制。結合網路政策、RBAC、准入控制和執行時安全,建立多層防禦。
自動化政策測試 - 將政策測試整合到CI/CD管道中,確保佈署前捕捉設定錯誤。
使用基準設定作為起點 - 利用CIS Kubernetes Benchmark等行業標準作為基準設定的起點,然後根據特定需求進行調整。
定期審查和更新政策 - 安全是一個持續的過程。定期審查政策以確保它們仍然有效並符合最新的安全最佳實踐。
政策與組織文化
技術政策只是等式的一半;組織文化也在安全體系中扮演著重要角色。即使是最嚴格的政策也可能被繞過,如果組織文化不重視安全。
培養安全意識文化,鼓勵團隊成員報告潛在問題,並將安全考慮納入開發生命週期的每個階段。這種整體方法比任何單一技術控制更有效。
在Kubernetes環境中實施強大的安全政策需要技術專業知識、組織支援和持續的警惕。透過遵循本文概述的原則和實踐,可以顯著提高Kubernetes佈署的安全狀態,保護關鍵工作負載免受不斷發展的威脅。
安全政策是保護Kubernetes環境的關鍵元件,但它們必須建立在堅實的基礎上,並得到組織文化的支援才能真正有效。透過結合技術控制、最佳實踐和安全意識文化,可以建立一個強大的防禦體系,抵禦現代威脅環境中的挑戰。
Kubernetes 存取控制機制:安全防護的第一道防線
在現代容器化環境中,存取控制政策是確保系統安全的根本。Kubernetes 作為容器協調平台的長官者,提供了彈性與可擴充套件的身分驗證和授權機制,但這些機制若未正確設定,可能會留下嚴重的安全漏洞。
我在多年的容器安全實踐中發現,大多數 Kubernetes 環境的安全問題並非來自於平台本身的缺陷,而是源於設定不當或對威脅理解不足。本文將探討 Kubernetes 的存取控制政策,分析潛在威脅模型,並提供實用的防禦策略。
Kubernetes 安全威脅模型分析
瞭解過去的安全漏洞能幫助我們構建更強健的防禦機制。以下是幾個值得關注的 Kubernetes 存取控制相關漏洞案例:
關鍵漏洞回顧與分析
API 伺服器資訊洩露 (CVE-2016-5392)
在多租戶環境中,API 伺服器允許已驗證的遠端使用者透過與 watch-cache 列表相關的向量,取得其他專案的敏感資訊。這揭示了早期 Kubernetes 在多租戶隔離上的弱點。
未授權 API 存取 (CVE-2018-5256)
某些版本的 CoreOS Tectonic 在 /api/kubernetes/
路徑上掛載了直接代理,無需身分驗證即可存取,使攻擊者能直接連線到 API 伺服器。這類別設定錯誤常見於自建環境中。
TLS 設定缺陷 (CVE-2019-3818)
kube-rbac-proxy 容器未正確遵循 TLS 設定,允許使用不安全的加密方式和 TLS 1.0。攻擊者可能針對具有弱設定的 TLS 連線,嘗試破解加密。
容器許可權提升 (CVE-2019-11245)
某些 kubelet 版本未明確指定 runAsUser,導致容器重啟時可能嘗試以 UID 0(root)執行。這突顯了預設安全設定的重要性。
資源範圍混淆 (CVE-2019-11247)
Kubernetes API 伺服器錯誤地允許以名稱空間資源的方式存取叢集範圍的自定義資源。這意味著僅有單一名稱空間存取許可權的使用者可能夠建立、檢視、更新或刪除叢集範圍的資源。
中間人攻擊 (CVE-2020-8554)
攻擊者可能在多租戶環境中執行中間人攻擊,攔截其他租戶的流量。為解決此問題,新增了 DenyServiceExternalIPs 准入控制器,因為當時尚無直接的修補方案。
這些漏洞案例提醒我們,即使是設計良好的系統也可能存在安全盲點。在設計 Kubernetes 安全策略時,必須從多個角度考慮潛在威脅。
關鍵安全機制與最佳實踐
緊急存取機制 (Breakglass Scenario)
在緊急情況下,可能需要繞過預設的存取控制機制。這種緊急存取通常具有高許可權,並且往往有時間限制。雖然 Kubernetes 本身沒有內建緊急存取功能,但許多企業級解決方案提供了這項功能。
例如,Google Kubernetes Engine (GKE) 的二進位授權緊急存取功能就是一個實用的參考案例。當啟用緊急存取時,系統會通知相關負責人,並記錄該帳戶的操作以供稽核。
稽核機制的實作與設定
Kubernetes 內建了稽核功能,每個 API 請求都會生成一個稽核事件。這些事件經過預處理後,會根據設定寫入後端,目前支援日誌檔案和 webhook(傳送事件到外部 HTTP API)。
稽核級別可設定,從 None(不記錄事件)到 RequestResponse(記錄事件中繼資料、請求和回應主體)。以下是一個捕捉 ConfigMap 事件的稽核政策範例:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Request
resources:
- group: ""
resources: ["configmaps"]
這個稽核政策定義了對 ConfigMap 資源的稽核級別。它使用了 audit.k8s.io/v1
API 版本,設定了 Request
級別的稽核,這意味著系統將記錄關於 ConfigMap 操作的請求內容,但不包含回應內容。這對於監控設定變更特別有用,同時避免了記錄過多資訊造成的儲存壓力。
在實際佈署中,我建議尋找稽核級別與保留期間之間的平衡。過度詳細的稽核可能會產生大量日誌,而保留期太短則可能在需要調查安全事件時缺乏足夠的歷史記錄。
許多安全和可觀察性供應商根據 Kubernetes 的稽核功能提供了額外的功能,例如:
- Sysdig 的「Kubernetes Audit Logging」
- Datadog 的「Kubernetes Audit Logs」
- Splunk/Outcold 的「Monitoring Kubernetes: Metrics and Log Forwarding」
身分驗證與授權架構
在 Kubernetes 叢集中,存在著各種資源,包括叢集內部資源(如 Pod 或名稱空間)和叢集外部資源(例如雲端提供商的負載平衡器)。定義和檢查人員或程式存取這些資源的許可權是安全架構的核心。
Kubernetes 存取控制流程
在 Kubernetes 的存取控制架構中,身分驗證(Authentication)和授權(Authorization)是兩個關鍵步驟:
- 身分驗證:驗證身分的過程,確認請求者是誰
- 授權:檢查許可權的過程,確定請求者能做什麼
API 伺服器首先透過一個或多個已設定的身分驗證模組(如客戶端憑證、密碼或 JWT)對請求進行身分驗證。如果無法驗證請求,API 伺服器會以 401 HTTP 狀態碼拒絕該請求。
一旦身分驗證成功,API 伺服器會進入授權階段。在這一步中,它使用已設定的授權模組來確定是否允許存取。授權過程會考慮憑證、請求路徑、資源型別(Pod、服務等)和動詞(建立、取得等)。如果至少有一個模組授予存取許可權,則請求被允許;否則,回傳 403 HTTP 狀態碼。
目前最廣泛使用的授權模組是根據角色的存取控制(RBAC),我們將在後續章節中詳細討論。
使用者身分管理
人類使用者的身分管理
與機器或應用程式不同,Kubernetes 並不將人類使用者視為一等公民。換句話說,Kubernetes 核心中沒有代表人類使用者的資源。
在實務中,組織通常希望將 Kubernetes 叢集使用者對映到現有的使用者目錄,如 LDAP 伺服器或 Azure Directory,並理想情況下提供單一登入(SSO)功能。
實作這一目標有兩種選擇:購買或自建。如果使用雲端提供商的 Kubernetes 發行版,可以檢查其提供的整合方案。如果打算自行建立 SSO,有多種開放原始碼工具可供選擇:
- 根據 OpenID Connect (OIDC)/OAuth 2.0 的解決方案,如 Dex
- 根據 Security Assertion Markup Language (SAML) 的解決方案,如 Teleport 提供的方案
- 更完整的開放原始碼產品如 Keycloak,支援從 SSO 到政策執行的各種使用案例
工作負載身分識別
與人類使用者不同,工作負載(如擁有 Pod 的 Deployment)在 Kubernetes 中確實是一等公民。
服務帳戶(Service Accounts)
在 Kubernetes 中,服務帳戶是應用程式的身分表示。服務帳戶是名稱空間範圍的資源,可以在 Pod 的上下文中使用,以便應用程式向 API 伺服器進行身分驗證。其標準形式如下:
system:serviceaccount:NAMESPACE:NAME
作為控制平面的一部分,三個控制器共同實作服務帳戶自動化,管理 Secret 和令牌:
ServiceAccount 准入控制器:作為 API 伺服器的一部分,在 Pod 建立和更新時運作。控制器檢查 Pod 使用的服務帳戶是否存在,如果不存在則拒絕該 Pod(或者,如果未指定服務帳戶,則使用預設服務帳戶)。此外,它還管理一個卷,透過一個眾所周知的位置提供服務帳戶:
/var/run/secrets/kubernetes.io/serviceaccount
TokenController:作為控制平面元件控制器管理器的一部分,監視服務帳戶並建立或刪除相應的令牌。這些是 JWT(JSON Web Token)令牌。
ServiceAccountController:確保每個名稱空間中都有一個名為
default
的服務帳戶。
這三個控制器協同工作,確保服務帳戶的自動化管理和令牌的生命週期管理。
根據角色的存取控制 (RBAC)
根據角色的存取控制是 Kubernetes 中最廣泛使用的授權機制。RBAC 允許管理員定義角色,並將這些角色繫結到特定使用者或服務帳戶。
RBAC 的核心概念包括:
- 角色(Role):定義了在特定名稱空間內可以對資源執行的操作
- 叢集角色(ClusterRole):類別似於角色,但適用於整個叢集
- 角色繫結(RoleBinding):將角色繫結到使用者或服務帳戶
- 叢集角色繫結(ClusterRoleBinding):將叢集角色繫結到使用者或服務帳戶
以下是一個簡單的 RBAC 設定範例,允許 my-app
服務帳戶讀取特定名稱空間中的 Pod 和服務:
# 建立一個角色
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "watch", "list"]
---
# 將角色繫結到服務帳戶
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: ServiceAccount
name: my-app
namespace: default
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
這個 RBAC 設定由兩部分組成:
- 首先定義了一個名為
pod-reader
的 Role,授予對 core API 組(由空字串""
表示)中的 pods 和 services 資源的讀取許可權(get、watch、list 動作)。 - 然後建立了一個 RoleBinding,將上面定義的 Role 繫結到 default 名稱空間中的
my-app
服務帳戶。
這種設定確保了 my-app
服務帳戶只能讀取 Pod 和服務資訊,而不能修改或刪除它們,體現了最小許可權原則。在實際應用中,我發現精確定義 RBAC 許可權是防止橫向移動攻擊的關鍵。