跳至主要內容

6.2.3 RBAC 授权模式详解

Change Lee...大约 11 分钟容器k8sRBAC

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个角色和角色绑定时,必须让初始用户具备其尚未被授予的权限,要进行初始的角色和角色绑定设置,有以下两种办法:

  1. 使用属于 system:masters组的身份,这一群组默认具有 cluster-admin 这一超级角色的绑定。
  2. 如果 API Server 以--insecure-port 参数运行,则客户端通过这个非安全端口进行接口调用,这一端口没有认证鉴权的限制。

对Service Account 的授权管理

默认的RBAC 策略为控制平台组件、节点和控制器授予有限范围的权限,但是除kube-system 外的Service Account是没有任何权限的(除了所有认证用户都具有的discovery权限)

现在实践以安全性递减的方式排序

  1. 为一个应用专属的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
  1. 为一个命名空间中名为 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
  1. 为命名空间中所有Service Account都授予一个角色

如果希望在一个命名空间中,任何的Service Account 的应用都具有一个角色,则可以为这个命名空间的 Service Account 群组进行授权
例如: 为my-namespace 命名空间中的所有 Service Account赋予只读权限

kubectl create rolebinding serviceaccount-view \ 
--clusterrole=view \
--group=serviceaccounts:my-namespace \
--namespace=my-namespace
  1. 为集群范围内的所有Service Account都授予一个低权限角色(不推荐)

如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有 Service Account。
例如:为所有命名命名空间中的所有 Service Account授予只读权限

kubectl create clusterrolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts
  1. 为所有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/autoupdateopen in new window" 值设置为 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
上次编辑于:
贡献者: change,lichangyangccm@163.com
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3