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
13apiVersion: 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
4volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-jbcp7
readOnly: truepod
要访问集群的时候,默认利用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