1、基本概念
RBAC(Role-Based Access Control,基於角色的訪問控制)在k8s v1.5中引入,在v1.6版本時升級為Beta版本,並成為kubeadm安裝方式下的默認選項,相對於其他訪問控制方式,新的RBAC具有如下優勢:
- 對集群中的資源和非資源權限均有完整的覆蓋
整個RBAC完全由幾個API對象完成,同其他API對象一樣,可以用kubectl或API進行操作
可以在運行時進行調整,無需重啟API Server
要使用RBAC授權模式,需要在API Server的啟動參數中加上--authorization-mode=RBAC
2、RBAC原理和用法
2.1 RBAC的API資源對象說明
RBAC引入了4個新的頂級資源對象:Role、ClusterRole、RoleBinding、ClusterRoleBinding。同其他API資源對象一樣,用戶可以使用kubectl或者API調用等方式操作這些資源對象。
- 角色(Role)
一個角色就是一組權限的集合,這里的權限都是許可形式的,不存在拒絕的規則。在一個命名空間中,可以用角色來定義一個角色,如果是集群級別的,就需要使用ClusterRole了。
角色只能對命名空間內的資源進行授權,下面的例子中定義的角色具備讀取Pod的權限:
kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: pod-reader rules: - apiGroups: [""] # 空字符串表示核心API群 resource: ["pods"] verbs: ["get", "watch", "list"]
rules中的參數說明:
- apiGroup:支持的API組列表,例如:APIVersion: batch/v1、APIVersion: extensions:v1、apiVersion:apps/v1等
resources:支持的資源對象列表,例如:pods、deployments、jobs等
verbs:對資源對象的操作方法列表,例如:get、watch、list、delete、replace、patch等
- 集群角色(ClusterRole)
集群角色除了具有和角色一致的命名空間內資源的管理能力,因其集群級別的范圍,還可以用於以下特殊元素的授權。
- 集群范圍的資源,例如Node
非資源型的路徑,例如/healthz
包含全部命名空間的資源,例如pods
下面的集群角色可以讓用戶有權訪問任意一個或所有命名空間的secrets:
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata:
# name: secret-reader # ClusterRole不受限於命名空間,所以省略了namespace name的定義 rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"]
- 角色綁定(RoleBinding)和集群角色綁定(ClusterRoleBinding)
角色綁定或集群角色綁定用來把一個角色綁定到一個目標上,綁定目標可以是User、Group或者Service Account。使用RoleBinding為某個命名空間授權,ClusterRoleBinding為集群范圍內授權。
RoleBinding可以引用Role進行授權,下例中的RoleBinding將在default命名空間中把pod-reader角色授予用戶jane,可以讓jane用戶讀取default命名空間的Pod:
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: read-pods namespace: default subjects: - kind: User name: jane apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
RoleBinding也可以引用ClusterRole,對屬於同一命名空間內ClusterRole定義的資源主體進行授權。一種常見的做法是集群管理員為集群范圍預先定義好一組角色(ClusterRole),然后在多個命名空間中重復使用這些ClusterRole。
使用RoleBinding綁定集群角色secret-reader,使dave只能讀取development命名空間中的secret:
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: read-secrets namespace: development subjects: - kind: User name: dave apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
集群角色綁定中的角色只能是集群角色,用於進行集群級別或者對所有命名空間都生效的授權。
允許manager組的用戶讀取任意namespace中的secret
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: read-secrets-global subjects: - kind: Group name: manager apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
2.2 對資源的引用方式
多數資源可以用其名稱的字符串來表達,也就是Endpoint中的URL相對路徑,例如pods。然后,某些Kubernetes API包含下級資源,例如Pod的日志(logs)。Pod日志的Endpoint是GET /api/v1/namespaces/{namespaces}/pods/{name}/log。
Pod是一個命名空間內的資源,log就是一個下級資源。要在一個RBAC角色中體現,則需要用斜線/來分割資源和下級資源。若想授權讓某個主體同時能夠讀取Pod和Pod log,則可以配置resources為一個數組:
kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: pod-and-pod-logs-reader rules: - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list"]
資源還可以通過名字(ResourceName)進行引用。在指定ResourceName后,使用get、delete、update、patch動詞的請求,就會被限制在這個資源實例范圍內。例如下面的聲明讓一個主體只能對一個叫my-configmap的configmap進行get和update操作:
kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: configmap-updater rules: - apiGroups: [""] resources: ["configmap"] resourceNames: ["my-configmap"] verbs: ["update", "get"]
2.3 常見的角色(Role)示例
- 允許讀取核心API組中Pod的資源:
rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]
- 允許讀寫"extensions"和"apps"兩個API組中的deployment資源
rules: - apiGroups: ["extensions", "apps"] resources: ["deployments"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- 允許讀寫pods及讀寫jobs
rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] - apiGroups: ["batch", "extensions"] resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- 允許讀取一個名為my-config的ConfigMap(必須綁定到一個RoleBinding來限制到一個namespace下的ConfigMap):
rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-config"] verbs: ["get"]
- 讀取核心組的node資源(Node屬於集群級別的資源,必須放在ClusterRole中,並使用ClusterRoleBinding進行綁定):
rules: - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"]
- 允許對非資源端點/healthz及其所有子路徑進行GET/POST操作(必須使用ClusterRole和ClusterRoleBinding):
rules: - nonResourceURLs: ["/healthz", "/healthz/*"] verbs: ["get", "post"]
2.4 常用的角色綁定
- 用戶名Alice@example.com
subjects: - kind: User name: "Alice@example.com" apiGroup: rbac.authorization.k8s.io
- 組名frontend-admins
subjects: - kind: Group name: "frontend-admins" apiGroup: rbac.authorization.k8s.io
- kube-system命名空間中的默認Service Account
subjects: - kind: ServiceAccount name: default namespace: kube-system
- qa命名空間中的所有Service Account
subjects: - kind: Group name: system:serviceaccounts:qa apiGroup: rbac.authorization.k8s.io
- 所有Service Account
subjects: - kind: Group name: system:serviceaccounts apiGroup: rbac.authorization.k8s.io
- 所有認證用戶
subjects: - kind: Group name: system:authentication apiGroup: rbac.authorization.k8s.io
- 所有未認證用戶
subjects: - kind: Group name: system:unauthentication apiGroup: rbac.authorization.k8s.io
- 全部用戶
subjects: - kind: Group name: system:authentication apiGroup: rbac.authorization.k8s.io - kind: Group name: system:unauthentication apiGroup: rbac.authorization.k8s.io
2.5 默認的角色和角色綁定
API Server會創建一套默認的ClusterRole和ClusterRoleBinding對象,其中很多是以system:為前綴的,以表明這些資源屬於基礎架構,對這些對象的改動可能造成集群故障。
所有默認的ClusterRole和RoleBinding都會用標簽kubernetes.io/bootstrapping=rbac-defaults進行標記。
常見的系統角色如下:
有些默認角色不是以system:為前綴的,這部分角色是針對用戶的,其中包含超級用戶角色cluster-admin,有的用於集群一級的角色cluster-status,還有針對namespace的角色admin、edit、view
常見的用戶角色如下:
- 核心Master組件角色
2.6 授權注意事項:預防提權和授權初始化
RBAC API拒絕用戶利用編輯角色或者角色綁定的方式進行提權。這一限制是在API層面做出的,因此即使RBAC沒有啟用也仍然有效。
用戶只能在擁有一個角色的所有權限,且與該角色的生效范圍一致的前提下,才能對角色進行創建和更新。例如用戶user-1沒有列出集群中所有secret的權限,就不能創建具有這一權限的集群角色。要讓一個用戶能夠創建或更新角色,需要以下權限:
- 為其授予一個允許創建/更新Role或ClusterRole資源對象的角色;
為用戶授予角色,要覆蓋該用戶所能控制的所有權限范圍。用戶如果嘗試創建超出其自身權限的角色或者集群角色,則該API調用會被禁止。
如果一個用戶的權限包含了一個角色的所有權限,那么就可以為其創建和更新角色綁定;或者如果被授予了針對某個角色的綁定授權,則也有權完成此操作。
例如:user1沒有列出集群內所有secret的權限,就無法為一個具有這樣權限的角色創建集群角色綁定。要使用戶能夠創建、更新這一角色綁定,則需要有如下做法:
- 為其授予一個允許創建和更新角色綁定或者集群角色綁定的角色
為其授予綁定某一角色的權限,有隱式或顯式兩種方法
- 隱式:讓其具有所有該角色的權限
- 顯式:讓用戶授予針對該角色或集群角色綁定操作的權限
讓user-1有對user-1-namespace命名空間中的其他用戶授予admin、edit及view角色
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: role-grantor rules: - apiGroups: ["rbac.authorization.k8s.io"] resources: ["rolebindings"] verbs: ["create"] - apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles"] verbs: ["bind"] resourceNames: ["admin", "edit", "view"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: role-grantor-binding namespace: user-1-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: role-grantor subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: user-1
在進行第一個角色和角色綁定時,必須讓初始用戶具備其尚未被授予的權限,要進行初始的角色和角色綁定設置,有以下兩種方法:
- 使用屬於system:masters組的身份,這一群組默認具有cluster-admin這一超級角色的綁定。
如果API Server以--insecure-port參數運行,則客戶端通過這個非安全端口進行接口調用,這一端口沒有認證鑒權的限制。
贊助作者: