Kubernetes认证、鉴权

Kubernetes API Server 安全体系基础

一、API Server及其各客户端的通信模型

1、API Server是Kubernetes集群的网关,是能够与etcd通信惟一入口

1)kube-controller-manager、kube-scheduler、kubelet、kube-proxy,以及后续部署的集群插件CoreDNS、Project Calico等,彼此间互不通信,彼此间的所有协作均经由API Server的REST API进行,它们都是API Server的客户端
2)确保对API Server的安全访问至关重要
  a、客户端对API Server的访问应经过身份验证及权限检查
  b、为防止中间人攻击,各类客户端与API Server间的通信都应使用TLS进行加密

2、各kubelet也会监听一些套接字,提供一个小型的REST API

1)10250是具有所在节点上Pod管理权限的读写端口,应谨慎管理
2)10255仅提供只读操作,是REST API的子集
3)另外,10248是本地healthz端点使用的端口

 二、API Server内置的访问控制机制

1、API Server内置了一个有着三级别的访问控制机制

1)认证:核验请求者身份的合法性
2)授权:核验请求的操作是否获得许可
3)准入控制:检查操作内容是否合规

 2、插件化机制,每种访问控制机制均有一组专用的插件栈

1)认证:身份核验过程遵循“或”逻辑,且任何一个插件核验成功后都将不再进行后续的插件验证
  a、均不成功,则失败,或以“匿名者”身份访问
  b、建议禁用“匿名者”
2)授权:鉴权过程遵循“或”逻辑,且任何一个插件对操作的许可授权后都将不再进行后续的插件验证
  a、均未许可,则拒绝请求的操作
3)准入控制:内容合规性检查过程遵循“与”逻辑,且无论成败,每次的操作请求都要经由所有插件的检验
  a、将数据写入etcd前,负责检查内容的有效性,因此仅对“写”操作有效
  b、分两类:validating(校验)和 mutating(补全或订正) 

三、Kubernetes上的用户

1、“用户”即服务请求者的身份指代,一般使用身份标识符进行识别

1)用户标识:用户名或者ID
2)用户组

2、Kubernetes系统的用户大体可分为 2 类

1)Service Account:服务账户,指Pod内的进程访问API Server时使用的身份信息
  a、API Server使用ServiceAccount类型的资源对象来保存该类账号
  b、认证到API Server的认证信息称为Service Account Token,它们保存于同名的专用类型的Secret对象中
  c、名称空间级别
2)User Account:用户账户,指非Pod类的客户端访问API Server时使用的身份标识,一般是现实中的“人”
  a、API Server没有为这类账户提供保存其信息的资源类型,相关的信息通常保存于外部的文件或认证系统中
  b、身份核验操作可由API Server进行,也可能是由外部身份认证服务完成
  c、本身非由Kubernetes管理,因而作用域为整个集群级别

3、不能被识别为Service Account,也不能被识别为User Account的用户,即“匿名用户”

认证插件、认证体系、kubeconfig及配置案例

一、身份认证策略

1、X.509客户端证书认证

2、持有者令牌(bearer token)

  a、静态令牌文件(Static Token File)
  b、Bootstrap令牌
  c、 Service Account令牌
  d、OIDC(OpenID Connect)令牌
  e、 Webhook令牌

3、身份认证代理(Authenticating Proxy)

4、匿名请求

二、API Server启用的身份认证机制

1、基于认证插件支持多种认证方式,而相应认证插件的启用需要经由kube-apiserver上的专用选项完成

2、kubeadm v1.23 部署的集群默认启用的认证机制如右图红框中的选项,它们依次是

1) X509客户端证书认证
2)Bootstrap令牌认证
3)身份认证代理
4)Service Account认证

3、注意:API Server并不保证各认证插件的生效次序与定义的次序相同

 三、kubelet启用的身份认证机制

1、kubelet的REST API端点默认通过TCP协议的10250端口提供,支持管理操作 

2、需要对客户端身份进行认证 

1)启用的身份认证
  a、 webhook
  b、x509客户端证书认证
  c、注意:建议显式禁用匿名用户
2)API Server是该API端点的客户端,因此,kubelet需要在验证客户端身份时信任给API Server颁发数字证书的CA

四、身份认证策略(2)

1、X.509数字证书认证

1)在双向TLS通信中,客户端持有数字证书,而API Server信任客户端证书的颁发者
  a、信任的CA,需要在kube-apiserver程序启动时,通过--client-ca-file选项传递
2)认证通过后,客户端数字证书中的CN(Common Name)即被识别为用户名,而O(Organization)被识别为组名
3)kubeadm部署的Kubernetes集群,默认使用 /etc/kubernetes/pki/ca.crt 进行客户端认证
  a、/etc/kubernetes/pki/ca.crt是kubeadm为Kubernetes各组件间颁发数字证书的CA

2、静态令牌文件

1)令牌信息保存于文本文件中
2)由kube-apiserver在启动时通过--token-auth-file选项加载
3)加载完成后的文件变动,仅能通过重启程序进行重载,因此,相关的令牌会长期有效
4)客户端在HTTP请求中,通过“Authorization Bearer TOKEN”标头附带令牌令牌以完成认证

3、Service Account令牌

1) 该认证方式将由kube-apiserver程序内置直接启用
2)它借助于经过签名的Bearer Token来验证请求
  a、签名时使用的密钥可以由--service-account-key-file选项指定,也可以默认使用API Server的tls私钥
3)用于将Pod认证到API Server之上,以支持集群内的进程与API Server通信
  a、Kubernetes可使用ServiceAccount准入控制器自动为Pod关联ServiceAccount

4、OpenID Connect(OIDC)令牌

1)OAuth2认证机制,通常由底层的IaaS服务所提供

5、Webhook令牌认证

1) 是一种用于验证Bearer Token的回调机制
2)能够扩展支持外部的认证服务,例如LDAP等

6、身份认证代理

1)由kube-apiserver从请求报文的特定HTTP标头中识别用户身份,相应的标头名称可由特定的选项配置指定
2)kube-apiserver应该基于专用的CA来验证代理服务器身份

五、静态令牌认证配置案例

1、静态令牌认证的基础配置

1)令牌信息保存于文本文件中
  a、文件格式为CSV,每行定义一个用户,由“令牌、用户名、用户ID和所属的用户组”四个字段组成,用户组为可选字段
  b、格式:token,user,uid,"group1,group2,group3"
2)由kube-apiserver在启动时通过--token-auth-file选项加载
3)加载完成后的文件变动,仅能通过重启程序进行重载,因此,相关的令牌会长期有效
4) 客户端在HTTP请求中,通过“Authorization Bearer TOKEN”标头附带令牌令牌以完成认证

2、配置示例

1) 生成token,命令:echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
[root@master ~]#  echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"    
d6ab9b.f78bd3d0690a6f55
[root@master ~]#  echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"    
926226.75e35001522d4a5b
[root@master ~]#  echo "$(openssl rand -hex 3).$(openssl rand -hex 8)" 
856180.cbe5e6ebe3906267
2)生成static token文件
vim token.csv
d6ab9b.f78bd3d0690a6f55,nuo,0725,"kubeusers,kubeadin"
926226.75e35001522d4a5b,xing,1015,"kubersers"
856180.cbe5e6ebe3906267,ting,1011,"kubersers"
3)配置kube-apiserver加载该静态令牌文件以启用相应的认证功能
[root@master manifests]# cp kube-apiserver.yaml /tmp/
[root@master manifests]# vim /tmp/kube-apiserver.yaml 

  [root@master manifests]# cp /tmp/kube-apiserver.yaml ./

 

 

4)测试,命令:
[root@node1 kubernetes]# kubectl --server https://master:6443 --token="d6ab9b.f78bd3d0690a6f55" --certificate-authority=/etc/kubernetes/pki/ca.crt get pods
Error from server (Forbidden): pods is forbidden: User "nuo" cannot list resource "pods" in API group "" in the namespace "default"

curl -k -H "Authorization: Bearer TOKEN"  -k https://API_SERVER:6443/api/v1/namespaces/default/pods/

[root@node1 kubernetes]# curl -k -H "Authorization: Bearer 856180.cbe5e6ebe3906267"  -k https://master:6443/api/v1/namespaces/default/pods/
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"ting\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403

 https://API_SERVER:6443/api/v1/namespaces/NS_NAME/kinds/OBJECT_NAME  #core

https://API_SERVER:6443/apis/GROUP_NAME/VERSION/namespaces/NS_NAME/kinds/OBJECT_NAME #非核心资源群组

 六、X509 数字证书认证

 1、X509客户端认证依赖于PKI证书体系,kubeadm部署Kubernetes集群时会自动生成所需要的证书,它们位于/etc/kubernetes/pki目录下

 2、依赖到的PKI体系 

1)如下图
 
 

 

 2)对Service Account的token进行签名还需要用到一个可选的密钥对儿

3、所有的证书

1)各kubelet的证书可在Bootstrap过程中自动生成证书签署请求,而后由Kubernetes CA予以签署

2)各kube-proxy、kube-scheduler和kube-controller-manager也都有相应的数字证书以完成向API Server的身份认证 

4、X509数字证书认证测试

1) 创建客户端私钥和证书签署请求,为了便于说明问题,以下操作在master节点上以/etc/kubernetes/为工作目录
  ① 生成私钥: (umask 077; openssl genrsa -out ./nuo.key 4096)
[root@master pki]# (umask 077; openssl genrsa -out ./nuo.key 2048)
Generating RSA private key, 2048 bit long modulus
................................................................................+++
.......................................+++
e is 65537 (0x10001)
  ② 创建证书签署请求: openssl req -new -key ./nuo.key -out ./nuo.csr -subj "/CN=nuo/O=kubeadmins"
  ③ 由Kubernetes CA签署证书: openssl x509 -req -days 365 -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -in ./nuo.csr -out ./nuo.crt
[root@master pki]#  openssl x509 -req -days 365 -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -in ./nuo.csr -out ./nuo.crt
Signature ok
subject=/CN=nuo/O=kubeadmins
Getting CA Private Key
  ④ 将pki目录下的mason.crt、mason.key和ca.crt复制到某部署了kubectl的主机上,即可进行测试
    这里以k8s-node01为示例;只需要复制mason.crt和mason.key即可,因为集群工作节点上已经有cr.crt文件
    命令:scp -rp ./pki/{mason.crt,mason.key} k8s-node01:/etc/kubernetes/pki

          scp -p nuo.crt nuo.key 192.168.84.156:/etc/kubernetes/pki/

2)在node01上发起访问测试
  ① 使用kubectl测试:kubectl get pods --client-certificate=$HOME/.certs/nuo.crt --client-key=$HOME/.certs/nuo.key --server=https://master:6443/ --certificate-authority=/etc/kubernetes/pki/ca.crt
[root@node1 pki]# kubectl get pods --client-certificate=/etc/kubernetes/pki/nuo.crt --client-key=/etc/kubernetes/pki/nuo.key --server=https://master:6443/ --certificate-authority=/etc/kubernetes/pki/ca.crt
Error from server (Forbidden): pods is forbidden: User "nuo" cannot list resource "pods" in API group "" in the namespace "default"
  ② 也可以使用curl命令进行测试
 

七、kubeconfig基础

1、kubeconfig是YAML格式的文件,用于存储身份认证信息,以便于客户端加载并认证到API Server

1)kubeconfig保存有认证到一至多个Kubernetes集群的相关配置信息,并允许管理员按需在各配置间灵活切换
  a、clusters:Kubernetes集群访问端点(API Server)列表
  b、users:认证到API Server的身份凭据列表
  c、contexts:将每一个user同可认证到的cluster建立关联的上下文列表
  d、current-context:当前默认使用的contex
2)客户端程序加载的kubeconfig文件的途径及次序
  a、--kubeconfig选项
  b、 KUBECONFIG环境变量:其值是包含有kubeconfig文件的列表
  c、默认路径:$HOME/.kube/config 

 

 

 

 2、命令:kubectl config SUBCOMMAND [options] 

1)打印加载的kubeconfig
  a、view
2)cluster相关的子命令
  a、get-clusters
  b、set-cluster
  c、delete-cluster
3)user相关的子命令
  a、get-users
  b、set-credentials
  c、delete-user
3)context相关的子命令
  a、get-contexts
  b、set-context
  c、delete-context
  d、rename-context
4)current-context相关的子命令
  a、current-context
  b、use-context

3、示例1:为静态令牌认证的用户设定一个自定义的kubeconfig文件 

1)定义Cluster
  a、提供包括集群名称、API Server URL和信任的CA的证书相关的配置;clusters配置段中的各列表项名称需要惟一;
  b、命令:kubectl config set-cluster kube-test[集群名] --embed-certs=true[based64加密]  --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://master:6443" --
kubeconfig=$HOME/.kube/kubeusers.conf
[root@master .kube]# kubectl config set-cluster kube-test --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://master:6443" --kubeconfig=$HOME/.kube/kubeusers.conf
Cluster "kube-test" set.

[root@master .kube]# kubectl config view --kubeconfig=kubeusers.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://master:6443
name: kube-test
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null

2) 定义User
  a、添加身份凭据,使用静态令牌文件认证的客户端提供令牌令牌即可
  b、命令:kubectl config set-credentials jerry --token="$JERRY_TOKEN" --kubeconfig=$HOME/.kube/kubeusers.conf
[root@master .kube]# kubectl config set-credentials nuo --token="d6ab9b.f78bd3d0690a6f55" --kubeconfig=$HOME/.kube/kubeusers.conf
User "nuo" set.
3) 定义Context
  a、为用户nuo的身份凭据与kube-test集群建立映射关系
  b、命令:kubectl config set-context jerry@kube-test --cluster=kube-test --user=jerry --kubeconfig=$HOME/.kube/kubeusers.conf
[root@master .kube]# kubectl config set-context nuo@kube-test --cluster=kube-test --user=nuo --kubeconfig=$HOME/.kube/kubeusers.conf
Context "nuo@kube-test" created.
④ 设定Current-Context
  a、命令: kubectl config use-context jerry@kube-test --kubeconfig=$HOME/.kube/kubeusers.conf
[root@master .kube]# kubectl config use-context nuo@kube-test --kubeconfig=$HOME/.kube/kubeusers.conf
Switched to context "nuo@kube-test".

 

4 、示例2:将基于X509客户端证书认证的mason用户添加至kubeusers.conf文件中,同一个列表下,不同项的名称不能相同

1)定义Cluster
  a、使用不同的身份凭据访问同一集群时,集群相关的配置无须重复定义
2) 定义User
  a、添加身份凭据,基于X509客户端证书认证时,需要提供客户端证书和私钥
  b、命令:kubectl config set-credentials nuo --embed-certs=true --client-certificate=/etc/kubernetes/pki/nuo.crt --client-key=/etc/kubernetes/pki/nuo.key --kubeconfig=$HOME/.kube/kubeusers.conf
[root@master .kube]# kubectl config set-credentials nuo --embed-certs=true --client-certificate=/etc/kubernetes/pki/nuo.crt --client-key=/etc/kubernetes/pki/nuo.key --kubeconfig=$HOME/.kube/kubeusers.conf
User "nuo" set.
3) 定义Context
  a、为用户nuo的身份凭据与kube-test集群建立映射关系
  b、命令:kubectl config set-context nuo@kube-test --cluster=kube-test --user=nuo --kubeconfig=$HOME/.kube/kubeusers.conf
4) 设定Current-Context
  a、命令: kubectl config use-context nuo@kube-test --kubeconfig=$HOME/.kube/kubeusers.conf

 

 Service Account及其应用

一、Service Account基础

1、Service Account的作用

1)Kubernetes原生(kubernetes-native)托管运行于Kubernetes之上,通常需要直接与API Server进行交互以获取必要的信息
2)API Server同样需要对这类来自于Pod资源中客户端程序进行身份验证,ServiceAccount也就是设计专用于这类场景的账号
3)ServiceAccount是API Server支持的标准资源类型之一

 2、在Pod上使用Service Account

1)自动设定:Service Account通常由API Server自动创建并通过 ServiceAccount准入控制器自动关联到集群中创建的每个Pod上
2)自定义:在Pod规范上,使用serviceAccountName指定要使用的特定ServiceAccount

二、ServiceAccount专用的Secret类型

1、ServiceAccount使用专用的Secret类型存储相关的敏感信息

1)类型标识为“kubernetes.io/serviceaccount”
2)有三个固定的数据项,键名称分别为
  ca.crt:Kubernetes CA的数字证书
  namespace:该ServiceAccount可适用的名称空间
  token:认证到API Server的令牌

2、ServiceAccount Admission Controller负责完成Pod上的ServiceAccount的自动化

1)为每个名称空间生成一个默认的default ServiceAccount及其依赖到的Secret对象

2)为未定义serviceAccountName的Pod资源自动附加名称空间下的serviceaccounts/default

3)为定义了serviceAccountName的Pod资源检查其引用的目标对象是否存在

三、创建和使用ServiceAccount

1、创建ServiceAccount

1)命令式命令 
命令:kubectl create serviceaccount NAME [--dry-run=server|client|none]

2)资源配置

apiVersion: v1
kind: ServiceAccount
metadata:
  name: …
  namespace: …
imagePullSecrets <[]Object>
secrets <[]Object>
automountServiceAccountToken <boolean>

 

2、Pod上引用ServiceAccount对象

1)仅支持引用同一名称空间下的对象
apiVersion: v1
kind: Pod
metadata:
   name: …
   namespace: …
spec:
   serviceAccountName <string>
   automountServiceAccountToken <boolean> …

 

鉴权插件、RBAC

一、Kubernetes的鉴权体系

1、API Server中的鉴权框架及启用的鉴权模块负责鉴权

1)支持的鉴权模块
  a、Node:专用的授权模块,它基于kubelet将要运行的Pod向kubelet进行授权;
  b、ABAC:通过将属性(包括资源属性、用户属性、对象和环境属性等)组合 在一起的策略,将访问权限授予用户;
  c、RBAC:基于企业内个人用户的角色来管理对计算机或网络资源的访问的鉴权方法;
  d、Webhook:用于支持同Kubernetes外部的授权机制进行集成;
2)另外两个特殊的鉴权模块是AlwaysDeny和AlwaysAllow

2、配置方法

1)在kube-apiserver上使用 --authorization-mode 选项进行定义

  a、kubeadm部署的集群,默认启用了Node和RBAC
2)多个模块彼此间以逗号分隔

二、RBAC 的基础术语

1、实体(Entity):在RBAC也称为Subject,通常指的是User、Group或者是ServiceAccount;

2、角色(Role):承载资源操作权限的容器;

3、资源(Resource):在RBAC中也称为Object,指代Subject期望操作的目标,例如Secret、Pod及Service对象等;

  a、仅限于/api/v1/…及/apis/<group>/<version>/…起始的路径;
  b、其它路径对应的端点均被视作“非资源类请求(Non-Resource Requests)”,例如/api或/healthz等端点;

4、动作(Actions):Subject可以于Object上执行的特定操作,具体的可用动作取决于Kubernetes的定义;

1)资源型对象
    只读操作:get、list、watch等
    读写操作:create、update、patch、delete、deletecollection等
2)非资源型端点仅支持get操作

5、角色绑定(Role Binding):将角色关联至实体上,它能够将角色具体的操作权限赋予给实体

三、RBAC 的基础概念

1、角色的类型

1)Cluster级别:称为ClusterRole,定义集群范围内的资源操作权限集合,包括集群级别及名称空间级别的资源对象;
2)Namespace级别:称为Role,定义名称空间范围内的资源操作权限集合;

2、角色绑定的类型

1)Cluster级别:称为ClusterRoleBinding,可以将实体(User、Group或ServiceAccount)关联至ClusterRole;
2)Namespace级别:称为RoleBinding,可以将实体关联至ClusterRole或Role;
    a、即便将Subject使用RoleBinding关联到了ClusterRole上,该角色赋予到Subject的权限
    b、也会降级到RoleBinding所属的Namespace范围之内;

四、RBAC的基本工作逻辑

1、Namespace、Subject、Role和RoleBinding之间的关系 

 

 

五、默认的ClusterRole及ClusterRoleBinding

1、启用RBAC鉴权模块时,API Server会自动创建一组ClusterRole和ClusterRoleBinding对象

1)多数都以“system:”为前缀,也有几个面向用户的ClusterRole未使用该前缀,如cluster-admin、admin等
2)它们都默认使用“kubernetes.io/bootstrapping: rbac-defaults”这一标签

2、默认的ClusterRole大体可以分为如下5个类别

1)API发现相关的角色
  a、包括system:basic-user、system:discovery和system:public-info-viewer
2)面向用户的角色
  a、包括cluster-admin、admin、edit和view
4)核心组件专用的角色
  a、包括system:kube-scheduler、system:volume-scheduler、system:kube-controller-manager、system:node和system:node-proxier等
5)其它组件专用的角色
  a、包括system:kube-dns、system:node-bootstrapper、system:node-problem-detector和system:monitoring等
6)内置控制器专用的角色

六、Role 资源

1、命令式命令

1)kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename]
  a、verb:允许在资源上使用的操作(verb)列表
  b、resources.group/subresource:操作可施加的目标资源类型或子资源列表
  c、resourcename:特定的资源对象列表,可选
2)示例:kubectl create role pods-viewer --verb="get,list,watch" --resource="pods" --namespace=default

2、生成的资源对象的资源配置 

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pods-viewer
  namespace: default
rules:
- apiGroups: 
- "" resources: - pods verbs: - get - list - watch

 

 

七、RoleBinding资源

1、命令式命令

1)命令:kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname]
  a、可以绑定到Role,也可以绑定到ClusterRole,后者会将ClusterRole的权限缩减至当前名称空间之内
  b、Subject可以是User、Group或者ServiceAccount
2)示例:将用户tom绑定至角色pods-viewer之上
  a、命令:kubectl create rolebinding tom-attachto-pods-viewer --role=pods-viewer --user=tom --namespace=default
  b、而后可测试tom用户是否可读取default名称空间内的pods资源,以及其它资源

2、引用ClusterRole

1)命令:kubectl create rolebinding jerry-attachto-cluster-admin --clusterrole=cluster-admin --user=jerry --namespace=test
2)而后可测试jerry用户对test及其它名称空间中的资源对象的访问权限
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: tom-attachto-pods-viewer
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pods-viewer
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: tom

 

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
   name: jerry-attachto-cluster-admin
   namespace: test
roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
   name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: jerry

 

八、ClusterRole和ClusterRoleBinding

1、命令式命令

1)ClusterRole:kubectl create clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename]
2)ClusterRoleBinding:kubectl create clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname]
3)示例:kubectl create clusterrolebinding mason --clusterrole=view --group=developers

2、资源规范

1)ClusterRole的资源规范同Role相似
2)ClusterRoleBidning的资源规范跟RoleBinding相似 

 

posted @ 2023-03-08 16:11  耿筱诺  阅读(311)  评论(0编辑  收藏  举报