写点什么

详解 k8s 中的 RBAC

作者:HummerCloud
  • 2023-02-01
    北京
  • 本文字数:3987 字

    阅读完需:约 13 分钟

详解 k8s 中的 RBAC

Kubernetes 主要通过 API Server 对外提供服务,对于这样的系统来说,如果不加以安全限制,那么可能导致请求被滥用,甚至导致整个集群崩塌。

Kubernetes 中提供了良好的多租户认证管理机制,RBAC 正式其中重要的一个,今天我们来详细聊聊 K8s 中的 RBAC。

K8s 中的权限管理


Kubernetes 主要通过 API Server 对外提供服务,Kubernetes 对于访问 API 的用户提供了相应的安全控制:认证和授权。认证解决用户是谁的问题,授权解决用户能做什么的问题。只有通过合理的权限控制,才能够保证整个集群系统的安全可靠。

下图是 API 访问需要经过的三个步骤,它们分别是:认证、授权和准入。


我们核心关注在鉴权部分,Kubernetes 提供了以下 4 种鉴权模式:

  • Node:一种特殊的授权模块,基于 Node 上运行的 Pod 为 Kubelet 授权

  • ABAC:基于属性的访问控制

  • RBAC:基于角色的访问控制

  • Webhook:HTTP 请求回调,通过一个 WEB 应用鉴定是否有权限进行某项操作

我们现在深入讨论的就是 RBAC 模式。

Rbac 基础

RBAC 就是一个权限控制模型,这个模型是经过时间沉淀之后,相当通用、成熟且被大众接受认可的一个模型。我的理解是 RBAC 和数学公式是一个道理,数学题可以套用数学公式,而权限系统也可以套用 RBAC 权限模型。

RBAC(Role-Based Access Control)权限模型的概念,即:基于角色的权限控制。通过角色关联用户,角色关联权限的方式间接赋予用户权限。

按照小白(我)的逻辑呢,权限嘛,只要给用户分配权限就好咯,何必多此一举,中间加一个角色,把权限倒个手。

其实之所以在中间加一层角色,是为了增加安全性和效率,而且后续扩展上也会提升不少。

打个比方,比如多个用户拥有相同的权限,在分配的时候就要分别为这几个用户指定相同的权限,修改时也要为这几个用户的权限进行一一修改。有了角色后,只需要为该角色制定好权限后,将相同权限的用户都指定为同一个角色即可,便于权限管理。对于批量的用户权限调整,只需调整用户关联的角色权限,无需对每一个用户都进行权限调整,既大幅提升权限调整的效率,又降低了漏调权限的概率。

k8s 中的 RBAC

RBAC 鉴权机制使用 rbac.authorization.k8s.io API 组来驱动鉴权决定, 允许你通过 Kubernetes API 动态配置策略。

要启用 RBAC,在启动 API 服务器时将 --authorization-mode 参数设置为一个逗号分隔的列表并确保其中包含 RBAC。

核心元素

掌握 K8s 中的 RBAC,首先我们要了解会涉及到的基本概念和元素

  • Rule:规则,一组属于不同 API Group 的操作集合;

  • Role:角色,用于定义一组对 Kubernetes API 对象操作的一组规则,范围限定在 namespace;

  • ClusterRole:集群角色,该角色不受 namespace 的限制;

  • Subject:对象,也就是规则作用的对象;

  • RoleBinding:将角色和对象进行绑定,范围限定在 namespace;

  • ClusterRoleBinding:将集群角色和对象进行绑定,不受 namespace 限制;

Role 与 ClusterRole

在 RBAC API 中,一个角色包含了一套表示一组权限的规则。权限以纯粹的累加形式累积(没有” 否定” 的规则)。角色可以由命名空间(namespace)内的 Role 对象定义,而整个 Kubernetes 集群范围内有效的角色则通过 ClusterRole 对象实现。

一个 Role 对象只能用于授予对某一单一命名空间中资源的访问权限。以下示例描述了”default” 命名空间中的一个 Role 对象的定义,用于授予对 pod 的读访问权限:

kind: RoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  namespace: default  name: pod-readerrules:- apiGroups: [""] # 空字符串"" 表明使用 core API group  resources: ["pods"]  verbs: ["get", "watch", "list"]
复制代码

ClusterRole 对象可以授予与 Role 对象相同的权限,但由于它们属于集群范围对象, 也可以使用它们授予对以下几种资源的访问权限:

· 集群范围资源(例如节点,即 node)

· 非资源类型 endpoint(例如”/healthz”)

· 跨所有命名空间的命名空间范围资源(例如 pod,需要运行命令 kubectl get pods --all-namespaces 来查询集群中所有的 pod)

下面示例中的 ClusterRole 定义可用于授予用户对某一特定命名空间,或者所有命名空间中的 secret(取决于其 绑定 方式)的读访问权限:

kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  # 鉴于 ClusterRole 是集群范围对象,所以这里不需要定义 "namespace" 字段  name: secret-readerrules:- apiGroups: [""]  resources: ["secrets"]  verbs: ["get", "watch", "list"]
复制代码

RoleBinding 与 ClusterRoleBinding

角色绑定将一个角色中定义的各种权限授予一个或者一组用户。角色绑定包含了一组相关主体(即 subject, 包括用户 ——User、用户组 ——Group、或者服务账户 ——Service Account)以及对被授予角色的引用。在命名空间中可以通过 RoleBinding 对象授予权限,而集群范围的权限授予则通过 ClusterRoleBinding 对象完成。

RoleBinding 可以引用在同一命名空间内定义的 Role 对象。下面示例中定义的 RoleBinding 对象在”default” 命名空间中将”pod-reader” 角色授予用户”jane”。这一授权将允许用户”jane” 从”default” 命名空间中读取 pod。

以下角色绑定定义将允许用户 "jane" 从 "default" 命名空间中读取 pod。

kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: read-pods  namespace: defaultsubjects:- kind: User  name: jane  apiGroup: rbac.authorization.k8s.ioroleRef:  kind: Role  name: pod-reader  apiGroup: rbac.authorization.k8s.io
复制代码

RoleBinding 对象也可以引用一个 ClusterRole 对象用于在 RoleBinding 所在的命名空间内授予用户对所引用的 ClusterRole 中 定义的命名空间资源的访问权限。这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的命名空间中复用这些角色。

例如,尽管下面示例中的 RoleBinding 引用的是一个 ClusterRole 对象,但是用户”dave”(即角色绑定主体)还是只能读取”development” 命名空间中的 secret(即 RoleBinding 所在的命名空间)。

# 以下角色绑定允许用户 "dave" 读取 "development" 命名空间中的 secret。kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: read-secrets  namespace: development # 这里表明仅授权读取 "development" 命名空间中的资源。subjects:- kind: User  name: dave  apiGroup: rbac.authorization.k8s.ioroleRef:  kind: ClusterRole  name: secret-reader  apiGroup: rbac.authorization.k8s.io
复制代码

最后,可以使用 ClusterRoleBinding 在集群级别和所有命名空间中授予权限。下面示例中所定义的 ClusterRoleBinding 允许在用户组”manager” 中的任何用户都可以读取集群中任何命名空间中的 secret。

以下 ClusterRoleBinding 对象允许在用户组 "manager" 中的任何用户都可以读取集群中任何命名空间中的 secret。

kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: read-secrets-globalsubjects:- kind: Group  name: manager  apiGroup: rbac.authorization.k8s.ioroleRef:  kind: ClusterRole  name: secret-reader  apiGroup: rbac.authorization.k8s.io
复制代码

与资源绑定

大多数资源由代表其名字的字符串表示,例如”pods”,就像它们出现在相关 API endpoint 的 URL 中一样。然而,有一些 Kubernetes API 还 包含了” 子资源”,比如 pod 的 logs。在 Kubernetes 中,pod logs endpoint 的 URL 格式为:

GET /api/v1/namespaces/{namespace}/pods/{name}/log

在这种情况下,”pods” 是命名空间资源,而”log” 是 pods 的子资源。为了在 RBAC 角色中表示出这一点,我们需要使用斜线来划分资源 与子资源。如果需要角色绑定主体读取 pods 以及 pod log,您需要定义以下角色:

kind: RoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  namespace: default  name: pod-and-pod-logs-readerrules:- apiGroups: [""]  resources: ["pods", "pods/log"]  verbs: ["get", "list"]
复制代码

通过 resourceNames 列表,角色可以针对不同种类的请求根据资源名引用资源实例。当指定了 resourceNames 列表时,不同动作 种类的请求的权限,如使用”get”、”delete”、”update” 以及”patch” 等动词的请求,将被限定到资源列表中所包含的资源实例上。例如,如果需要限定一个角色绑定主体只能”get” 或者”update” 一个 configmap 时,您可以定义以下角色:

kind: RoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  namespace: default  name: configmap-updaterrules:- apiGroups: [""]  resources: ["configmap"]  resourceNames: ["my-configmap"]  verbs: ["update", "get"]
复制代码

值得注意的是,如果设置了 resourceNames,则请求所使用的动词不能是 list、watch、create 或者 deletecollection。由于资源名不会出现在 create、list、watch 和 deletecollection 等 API 请求的 URL 中,所以这些请求动词不会被设置了 resourceNames 的规则所允许,因为规则中的 resourceNames 部分不会匹配这些请求。

对主体的引用

RoleBinding 或者 ClusterRoleBinding 可绑定角色到某 主体(Subject) 上。主体可以是组,用户或者服务账户。

Kubernetes 用字符串来表示用户名。用户名可以是普通的用户名,像 "alice";或者是邮件风格的名称,如 "bob@example.com", 或者是以字符串形式表达的数字 ID。你作为 Kubernetes 管理员负责配置身份认证模块, 以便后者能够生成你所期望的格式的用户名。

关于 HummerRisk

HummerRisk 是开源的云原生安全平台,以非侵入的方式解决云原生的安全和治理问题,核心能力包括混合云的安全治理和 K8S 容器云安全检测。

Github 地址:https://github.com/HummerRisk/HummerRisk

Gitee 地址:https://gitee.com/hummercloud/HummerRisk


发布于: 刚刚阅读数: 4
用户头像

HummerCloud

关注

还未添加个人签名 2022-09-07 加入

还未添加个人简介

评论

发布
暂无评论
详解 k8s 中的 RBAC_云原生_HummerCloud_InfoQ写作社区