你有了解过Kubernetes的认证受权链路吗?是否对TKE的权限控制CAM策略、服务角色傻傻分不清楚?本文将会向你介绍腾讯云TKE平台侧的访问控制
、Kubernetes访问控制链路
,以及演示如何将平台侧帐号对接到Kubernetes内。
当你在使用腾讯云容器服务TKE(Tencent Kubernetes Engine)的时候,若是多人共用一个帐号的状况下,是否有遇到如下问题呢?web
为了解决以上问题,腾讯云CAM(Cloud Access Management)提供了主帐号和子帐号的认证体系以及基于角色的权限控制。shell
而不一样的子帐号对于TKE平台侧资源的控制粒度比较粗(cluster实例级别),又会遇到如下问题:后端
为了解决以上两个问题,TKE针对平台侧资源
、Kubernetes资源
分别进行相应的访问控制管理。api
首先介绍下什么是平台侧资源,平台侧资源即Cluster资源
、CVM资源
、CLB资源
、VPC资源
等腾讯云资源,而访问的用户主要分为用户
和服务角色载体
。缓存
用户
就是咱们平时登陆控制台的主帐号、子帐号或者协做者帐号服务角色
是一种定义好带有某些权限的角色,能够将这个角色赋予某个载体
,能够是某个其余帐户,也能够是腾讯云下一个产品的服务提供者,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权限失败ui
能够依据团队的职责划分好用户组,将以前规划好的自定义策略绑定到一个用户组上,来方便的进行权限管理。
例如:有新同窗入职时可方便的加入指定用户组(如运维组),就能够获取到该用户组的权限,避免了繁琐的权限配置操做。url
使用TKE容器服务须要授予TKE平台为您操做CVMCLBVPCCBS等权限,因此首次访问TKE控制台须要确保赞成受权,即建立预设角色TKE_QCSRole,此角色默认授予TKE载体,该载体会经过CAM获取操做您集群的临时密钥,来进行相应的云API操做。
更多丰富的平台侧访问控制用法请访问CAM产品说明文档
介绍完平台侧资源的访问控制,咱们再来看看TKE集群内的资源如何进行权限管理。当不一样的子帐户都拥有访问同一个TKE Kubernetes集群权限以后,如何保证不一样的子帐户,对于集群内资源拥有不一样的角色和权限呢?让咱们首先从社区的Kubernetes访问链路来分析整个过程,从而向您介绍TKE是如何实现容器服务子帐户对接Kubernetes认证受权体系的。
首先从宏观的角度看下Kubernetes的请求链路是如何进行的。图片来源于k8s社区官网。
能够大概了解到一个请求的链路是依次经过Authentication(认证,简称Authn)、Authorization(受权,简称Authz)、AdmissionControl(准入控制),从而获取到后端持久化的数据。
从图中能够看到Authn、Authz、AdmissionControl是由多个模块组成的,每一个步骤都有多种方式构成的。
在进入认证模块以前会将HTTP的Request进行构建context,而context中就包含了用户的RequestInfo,userInfo、Verb、APIGroup、Version、Namespace、Resource、Path等。
带着这些信息,下面咱们来一次看下准入过程当中的每一个步骤吧。
认证的过程的证实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集群默认的认证策略。
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)值。
APIServer启动参数--client-ca-file=SOMEFILE
指定CA证书,而在TKE的K8s集群建立过程当中,会对集群进行自签名CA密钥和证书用于管理,若是用户下发的客户端证书是由此CA证书的密钥签发的,那么就能够经过客户端证书认证,并使用客户端证书中的CommonName、Group字段分别做为Kubernetes的UserInfo中Username和Group信息。
目前TKE对接子帐户都是经过自签名的CA凭证进行签发子帐户Uin对应CN的客户端证书。
Bearer Token的认证方式包含不少,好比启动参数指定的、ServiceAccount(也是一种特殊的BeaerToken)、BootstrapToken、OIDCIssure、WebhookToken
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)值。
ServiceAccount也是一种特殊beaer token,ServiceAccount在Kubernetes中是一种资源,建立一个ServiceAccount资源以后默认会建立一个Secret资源,而Secret资源中就包含了一个JWT格式的Token字段,以Bearer Token的方式请求到Kube-APIServer,Kube-APIServer解析token中的部分user信息,以及validate如下ServiceAccount是否存在便可进行认证检查。这种方式即以前提到的“两种用户”中常见的集群内认证方式,ServiceAccount,主要用于集群内资源访问APIServer,但不限于集群内。
此项开关在Kubernetes v1.18版本中才为stable版本,此类Token是专门用来引导集群安装使用的,须要配合controller-manager的TokenCleaner。
目前TKE默认开启此配置。
OIDCToken的认证方式是结合OAuth2向身份提供方获取ID Token来访问APIServer。
如须要开启此项功能,须要在APIServer的启动参数中指定oidc的配置参数,例如--oidc-issuer-url
指定oidc身份提供方的地址,--oidc-client-id
指定身份提供方侧的帐户ID,--oidc-username-claim
身份提供方的用户名。
具体可参考Kubernetes官方文档,目前公有云TKE没有使用此参数对接腾讯云帐户,由于涉及用户须要主动登陆受权后才可返回Id Token,和当前官网交互冲突,能够在后续CLI工具中实现。
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的受权模式支持一下几种,和认证同样,参考开始说的RequestInfo context,可知用户Reqeust的context除了认证须要的userInfo,还有一些其余的字段例如Verb、APIGroup、APIVersion、Resource、Namespaces、Path……
受权就是判断user是否拥有操做资源的相应权限。
Kubernetes支持AlwaysAllow、AlwaysDeny、Node、ABAC、RBAC、Webhook受权Mode,和认证同样,只要有一种鉴权模块经过,便可返回资源。
在这里重点介绍下面两种方式
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模式是一种基于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
andMutatingAdmissionWebhooks
, both of which are in beta status as of Kubernetes 1.13.
k8s支持30多种admission control 插件 ,而其中有两个具备强大的灵活性,即ValidatingAdmissionWebhooks
和MutatingAdmissionWebhooks
,这两种控制变换和准入以Webhook的方式提供给用户使用,大大提升了灵活性,用户能够在集群建立自定义的AdmissionWebhookServer进行调整准入策略。
TKE中1.10及以上版本也默认开启了ValidatingAdmissionWebhooks
、MutatingAdmissionWebhooks
了解更多Admission Controller参考这里
TKE权限实现对接子帐户主要的方案是:x509客户端认证
+Kubernetes RBAC受权
。
每一个子帐户都拥有单独的属于本身的客户端证书,用于访问KubernetesAPIServer。
更新
本身的证书。查看
、更新
其余子帐户证书。TKE控制台经过Kubernetes原生的RBAC受权策略,对子帐户提供细粒度的Kubernetes资源粒度权限控制。
主帐号
和集群建立者
默认拥有管理员权限,能够对其余拥有此集群DescribeCluster Action权限的子帐户进行权限管理。并提供预设的ClusterRole。
全部命名空间维度:
指定命名空间维度:
cloud.tencent.com/tke-rbac-generated: "true"
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今后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/) >【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!