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】。用戶可以像與其他 API 資源交互一樣,(通過 kubectl API 調用等方式)與這些資源交互。
Role 和 ClusterRole
在 RBAC API 中,一個角色包含一組相關權限的規則。權限是純粹累加的(不存在拒絕某操作的規則),即只能給權限累加,不存在給了XX權限,然后去掉XX01權限的情況。角色可以用 Role 來定義到某個命名空間(namespace)上, 或者用 ClusterRole 來定義到整個集群作用域(所有namespace)。
一個 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。
將 “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 引用的是 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 可用來在集群級別並對所有命名空間執行授權。
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” ;郵件風格的名字,比如“bob@example.com” ;或表示為字符串的數字用戶id。
注意:前綴 system:
是保留給Kubernetes系統使用的,因此應該確保不會出現名稱以system: 開頭的用戶或組。除了這個特殊的前綴,RBAC授權系統不要求用戶名使用任何格式。
ServiceAccounts具有前綴為system:serviceaccount:
的名稱,屬於具有前綴為system:serviceaccounts:的名稱的組。
RoleBinding的示例
下面的示例只是展示 RoleBinding 中 subjects 的部分。
用戶的名稱為 “alice@example.com” :
1 subjects: 2 - kind: User 3 name: "alice@example.com" 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 對象中枚舉出來的約束。
相關閱讀