基于角色的访问控制(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"表示某具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"是集群层面角色,它可以包含更大范围的受权规则:
下例中的"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"]
角色只包含许可规则,需要将角色赋予某个主体如用户、用户组、服务账号,然后主体就拥有了角色中所包含的许可规则授予的权限,这个过程就是绑定。在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
以上例子中的访问控制都是基于资源类型,当授权时,所有同类型的资源都被授权,有时候可能需要更细粒度的资源访问控制,比如特定资源。大部分类型的资源可以通过字符串名称引用,如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等集合才支持的操作。
从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中的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绑定才会生效):
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
允许对非资源类型的endpoint /healthz及其所有的子资源执行GET、POST请求(此规则必需们于ClusterRole中,必需通过ClusterRoleBinding绑定):
rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # '*' in a nonResourceURL is a suffix glob match
verbs: ["get", "post"]
在"RoleBinding"与"ClusterRoleBinding"中,将定义好的Role与主体绑定,主体可以是用户(users)、用户组(groups)、服务账号(service account)。
用户用字符串标识,可以是普通字符串、数字ID、邮件地址,生成何种格式的用户名取决于管理员在authentication modules中的配置。RBAC认证系统对用户名没有格式要求。但是前缀system:被保留供系统使用,所以管理员应确保用户名不包含此前缀。
目前,有关组的信息由Authenticator modules提供,也是用字符串标识,要求与用户名一样,也不能包含system:前缀。
服务账号是有特殊前缀的用户名,普通服务账号名加前缀"system:serviceaccount:",组服务账号加前缀"system:serviceaccounts:"。
以下示例仅显示RoleBinding中的Subjects部分。
subjects:
- kind: User
name: "[email protected]"
apiGroup: rbac.authorization.k8s.io
组名frontend-admins
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
kube-system namespace下所有默认服务账号:
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
所有名为qa的namespace下的服务账号:
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
所有服务账号,无论何处:
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
所有已认证用户(version 1.5+):
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
所有未认证用户(version 1.5+):
subjects:
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
所有用户(version 1.5+):
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
Apiserver默认创建了一系列ClusterRole与ClusterRoleBinding对象,大部分以"system:"前缀,表示这些对象由系统管理。修改这些对象可能会使整个系统生效。例如ClusterRole system:node,其包含kubelet的访问许可规则,如果被修改,kubelet可能无法正常工作。
所有系统默认ClusterRole、ClusterRoleBinding都被打上kubernetes.io/bootstrapping=rbac-defaults标签。
在第一次的启动阶段,apiserver自动更新补全默认ClusterRole中缺失的许可规则,同样自动更新补全ClusterRoleBinding中缺失的主题,这允许通过重启修复被无意修改的默认值,或者是apiserver升级可通过重启应用新规则。
可以为某个默认Role或者binding指定注解rbac.authorization.kubernetes.io/autoupdate=true,那么对于被添加注解的Role或者ClusterRoleBing,这种自动对帐机制将失效,但要注意系统失效问题。
从1.6版本开始,当RBAC激活时这种自动对帐功能自动打开。
Default ClusterRole | Default ClusterRoleBinding | Description |
---|---|---|
system:basic-user | system:authenticated and system:unauthenticatedgroups | Allows a user read-only access to basic information about themselves. |
system:discovery | system:authenticated and system:unauthenticatedgroups | Allows read-only access to API discovery endpoints needed to discover and negotiate an API level. |
前文讲过,不是所有的默认Role都以system:为前缀,不以system:为前缀的Role预期是面向用户的,如超级Role cluster-admin。通过ClusterRoleBindings在集群层面授权,或者是在特定namespace下用RoleBinding授权(admin, edit, view)。
从版本1.9开始,允许管理员通过聚合ClusterRole将针对用户自定义资源的Role聚合到这种默认Role中,前文已经提到过,如果想将自定义资源的Role加入到默认的面向用户Role,如“admin”, “edit”, or “view”,则在创建自定义资源的ClusterRole时加入如下标签:
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"
Default ClusterRole | Default ClusterRoleBinding | Description |
---|---|---|
cluster-admin | system:masters group | Allows super-user access to perform any action on any resource. When used in a ClusterRoleBinding, it gives full control over every resource in the cluster and in all namespaces. When used in a RoleBinding, it gives full control over every resource in the rolebinding's namespace, including the namespace itself. |
admin | None | Allows admin access, intended to be granted within a namespace using a RoleBinding. If used in a RoleBinding, allows read/write access to most resources in a namespace, including the ability to create roles and rolebindings within the namespace. It does not allow write access to resource quota or to the namespace itself. |
edit | None | Allows read/write access to most objects in a namespace. It does not allow viewing or modifying roles or rolebindings. |
view | None | Allows read-only access to see most objects in a namespace. It does not allow viewing roles or rolebindings. It does not allow viewing secrets, since those are escalating. |
Default ClusterRole | Default ClusterRoleBinding | Description |
---|---|---|
system:kube-scheduler | system:kube-scheduler user | Allows access to the resources required by the kube-scheduler component. |
system:volume-scheduler | system:kube-scheduler user | Allows access to the volume resources required by the kube-scheduler component. |
system:kube-controller-manager | system:kube-controller-manager user | Allows access to the resources required by the kube-controller-manager component. The permissions required by individual control loops are contained in the controller roles. |
system:node | None in 1.8+ | Allows access to resources required by the kubelet component, including read access to all secrets, and write access to all pod status objects. As of 1.7, use of the Node authorizer and NodeRestriction admission plugin is recommended instead of this role, and allow granting API access to kubelets based on the pods scheduled to run on them. Prior to 1.7, this role was automatically bound to the `system:nodes` group. In 1.7, this role was automatically bound to the `system:nodes` group if the `Node` authorization mode is not enabled. In 1.8+, no binding is automatically created. |
system:node-proxier | system:kube-proxy user | Allows access to the resources required by the kube-proxy component. |
Default ClusterRole | Default ClusterRoleBinding | Description |
---|---|---|
system:auth-delegator | None | Allows delegated authentication and authorization checks. This is commonly used by add-on API servers for unified authentication and authorization. |
system:heapster | None | Role for the Heapster component. |
system:kube-aggregator | None | Role for the kube-aggregator component. |
system:kube-dns | kube-dns service account in the kube-system namespace | Role for the kube-dns component. |
system:kubelet-api-admin | None | Allows full access to the kubelet API. |
system:node-bootstrapper | None | Allows access to the resources required to perform Kubelet TLS bootstrapping. |
system:node-problem-detector | None | Role for the node-problem-detector component. |
system:persistent-volume-provisioner | None | Allows access to the resources required by most dynamic volume provisioners. |
Kubernetes controller manager负责运行所有核心control loops。当为controller manager指定标志--use-service-account-credentials时,每个control loop使用一个单独的服务账号以及与其对应的以system:为前缀的role。如果controller manager没有指定此选项,所有的control loops使用自己的credential,这个credential必需被授权所有的role,这些role包括:
RBAC会阻止用户通过编辑Role或者Binding扩权,这是管理员的权限。比如用户"user-1"没有读取集群内secrets的权限,那么同样它也没有权限创建包含读取集群内secrets许可规则的ClusterRole,也就是说用户创建、修改Role之前要先获得Role内包含的所有许可规则。允许用户创建、修改Role的步骤:
同样,用户只有已经获取了Role中所有的许可规则,才能对这个Role创建、修改绑定。允许用户创建、修改Role绑定的步骤:首先由系统管理员授予它们创建、修改Role、ClusterRole的权限。
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"]
resourceNames: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: role-grantor-binding
namespace: user-1-namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: role-grantor
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: user-1
在引导阶段授予初始用户权限,如下:
kubectl命令行管理Role、RoleBinding。
在某个namespace之下绑定Role、ClusterRole。
Grant the admin
ClusterRole
to a user named “bob” in the namespace “acme”:
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
Grant the view
ClusterRole
to a service account named “myapp” in the namespace “acme”:
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount
在集群层面绑定ClusterRole。
Grant the cluster-admin
ClusterRole
to a user named “root” across the entire cluster:
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
Grant the system:node
ClusterRole
to a user named “kubelet” across the entire cluster:
kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet
Grant the view
ClusterRole
to a service account named “myapp” in the namespace “acme” across the entire cluster:
kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
系统默认授予kube-system命名空间中的所有服务账号授予权限,使它们能访问控制面、控制器等组件。除此之外的服务账号由管理员管理授权,良好的授权管理能增强安全性,基本方法如下:
1.为特定应用的服务号授权。理解就是某个应用需要使用某个服务账号,应用持有这个服务账号的名称,这个服务账号归这个应用专用,就是为这种服务账号授权,例如,在"my-namespace"中为"my-sa"服务账号授予只读权限:
kubectl create rolebinding my-sa-view \
--clusterrole=view \
--serviceaccount=my-namespace:my-sa \
--namespace=my-namespace
2.为"default"服务账号授权,如果应用没有在规格中明确指定服务账号,那么全部都使用这个账号。例如,在"my-namespace"中为"default"服务账号授予只读权限:
kubectl create rolebinding default-view \
--clusterrole=view \
--serviceaccount=my-namespace:default \
--namespace=my-namespace
目前,大部分插件运行在kube-system名称空间,并且使用"default"服务账号。为了使插件拥有超级权限,需要在kube-system名称空间下将cluster-admin角色指定给default服务账号。
kubectl create clusterrolebinding add-on-cluster-admin \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:default
3.在一个namespace中为所有的服务账号指定一个Role。如下,注意group内容:
kubectl create rolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts:my-namespace \
--namespace=my-namespace
4.为集群中所有的服务账号指定Role(一刀切,不推荐):
kubectl create clusterrolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts
5.为所有服务账号授予超级用户权限(不安全,强烈不推荐):
kubectl create clusterrolebinding serviceaccounts-cluster-admin \
--clusterrole=cluster-admin \
--group=system:serviceaccounts
以下方法授予所有服务账号管理员权限:
kubectl create clusterrolebinding permissive-binding \
--clusterrole=cluster-admin \
--user=admin \
--user=kubelet \
--group=system:serviceaccounts