引言:
https://kubernetes.io/docs/reference/access-authn-authz/rbac/
https://kubernetes.io/docs/reference/access-authn-authz/rbac/
Role-based access control (RBAC) :
基於角色的權限控制,在k8s為了實現這種機制,是利用四種object:Role, ClusterRole, RoleBinding and ClusterRoleBinding來達成權限控制的
整體的核心思想是k8s的rbac是白名單機制,想讓他具備什么權限,就先創建某個角色Role然后定制rules,再將某個用戶user與該role進行綁定bind得到這種綁定關系為RoleBind
一,相關的API Object
1.Role and ClusterRole
一個role或者cluster role這樣的object,包含了若干的rules,這些rules代表是一組的permissions(准入,權限),這些准入是疊加起作用的,並且不存在deny規則,即都是"允許干xxx",而不是"不允許干xxx"....
1)role: 他屬於某個特定的namespace,所以你創建的時候就該指定你創建的role屬於哪個namespace。
2)clusterRole
定義: 是一個集群范圍的概念,也就是說他並不屬於某個特定的namespce,他有很多用法,例如:
define permissions on namespaced resources and be granted within individual namespace(s)
define permissions on namespaced resources and be granted across all namespaces
define permissions on cluster-scoped resources
定義: 是一個集群范圍的概念,也就是說他並不屬於某個特定的namespce,他有很多用法,例如:
define permissions on namespaced resources and be granted within individual namespace(s)
define permissions on namespaced resources and be granted across all namespaces
define permissions on cluster-scoped resources
wxy: 雖然clusterRole是沒有namespace概念的,但是他在賦予的時候,是可以具體到某個單獨的ns,當然也可以是所有ns,具體用法見后面
使用: clusterRole也可以像Role一樣使用,畢竟他是集群級別的,所以可以在如下的場景下進行權限的賦予:
cluster-scoped resources (like nodes)
non-resource endpoints (like /healthz)
namespaced resources (like Pods), across all namespaces For example: kubectl get pods --all-namespaces.
cluster-scoped resources (like nodes)
non-resource endpoints (like /healthz)
namespaced resources (like Pods), across all namespaces For example: kubectl get pods --all-namespaces.
注: 是不可以定義ClusterRole為哪個namespace的,即不可以namespaced。 wxy: 使用時可以....
總結起來就是,想要頂一個額在namespace內使用的角色,用Role類型object,想要一個集群范圍內的role則ClusterRole,
另外,a ClusterRole that can be used to grant read access to SOME OBJECT in any particular namespace, or across all namespaces (depending on how it is bound),所以接下來看看綁定相關的object。
k8s的api舉例:
例1:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
...
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
例1:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
...
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
例2:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
...
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
...
注意:
# kubectl get Role -nkube-system
和
# kubectl get ClusterRole
解析:
ClusterRole是集群范圍的object,所以不需要指定ns直接查看,Role是特定某個ns下的object,所以需要指定查看的是哪個ns
# kubectl get Role -nkube-system
和
# kubectl get ClusterRole
解析:
ClusterRole是集群范圍的object,所以不需要指定ns直接查看,Role是特定某個ns下的object,所以需要指定查看的是哪個ns
2.RoleBinding and ClusterRoleBinding
所謂role bingding,就是指將role中定義的權限賦予某個用戶,或者一組用戶。這里面涉及多種概念包括users, groups, or service accounts, 以及所賦予的role的引用。RoleBinding授予特定命名空間中的權限,而ClusterRoleBinding授予在群集范圍內訪問的權限。
RoleBinding可以引用同一名稱空間中的任何Role。或者,RoleBinding也可以引用ClusterRole並將該ClusterRole綁定到RoleBinding所屬的名稱空間。如果要將ClusterRole綁定到群集中的所有名稱空間,請使用ClusterRoleBinding
另外,根據官網的信息,以及實際操作發現,如果創建ClusterRoleBinding時指定namespace, 雖然不會報錯但也不會生效
wxy: 這個和如果為服務賬號創建綁定時指定的namespace不是一回事。
另外,根據官網的信息,以及實際操作發現,如果創建ClusterRoleBinding時指定namespace, 雖然不會報錯但也不會生效
wxy: 這個和如果為服務賬號創建綁定時指定的namespace不是一回事。
wxy:role只是規則,規則是給人用的,這里的人可以是用戶,組,或服務賬戶,賦予user某種role,該user就具備了哪些權限,所以xxBinding的作用就是“賦予”這種行為,確切的說是給自己旗下的user挑選一個role,即指定一個role引用。
注意:()roleBind操作是站在用戶的角度,去選擇role,引用的這個role可以是本namespace下的,也可以是 整個集群的,一旦是集群下的role,那么就相當於給這個role縮小了范圍,和namespace范圍的rule沒什么區別了。如果是想讓這個集群級用戶能具備某種集群級權限,則就必須要使用ClusterRoleBinding的引用。
所以,可以在整個集群中定義一組通用角色,然后在多個名稱空間中重用它們。
注意:()roleBind操作是站在用戶的角度,去選擇role,引用的這個role可以是本namespace下的,也可以是 整個集群的,一旦是集群下的role,那么就相當於給這個role縮小了范圍,和namespace范圍的rule沒什么區別了。如果是想讓這個集群級用戶能具備某種集群級權限,則就必須要使用ClusterRoleBinding的引用。
所以,可以在整個集群中定義一組通用角色,然后在多個名稱空間中重用它們。
舉例說明
例1:RoleBinding的用法1:針對某個namespace進行Role級別權限的賦予
僅賦予jane操作default命名空間的資源,至於具體能操作哪些,要看pod-reader這個規則的具體定義
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" specifies the binding to a Role / ClusterRole
kind: Role #this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io
例2: RoleBinding的用法2: 針對某個namespace進行ClusterRole級別權限的賦予
僅賦予dave操作development命名空間的資源,至於具體能操作哪些,要看secret-reader這個規則的具體定義
wxy: ClusterRole和Role雖然在這里的用法沒有什么區別,但是顯而易見,secret-reader是集群級別的,所以可以復用到多個ns下
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace. You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
name: read-secrets
# The namespace of the RoleBinding determines where the permissions are granted.This only grants permissions within the "development" namespace.
namespace: development
subjects:
- kind: User ---也可以是Group,表示賦予誰...
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
僅賦予dave操作development命名空間的資源,至於具體能操作哪些,要看secret-reader這個規則的具體定義
wxy: ClusterRole和Role雖然在這里的用法沒有什么區別,但是顯而易見,secret-reader是集群級別的,所以可以復用到多個ns下
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace. You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
name: read-secrets
# The namespace of the RoleBinding determines where the permissions are granted.This only grants permissions within the "development" namespace.
namespace: development
subjects:
- kind: User ---也可以是Group,表示賦予誰...
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
例3: ClusterRoleBinding的用法: 給用戶賦予一個ClusterRole級別的權限,讓其可以操作整個集群
小小結:
一: 給用戶賦予命名空間級別(ns)的權限
1)ns下創建RoleBinding(manifest中需要指定namespace), 綁定ns下的Role,
2)ns下創建RoleBinding(manifest中需要指定namespace),綁定集群級別的ClusterRole
二:給用戶賦予集群級別的權限
1)創建ClusterRoleBinding(manifest中不需要指定namespace,指定了也不生效),綁定集群級別的ClusterRole
一: 給用戶賦予命名空間級別(ns)的權限
1)ns下創建RoleBinding(manifest中需要指定namespace), 綁定ns下的Role,
2)ns下創建RoleBinding(manifest中需要指定namespace),綁定集群級別的ClusterRole
二:給用戶賦予集群級別的權限
1)創建ClusterRoleBinding(manifest中不需要指定namespace,指定了也不生效),綁定集群級別的ClusterRole
二. 聚合ClusterRoles(Aggregated ClusterRoles)
我們可以將多個ClusterRole匯聚到一個聯合ClusterRole中. 對於一個controller,作為集群控制平面的一部分,會一直watch 攜帶aggregationRule set的ClusterRole對象。
aggregationRule定義了一個標簽selector,controller使用這個selector與其他ClusterRole進行匹配,匹配成功的ClusterRole將會被導入到該對象的rules中。
例如:
我們可以將多個ClusterRole匯聚到一個聯合ClusterRole中. 對於一個controller,作為集群控制平面的一部分,會一直watch 攜帶aggregationRule set的ClusterRole對象。
aggregationRule定義了一個標簽selector,controller使用這個selector與其他ClusterRole進行匹配,匹配成功的ClusterRole將會被導入到該對象的rules中。
例如:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true" ---如果有一個ClusterRole,他攜帶的labels符合我的要求,則他的rules會自動填充到我的rules中
rules: [] # The control plane automatically fills in the rules
kind: ClusterRole
metadata:
name: monitoring
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true" ---如果有一個ClusterRole,他攜帶的labels符合我的要求,則他的rules會自動填充到我的rules中
rules: [] # The control plane automatically fills in the rules
對於缺省的面向用戶的roles使用ClusterRole 聚合的,會讓作為集群管理員的你,將針對用戶資源或者聚合API server的rules都包含進來,即擴展了缺省roles。
三: 缺省角色和角色綁定
API servers 創建了一組缺省的ClusterRole以及ClusterRoleBinding對象,他們大部分是以system:為前綴的,這表示這些資源是直接受集群的控制平面管理的,所有的缺省ClusterRoles和ClusterRoleBindings都被打上了kubernetes.io/bootstrapping=rbac-defaults這個標簽。
自動調諧(Auto-reconciliation)
每一次的啟動,API server都會更新那些with any missing permissions的缺省集群角色 ,並且更新那些 with any missing subjects的集群角色綁定,這樣使得集群能夠修復那些意外的修改,從而一旦新Kubernetes版本中有權限和主題的更改,有助於保持角色和角色綁定為最新。
每一次的啟動,API server都會更新那些with any missing permissions的缺省集群角色 ,並且更新那些 with any missing subjects的集群角色綁定,這樣使得集群能夠修復那些意外的修改,從而一旦新Kubernetes版本中有權限和主題的更改,有助於保持角色和角色綁定為最新。
要選擇退出這種調諧,那么需要將缺省群集角色或角色綁定上的rbac.authorization.kubernetes.io/autoupdate 注解設置為false。請注意,缺少默認權限和主題可能會導致群集無法正常運行。如果RBAC authorizer 模塊處於活動狀態,則默認情況下會啟用自動調諧。
1.API discovery 角色
對於無論是否經過身份驗證的用戶, 缺省的角色綁定都允許他們 去讀取 被認可為公開訪問是安全的API 信息(包括CRD)。如果想要禁止未經身份驗證的匿名用戶訪問,則需要在API server的配置中添加上 --anonymous-auth=false。
想要看看這方面的配置信息,可以使用如下的命令:
kubectl get clusterroles system:discovery -o yaml
2. User-facing 角色(面向用戶的角色)
一些缺省的ClusterRoles是不帶"system:"前綴,這意味他們是面向用戶的角色,其中包括超級用戶角色(cluster-admin), 這些角色如果是要在集群范圍內被授予,則通過ClusterRoleBindings,如果是想要在ns范圍內被授予,則使用RoleBindings (admin, edit, view).
面向用戶的ClusterRoles,是 使用ClusterRole aggregation 機制來允許管理員將針對custom resource的rules包含在自己的ClusterRoles中。為了給admin, edit, or view這些角色添加rules,則需要創建的ClusterRoles具備以下一個或多個labels:
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
3.Core component 角色(核心組件角色)
system:kube-scheduler
system:volume-scheduler
...
4.Other component 角色
system:node-bootstrapper
...
system:node-bootstrapper
...
5.for built-in controllers的角色
三,權限提升預測機制 和 bootstrapping
RBAC API通過編輯角色或角色綁定來防止用戶提升特權。因為這是在API 級別強制執行的,所以即使未使能RBAC授權,它也適用。
wxy: 我理解他的意思是說,因為所有的操作都是通過調用api完成的,所以你不可能隨心所欲提升權限,因為api本身就是一道關卡。
RBAC API通過編輯角色或角色綁定來防止用戶提升特權。因為這是在API 級別強制執行的,所以即使未使能RBAC授權,它也適用。
wxy: 我理解他的意思是說,因為所有的操作都是通過調用api完成的,所以你不可能隨心所欲提升權限,因為api本身就是一道關卡。
N: ServiceAccount權限
缺省的RBAC策略向控制平面組件,節點,controller授予了有限范圍的權限,但並沒有對kube-system namespace之外的的服務賬戶授予任何權限(除了給所有認證用戶授予了discovery權限)
缺省的RBAC策略向控制平面組件,節點,controller授予了有限范圍的權限,但並沒有對kube-system namespace之外的的服務賬戶授予任何權限(除了給所有認證用戶授予了discovery權限)
=============================
一個利用RBAC進行權限管控的實現方案
前情提要:
一個第三方軟件通過讀取
/etc/kubernetes/admin.conf(使用kubeadmin部署的集群會存在這個文件)文件中的證書信息,以超級管理員的身份操作集群
目前的需求是:限制第三方的權限,讓其只可以訪問指定namespace下的資源,和不屬於namespace范疇的資源
實現步驟:
第0步: 准備一個即將被第三方托管的集群,確定使用的命名空間,且這些命名空間需確實存在
第1步: 創建一個用戶,並為這個用戶簽發證書,假如這個用戶叫做wxy,命令如下:
openssl genrsa -out wxy.key 2048
openssl req -new -key wxy.key -out wxy.csr -subj "/CN=wxy"
openssl genrsa -out wxy.key 2048
openssl req -new -key wxy.key -out wxy.csr -subj "/CN=wxy"
openssl x509 -req -in wxy.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out wxy.crt -days 3650
說明: 其中CA的路徑必須是集群的根證書所在路徑,一般情況下都是/etc/kubernetes/pki/
第2步: 替換/etc/kubernetes/admin.conf 中的相關的內容,
1)將上一步中生成的證書文件進行base64加密
cat wxy.crt |base64 --wrap=0
cat wxy.key |base64 --wrap=0
2)修改配置文件,需替換部分如下:
# vi /etc/kubernetes/admin.conf
...
aXRLTGJsMVRoc29lZ1lWemVDWGJHbTE0S3IrbjhuU2JGTkdUOD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: https://192.168.48.232:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: wxy ---替換成自定義用戶
name: wxy@kubernetes ---替換成自定義用戶
current-context: wxy@kubernetes ---替換成自定義用戶
kind: Config
preferences: {}
users:
- name: wxy ---替換成自定義用戶
user:
client-certificate-data: {{---替換成wxy.crt加密后的內容---}}
client-key-data: {{---替換成wxy.key加密后的內容---}}
# vi /etc/kubernetes/admin.conf
...
aXRLTGJsMVRoc29lZ1lWemVDWGJHbTE0S3IrbjhuU2JGTkdUOD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: https://192.168.48.232:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: wxy ---替換成自定義用戶
name: wxy@kubernetes ---替換成自定義用戶
current-context: wxy@kubernetes ---替換成自定義用戶
kind: Config
preferences: {}
users:
- name: wxy ---替換成自定義用戶
user:
client-certificate-data: {{---替換成wxy.crt加密后的內容---}}
client-key-data: {{---替換成wxy.key加密后的內容---}}
第3步: 創建role,一個用來限制自定義用戶權限的資源類型,這個權限的規則遵從k8s的RBAC,可根據需要自行定制
在這里我創建了一個角色允許其獲取節點信息,namespace信息,創建PV,而其他屬於namespace范疇下的資源則不允許訪問
wxy-admin.json:從edit 和 system:node中繼承來的
在這里我創建了一個角色允許其獲取節點信息,namespace信息,創建PV,而其他屬於namespace范疇下的資源則不允許訪問
wxy-admin.json:從edit 和 system:node中繼承來的
第4步: 將角色role與我們自定義用戶進行綁定,命令如下:
1)與上一步創建的自定義角色wxy-admin綁定
kubectl create clusterrolebinding wxy-admin-binding --clusterrole=wxy-admin --user=wxy
kubectl create clusterrolebinding wxy-admin-binding --clusterrole=wxy-admin --user=wxy
2)與k8s內置的集群管理員角色cluster-admin進行綁定,但要求其只在001命名空間下具有該角色,達到權限縮小到namespace的目的
kubectl create rolebinding wxy-001-admin-binding --clusterrole=cluster-admin --user=wxy--namespace=001
kubectl create rolebinding wxy-001-admin-binding --clusterrole=cluster-admin --user=wxy--namespace=001
另:
如果查看的是不允許的namespace下資源,則會報錯,比如如下:
Failure executing: GET at: https://x.x.x.x:6443/api/v1/namespaces/kube-system/pods. Message: Forbidden! User kubernetes-admin doesn't have permission. pods is forbidden: User "wxy" cannot list resource "pods" in API group "" in the namespace "kube-system"
根據錯誤信息就可以知道,因為權限問題,請求被拒絕了!
如果查看的是不允許的namespace下資源,則會報錯,比如如下:
Failure executing: GET at: https://x.x.x.x:6443/api/v1/namespaces/kube-system/pods. Message: Forbidden! User kubernetes-admin doesn't have permission. pods is forbidden: User "wxy" cannot list resource "pods" in API group "" in the namespace "kube-system"
根據錯誤信息就可以知道,因為權限問題,請求被拒絕了!