引言:
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"
根据错误信息就可以知道,因为权限问题,请求被拒绝了!