Kubernetes K8S之鑑權RBAC詳解
Kubernetes K8S之鑑權概述與RBAC詳解
K8S認證與授權
認證「Authentication」
認證有如下幾種方式:
1、HTTP Token認證:通過一個Token來識別合法使用者。
HTTP Token的認證是用一個很長的特殊編碼方式的並且難以被模仿的字串來表達客戶的一種方式。每一個Token對應一個使用者名稱,儲存在API Server能訪問的檔案中。當客戶端發起API呼叫請求時,需要在HTTP Header裡放入Token。
2、HTTP Base認證:通過使用者名稱+密碼的方式認證
使用者名稱:密碼 用base64演算法進行編碼後的字串放在HTTP Request中的Heather Authorization 域裡傳送給服務端,服務端收到後進行解碼,獲取使用者名稱和密碼。
3、最嚴格的HTTPS證書認證:基於CA根證書籤名的客戶端身份認證方式
授權「Authorization」
認證只是確認通訊的雙方都是可信的,可以相互通訊。而授權是確定請求方有哪些資源的許可權。API Server目前支援如下幾種授權策略(通過API Server的啟動引數--authorization-mode
設定)
- AlwaysDeny:表示拒絕所有請求。僅用於測試
- AlwaysAllow:表示允許所有請求。如果有叢集不需要授權流程,則可以採用該策略
- Node:節點授權是一種特殊用途的授權模式,專門授權由 kubelet 發出的 API 請求
- Webhook:是一種 HTTP 回撥模式,允許使用遠端 REST 端點管理授權
- ABAC:基於屬性的訪問控制,表示使用使用者配置的授權規則對使用者請求進行匹配和控制
- RBAC:基於角色的訪問控制,預設使用該規則
RBAC授權模式
RBAC(Role-Based Access Control)基於角色的訪問控制,在Kubernetes 1.5 中引入,現為預設標準。相對其他訪問控制方式,擁有如下優勢:
1、對叢集中的資源和非資源均擁有完整的覆蓋
2、整個RBAC完全由幾個API物件完成,同其他API物件一樣,可以用kubectl或API進行操作
3、可以在執行時進行操作,無需重啟API Server
RBAC API型別
RBAC API 所宣告的四種頂級型別【Role、ClusterRole、RoleBinding 和 ClusterRoleBinding
Role 和 ClusterRole
在 RBAC API 中,一個角色包含一組相關許可權的規則。許可權是純粹累加的(不存在拒絕某操作的規則),即只能給許可權累加,不存在給了XX許可權,然後去掉XX01許可權的情況。角色可以用 Role 來定義到某個名稱空間(namespace)上, 或者用 ClusterRole 來定義到整個叢集作用域(所有namespace)。
一個 Role 只可以用來對某一名稱空間中的資源賦予訪問許可權。
Role示例:定義到名稱為 “default” 的名稱空間,可以用來授予對該名稱空間中的 Pods 的讀取許可權:
1 apiVersion: rbac.authorization.k8s.io/v1 2 kind: Role 3 metadata: 4 name: pod-reader 5 namespace: default 6 rules: 7 - apiGroups: [""] # "" 指定核心 API 組 8 resources: ["pods"] 9 verbs: ["get", "watch", "list"]
ClusterRole 可以授予的許可權和 Role 相同,但是因為 ClusterRole 屬於叢集範圍,所以它也可以授予以下訪問許可權:
- 叢集範圍資源 (比如 nodes訪問)
- 非資源端點(比如 “/healthz” 訪問)
- 跨名稱空間訪問的有名稱空間作用域的資源(如 Pods),比如執行命令
kubectl get pods --all-namespaces
時需要此能力
可用來對某特定名稱空間下的 Secrets 的讀取操作授權,或者跨所有名稱空間執行授權(取決於它是如何繫結的):
1 apiVersion: rbac.authorization.k8s.io/v1 2 kind: ClusterRole 3 metadata: 4 name: secret-reader 5 # 此處的 "namespace" 被省略掉是因為 ClusterRoles 是沒有名稱空間的。 6 rules: 7 - apiGroups: [""] 8 resources: ["secrets"] 9 verbs: ["get", "watch", "list"]
RoleBinding 和 ClusterRoleBinding
角色繫結(RoleBinding)是將角色中定義的許可權賦予一個使用者或者一組使用者。 它包含若干主體【subjects】(users、groups或 service accounts)的列表和對這些主體所獲得的角色引用。
可以使用 RoleBinding 在指定的名稱空間中執行授權,或者在叢集範圍的名稱空間使用 ClusterRoleBinding 來執行授權。
一個 RoleBinding 可以引用同一的名稱空間中的 Role。
RoleBinding示例將 “pod-reader” 角色授予在 “default” 名稱空間中的使用者 “jane”; 這樣,使用者 “jane” 就具有了讀取 “default” 名稱空間中 pods 的許可權。
在下面的例子中,角色繫結使用 roleRef 將使用者 “jane”繫結到前文建立的角色 Role,其名稱是 pod-reader。
1 apiVersion: rbac.authorization.k8s.io/v1 2 # 此角色繫結,使得使用者 "jane" 能夠讀取 "default" 名稱空間中的 Pods 3 kind: RoleBinding 4 metadata: 5 name: read-pods 6 namespace: default 7 subjects: 8 - kind: User 9 name: jane # 名稱大小寫敏感 10 apiGroup: rbac.authorization.k8s.io 11 roleRef: 12 kind: Role #this must be Role or ClusterRole 13 name: pod-reader # 這裡的名稱必須與你想要繫結的 Role 或 ClusterRole 名稱一致 14 apiGroup: rbac.authorization.k8s.io
roleRef 裡的內容決定了實際建立繫結的方法。kind 可以是 Role 或 ClusterRole,name 是你要引用的 Role 或 ClusterRole 的名稱。
RoleBinding 也可以引用 ClusterRole,這可以允許管理者在 整個叢集中定義一組通用的角色,然後在多個名稱空間中重用它們。
RoleBinding示例2下面的例子,RoleBinding 引用的是 ClusterRole, “dave” (subjects區分大小寫)將只可以讀取在”development” 名稱空間( RoleBinding 的名稱空間)中的”secrets” 。
1 apiVersion: rbac.authorization.k8s.io/v1 2 # 這個角色繫結允許 "dave" 使用者在 "development" 名稱空間中有讀取 secrets 的許可權。 3 kind: RoleBinding 4 metadata: 5 name: read-secrets 6 namespace: development # 這裡只授予 "development" 名稱空間的許可權。 7 subjects: 8 - kind: User 9 name: dave # 名稱區分大小寫 10 apiGroup: rbac.authorization.k8s.io 11 roleRef: 12 kind: ClusterRole 13 name: secret-reader 14 apiGroup: rbac.authorization.k8s.io
最後,ClusterRoleBinding 可用來在叢集級別並對所有名稱空間執行授權。
ClusterRoleBinding示例1 apiVersion: rbac.authorization.k8s.io/v1 2 # 這個叢集角色繫結允許 "manager" 組中的任何使用者讀取任意名稱空間中 "secrets"。 3 kind: ClusterRoleBinding 4 metadata: 5 name: read-secrets-global 6 subjects: 7 - kind: Group 8 name: manager # 名稱區分大小寫 9 apiGroup: rbac.authorization.k8s.io 10 roleRef: 11 kind: ClusterRole 12 name: secret-reader 13 apiGroup: rbac.authorization.k8s.io
當我們建立binding後,則不能修改binding所引用的Role或ClusterRole。嘗試修改會導致驗證錯誤;如果要改變binding的roleRef,那麼應該刪除該binding物件並且建立一個新的用來替換原來的。
Referring to resources【資源引用】
Kubernetes叢集內一些資源一般以其名稱字串來表示,這些字串一般會在API的URL地址中出現;同時某些資源也會包含子資源,例如pod的logs資源就屬於pods的子資源,API中URL樣例如下:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
在這種情況下,”pods” 是有名稱空間的資源,而 “log” 是 pods 的子資源。在 RBAC 角色中,使用”/“分隔資源和子資源。
允許一個主體(subject)要同時讀取 pods 和 pod logs,你可以這麼寫:
1 apiVersion: rbac.authorization.k8s.io/v1 2 kind: Role 3 metadata: 4 namespace: default 5 name: pod-and-pod-logs-reader 6 rules: 7 - apiGroups: [""] 8 resources: ["pods", "pods/log"] 9 verbs: ["get", "list"]
對於某些請求,也可以通過 resourceNames 列表按名稱引用資源。
例如:在指定時,可以將請求型別限制到資源的單個例項。限制只可以 “get” 和 “update” 到單個configmap,則可以這麼寫:
1 apiVersion: rbac.authorization.k8s.io/v1 2 kind: Role 3 metadata: 4 namespace: default 5 name: configmap-updater 6 rules: 7 - apiGroups: [""] 8 resources: ["configmaps"] 9 resourceNames: ["my-configmap"] 10 verbs: ["update", "get"]
需要注意的是,create 請求不能被 resourceName 限制,因為在鑑權時還不知道物件名稱。 另一個例外是 deletecollection。
Referring to subjects【主體引用】
RoleBinding或ClusterRoleBinding繫結一個role到主體(subjects)。主體(subjects)可以是groups,users或ServiceAccounts。
Kubernetes將使用者名錶示為字串。這些可以是:普通名稱,比如“alice” ;郵件風格的名字,比如“[email protected]” ;或表示為字串的數字使用者id。
注意:字首system:
是保留給Kubernetes系統使用的,因此應該確保不會出現名稱以system: 開頭的使用者或組。除了這個特殊的字首,RBAC授權系統不要求使用者名稱使用任何格式。
ServiceAccounts具有字首為system:serviceaccount:
的名稱,屬於具有字首為system:serviceaccounts:的名稱的組。
RoleBinding的示例
下面的示例只是展示 RoleBinding 中 subjects 的部分。
使用者的名稱為 “[email protected]” :
1 subjects: 2 - kind: User 3 name: "[email protected]" 4 apiGroup: rbac.authorization.k8s.io
組的名稱為 “frontend-admins” :
1 subjects: 2 - kind: Group 3 name: "frontend-admins" 4 apiGroup: rbac.authorization.k8s.io
預設service account在 kube-system 名稱空間中:
1 subjects: 2 - kind: ServiceAccount 3 name: default 4 namespace: kube-system
在名稱為 “qa” 名稱空間中所有的服務賬號:
1 subjects: 2 - kind: Group 3 name: system:serviceaccounts:qa 4 apiGroup: rbac.authorization.k8s.io
在任意名稱空間的所有service accounts:
1 subjects: 2 - kind: Group 3 name: system:serviceaccounts 4 apiGroup: rbac.authorization.k8s.io
所有認證過的使用者(版本 1.5+):
1 subjects: 2 - kind: Group 3 name: system:authenticated 4 apiGroup: rbac.authorization.k8s.io
所有未認證的使用者(版本 1.5+):
1 subjects: 2 - kind: Group 3 name: system:unauthenticated 4 apiGroup: rbac.authorization.k8s.io
所有使用者 (版本 1.5+):
1 subjects: 2 - kind: Group 3 name: system:authenticated 4 apiGroup: rbac.authorization.k8s.io 5 - kind: Group 6 name: system:unauthenticated 7 apiGroup: rbac.authorization.k8s.io
准入控制
准入控制是API Server的外掛集合,通過新增不同的外掛,實現額外的准入控制規則。甚至於API Server的一些主要的功能都需要通過Admission Controllers實現,比如:ServiceAccount。
檢視哪些外掛是預設啟用的:
kube-apiserver -h | grep enable-admission-plugins
在 1.17 中,它們是:
1 NamespaceLifecycle, LimitRanger, ServiceAccount, 2 TaintNodesByCondition, Priority, DefaultTolerationSeconds, 3 DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, 4 MutatingAdmissionWebhook, ValidatingAdmissionWebhook, RuntimeClass, ResourceQuota部分外掛功能:
NamespaceLifecycle
該准入控制器禁止在一個正在被終止的 Namespace 中建立新物件,並確保使用不存在的 Namespace 的請求被拒絕。該准入控制器還會禁止刪除三個系統保留的名稱空間,即 default、kube-system 和 kube-public。
刪除 Namespace 會觸發刪除該名稱空間中所有物件(pod、services 等)的一系列操作。為了確保這個過程的完整性,我們強烈建議啟用這個准入控制器。
LimitRanger
該准入控制器會觀察傳入的請求,並確保它不會違反 Namespace 中 LimitRange 物件列舉的任何約束。
ServiceAccount
該准入控制器實現了 serviceAccounts 的自動化。 如果打算使用 Kubernetes 的 ServiceAccount 物件,強烈建議您使用這個准入控制器。
ResourceQuota
該准入控制器會監測傳入的請求,並確保它不違反任何一個 Namespace 中的 ResourceQuota 物件中枚舉出來的約束。