6.2.3 RBAC 授权模式详解
RBAC (Role-Based Access Control,基于角色的访问控制 ) 作为kubeadm
的默认选项。
RBAC 有如下优势:
- 对集群中的资源和非资源权限均有完整的覆盖
- 整个RBAC 完全由几个API 对象完成,同其他API 对象一样,可以使用
kubectl
或API 进行操作。 - 可以在运行时进行调整,无须重新启动API Server 。
要使用RBAC ,需要在API Server 启动参数中加入 --authorization-mode=RBAC.
RBAC 的API 资源对象说明
RBAC 引入了4个新的顶级资源对象:Role,ClusterRole,RoleBinding,ClusterRoleBinding.
角色(Role)
一个角色就是一组权限的集合,这里的权限都是许可形式的,不存在拒绝的规则。在一个namespace
命名空间中,可以用Role来定义一个角色。如果是集群级别,就需要使用ClusterRole了。
角色只能对命令空间内的资源进行授权
下面的授权角色具备读取default 命名空间下的 Pods的
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # ""空字符串,表示核心API群
resources: ["pods"]
verbs: ["get","list","watch"]
rules 中的参数说明如下:
- apiGroups: 支持的API 组列表,例如:
apiVersion:batch/v1
,apiVersion: extensions:v1beta1
,apiVersion: apps/v1beta1
等。 - resources: 支持的资源对象列表,例如:pods,deployments,jobs等。
- verbs: 对资源对象的操作方法列表,例如:get,list,watch,delete,replace,patch等,
群集角色(ClusterRole)
集群角色除了具有和角色一致的命名空间内资源的管理能力,因其群集级别的范围,还可以用于以下特殊元素的授权。
- 集群范围的资源,如 Node
- 非资源型的路径,例如: /healthz
- 包含全部命名空间的资源 ,如 Pods ,用于 (kubectl get pods --all-namespace 这样的操作授权)
下面的集群角色可以让用户有权访问任意一个或者所有命名空间的secrets(视其绑定方式而定)
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: secret-reader
#namespace: kube-system # 如果指定,则限制单个namespace,不指定则不限制
rules:
- apiGroups: [""]
resources: ["secuets"]
verbs: ["get","watch","list"]
角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding)
角色绑定或者集群角色绑定,用来把一个角色绑定到一个目标上,绑定目标可以是User(用户),Group(组)或者Service Account。使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。
Rolebinding 可以引用Role进行授权。让jane 读取 default命名空间中的Pod
kind: RoleBinding
apiVersion: rabc.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定义的资源主体进行授权。
例:虽然secret-read 是集群角色,但是因为使用RoleBinding,所有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.l8s.io
ruleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
集群角色绑定中的角色只能是集群角色,用于进行集群级别或者对所有命名空间都生效的授权。
例:允许 manager组的用户读取任意namaspace中的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
对资源的引用方式
Pod 是一个命名空间内的资源,log 就是下级资源。要在一个RBAC角色中体现,就需要用“/”来分隔资源和下级资源。
如果想授权某个主体同时读取Pod和Pod log ,则可以配置resources 为一个数组。
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: defalult
name: pod-and-log-reader
rules:
- apiGroups: [""]
resources: ["pods","pods/log"]
verbs: ["get","watch","list"]
资源还可以通过名称(ResourceName)进行引用,在指定ResourceName后,使用get,delete,update和patch 动词的请求,就会限制在这个资源内
如: 让一个主体只能对一个ConfigMap 进行get和update操作。
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
resources: ["ConfigMap"]
resourceName: ["my-configmap"]
verbs: ["update","get"]
可想而知,resourceName 这种用法对list,watch,create 或 deletecollection 操作的是无效的,这是因为必须通过URL进行授权,而资源名称在 list,watch,create或deletecollection请求中只是请求body的一部分。
常用的角色示例
1、允许读取核心API 级别的Pod资源
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","watch","list"]
2、允许读写extensions和apps两个API 组中的deployment资源
rules:
- apiGroups: ["extensions","apps"]
resources: ["deployments"]
verbs: ["get","watch","list","create","patch","update","delete"]
3、允许读取Pods及读写jobs
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["jobs"]
verbs: ["get","watch","list","update","create","delete","patch"]
4、允许读取一个名为 my-configmap 的ConfigMap(必须绑定到一个RoleBinding 来限制到一个namespace下的ConfigMap)
rules:
- apiGroups: [""]
resources: ["ConfigMap"]
resouceName: ["my-configmap"]
verbs: ["get"]
5、读取核心组的Node资源(Node属于集群级资源,所有必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定)
kind: ClusterRole
……
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get","watch","list"]
6、允许对非资源端点"/healthz" 及其子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding)
kind: ClusterRole
……
rules:
- nonResourceURLs: ["/healthz","/healthz/*"]
verbs: ["get","post"]
常见角色绑定
1、用户名为 alice@example.com
subjects:
- kind: User
name: "alice@example.com"
apiGroup: rbac.authorization.k8s.io
2、组名frontend-admins
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
3、kube-system命名空间中的默认Service Account
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
4、qa命名空间中的所有Service Account
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
5、所有Service Account
subjects:
- kind: Group
name: system: serviceaccounts
apiGroup: rbac.authorization.k8s.io
6、所有认证用户(Kubernetes 1.5 以上版本)
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
7、所有未认证用户(Kubernetes 1.5以上版本)
subjects:
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
8、全部用户(Kubernetes 1.5以上版本)
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:unthenticated
apiGroup: rbac.authorization.k8s.io
默认的角色和角色绑定
API Server会创建一套默认的 ClusterRole和ClusterRoleBinding对象,其中很多是以“system” 为前缀的,以表明这些资源是属于基础架构,对这些对象的改动可能造成集群故障。有些默认角色不是以"system" 为前缀的,这部分角色是针对用户的,其中包含超级用户角色(cluster-admin),有的用于集群一级角色(cluster-status)还有针对Namespace的角色(admin,edit,view)
所有默认的ClusterRole和RoleBinding都会采用标签kubernetes.io/bootstrapping=rbac-defaults
进行标记。
Kubernetes Controller Manager 负责的是核心控制流。如果用 --user-service-account-credentials调用,则每个控制过程都会使用不同的ServiceAccount启动,因此就有了对应各个控制过程的角色,前缀是system:controller
.如果Controller Manager 没有用--user-service-account-credentials 启动参数,则将使用自己的凭据运行各个控制流程,这就需要为该凭据授予相关的角色。
授权注意事项: 预防提升权限和授权初始化
RBAC API 拒绝用户通过编辑角色或者角色绑定进行提升权限。这一限制是在API 层面做出来的,因此即使RBAC没有启用也仍然有效。
用户要对角色进行创建或者更新操作,需要满足下列至少一个条件:
- 拥有一个角色的所有权限,且与该角色的生效范围一致(如果是集群角色,则是集群范围,如果是普通角色则是同一个命名空间或者整个集群)
- 为用户显示授予针对该角色或集群角色的提权(escalate)操作的权限(要求kubernetes 1.12 版本及以上版本)
例如:下面的集群角色和角色绑定能让 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"]
resourceName: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rule-grantor-binding
namespace: use-1-namespace
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: user-1
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: role-grantor
在进行第1个角色和角色绑定时,必须让初始用户具备其尚未被授予的权限,要进行初始的角色和角色绑定设置,有以下两种办法:
- 使用属于
system:masters
组的身份,这一群组默认具有 cluster-admin 这一超级角色的绑定。 - 如果 API Server 以--insecure-port 参数运行,则客户端通过这个非安全端口进行接口调用,这一端口没有认证鉴权的限制。
对Service Account 的授权管理
默认的RBAC 策略为控制平台组件、节点和控制器授予有限范围的权限,但是除kube-system 外的Service Account是没有任何权限的(除了所有认证用户都具有的discovery权限)
现在实践以安全性递减的方式排序
- 为一个应用专属的Service Account赋权(最佳实践)
这个应用需要在Pod的Spec中指定一个serviceaccountname
例如:为my-namespace中的 “my-sa" Service Account授予只读权限
kubectl create rolebinding my-sa-view \
--clusterrole=view \
--servcieaccount=my-namespace:my-sa \
--namespace=my-namespace
- 为一个命名空间中名为 default 的Service Account授权
如果一个应用没有指定serviceAccountName ,则会使用名为 default 的Service Account.注意: 赋给 Service Account "default" 的权限,会让所有没有指定serviceAccountName 的Pod 都具有这些权限
例如:在 my-namespace 命名空间中为 Service Account "default" 授予只读权限:
kubectl create rolebinding default-view \
--clusterrole=view \
--serviceaccount=my-namespace:default \
--namespace=my-namespace
另外,许多系统级 Add-Ons 都需要在kube-system命名空间中运行,要让这些Add-Ons 能够使用超级用户权限,则可以把 cluster-admin 权限赋予 kube-system 命名空间中的名为 default 的 Service Account 。注意,这一操作意味着 Kube-system命名空间包含了通向API 超级用户的捷径。
kubectl create rolebinding add-on-cluster-admin \
--clusterrole=cluster-admin
--serviceaccount=kube-system:default
- 为命名空间中所有Service Account都授予一个角色
如果希望在一个命名空间中,任何的Service Account 的应用都具有一个角色,则可以为这个命名空间的 Service Account 群组进行授权
例如: 为my-namespace 命名空间中的所有 Service Account赋予只读权限
kubectl create rolebinding serviceaccount-view \
--clusterrole=view \
--group=serviceaccounts:my-namespace \
--namespace=my-namespace
- 为集群范围内的所有Service Account都授予一个低权限角色(不推荐)
如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有 Service Account。
例如:为所有命名命名空间中的所有 Service Account授予只读权限
kubectl create clusterrolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts
- 为所有Service Account授权超级用户权限(强烈不推荐)
如果完全不在意权限,则可以把超级用户分配给每个Service Account
kubectl create clusterrolebinding serviceaccounts-cluster-admin \
--clusterrole=cluster-admin \
--group=system:serviceaccounts
使用kubectl 命令行某些人创建资源对象
除了使用 YAML 配置文件来创建这些资源对象,也可以直接使用 kubectl 命令行工具对它们进行创建。
1、在命名空间acme中为用户 bob授权 admin ClusterRole
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
2、在命名空间acme 中为名为 myapp 的Service Account授予view ClusterRole
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
3、在全集群范围内为用户root授予cluster-admin ClusterRole
kubectl create rolebinding root-cluster-admin-binding --user=root --clusterrole=cluster-admin
4、在全集群范围内为用户 kubelet授予 system:node ClusterRole
kubectl create rolebinding kubelet-node-binding --user=kubelet --clusterrole=system:node
5、在全群集范围内为名为 myapp 的 Service Account授予 view ClusterRole
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
RBAC 的 Auto-reconciliation(自动恢复)功能
每次启动,API Server 都会更新默认的集群角色的缺失权限,也会刷新在默认的角色绑定中缺失的主体,这样就防止了一些破坏性的修改。
如果不希望使用这一功能,则可以将一个默认的集群角色或者角色绑定的 Annotation 注解 "rbac.authorization.kubernetes.io/autoupdate" 值设置为 false
从旧版的授权策略升级到 RBAC
默认的 RBAC 策略为控制台组件、节点和控制器授予了受限的权限,但是不会为kube-system 以外的 ServiceAccount 授予任何权限。这样一来,可能会出现一些工作负载造成的影响,这里有两种办法解决这个问题:
一、 并行认证 RBAC 和 ABAC 同时运行,并包含传统的 ABAC策略:
--authorization-mode=RBAC,ABAC --authorization-policy-file=mypolicy.json1
首先会由 RBAC尝试鉴权,如果得到的结果是拒绝,就轮到 ABAC 生效,这个所有应用只要满足 RBAC 或者 ABAC 之一即可工作。
使用5
或者更详细的日志级别(--v=5 或 --vmodule=rbac*=5 ) 则可以在 API Server 日志中看到 RBAC 的拒绝行为(前缀: RBAC DENY)。可以利用这一信息确定老百姓授予何种权限给用户、组或者Service Account。等到管理员按照 RBAC 的方式对相关组件进行了授权,并且日志中不在出现 RBAC 的拒绝信息,就可以移除 ABAC的认证方式了。
二、 粗放管理。可以使用 RBAC 的角色绑定,复制一个粗放的策略。
警告: 下面的策略让所有的 Service Account都具有了集群的管理员权限,所有容器运行的应用都会自动接收 Service Account的认证,能够对任何API 做任何事情,包括查看 Secret和修改授权。
kubectl create clusterrolebinding permissive-binding \
--clusterrole=cluster-admin \
--user=admin \
--user=kubelet \
--group=system:serviceaccounts