关于权限控制:一文读懂-TKE-及-Kubernetes-访问权限控制

38次阅读

共计 9995 个字符,预计需要花费 25 分钟才能阅读完成。

你有理解过 Kubernetes 的认证受权链路吗?是否对 TKE 的权限管制 CAM 策略、服务角色傻傻分不清楚?本文将会向你介绍 腾讯云 TKE 平台侧的访问控制Kubernetes 访问控制链路,以及演示如何将平台侧账号对接到 Kubernetes 内。

当你在应用腾讯云容器服务 TKE(Tencent Kubernetes Engine)的时候,如果多人共用一个账号的状况下,是否有遇到以下问题呢?

  • 密钥由多人共享,泄密危险高。
  • 无奈限度其他人的拜访权限,其他人误操作易造成平安危险。

为了解决以上问题,腾讯云 CAM(Cloud Access Management)提供了主账号和子账号的认证体系以及基于角色的权限管制。

而不同的子账号对于 TKE 平台侧资源的管制粒度比拟粗(cluster 实例级别),又会遇到以下问题:

  • 同一个集群由多子账号可拜访,无奈保障集群资源级别、命名空间级别的读写管制。
  • 集群的高权限子账户无奈对低权限子账户进行受权治理。

为了解决以上两个问题,TKE 针对 平台侧资源 Kubernetes 资源 别离进行相应的访问控制治理。

平台侧访问控制

首先介绍下什么是平台侧资源,平台侧资源即 Cluster 资源CVM 资源CLB 资源VPC 资源 等腾讯云资源,而拜访的用户次要分为 用户 服务角色载体

  1. 用户 就是咱们平时登录控制台的主账号、子账号或者协作者账号
  2. 服务角色 是一种定义好带有某些权限的角色,能够将这个角色赋予某个 载体,能够是某个其余账户,也能够是腾讯云下一个产品的服务提供者,CAM 会默认为产品提供一个预设的载体和默认的角色,例如 TKE 的默认角色就是 TKE_QCSRole,而载体就是ccs.qcloud.com

而这个角色有什么用途呢?举个 TKE 的例子,比方 TKE 的 service-controller 会 Watch 集群内的 Service 资源,如果须要创立 LoadBalance 类型的 Service,会通过云 API 购买并创立 CLB 资源,而 service-controller 是 TKE 平台为用户部署的,去拜访云 API 须要有身份,这个身份就是ccs.qcloud.com 载体,而权限则须要用户给载体授予一个角色,即 TKE_QCSRole。只有用户在受权 TKE 载体之后,TKE 才能够通过服务表演的形式代替用户购买 CLB。
上面我会简略为你介绍如何给 用户 受权,以及如何给 TKE 平台授予 角色

定制策略

TKE 通过接入 CAM,对集群的 API 接口级别进行权限细分,须要您在 CAM 控制台对子账户进行不同的权限授予。同时 TKE 也在 CAM 侧提供了预设的权限,提供您默认抉择,例如:

也能够自定义策略,具体策略定制请参考 CAM 产品介绍文档

例如领有只读权限的子账户尝试批改集群名称,将会在 API 接口时校验 CAM 权限失败

划分用户组

能够根据团队的职责划分好用户组,将之前布局好的自定义策略绑定到一个用户组上,来不便的进行权限治理。
例如:有新同学入职时可不便的退出指定用户组(如运维组),就能够获取到该用户组的权限,防止了繁琐的权限配置操作。

授予 TKE 角色权限

应用 TKE 容器服务须要授予 TKE 平台为您操作 CVMCLBVPCCBS 等权限,所以首次拜访 TKE 控制台须要确保批准受权,即创立预设角色 TKE_QCSRole,此角色默认授予 TKE 载体,该载体会通过 CAM 获取操作您集群的长期密钥,来进行相应的云 API 操作。

更多

更多丰盛的平台侧访问控制用法请拜访 CAM 产品阐明文档

Kubernetes 访问控制

介绍完平台侧资源的访问控制,咱们再来看看 TKE 集群内的资源如何进行权限治理。当不同的子账户都领有拜访同一个 TKE Kubernetes 集群权限之后,如何保障不同的子账户,对于集群内资源领有不同的角色和权限呢?让咱们首先从社区的 Kubernetes 拜访链路来剖析整个过程,从而向您介绍 TKE 是如何实现容器服务子账户对接 Kubernetes 认证受权体系的。

Overview

首先从宏观的角度看下 Kubernetes 的申请链路是如何进行的。图片来源于 k8s 社区官网。

能够大略理解到一个申请的链路是顺次通过 Authentication(认证,简称 Authn)、Authorization(受权,简称 Authz)、AdmissionControl(准入管制),从而获取到后端长久化的数据。

从图中能够看到 Authn、Authz、AdmissionControl 是由多个模块组成的,每个步骤都有多种形式形成的。

在进入认证模块之前会将 HTTP 的 Request 进行构建 context,而 context 中就蕴含了用户的 RequestInfo,userInfo、Verb、APIGroup、Version、Namespace、Resource、Path 等。

带着这些信息,上面咱们来一次看下准入过程中的每个步骤吧。

Kubernetes 认证

认证的过程的证实 user 身份的过程。

Kubernetes 中有两类用户,一类是 ServiceAccount,一类是集群实在的用户。

ServiceAccount 账户是由 Kubernetes 提供 API(资源)进行创立和治理的,ServiceAccount 能够认为是非凡的 Secret 资源,可用户集群内资源拜访 APIServer 的认证所用。通过能够通过 mount 的形式挂载到 Pod 内进行应用。

实在的用户通常是从内部发动申请拜访 APIServer,由管理员进行治理认证凭证,而 Kubernetes 自身不治理任何的用户和凭证信息的,即所有的用户都是逻辑上的用户,无奈通过 API 调用 Kubernetes API 进行创立实在用户。

Kubernetes 认证的形式泛滥,常见的有 TLS 客户端证书双向认证、BearerToken 认证、BasicAuthorization 或认证代理(WebHook)

所有的认证形式都是以插件的模式串联在认证链路中,只有有一种认证形式通过,即可通过认证模块,且后续的认证形式不会被执行。

在此处参考一点点 Kubernetes APIServer Authentication 模块的代码,能够发现,任何的认证形式都是一下 Interface 的实现形式都是接管 http Request 申请,而后会返回一个 user.Info 的构造体,一个 bool,以及一个 error

// Request attempts to extract authentication information from a request and returns
// information about the current user and true if successful, false if not successful,
// or an error if the request could not be checked.
type Request interface {AuthenticateRequest(req *http.Request) (user.Info, bool, error)
}

user.Info 中蕴含了用户的信息,包含 UserName、UUID、Group、Extra。

bool 返回了用户是否通过认证,false 的话即返回无奈通过认证,即返回 401 谬误。

error 则返回了当 Request 无奈被查看的谬误,如果遇到谬误则会持续进行下一种注册的形式进行认证。

如果认证通过,则会把 user.Info 写入到到申请的 context 中,后续申请过程能够随时获取用户信息,比方受权时进行鉴权。

上面我会以 Kubernetes 代码中的认证形式程序,筛选几项认证形式,并联合 TKE 开启的认证形式来向你介绍 TKE 创立的 Kubernetes 集群默认的认证策略。

Basic Authentication

APIServer 启动参数 --basic-auth-file=SOMEFILE 指定 basic 认证的 csv 文件,在 APIServer 启动之后批改此文件都不会失效,须要重启 APIServer 来更新 basic authentication 的 token。csv 文件格式为:token,user,uid,"group1,group2,group3"

申请时,须要指定 HTTP Header 中 Authentication 为 Basic,并跟上 Base64Encode(user:passward)值。

x509 客户端证书

APIServer 启动参数 --client-ca-file=SOMEFILE 指定 CA 证书,而在 TKE 的 K8s 集群创立过程中,会对集群进行自签名 CA 密钥和证书用于治理,如果用户下发的客户端证书是由此 CA 证书的密钥签发的,那么就能够通过客户端证书认证,并应用客户端证书中的 CommonName、Group 字段别离作为 Kubernetes 的 UserInfo 中 Username 和 Group 信息。

目前 TKE 对接子账户都是通过自签名的 CA 凭证进行签发子账户 Uin 对应 CN 的客户端证书。

Bearer Token

Bearer Token 的认证形式蕴含很多,比方启动参数指定的、ServiceAccount(也是一种非凡的 BeaerToken)、BootstrapToken、OIDCIssure、WebhookToken

1. 默认指定 Token csv 文件

APIServer 启动参数 --token-auth-file=SOMEFILE 指定 Bearer Token 认证的 csv 文件。和 Basic Authentication 形式类似,只不过申请 APIServer 时,指定的 HTTP 认证形式为 Bearer 形式。此 Bearer 后间接跟 passward 即可。csv 文件格式为:password,user,uid,"group1,group2,group3"

申请时,须要指定 HTTP Header 中 Authentication 为 Bearer,并跟上 Base64Encode(user:passward)值。

2. ServiceAccount

ServiceAccount 也是一种非凡 beaer token,ServiceAccount 在 Kubernetes 中是一种资源,创立一个 ServiceAccount 资源之后默认会创立一个 Secret 资源,而 Secret 资源中就蕴含了一个 JWT 格局的 Token 字段,以 Bearer Token 的形式申请到 Kube-APIServer,Kube-APIServer 解析 token 中的局部 user 信息,以及 validate 以下 ServiceAccount 是否存在即可进行认证查看。这种形式即之前提到的“两种用户”中常见的集群内认证形式,ServiceAccount,次要用于集群内资源拜访 APIServer,但不限于集群内。

3. BootstrapToken

此项开关在 Kubernetes v1.18 版本中才为 stable 版本,此类 Token 是专门用来疏导集群装置应用的,须要配合 controller-manager 的 TokenCleaner。

目前 TKE 默认开启此配置。

4. OpenID Connect Tokens

OIDCToken 的认证形式是联合 OAuth2 向身份提供方获取 ID Token 来拜访 APIServer。

如须要开启此项性能,须要在 APIServer 的启动参数中指定 oidc 的配置参数,例如 --oidc-issuer-url 指定 oidc 身份提供方的地址,--oidc-client-id指定身份提供方侧的账户 ID,--oidc-username-claim身份提供方的用户名。

具体可参考 Kubernetes 官网文档,目前私有云 TKE 没有应用此参数对接腾讯云账户,因为波及用户须要被动登录受权后才可返回 Id Token,和以后官网交互抵触,能够在后续 CLI 工具中实现。

5. Webhook Token Server

Webhook Token 是一种 hook 的形式来校验是否认证通过。

APIServer 启动参数 --authentication-token-webhook-config-file--authentication-token-webhook-cache-ttl来别离指定 Webhook 地址以及 token 的 cache ttl。

若 APiServer 开启此形式进行认证校验,则在承受到用户的 Request 之后,会包装 Bearer Token 成一个 TokenReview 发送给 WebHookServer,Server 端接管到之后会进行校验,并返回 TokenReview 接口,在 status 字段中进行反馈是否通过校验通过和 user.Info 信息。

总结

以上即为 Kubernetes APIServer 认证的几种形式,TKE 在每种认证形式都有反对。供用户灵便应用。

目前 TKE 正在推应用 x509 客户端证书形式来进行认证治理,以不便进行对接子账户的创立、受权治理、更新。

Kubernetes 受权

Kubernetes 的受权模式反对一下几种,和认证一样,参考开始说的 RequestInfo context,可知用户 Reqeust 的 context 除了认证须要的 userInfo,还有一些其余的字段例如 Verb、APIGroup、APIVersion、Resource、Namespaces、Path……

受权就是判断 user 是否领有操作资源的相应权限。

Kubernetes 反对 AlwaysAllow、AlwaysDeny、Node、ABAC、RBAC、Webhook 受权 Mode,和认证一样,只有有一种鉴权模块通过,即可返回资源。

在这里重点介绍上面两种形式

RBAC

RBAC(Role-Based Access Control),Kubernetes 提供 ClusterRole、Role 资源,别离对应集群维度、Namespace 维度角色权限管控,用户能够自定义相应的 ClusterRole、Role 资源,绑定到曾经认证的 User 之上。

如下 tke:pod-reader ClusterRole,定义了该角色能够拜访 core apigroup 上面对 pods 资源的 get/watch/list 操作

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: tke:pod-reader
rules:
- apiGroups: [""] #"" 指定外围 API 组
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  
---
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定使得用户 "alex" 可能读取 "default" 命名空间中的 Pods
kind: ClusterRoleBinding
metadata:
  name: alex-ClusterRole
subjects:
- kind: User
  name: alex
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: tke:pod-reader # 这里的名称必须与你想要绑定的 Role 或 ClusterRole 名称统一
  apiGroup: rbac.authorization.k8s.io

通过以上的 yaml 配置,通过认证模块达到受权模块的 requestInfo 中 userInfo 信息是 alex 的申请,在受权模块中走到 RBAC 受权模块时,则会进行查问集群的 ClusterRole/ClusterRoleBinding 信息。进行判断是否领有 context 相应操作的权限。

TKE 的对接子账户的权限受权策略就是应用的 Kubernetes 原生的 RBAC 进行对子账户资源访问控制,这样合乎原生,合乎有 K8s 应用习惯的用户。

WebHook

Webhook 模式是一种基于 HTTP 回调的形式,通过配置好受权 webhook server 地址。当 APIServer 接管到 request 的时候,会进行包装 SubjectAccessReview 申请 Webhook Server,Webhook Server 会进行判断是否能够拜访,而后返回 allow 信息。

以下是 kubernetes 社区一个例子,以供参考。

{
  "apiVersion": "authorization.k8s.io/v1beta1",
  "kind": "SubjectAccessReview",
  "spec": {
    "resourceAttributes": {
      "namespace": "kittensandponies",
      "verb": "get",
      "group": "unicorn.example.org",
      "resource": "pods"
    },
    "user": "alex",
    "group": [
      "group1",
      "group2"
    ]
  }
}
{
  "apiVersion": "authorization.k8s.io/v1beta1",
  "kind": "SubjectAccessReview",
  "status": {"allowed": true}
}

目前 TKE 没有思考应用 Webhook 的模式,然而 Webhook 模式提供了弱小的灵活性,比方对接 CAM,实现 K8s 权限对接到平台侧,然而也有肯定的危险和挑战,比方依赖 CAM 的稳定性;申请提早、缓存 /TTL 的配置;CAM action 配置与 K8s 权限对应关系。此项受权模式依然在思考中,有需要的用户能够反馈。

准入管制

什么是 admission controller?

In a nutshell, Kubernetes admission controllers are plugins that govern and enforce how the cluster is used.

Admission controllers 是 K8s 的插件,用来治理和强制用户如何来操作集群。

Admission controllers 次要分为两个 phase,一个是 mutating,一个是 validating。这两个阶段都是在 authn&authz 之后的,mutating 做的变更准入,就是会对 request 的 resource,进行转换,比方填充默认的 requestLimit?而 validating admission 的意思就是验证准入,比方校验 Pod 正本数必须大于 2。

API Server 申请链路:

ValidatingAdmissionWebhooks and MutatingAdmissionWebhooks, both of which are in beta status as of Kubernetes 1.13.

k8s 反对 30 多种 admission control 插件,而其中有两个具备弱小的灵活性,即 ValidatingAdmissionWebhooksMutatingAdmissionWebhooks,这两种管制变换和准入以 Webhook 的形式提供给用户应用,大大提高了灵活性,用户能够在集群创立自定义的 AdmissionWebhookServer 进行调整准入策略。

TKE 中 1.10 及以上版本也默认开启了ValidatingAdmissionWebhooksMutatingAdmissionWebhooks

理解更多 Admission Controller 参考这里

kubernetes 权限对接子账户

TKE 权限实现对接子账户次要的计划是:x509 客户端认证+Kubernetes RBAC 受权

认证

每个子账户都领有独自的属于本人的客户端证书,用于拜访 KubernetesAPIServer。

  • 用户在应用 TKE 的新受权模式时,不同子账户在获取集群拜访凭证时,即前台拜访集群详情页或调用 DescribeClusterKubeconfig 时,会展现子账户本人的 x509 客户端证书,此证书是每个集群的自签名 CA 签发的。
  • 该用户在控制台拜访 Kubernetes 资源时,后盾默认应用此子账户的客户端证书去拜访用户 Kubernetes APIServer。
  • 反对子账户 更新 本人的证书。
  • 反对主账户或集群 tke:admin 权限的账户进行 查看 更新 其余子账户证书。

受权

TKE 控制台通过 Kubernetes 原生的 RBAC 受权策略,对子账户提供细粒度的 Kubernetes 资源粒度权限管制。

  • 提供受权治理页,让 主账号 集群创建者 默认领有管理员权限,能够对其余领有此集群 DescribeCluster Action 权限的子账户进行权限治理。
  • 并提供预设的 ClusterRole。

    • 所有命名空间维度:

      • 管理员(tke:admin):对所有命名空间下资源的读写权限,对集群节点,存储卷,命名空间,配额的读写权限,可子账号和权限的读写权限
      • 运维人员(tke:ops):对所有命名空间下控制台可见资源的读写权限,对集群节点,存储卷,命名空间,配额的读写权限
      • 开发人员(tke:dev):对所有命名空间下控制台可见资源的读写权限
      • 受限人员(tke:ro):对所有命名空间下控制台可见资源的只读权限
      • 用户自定义 ClusterRole
    • 指定命名空间维度:

      • 开发人员(tke:ns:dev):对所选命名空间下控制台可见资源的读写权限,须要抉择指定命名空间。
      • 只读用户(tke:ns:ro):对所选命名空间下控制台可见资源的只读权限,须要抉择指定命名空间。

  • 所有预设的 ClusterRole 都将带有固定 label:cloud.tencent.com/tke-rbac-generated: "true"
  • 所有预设的 ClusterRoleBinding 都带有固定的 annotations:cloud.tencent.com/tke-account-nickname: yournickname,及 label:cloud.tencent.com/tke-account: "yourUIN"

更多

当然,除了 TKE 控制台提供的预设受权策略,管理员也能够通过 kubectl 操作 ClusterRole/Role 来实现自定义角色的灵便配置细粒度权限,以及操作 ClusterRoleBinding/RoleBinding 进行权限绑定,绑定到任意的角色权限之上。

例如你想设置 CAM 侧用户组为 productA 产品的 pod-dev 的用户权限只可能 get/list/watch product- a 命名空间下的 pods 资源,则你能够这样操作:

  • 创立自定义 ClusterRole/Role:dev-pod-reader,yaml 实例如下,文件名为 developer.yaml

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole # 这里应用 ClusterRole 能够复用给产品其余命名空间
    metadata:
      name: pod-dev # pod-dev 此角色为只能读取 pod 的开发
    rules:
    - apiGroups: [""] #"" 指定外围 API 组
      resources: ["pods"]
      verbs: ["get", "watch", "list"]
    
  • 应用 kubectl 或者通过 TKE 控制台 YAML 创立资源 创立上述 Role
  • 绑定 dev 用户组下的 dev1、dev2、dev3 用户,绑定自定义权限 pod-dev 到 product- a 命名空间下
  • 从此 dev1,dev2,dev3 用户则只能应用 get/list/watch 拜访 product- a 下的 pods 资源

$ kubectl –kubeconfig=./dev.kubeconfig get pods
Error from server (Forbidden): pods is forbidden: User “10000001xxxx-1592395536” cannot list resource “pods” in API group “” in the namespace “default”
$ kubectl –kubeconfig=./dev.kubeconfig get pods -n product-a
No resources found.


### 参考

1. [kubernetes 认证介绍](https://kubernetes.io/docs/reference/access-authn-authz/authentication/)
2. [kubernetes 受权介绍](https://kubernetes.io/docs/reference/access-authn-authz/authorization/)
3. [kubernetesRBAC 介绍](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)
>【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

正文完
 0