基于角色的访问控制(RBAC),是一种其于用户的角色控制其对资源访问的方法。
RBAC利用rbac.authorization.k8s.io API组实现授权决策,允许管理通过kubernetes API动态配置策略。
在kubernetes 1.8版本中RBAC成为稳定特性,由rbac.authorization.k8s.io/v1 API在后端实现。
通过为apiserver指定--authorization-mode=RBAC选项打开RBAC功能。
概述
本节介绍RBAC API声明定义的四种顶级资源类型,它们的使用方法与普通的标准资源类型相同,如通过kubectl create -f 创建资源。
Role and ClusterRole
角色是一系列许可规则的集合,其中不包含拒绝规则。角色分成两种类型,"Role"表示某具namespace内部的角色,用"Role"类型资源表示。"ClusterRole"表示集群层面的角色,用"ClusterRole"类型的资源表示。
"Role"类型的角色只能被授权访问其所属的单个namespace之下的资源。以下示例表示default namespace下、具有读pod授权规则的"Role":
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
"ClusterRole"也可以像上例中的普通"Role"一样包含访问某个namespace的授权规则,但是因为"ClusterRole"是集群层面角色,它可以包含更大范围的受权规则:
- 集群范围内资源,如node资源,它属于集群但不属于任何namespace
- 非资源类型endpoint,如/healthz
- 跨namespace,如存在于不同namespace下的pod
下例中的"ClusterRole"包含访问任意namespace下secrets资源的读权限:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
# "namespace" omitted since ClusterRoles are not namespaced
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
RoleBinding and ClusterRoleBinding
角色只包含许可规则,需要将角色赋予某个主体如用户、用户组、服务账号,然后主体就拥有了角色中所包含的许可规则授予的权限,这个过程就是绑定。在kubernetes中通过创建"RoleBingding"与"ClusterRoleBinding"两种类型的对象描述此过程,"RoleBinding"发生在某个namespace之下,"ClusterRoleBinding"发生在集群层面。绑定对象中包含一个主体列表,如用户、用户组、服务账号等,还包含一个"Role",表示访问列表中的主体拥有"Role"中定义的许可规则。
"RoleBinding"是namespace范围内的绑定,也就是访问的对象是本namespace所属的资源。其中的"Role"可能是相同namespace下的"Role",也可能是集群范围内的"ClusterRole"。
下例中的"RoleBinding"表示,在default namespace之内,将用户jane与上例中在同相namespace下创建的"Role"绑定,最后结果是用户jane被授权读访问default namespace下所有pod。
# This role binding allows "jane" to read pods in the "default" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
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
前文讲"RoleBinding"中的roleRef可以是"ClusterRole"。"ClusterRole"由系统管理员定义,一般情况下包含一些具有共性、可重复使用的许可规则,然后namespace管理员通过"RoleBinding"在namespace内部将"ClusterRole"与主体绑定。下例"RoleBing"使用"ClusterRole",提示主体dave被授权读"deployment" namespace下的secrets资源:
# This role binding allows "dave" to read secrets in the "development" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets
namespace: development # This only grants permissions within the "development" namespace.
subjects:
- kind: User
name: dave # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
"ClusterRoleBing"是集群层面的绑定,比namespace层面的"RoleBing"更高。可以授权主机访问所有或者多个namespace下的资源。下例将读所有namespace下secrets的的权限授予manager用户组下的所有用户:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
Referring to Resources
以上例子中的访问控制都是基于资源类型,当授权时,所有同类型的资源都被授权,有时候可能需要更细粒度的资源访问控制,比如特定资源。大部分类型的资源可以通过字符串名称引用,如pod等。但是,对于像某个pod的log这种子资源,它们没有名字,那么它又是如何引用?在RBCS中如果控制它们的访问呢?如下例中的子资源:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
定义如下规则,包含对namespace下所有pod资源及pod子资源的读许可,注意子资源表示方法,下例中仍然没有对pod资源的名称为限定:
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"]
下列通过resourceNames字段,限定资源名称:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
显而易见,如果resourceNames字段被设置,那么verbs字段内就不可以包含list、create、watch、delete等操作。因为resourceNames限定的是具体的对象,不是对象集合,根据REST规范的定义,具体的对象不支持list、create、watch、delete等集合才支持的操作。
Aggregated ClusterRoles
从1.9版本开始支持"ClusterRole"聚合,新加aggregationRule子对象,通过其中的标签选择器聚合所有符合条件的"ClusterRole",取所有许可规则的并集作为新创建"ClusterRole"的许可规则,方便Role管理,如下例:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: monitoring
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # Rules are automatically filled in by the controller manager.
假如在创建完上述"ClusterRole"后,又新创建了包含标签rbac.example.com/aggregate-to-monitoring: true的"ClusterRole",那么新创建的"ClusterRole"仍然会被聚合,如:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: monitoring-endpoints
labels:
rbac.example.com/aggregate-to-monitoring: "true"
# These rules will be added to the "monitoring" role.
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
系统中存在面向用户的默认Role,由系统自动创建。但是默认Role是系统内建,默认情况下只针对系统内建的资源类型。对于用户自定义资源类型,有时候也需要应用系统默认Role,如何实现?系统默认Role是聚合类的"ClusterRole",那么在为自定义资源类型定义Role时,只要包含特定的标签,则新定义的Role就会被自动聚合到系统的默认Role中,那么系统默认Role也就支持了用户自定义的新类型。
例如,用户自定义新类型"CronTabs",访问新资源的API组为"stable.example.com",按如下方法为新资源定义"ClusterRole",并指定如下标签,则所定义的许可规则会自动聚合到系统中默认的"admin、edit、view"Role中:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: aggregate-cron-tabs-edit
labels:
# Add these permissions to the "admin" and "edit" default roles.
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rules:
- apiGroups: ["stable.example.com"]
resources: ["crontabs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: aggregate-cron-tabs-view
labels:
# Add these permissions to the "view" default role.
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["stable.example.com"]
resources: ["crontabs"]
verbs: ["get", "list", "watch"]
Role Examples
以下示例只显示Role中的rules字段。
允许核心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"]
允许核心API组读pod、读写job:
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
允许核心API组读名为"my-config"的ConfigMap类型的资源(必需用RoleBinding限定在某个namespace之下):
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-config"]
verbs: ["get"]
允许核心API组读node资源(因为node是集群资源不属于任何namespace,因而引此规则类型必需是ClusterRole,必需用ClusterRoleBinding绑定才会生效):