您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何解析K8s安全中的訪問控制,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
導讀:訪問控制是云原生安全的一個重要組成部分,也是 K8s 集群在多租環境下必要且基本的安全加固手段。在 K8s 體系中,訪問控制又分為三個重要的組成部分,請求認證,鑒權和運行時刻的 admission 準入控制。在本文中,作者將帶領大家了解這 3 部分的基本定義和使用方法,并給出多租環境下安全加固的相關最佳實踐。
大家都知道訪問控制是云原生安全中的一個重要組成部分。也是一個 Kubernetes 集群在多租戶環境下必須要采取的一個基本的安全防護手段。
那么在概念上可以抽象的定義為誰在何種條件下可以對什么資源做什么操作。這里的資源就是在 Kubernetes 中我們熟知的:Pod、 ConfigMaps、Deployment、Secrets 等等這樣的資源模型。
由上圖來介紹一下 Kubernetes API 的請求從發起到其持久化入庫的一個流程。
首先看一下請求的發起,請求的發起分為兩個部分:
第一個部分是人機交互的過程。 是大家非常熟悉的用 kubectl 對 apiserver 的一個請求過程;
第二個部分是 Pod 中的業務邏輯與 apiserver 之間的交互。
當我們的 apiserver 收到請求后,就會開啟訪問控制流程。這里面分為三個步驟:
Authentication 認證階段:判斷請求用戶是否為能夠訪問集群的合法用戶。如果用戶是個非法用戶,那 apiserver 會返回一個 401 的狀態碼,并終止該請求;
如果用戶合法的話,我們的 apiserver 會進入到訪問控制的第二階段 Authorization:鑒權階段。在該階段中 apiserver 會判斷用戶是否有權限進行請求中的操作。如果無權進行操作,apiserver 會返回 403 的狀態碼,并同樣終止該請求;
如果用戶有權進行該操作的話,訪問控制會進入到第三個階段:AdmissionControl。在該階段中 apiserver 的 admission controller 會判斷請求是否是一個安全合規的請求。如果最終驗證通過的話,訪問控制流程才會結束。
此時我們的請求將會轉換為一個 Kubernetes objects 相應的變更請求,最終持久化到 ETCD 中。
對于認證來說,首先我們要確定請求的發起方是誰。并最終通過認證過程將其轉換為一個系統可識別的用戶模型用于后期的鑒權,那么先來看一下 Kubernetes 中的用戶模型。
什么是用戶管理能力呢?我們無法像操作 Pod 一樣,通過 API 的方式創建刪除一個用戶實例。同時我們也無法在 ETCD 中找到用戶對應的存儲對象。
在 Kubernetes 的訪問控制流程中用戶模型是如何產生的呢?答案就在請求方的訪問控制憑證中,也就是我們平時使用的 kube-config 中的證書,或者是 Pod 中引入的 ServerAccount。經過 Kubernetes 認證流程之后,apiserver 會將請求中憑證中的用戶身份轉化為對應的 User 和 Groups 這樣的用戶模型。在隨后的鑒權操作和審計操作流程中,apiserver 都會使用到改用戶模型實例。
Basic 認證
該認證方式下,管理員會將 Username 和 Password 組成的白名單放置在 apiserver 讀取的靜態配置文件上面進行認證,該方式一般用于測試場景,在安全方面是不推薦且不可拓展的一種方式。
X509 證書認證
該方式是 apiserver 中相對應用較多的使用方式,首先訪問者會使用由集群 CA 簽發的,或是添加在 apiserver Client CA 中授信 CA 簽發的客戶端證書去訪問 apiserver。apiserver 服務端在接收到請求后,會進行 TLS 的握手流程。除了驗證證書的合法性,apiserver 還會校驗客戶端證書的請求源地址等信息。開啟雙向認證,X509 認證是一個比較安全的方式,也是 Kubernetes 組件之間默認使用的認證方式,同時也是 kubectl 客戶端對應的 kube-config 中經常使用到的訪問憑證。
Bearer Tokens(JSON Web Tokens)
Service Account
OpenID Connect
Webhooks
該方式的 Tokens 是通用的 JWT 的形式,其中包含了簽發者、用戶的身份、過期時間等多種元信息。它的認證方式也是常見的私鑰加簽,公鑰驗簽的一個基本流程。基于 Token 的認證使用場景也很廣泛,比如 Kubernetes Pod 應用中經常使用到的 Service Account,其中就會自動綁定一個簽名后的 JWT Token 用于請求 apiserver。
另外 apiserver 還支持基于 OpenID 協議的 Token 認證,可以通過對 apiserver 的配置連接一個指定的外部 IDP,同時可以通過 Keycloak,Dex 這樣的開源服務來管理 IDP,請求者可以按照自己熟悉的方式在原身份認證服務上進行登錄認證,并最終返回一個相應的 JWT token,為了后面的 apiserver 的鑒權流程。
除此之外,還可以使用 Webhooks 的方式,將請求的 Token 發送到指定外部服務進行 Token 的驗簽。
對于一個集群證書體系來說,認證機構 (CA) 是一個非常重要的證書對。它會被默認放置在集群 Master 節點上的 /etc/Kubernetes/pki/ 目錄下。集群中所有組件之間的通訊用到的證書,其實都是由集群根 CA 來簽發的。在證書中有兩個身份憑證相關的重要字段:一個是 CN,一個是 O。
另外可以通過 openssl 命令來進行證書的解析。上圖右側可以看到,通過 Subject 中的 O 和 CN 字段可以查看對應的信息。
上面每一個組件證書都有自己指定的 Common Name 和 Organization 用于特定角色的綁定。這樣的設置可以使各系統組件只綁定自身功能范圍內的角色權限。從而保證了每個系統組件自身權限的最小化。
Kubernetes 集群本身就提供了證書簽發的 API,而在集群的創建過程中,像 kubeadm 這樣的集群安裝工具,會基于不同的 CSR 簽發請求調用 apiserver 對應接口。此時 apiserver 會根據請求,以這種 csr 資源模型的形式創建對應的簽發請求實例。剛開始創建的簽發實例都會處于 pending 的狀態,直到有權限的管理員進行審批后,這個 csr 才會處于 approved 的狀態,請求對應的證書就會被簽發。
通過上圖右側中的命令可以來查看相應的證書內容信息。
首先開發人員需用通過 openssl 等證書工具生成私鑰,然后創建對應的 x509 csr 請求文件,需要在 subj 字段中指定用戶 user 和組 group,最后通過 API 創建 K8s csr 實例并等待管理員審批。
對于集群管理員,他可以直接讀取集群根 CA,并通過 x509 的 csr 請求文件簽發證書,所以它無需定義或審批 csr 實例。上圖中最后一行是一個 openssl 簽發示例,命令中需要指明 csr 和 ca.crt 的文件路徑,以及簽發證書的過期時間信息。
另外各個云廠商也會基于登錄用戶和目標集群一鍵化生成對應的集群訪問憑證,方便用戶的使用。
除了證書認證之外,Service Account 也是 apiserver 中應用比較廣泛的一種方式。對于 Service Account 來說,它是 K8s 中唯一能夠通過 API 方式管理的 APIService 訪問憑證,其他特性在上圖中可以看到。
圖中也給出了一些使用 kubectl 進行 Service Account API 相關增刪改查的示例,同時我們可以為已經存在的 serviceaccount 手動創建其 token 對應的 secret,有興趣的同學可以在 Kubernetes 集群中操作執行一下。
接著看一下 Service Account 的使用。
首先可以通過 get secret –oyaml 命令查看 serviceaccount 對應的指定 secret,其中 token 字段即為經過了 base64 編碼的 JWT 格式的認證 token。
在部署一個應用時,我們可以通過 template -> spec -> containers 中的 serviceAccountName 字段聲明需要使用的 Service Account 名稱。注意如果是在 Pod 創建過程中,發現制定的 ServiceAccount 不存在,則該 Pod 創建過程會被終止。
在生成的 pod 模板中可以看到指定 serviceaccount 對應的 secret 中的 ca,namespace 和認證 token 會以文件的形式掛載到容器中的指定目錄下。另外對于已經創建的 Pod,我們不能更新其已經掛載的 ServiceAccount 內容。
kubeconfig 是用戶本地連接 Kubernetes 集群使用的重要訪問憑證,接著來介紹一下 kubeconfig 的配置和使用。
當一個請求在完成 apiserver 認證后,可以認為它是一個合法的用戶,那么如何控制該用戶在集群中的哪些 namespace 中訪問哪些資源,對這些資源又能進行哪些操作呢?
這就由訪問控制的第二步 Kubernetes 鑒權來完成。apiserver 本身支持多種鑒權方式,在本節內容中,我們主要介紹在安全上推薦的鑒權方式 RBAC。
第一要素是 Subjects,也就是主體。可以是開發人員、集群管理員這樣的自然人,也可以是系統組件進程,或者是 Pod 中的邏輯進程;
第二個要素是 API Resource,也就是請求對應的訪問目標。在 Kubernetes 集群中也就是各類資源;
第三要素是 Verbs,對應為請求對象資源可以進行哪些操作,包括增刪改查、list、get、watch 等。
這里舉個例子,假設有個通過合法認證的用戶 Bob,他請求 list 某個 namespace下的 Pods,改請求的鑒權語義記為:Can Bob list pods ?其中 Bob 即為請求中的 Subject,list 為對應的請求動作 Action,而 pods 為對應的請求資源 Resource。
上面介紹了 RBAC 角色模型的三要素,在整個 RBAC 策略定義下,還需要將這個角色綁定到一個具體的控制域內。這就是 Kubernetes 大家熟悉的命名空間。通過 namespace 可以將 Kubernetes api 資源限定在不同的作用域內。從而幫助我們在一個多租戶集群中,對用戶進行邏輯上的隔離。
上面的事例可以改為 User A can create pods in namespace B。這里需要注意的是,如果不進行任何的權限綁定,RBAC 會拒絕所有訪問。
通常 RBAC 會進行對 apiserver 的細粒度訪問控制,但是這個細粒度是個相對的概念,RBAC 是面向模型級別的綁定。它不能綁定到 namespace 中的一個具體的 object 實例,更不能綁定到指定資源的任意一個 field。
RBAC 對訪問權限的控制粒度上,它可以細化到 Kubernetes api 的 subresources 級別。比如針對一個訪問者,我們可以控制其在指定 namespace 下對 nodes/status 模型的訪問。
接著介紹 RBAC 具體的綁定權限和對象。
首先是角色 Role,它定義了用戶在指定的 Kubernetes 命名空間資源上可以進行哪些操作。比如可以定一個 namespace 中 pod 的只讀權限,同時還可以定義一個 namespace 管理員權限,它具有對這個命名空間下所有對象資源的所有操作權限。
如上圖所示,是一個 Role 的定義模板編排文件,其中 resource 字段定義了這個角色可以訪問哪些資源,verbs 字段定義了這個角色有哪些操作的權限。在 apiGroups 中,需要指定目標資源的 apiGroups 名稱,這里可以通過官方 API 文檔查詢,如果指定的 Group 是 core,那么在角色模板中的 apiGroups 可置為空。
當我們完成了一個 namespace 下的角色定義之后,還需要建立其與使用這個角色的主體之間在 namespace 下的綁定關系,這里需要一個 RoleBinding 模型。使用 RoleBinding 可以將 Role 對應的權限模型綁定到對應的 Subject 上。
比如這里可以將名為 test 的 namespace 中的 pod 只讀權限同時綁定給用戶 test1 和 test2 以及 proc1。也可以將 namespace test 只讀權限綁定 tech-lead group 中的 test1 用戶,這樣用戶 test2 和 proc1 是沒有 get namespace 權限的。
接著看一下對應的 RoleBinding 編排文件模板。
其中 roleRef 字段中聲明了我們需要綁定的角色,一個綁定只能指定唯一的 Role。在 subject 字段中定義了我們要綁定的對象,這里可以是 User,Group 或者是 Service Account。它同時支持綁定多個對象。
除了定義指定 namespace 中的權限模型,也可以通過 ClusterRole 定義一個集群維度的權限模型。在一個 Cluster 實例中,可以定義集群維度的權限使用權限,比如像 PV、Nodes 在 namespace 中不可見的資源權限,可以在 ClusterRole 中定義,而操作這些資源的動作同樣是之前 Role 中支持的增刪改查和 list、watch 等操作。
下圖為 ClusterRole 編排文件模板:
ClusterRole 編排文件幾乎和 Role 是一模一樣的,唯一不同的地方是 ClusterRole 中是所有集群維度的權限定義,不支持 namespace 的定義。
同樣在 ClusterRole 的基礎上,可以將其綁定在對應的 Subject 主體上。而 ClusterRoleBinding 模型實例可以幫助我們在集群所有命名空間上將 ClusterRole 綁定到具體的 Subject 對象上。
比如這里可以將所有 namespace 的 list 權限綁定給 group 為 sre 或者 devops 的管理員 admin1 和 admin2。
相比較于 RoleBinding,ClusterRoleBinding 模板定義也只是在 namespace 和 roleRef 中的權限對象模型定義上有不同,其他的定義格式是一樣的。
通過上文的學習,我們知道在不進行任何權限的綁定下,RABC 會拒絕所有的訪問。那么我們的系統組件之間是如何互相請求呢?
其實在集群創建的時候,處理系統各組件的客戶端證書,它們各自的角色和環境對象也會被創建出來,以滿足組件業務之間交互必須的權限要求。
下面看幾個預置的集群角色:
通過以上對 RBAC 的學習,大家應該對 Kubernetes 中 RBAC 中的模型定義有了一定的了解,但是在某些復雜的多租戶業務場景下,如何在權限模板中針對各個 API 模型定義相應的動作策略,還是需要一定的理論和實踐基礎的。而對一個應用開發人員來說,kubectl 可能更為直觀和熟悉些,這里也給出了一些 kubectl 操作和 RBAC 中的對應關系。
比如當我們希望 edit 一個 deploy 的時候,需要在相應的角色模板中增加對 Deployment 資源的 get、patch 這樣的權限。如果希望 exec 到一個 pod 中,需要在相應的角色模板中增加對 pod 的 get 權限,以及針對 pod/exec 模型的 create 權限。
通過 docker hub 上的統計結果可以看到,主流的業務鏡像有 82.4% 是以 root 用戶來啟動的。通過這個調查可以看到對 Security Context 的相關使用是不容樂觀的。
經過對上面的分析結果可以看出來,如果我們能夠對業務容器配置足夠安全的運行時刻參數,其實攻擊者很難有可乘之機。那么我們究竟應該在部署 Kubernetes 集群中的業務容器做哪些 runtime 運行時刻的安全加固呢?
首先還是要遵循權限最小化原則,除了業務運行所必需的系統權限,其他權限都是可以去除的;
此外還可以通過在 pod 或者 container 維度設置 Security Context 參數,進行業務容器運行時刻的安全配置;
另外就是可以通過開啟 Pod Security Policy,在 apiserver 請求的 Admission 階段強制校驗容器的安全配置;
除了 PSP 的開啟之外,如上圖還列舉了常見的,使用比較多的配置參數。
由于 PSP 策略相對復雜一些,這里介紹一下使用注意事項。
首先可以通過 API 直接操作 PSP 的安全策略實例,如上圖左側是 PSP 策略支持的配置參數,包括特權容器,系統capabilities,運行時刻用戶 id 和文件系統權限等多種配置。大家也可以在官方文檔找到各個參數的詳細說明。
而 PSP 的作用正是在業務容器運行前,基于這個策略校驗安全參數配置,如果不滿足該安全策略,則禁止該 Pod 運行。
最后在 PSP 的使用上,我們需要注意幾點,如上圖右側所示。
最后在對多租環境下,如何利用 Kubernetes 下原生的安全能力做安全加固做一個最佳實踐的小結。
看完上述內容,你們對如何解析K8s安全中的訪問控制有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。