Kubernetes RBAC 最佳安全實踐
「引言」
Kubernetes 是一個開源的容器編排平臺,用于自動化部署、擴展和管理容器化應用程序。它提供了豐富的功能,如服務發現、負載均衡、自動縮放等。隨著 Kubernetes 在云原生領域的廣泛應用,「有效管理誰可以對 Kubernetes 集群執行何種操作變得至關重要」。本文將簡要介紹 Kubernetes的認證與授權體系以及RBAC授權原理。通過實際案例展示RBAC管理不當可能導致的安全風險,然后向大家分享RBAC安全研發與運維的最佳實踐,以及我們在字節跳動內部的安全防護和治理經驗。
背景知識
?
如果您對相關背景知識比較了解,可直接跳轉到“RBAC 安全風險剖析”、“RBAC 安全研發與運維最佳實踐” 章節閱讀。
?
本章節將對 Kubernetes 的認證和授權體系進行概述,了解這些機制的原理有助于理解不同場景下集群權限的安全風險。特別是那些能夠被輕易利用的未授權訪問漏洞,以及那些容易被忽視的權限提升與橫向移動攻擊風險。
Kubernetes 認證與授權體系
Kubernetes 的認證與授權體系主要用于滿足對關鍵服務 API(API Server、Kubelet Server)的訪問控制。在經過多年的發展后,Kubernetes 已經實現了一套比較完善的認證與授權機制,可以滿足用戶大多數場景的使用需求。
「API Server」
Kubernetes 是一個以容器技術為基礎,以聲明式 API Server 為核心的分布式容器編排系統。Kubernetes 幾乎所有的功能都通過 API Server 對外暴露。而 API Server 支持了多種認證機制,內置了多種授權模式和準入控制器,允許用戶根據需要靈活配置和使用。
簡單來說,當一個用戶訪問 Kubernetes 的 API Server 時,API Server 會使用啟用的認證器依次對請求進行身份認證,API Server 使用第一個成功認證的身份來標識請求者;然后再使用啟用的授權器依次對請求進行授權策略的檢查,當有任意一個授權器顯式地允許、拒絕一個請求時,則立刻返回當前授權結果(如果沒有授權器顯式地授權,那么請求也將被拒絕)。除此之外,在 API Server 真正處理請求前,它還會使用啟用的準入控制器對請求進一步變異和驗證。只有所有的準入控制器都驗證通過后,請求才會被真正處理。
?
注意:API Server 不保證認證器和準入控制器的執行順序,但會按照授權模式的配置順序進行鑒權。
?
「Kubelet Server」
Kubernetes 中還有一個非常重要的組件,那就是 Kubelet。它充當了分布式系統中的 Agent 角色,并使用節點專屬的用戶證書訪問 API Server,管理節點上的資源。但 Kubelet 自身也會作為服務端,對外提供服務。從而實現在容器內執行命令、獲取指標信息、容器日志、宿主機日志等功能。
Kubernetes 也為 Kubelet Server 提供了多種認證和授權模式。值得一提的是其中的 webhook 認證和 webhook 授權,它們本質上是向 API Server 發送 TokenReview 和 SubjectAccessReview 請求,對客戶端的身份進行認證與授權。
「小結」
Kubernetes 為 API Server 和 Kubelet Server 支持了多種認證機制、授權機制、準入控制器,以及靈活的自定義接口。這些機制雖然能夠滿足各種用戶需求,但也給用戶帶來了困擾。因為如果不了解這些機制的原理和負面影響,就很容易為集群引入安全風險和入侵檢測盲點。特別是那些能夠被輕易利用的未授權訪問漏洞,以及那些容易被忽視的提權與橫向移動攻擊風險。
請參見附錄和參考文獻,了解更多 API Server 和 Kubelet Server 的認證、授權、準入控制的技術細節。
Kubernetes RBAC 授權原理
RBAC 是 Kubernetes 默認啟用的授權機制,也是 Kubernetes 核心組件所使用的授權機制。用戶在使用集群時,往往需要使用 RBAC 授權機制來為其用戶賬號授權,以便部署、運維工作負載及所需的各種資源。各類云原生應用的 Operator、Controller 往往也需要利用 RBAC 授權機制來為其服務賬戶授權,以確保它們能夠訪問必要的資源,從而實現其功能。
下面的示意圖展示了用戶賬號和服務賬號訪問 API Server 時的認證、授權、準入控制過程。
在 Kubernetes 的 RBAC 授權體系中,引入了以下幾種概念:
「Subject」
- 在 Kubernetes 環境中有三類 Subject 可以被授予 RBAC 角色權限。
「Rule」
- 用于在
Role
,ClusterRole
內部定義具體權限,每一個 rule 都可以通過 apiGroups, resources, resourcesName, verbs, nonResourceURLs 來定義允許對什么資源(API 組,資源類型,資源名稱 )執行什么操作(動詞)。 - 注意:rule中的apiGroups, resources, resourcesNames, verbs, nonResourceURLs 支持使用通配符
「Role & ClusterRole」
Role
用來定義當前命名空間范圍內資源的角色,它通過Rules
顯式地定義權限。ClusterRole
用來定義集群范圍內資源的角色,它通過Rules
顯式地定義權限。
「Role & ClusterRoleBinding」
RoleBinding
將某個ClusterRole
或當前命名空間中的某個Role
綁定到 subjects,使 subjects 獲得當前命名空間中的ClusterRole
、Role
所定義的角色權限,例如可以在命名空間 A 中創建 RoleBinding,將命名空間 A 中的 Role 與命名空間 B 中的 ServiceAccount 綁定。那么命名空間 B 中的 ServiceAccount 將獲得命名空間 A 中的 Role 定義的權限。ClusterRoleBinding
將某個ClusterRole
綁定到 subjects,使 subjects 獲得ClusterRole
所定義的角色權限。
由以上可知,Role
和 ClusterRole
內的 rules
代表一系列顯式授予的權限,遵從 Deny-by-Default 安全模型。由于不支持 "deny" 規則,因而不支持顯式的排除某些權限。
這一特點使得某些應用場景無法利用 RBAC 授權機制實現:在授予所有已知、未知 CRD 資源操作權限的同時,顯式地排除某些敏感權限。但我們可以借助 ABAC、Webhook 授權模式,結合準入控制器來為此類場景的服務賬號進行權限管理,從而緩解這類問題。
下面是一個通過 RBAC 授權機制為 ServiceAccount 綁定權限的示例:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: example-clusterrole
namespace: example-ns
rules:
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- replicasets
- statefulsets
resourcesNames:
- test
verbs:
- '*'
- nonResourceURLs:
- /healthz
- /healthz/*
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: example-rolebinding
namespace: example-ns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: example-clusterrole
subjects:
- kind: ServiceAccount
name: example-sa
namespace: example-ns
RBAC 安全風險剖析
Kubernetes 是一個分布式的容器編排系統。除了要確保 Kubernetes 基礎組件的配置安全(例如 API Server、Kubelet Server 基本的認證授權配置等,對應 CIS Kubernetes Benchmark 中的第一至第四章中的要求)外,我們還需要對其 RBAC 授權配置進行精細化管理。
正確的授予主體 RBAC 權限能夠避免為集群引入不必要的穩定性 & 安全性風險,而不恰當的權限設置可能導致敏感數據泄露、資源濫用、權限提升,甚至威脅整個集群的安全。接下來我們將借助文獻和案例來進一步說明其安全風險。
概述
在 Kubernetes 中,可以通過對資源的操作來實現信息竊取、權限提升、橫向移動等攻擊。例如可以利用 pods/exec 資源的 create 權限通過 API Server 在指定容器內執行任意命令,也可以利用 nodes/proxy 資源的 create 權限直接訪問 Kubelet Server 在指定容器內執行任意命令,還可以利用 pods 的 create 權限創建具有安全風險的容器、利用 pods 的 patch 權限在指定 Pod 的容器內執行代碼......「隨著 Kubernetes 的廣泛使用,此類風險在云廠商、PaaS平臺、云原生應用、SaaS產品中愈演愈烈,輕則被用于后滲透入侵,重則會給產品引入安全漏洞。」
Palo Alto Networks 的安全研究員深入分析了 Kubernetes 中的所有敏感權限,并根據其危害類型將其分類和分級[2](嚴重等級請參考開源項目 rbac-police 的風險權限掃描策略集[3])。如下圖所示,在這些敏感權限中,有許多都可以被攻擊者用于信息泄漏、權限提升、橫向移動等攻擊,最終實現整個集群的接管。
Palo Alto Networks 的研究結果表明,在針對主流公有云、CNI 廠商的分析中,有將近 50% 的廠商存在容器逃逸后輕易導致集群淪陷的安全問題。另外有 25% 的廠商存在容器逃逸后在一定條件下導致集群淪陷的安全風險[2]。
公開案例
- RBAC Buster:來自 Aqua Sec 的研究者通過蜜罐首次捕獲到利用 Kubernetes 的 RBAC 配置漏洞進行攻擊的行為,黑客通過創建后門訪問集群,導致未授權訪問和數據泄露的風險。詳見 First-Ever Attack Leveraging Kubernetes RBAC to Backdoor Clusters[5]
- Sys:All:研究團隊 The Orca Research Pod 掃描了 250,000 個 GKE 集群(約總數的 2%),發現其中 1300 個集群存在錯誤配置的角色綁定,其中有 108 個集群允許攻擊者使用任何有效的谷歌帳號接管集群。詳見:How A Simple Loophole in Google Kubernetes Engine Puts Clusters at Risk of Compromise[6] & GCP-2024-003 security-bulletins[7]
- 在 OWASP Kubernetes Top 10 安全風險中,RBAC 配置錯誤導致的“權限過多”問題排名第三,可能引發未授權操作和權限提升。詳見 OWASP Kubernetes Top 10[8]
風險示例
下面的示例演示了攻擊者可以利用任意 secrets 的 create 權限,來獲取了包含敏感權限的 ServiceAccount(這里以竊取 prometheus-agent SA 的 token 為例)的 token。對此,我們建議使用專用命名空間中的 Role 來定義所需權限,從而與 kube-system 等敏感命名空間隔離。
下面的示例演示了攻擊者可以利用任意 secrets 的 get 權限,來爆破獲取保存 SA token 的 secrets。雖然爆破 SA token 需要較長時間(爆破一個擁有 5 個隨機字符串的 SA token 最多需要 27^5 次),但此權限也可能被用于竊取其他已知名稱的 secrets 資源。對此,我們建議使用 Role 定義角色,或者通過 resourceNames 對 secrets 的權限范圍進行約束,而非授予全部命名空間中任意 secrets 的 get 權限。
以上數據和案例表明,Kubernetes RBAC 權限管理已成為一個必須認真對待并及時采取有效防御措施的安全問題。
RBAC 安全研發與運維最佳實踐
基于我們在字節跳動內部的安全實踐,我們為 RBAC 授權配置總結了如下原則,以指引大家進行 Kubernetes RBAC 權限管理,從而降低由此為集群引入的安全風險。
遵循最小權限原則
在 RBAC 角色中分配權限時,請遵循最小權限原則授予執行任務所需的最低權限。例如:
- 優先使用 Role, RoleBinding 授予一個、多個特定命名空間中的權限。
- 定義 rule 時,使用明確的 apiGroups, resources, verbs 以及 resourceNames 來限定權限范圍。
?
注意:
如果設置了 resourceNames 字段,那么請求權限不能是 list、watch、create、deletecollection,否則請求將不會被允許(「當使用 resourceNames 限制 list、watch 權限范圍時,客戶端必須在請求參數中指定 fieldSelector=metadata.name%3D{RESOURCENAME} 用于通過授權」)。但當 resourceNames 字段中包含 "" 時,將允許 list 請求。
雖然 RBAC 授權模式不支持通過 resourceNames 來約束 create、deletecollection 權限,但仍然建議通過 resourceNames 來約束 update、patch、get 等權限。
?
RBAC 權限最小化不應被視作“非黑即白”,哪怕組件的某些敏感權限無法收斂,最小化權限仍然對降低風險、增加入侵檢測的機率有重要作用。
避免使用默認角色/用戶/用戶組
一般情況下,Kubernetes 和基于 Kubernetes 的 PaaS 平臺會自動將一些默認角色綁定到默認用戶和用戶組,以保證系統的正常運行。如需查看 Kubernetes 創建的默認角色和綁定的完整列表,請參閱 Default roles and role bindings。
- 常見的默認角色有:cluster-admin, system:node, system:controller:daemon-set-controller ...
- 常見的系統用戶有:system:anonymous, system:kube-controller-manager, system:kube-scheduler, system:kube-proxy, system:serviceaccounts:NAMESPACE:default ...
- 常見的系統用戶組:system:unauthenticated, system:authenticated, system:serviceaccounts, system:nodes, system:monitoring, system:masters ...
大部分默認角色(例如 cluster-admin, edit, system:node 等)都會被授予較廣泛的權限。因此,我們「不建議」將默認角色綁定到服務賬號,除非您知道并接受由此帶來的安全風險。用戶可以根據實際需要將其綁定到用戶賬號上。
除此之外,我們「應當避免」為系統用戶(例如 system:anonymous, system:serviceaccounts:NAMESPACE:default 等)、系統用戶組(例如 system:authenticated, system:serviceaccounts 等)綁定額外的角色,這會導致權限的非預期擴散,引入嚴重的安全風險。
避免為 default 服務賬號授予權限
在附錄 1 的“準入控制機制”一節中,我們提到了默認啟用的 ServiceAccount 準入控制器。創建 Pod 時如果未指定 ServiceAccount,那么 ServiceAccount 準入控制器會將命名空間內名為 default 的 ServiceAccount 分配給 Pod。
因此,我們「應當避免」為 default 服務賬號授予權限,這會導致非預期的權限泄露。
盡量避免使用通配符
*
字符是一個適用于所有內容的通配符,「應盡量避免」在規則中使用通配符。這容易造成授權范圍過大,除非您明確知曉并接受此行為可能引入的安全風險。建議您在 RBAC 規則中明確指定 API 組(apiGroups)、資源(resources)、動詞(verbs),甚至是資源名稱(resourceNames)。
例如,在 verbs
字段中指定 *
將授予 get
、list
、watch
、patch
、update
、deletecollection
和 delete
等權限。下表舉例說明了如何避免在規則中使用通配符。
盡量避免使用敏感權限
設計角色前,請先仔細評估存在權限提升、命令執行、信息泄漏等安全風險的權限。例如 secrets 的操作權限、證書簽發權限、pods/exec 訪問權限等,更多請參考 Kubernetes RBAC - privilege escalation risks[9] 和 風險權限掃描策略集[3]。
為應用服務、控制組件授予敏感權限會給整個集群引入安全風險。在系統設計和開發時,「應盡量避免」使用它們,并配合其他手段進行安全編排、安全加固和入侵檢測。
盡量使用單獨規則對特定資源授予權限
規劃規則時,建議您嘗試以下簡要步驟,在每個角色中采用更高效、可讀、易于維護的規則設計[4]:
- 為主體需要訪問的每項資源上的動詞草擬單獨的 RBAC 規則。
- 草擬規則后,分析規則,以檢查多條規則是否具有相同的
verbs
列表。將這些規則合并為一條規則。 - 請將其余的所有規則彼此分散。
這種方法可實現更有條理的規則設計,將對多個資源授予相同動詞的規則組合起來,將為資源授予不同動詞的規則彼此分散[4]。
例如,如果您的工作負載需要獲取 deployments
資源的權限,但需要 daemonsets
資源的 list
和 watch
權限,則您應該在創建角色是使用單獨規則。當您將 RBAC 角色綁定到工作負載時,該角色將無法對 deployments
資源進行 watch
操作[4]。
再舉一例,如果您的工作負載需要 pods
資源和 daemonsets
資源的 get
和 watch
權限,您可以將它們組合成一條規則,因為工作負載需要在這兩個資源上使用相同的動詞[4]。
在下表中,這兩種規則設計均有效,但拆分規則會根據需要更精細地限制資源訪問權限[4]。
安全編排與其它
有些場景下,業務需求可能與安全要求產生沖突。例如一些應用必需某些敏感權限才可以正常運行或提供必要功能。對此,我們建議您考慮采取以下安全編排、縱深防御策略來盡量降低風險。
?
注意:如果您的組件是 DaemonSet 類型且必需某些敏感權限,我們強烈建議您對其進行重構或緩解(例如通過webhook準入控制器進行校驗等)。否則當出現節點淪陷的事件時,整個集群都將遭受威脅。
?
「使用專用命名空間」
- 如果應用僅需命名空間范圍內的權限,那么我們「強烈建議」將其部署在專用命名空間中,而非 kube-system 命名空間、default 命名空間、業務負載所在的命名空間,從而避免不必要的權限擴散。
- 例如某控制組件的 SA 會被授予所在命名空間 secrets 的 list & watch 權限用于維護 ssl 密鑰對。我們可以將其部署在專用命名空間(而非 kube-system 命名空間、業務負載所在的命名空間)來降低 SA token 泄漏后的能夠帶來的安全風險。
- 如果應用需要所有全局范圍內的敏感權限,那么「不建議」將其部署在 default 命名空間、業務負載所在的命名空間,從而避免潛在的權限擴散。
「制定特殊調度策略」
- 如果某些組件需要全局范圍內的敏感權限,那么「建議」制定合適的調度策略(通過節點污點、準入控制策略等確保調度策略不會被繞過),將此類組件強制調度到專用節點池或使用彈性容器部署組件,從而實現將包含敏感權限的控制組件與業務負載分離。避免業務負載所在節點淪陷后,敏感權限 SA token 泄漏帶來的安全風險。
「單獨部署敏感組件」
- 您也可以將需要敏感權限的組件部署到獨立的控制面,從而解決此類安全風險。
「建設縱深防御」
- 在實際業務場景中,不是所有的敏感權限都能夠被消除。尤其是那些風險等級較高,但業務又強依賴的權限。因此,除權限最小化、安全編排外,我們強烈建議您引入主機、Kubernetes 層面的威脅管理與入侵檢測能力。從而及時發現并管理風險,告警并響應潛在的入侵行為。
RBAC 安全防護與治理實踐
在許多企業中,往往會因為安全意識不足、云原生安全建設開展較晚、使用開源云原生應用等原因,已經為系統引入了大量 RBAC 權限風險。但由于涉及基礎設施,并且缺乏相應的知識和手段,針對這類風險的防護和治理往往充滿挑戰。接下來筆者將向大家介紹我們在字節跳動內部的一些經驗和實踐,拋磚引玉供大家參考。
整體思路
通過公開案例和紅藍演練等方式,向研發團隊展示 K8s RBAC 錯誤配置對生產環境安全性和穩定性造成的危害。與 DevOps 團隊在風險認知上達成一致,從而自上而下對齊治理目標。在開展治理工作前,應根據企業的實際情況制定合理的計劃。同時,安全團隊應提供治理所需的知識庫、工具和系統,與 Ops 團隊構建合適的治理流程,以確保治理工作順利推進。此外,安全團隊還應持續加強反入侵能力建設,為 K8s RBAC 等安全風險提供兜底保障。
制定計劃
制定切實可行的計劃,以及提供必要的工具與系統,是收斂 K8s RBAC 安全風險的重要前提和保障。
「數據驅動」
- 我們建議以數據驅動的方式開展防護和治理工作。通過持續的安全掃描來識別風險、評估風險嚴重性、明確優先級。通過定位風險引入的原因,來定位責任人和卡點,從而對癥下藥。
?
需要指出的是,雖然“RBAC 安全風險剖析”一章已經指出 Kubernetes 中有大量權限存在安全風險,但面對各種場景和現實因素,我們很可能無法要求業務避免使用所有的敏感權限。這需要我們在安全防護與業務需求之間取得平衡。
?
「明確優先級」
- 我們結合 RBAC 風險權限的可利用性、嚴重等級,以及影響范圍等,將其劃分成五個優先級(風險權限及其安全掃描策略請參考 風險權限掃描策略集[3]),以此來推進 K8s RBAC 的權限評估和治理。在完成風險評估和治理前后,我們還需借助入侵檢測等機制來進行持續監控與兜底。
「增量管控 & 存量整改」
- 通過在企業的 PaaS 平臺、K8s 集群內集成準入控制機制,以此來實現增量管控。建議提供必要的白名單機制,為無法立刻整改的應用進行臨時豁免。然后根據定期掃描結果來推動責任人進行存量組件的整改、灰度測試、全量更新。
防護與治理框架
在字節內部,我們構建了如下圖所示的安全防護和治理框架,并推進了權限治理工作。
在開發與集成階段,我們借助最佳安全實踐來指導研發部門進行安全的 RBAC 權限設計和開發。并在部分 CI/CD 流水線中集成了安全掃描,對存在危險 RBAC 配置的 chart 產物進行攔截、告警和記錄。
在部署階段,我們通過與 PaaS 平臺集成的準入控制機制、K8s 準入控制器來對非法的應用和資源進行增量管控。并指導關鍵業務通過安全編排等手段來降低具有敏感權限的控制組件的安全風險。這里我們基于開源項目 Kyverno 的策略引擎,實現了 Policy as Code。從而在流水線安全掃描、準入控制中實現策略兼容,降低了安全策略的維護成本。
在運行階段,我們通過定期掃描(基于開源項目 rbac-police)來持續識別風險。此外,我們還設計實現了針對服務賬號和用戶賬號的行為建模能力。此能力基于賬戶行為來生成最小權限的角色定義,為組件的權限收斂提供參考。由于不是所有的敏感權限都能得到整改,因此,在實踐中我們會基于 K8s 的審計日志進行入侵檢測,從而發現潛在的攻擊行為。
通過以上機制,我們構建了針對 K8s RBAC 安全風險的防護和治理框架,為字節內部大規模生產集群的 RBAC 安全治理和防護提供了必要能力。
總結
RBAC 是 Kubernetes 中的一項重要的授權機制,正確地配置 RBAC 對于保障基于 Kubernetes 的系統安全至關重要。在設計中,我們應遵循最小權限原則進行權限設計,并理解敏感權限的安全風險,為其引入必要的防護能力。在開發中,我們要注意避免過度授權、權限混亂等問題。在安全防護和運營中,我們還要平衡安全要求和業務需求,持續收斂安全風險,建立縱深防御體系。
希望本文能讓大家更好地理解 Kubernetes 的權限體系,了解 RBAC 授權模式的安全風險和最佳安全實踐,從而指導系統的安全設計、開發和防護,最終構建更加安全可靠的系統。
參考文獻
- https://kubernetes.io/docs/reference/access-authn-authz
- https://www.paloaltonetworks.com/apps/pan/public/downloadResource?pagePath=/content/pan/en_US/resources/whitepapers/kubernetes-privilege-escalation-excessive-permissions-in-popular-platforms
- https://github.com/PaloAltoNetworks/rbac-police/tree/main/lib
- https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac
- https://www.aquasec.com/blog/leveraging-kubernetes-rbac-to-backdoor-clusters
- https://orca.security/resources/blog/sys-all-google-kubernetes-engine-risk
- https://cloud.google.com/kubernetes-engine/security-bulletins#gcp-2024-003
- https://owasp.org/www-project-kubernetes-top-ten
- https://kubernetes.io/docs/concepts/security/rbac-good-practices/#privilege-escalation-risks