k8s认证鉴权体系
k8s认证鉴权体系
用户管理
- Kubernetes自身并没有用户管理能力,无法像操作- Pod一样,通过- API的方式创建/删除一个用户实例,也无法在- etcd中找到用户对应的存储对象。
- 在 Kubernetes的访问控制流程中,用户模型是通过请求方的访问控制凭证(如kubectl使用的kube-config中的证书、Pod中引入的ServerAccount)产生的。
- kube-apiserver认识的用户名其实是证书中的- CN字段,认识的用户组是证书中的- O字段。
认证
k8s的认证方式有以下几种:
- X509 client certs
- Static Token File
- Bootstrap Tokens
- Static Password File
- Service Account Tokens
- OpenId Connect Tokens
- Webhook Token Authentication
- Authticating Proxy
- Anonymous requests
- User impersonation
- Client-go credential plugins
常见的认证方式
clientCA认证
X509 认证是 Kubernetes 组件间默认使用的认证方式,同时也是 kubectl 客户端对应的 kube-config 中经常使用到的访问凭证。它是一个比较安全的方式。
首先访问者会使用由集群 CA 签发的,或是添加在 apiserver 配置中的授信 CA 签发的客户端证书去访问 apiserver 。apiserver 在接收到请求后,会进行TLS的握手流程。
除了验证证书的合法性,apiserver 还会校验客户端证书的请求源地址等信息,开启双向认证。
- 创建根 CA
- 签发其它系统组件的证书(Kubernetes集群中所有系统组件与apiserver通讯用到的证书,其实都是由集群根CA来签发的)
- 签发用户的证书
ServiceAccountAuth认证
- serviceAccount是- k8s中唯一能够通过- API方式管理的- apiServer访问凭证,通常用于- pod中的业务进程与- apiserver的交互。
- ServiceAccount解决- Pod在集群里面的身份认证问题,认证使用的授权信息存在- secret里面(由- SecretAccount Controller自行创建)。
- 当一个 namespace创建完成后,会同时在该namespace下生成名为default的serviceAccount和对应Secret:1 
 2
 3
 4
 5
 6
 7apiVersion: v1
 kind: ServiceAccount
 metadata:
 name: default
 namespace: default
 secrets:
 - name: default-token-nfdr4
- 对应的Secret里:- data字段有两块数据:- ca.crt用于对服务端的校验,- token用于- Pod的身份认证,它们都是用- base64编码过的。
- metadata里- annotations字段表明了关联的- ServiceAccount信息(被哪个- ServiceAccount使用)。
- type字段表明了该- Secret是- service-account-token。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- apiVersion: v1
 data:
 ca.crt: LS0tLS1...
 namespace: ZGVmYXVsdA==
 token: ZXlKaG...
 kind: Secret
 metadata:
 annotations:
 kubernetes.io/service-account.name: default
 kubernetes.io/service-account.uid: b2322727-08d5-4095-acbe-1afee4fb5e6c
 name: default-token-nfdr4
 namespace: default
 type: kubernetes.io/service-account-token
 
- 当然,用户也可以通过 api创建其它名称的ServiceAccount,并在该namespace的Pod的spec.ServiceAccount下指定,默认是default。
- Pod创建的时候,- Admission Controller会根据指定的- ServiceAccount把对应- secret的- ca.crt和- token文件挂载到固定目录- /var/run/secrets/kubernetes.io/serviceaccount下。- 1 
 2
 3
 4- volumeMounts:
 - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
 name: default-token-jbcp7
 readOnly: true
- pod要访问集群的时候,默认利用- Secret其中的- token文件来认证- Pod的身份,利用- ca.crt校验服务端。
OIDC认证
- 可以看到,APIServer本身与OIDC Server(即Identity Provider)并没有太多交互,需要我们自己获取到ID Token后,将其写入Kubectl的配置,由Kubectl使用ID Token来与APIServer交互。
- identity provider会提供- access_token、- id_token、- refresh_token
- 使用kubectl时通过--token参数添加id_token,或者直接把它添加到kubeconfig文件中,kubectl会把id_token添加到http头里
- apiserver会通过证书确认- JWT是否有效、确认- JWT是否过期、身份是否合法等
- 使用 OIDC认证,apiserver需要配置:- --oidc-issuer-url:- identity provider的地址
- --oidc-client-id:- client id,一般配成- kubernetes
- --oidc-username-claim: 如- sub
- --oidc-groups-claim: 如- groups
- --oidc-ca-file: 为- identity provider签名的- CA公钥
 
鉴权
采用 RBAC 判断用户是否有权限进行请求中的操作。如果无权进行操作,api-server 会返回403的状态码,并终止该操作, RBAC 包含三个要素:
- Subjects:可以是开发人员、集群管理员这样的自然人,也可以是系统组件进程、- Pod中的业务进程;
- API Resource:也就是请求对应的访问目标,在- Kubernetes集群中指各类资源对象;
- Verbs:对应为请求对象资源可以进行哪些操作,如- list、get、watch等。
部分常用操作需要的权限如下
- 上图中展示的是前文三要素中的 Resource和Verbs
Role
- Role编排文件描述的同样是三要素中的 Resource和Verbs
RoleBinding
- RoleBinding编排文件将- Role中的两个要素和- Subject绑定在一起了
集群纬度的权限
- 上边讨论的是namespace中的权限模型,除此之外,也可以通过ClusterRole定义一个集群维度的权限模型(如PV、Nodes等namespace中不可见的资源)。
- ClusterRole编排文件几乎和- Role一样,删除指定- namespace的那行即可。
- 通过ClusterRoleBinding进行ClusterRole和Subject的绑定。
系统预置的ClusterRole
- system:basic-user:- system:unauthenticated组(未认证用户组)默认绑定- Role,无任何操作权限
- cluster-admin:- system:masters组默认绑定的- ClusterRole,有集群管理员权限
- 系统组件(kube-controller-manager、kube-scheduler、kube-proxy……)都绑定了默认的ClusterRole
准入控制
- Admisson Controller(准入控制器)是一个拦截器,被编译进- API Server的可执行文件内部
- 以插件的形式运行在 apiserver进程中,会在鉴权阶段之后、对象被持久化到etcd之前,拦截apiserver的请求,对请求的资源对象执行自定义(校验、修改或拒绝等)操作。
- AC有几十种,大体上分为3类:- validating(验证型)用于验证- k8s的资源定义是否符合规则
- mutating(修改型)用于修改- k8s的资源定义,如添加label,一般运行在validating之前
- 既是验证型又是修改型
 
- 只要有一个准入控制器拒绝了该请求,则整个请求被拒绝(HTTP 403Forbidden)并返回一个错误给客户端。
例子
- ResourceQuota
- LimitRanger