22、认证体系与Service Account和Kubernetes的鉴权体系RBAC

时间:2021-08-22 01:10:23

认证体系与Service Account

1、 Kubernetes的访问控制体系

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

各kubelet也会监听一些套接字,提供一个小型的REST API
   ◼ 10250是具有所在节点上Pod管理权限的读写端口,应谨慎管理
   ◼ 10255仅提供只读操作,是REST API的子集
   ◼ 另外,10248是本地healthz端点使用的端口

22、认证体系与Service Account和Kubernetes的鉴权体系RBAC

API Server内置的访问控制机制
API Server内置了一个有着三级别的访问控制机制
   ◼ 认证:核验请求者身份的合法性
   ◼ 授权:核验请求的操作是否获得许可
   ◼ 准入控制:检查操作内容是否合规

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

2、API身份验证

kubernetes上的用户
“用户”即服务请求者的身份指代,一般使用身份标识符进行识别
   ◼ 用户标识:用户名或者ID
   ◼ 用户组

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

不能被识别为Service Account,也不能被识别为User Account的用户,即“匿名用户”
kubernetes系统上的账号分为两大类的总结:
Service Account:由kubernetes自行管理,并有对应的资源类型,存储在etcd中,名称空间级别资源

User Account:非由kubernetes自行管理,要委托给外部认证服务来实现,外部服务认证只要通过,API Server就认可他的身份,集群级别。
pod的类型
API Server管理的Pod
        (1) 自主式Pod
        (2) 由某个工作负载型控制器控制的Pod
    kubelet直接管理:静态Pod
        并非从API Server加载,而是自行通过某个资源配置文件加载的Pod;

    kubeadm部署的集群中,控制平面中的几个组件的Pod,均为静态Pod,其配置文件位于/etc/kubernetes/manifests/
        etcd 
        kube-apiserver
        kube-scheduler 
        kube-controller-manager        
kubelet通过自动加载某个目录中的资源配置文件启动的Pod,还会持续监视该目录下的配置文件中定义的资源的变动
并重建pod(以上配置文件不可直接编辑,建议复制到别处去修改完没问题后再一次性进行替换)

kubeadm部署的集群各组件认证功能的启用:
    kube-api-server: Master, /etc/kubernetes/manifests/kube-apiserver.yaml    
    各kubelet:/var/lib/kubelet/config.yaml
API Server启用的身份认证机制
基于认证插件支持多种认证方式,而相应认证插件的启用需要经由kube-apiserver上的专用选项完成


kubeadm v1.22 部署的集群默认启用的认证机制如右图红框中的选项,它们依次是
   ◼ X509客户端证书认证
   ◼ Bootstrap令牌认证
   ◼ 身份认证代理
   ◼ Service Account认证

注意:API Server并不保证各认证插件的生效次序与定义的次序相同
下标红框内依次对应的是kubeadm v1.22 部署的集群默认启用的认证机制
kube -API Server认证功能的启用所在位置/etc/kubernetes/manifests/kube-apiserver.yaml

22、认证体系与Service Account和Kubernetes的鉴权体系RBAC

kubelet启用的身份认证机制
kubelet的REST API端点默认通过TCP协议的10250端口提供,支持管理操作

暴漏出来的端点:
kubelet API功能简介
/pods   列出当前kubelet节点上的Pod
/run    在一个容器内运行指定的命令
/exec   在一个容器内运行指定的命令
/configz 设置Kubelet的配置文件参数
/debug   调试信息

需要对客户端身份进行认证
   ◼ 启用的身份认证
      ◆webhook
      ◆x509客户端证书认证
      ◆注意:建议显式禁用匿名用户
   ◼ API Server是该API端点的客户端,因此,kubelet需要在验证客户端身份时信任给API Server颁发数字证书的CA
kubelet认证功能的启用所在位置在/var/lib/kubelet/config.yaml

22、认证体系与Service Account和Kubernetes的鉴权体系RBAC

身份认证策略
X.509客户端证书认证

持有者令牌(bearer token)
   ◼ 静态令牌文件(Static Token File) #用户名和令牌基于文件保存
   ◼ Bootstrap令牌                  #只在节点加如集群时一次性使用
   ◼ Service Account令牌            
   ◼ OIDC(OpenID Connect)令牌      #API Server把认证请求转给第三方。对接公有云认证中心 
   ◼ Webhook令牌                   

身份认证代理(Authenticating Proxy)

匿名请求 #不能认证
X.509数字证书认证及X509数字证书认证测试示例
◼ 在双向TLS通信中,客户端持有数字证书,而API Server信任客户端证书的颁发者
      ◆信任的CA,需要在kube-apiserver程序启动时,通过--client-ca-file选项传递
   ◼ 认证通过后,客户端数字证书中的CN(Common Name)即被识别为用户名,而O(Organization)被识别为组名
   ◼ kubeadm部署的Kubernetes集群,默认使用 /etc/kubernetes/pki/ca.crt 进行客户端认证
      ◆/etc/kubernetes/pki/ca.crt是kubeadm为Kubernetes各组件间颁发数字证书的CA
X509客户端认证
X509客户端认证依赖于PKI证书体系,kubeadm部署Kubernetes集群时会自动生成所需要的证书,它们
位于/etc/kubernetes/pki目录下 

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

kubernetes-ca:除了etcd组件以外的其他组件都是由kubernetes-ca管理,给kube-apiserver签发服务端证书,给其他组件(除etcd外)签发客户端证书,其中kube-apiserver组件与kubelet组件互为客户端和服务端,因为他俩各自都提供了REST-API server    (/etc/kubernetes/pki/ca.crt来管理)

etcd-ca:做为kube-apiserver访问etcd的认证管理,此时前发给kube-apiserver是客户端证书,签发给etcd是服务端证书,其他组件不能直接访问etcd,只能通过kube-apiserver来访问etcd
多个etcd端点,构成etcd集群,三个端点互相通讯,每个端点都持有整个集群的所有数据,因而他们之间关系是对等的,签发的是对等证书来完成集群端点之间的加密通讯。

front-proxy-ca:kube-apiserver把认证功能委托给代理认证服务,需要加密通讯。
X.509数字证书认其他组件证依赖到的PKI体系如图所示

22、认证体系与Service Account和Kubernetes的鉴权体系RBAC

kubernetes-ca,etcd-ca,front-proxy-ca关联的文件

22、认证体系与Service Account和Kubernetes的鉴权体系RBAC

另外,对service account的token进行签名还需要用到一个可选的密钥对
X509客户端认证所有证书

22、认证体系与Service Account和Kubernetes的鉴权体系RBAC

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

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

X509数字证书认证测试
X509数字证书认证测试
   
   ◼ 创建客户端私钥和证书签署请求,为了便于说明问题,以下操作在master节点上以/etc/kubernetes/为工作目录
① 生成私钥: (umask 077; openssl genrsa -out ./pki/mason.key 4096)
② 创建证书签署请求: openssl req -new -key ./pki/mason.key -out ./pki/mason.csr -subj "/CN=mason/O=developers"
③ 由Kubernetes CA签署证书: openssl x509 -req -days 365 -CA ./pki/ca.crt -CAkey ./pki/ca.key -CAcreateserial -
in ./pki/mason.csr -out ./pki/mason.crt
④ 将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
   
   
   ◼ 在k8s-node01上发起访问测试
① 使用kubectl测试:kubectl get pods --client-certificate=$HOME/.certs/mason.crt --client-key=$HOME/.certs/mason.key --
server=https://kubeapi.magedu.com:6443/ --certificate-authority=/etc/kubernetes/pki/ca.crt
② 也可以使用curl命令进行测试
X509数字证书认证测试示例:
第一步:生成私钥,并定义umask为077,以免有人取走私钥信息
[root@K8s-master01 ~]#cd /etc/kubernetes/pki/
[root@K8s-master01 pki]#(umask 077; openssl genrsa -out mason.key 4096)
Generating RSA private key, 4096 bit long modulus (2 primes)
...........................................................................................++++
.++++
e is 65537 (0x010001)
[root@K8s-master01 pki]#ll mason.key
-rw------- 1 root root 3243 11月 18 15:40 mason.key

第二步:基于私钥创建证书签署请求(指定证书持有者mason,属于kubeadmin组)
[root@K8s-master01 pki]#openssl req -new -key ./mason.key -out ./mason.csr -subj "/CN=mason/O=kubeadmin"
[root@K8s-master01 pki]#ll mason.csr
-rw-r--r-- 1 root root 1606 11月 18 15:43 mason.csr

第三步:由kubernetesCA签署证书
[root@K8s-master01 pki]#openssl x509 -req -days 3650 -CAkey ./ca.key -CA ./ca.crt -CAcreateserial -in ./mason.csr -out ./mason.crt
Signature ok
subject=CN = mason, O = kubeadmin
Getting CA Private Key

第四步:将pki目录下的mason.crt、mason.key和ca.crt复制到某部署了kubectl的主机上,即可进行测试
      这里以k8s-node01为示例;只需要复制mason.crt和mason.key即可,因为集群工作节点上已经有ca.crt文件

[root@K8s-master01 pki]#scp mason.key mason.crt K8s-node02:/etc/kubernetes/pki/ 

第五步:在工作节点02上用kubectl进行访问测试
[root@K8s-node02 pki]#kubectl -s https://10.0.0.100:6443 --client-certificate=./mason.crt --client-key=./mason.key --insecure-skip-tls-verify=true get pods
Error from server (Forbidden): pods is forbidden: User "mason" cannot list resource "pods" in API group "" in the namespace "default"
会发现认证已经通过,但对资源的访问没有授权

也可不跳过证书进行访问,因为节点上有ca.crt证书
[root@K8s-node02 pki]#kubectl -s https://10.0.0.100:6443 --client-certificate=./mason.crt --client-key=./mason.key --certificate-authority=./ca.crt get pods

也可以使用curl命令来进行访问测试
[root@K8s-node02 pki]#curl --cert ./mason.crt --key ./mason.key --cacert ./ca.crt  https://10.0.0.100:6443/api/v1/namespaces/default/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"mason\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
静态令牌文件及静态令牌认证测试示例
◼ 令牌信息保存于文本文件中
   ◼ 由kube-apiserver在启动时通过--token-auth-file选项加载
   ◼ 加载完成后的文件变动,仅能通过重启程序进行重载,因此,相关的令牌会长期有效
   ◼ 客户端在HTTP请求中,通过“Authorization Bearer TOKEN”标头附带令牌令牌以完成认证

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

配置示例
① 生成token,命令:echo "$(openssl rand -hex 3).$(openssl rand -hex 8)" 
② 生成static token文件
③ 配置kube-apiserver加载该静态令牌文件以启用相应的认证功能
④ 测试,命令:curl -k -H "Authorization: Bearer TOKEN" -k 
https://API_SERVER:6443/api/v1/namespaces/default/pods/
关于④的测试命令:
API Server上的每个资源对象,都在RESTful API中有一个端点:
        v1:        https://API_SERVER:HOST/api/v1/namespaces/<NS_NAME>/<RESOURCE_NAME>/[<OBJECT_NAME>]
default名称空间下的mypod的Pod资源,URL路径直接访问:
curl https://API_SERVER:HOST/api/v1/namespaces/default/pods/mypod
       
其它群组:          https://API_SERVER:HOST/apis/GROUP_NAME/VERSION/namespaces/<NS_NAME>/<RESOURCE_NAME>/[<OBJECT_NAME>]

关于④的示例:
先查看pods
[root@K8s-master01 ~]#kubectl get pods
NAME                             READY   STATUS    RESTARTS        AGE
client-7438                      0/1     Error     0               39h
daemonset-demo-k4mmx             1/1     Running   2 (145m ago)    25h
daemonset-demo-nn96h             1/1     Running   1 (149m ago)    25h
daemonset-demo-wj4bq             1/1     Running   2 (146m ago)    25h
deployment-demo-8dcb44cb-fjt2t   1/1     Running   4 (143m ago)    39h
deployment-demo-8dcb44cb-j4pg5   1/1     Running   4 (143m ago)    37h
deployment-demo-8dcb44cb-lcdg5   1/1     Running   7 (142m ago)    37h
deployment-demo-8dcb44cb-nzqmz   1/1     Running   22 (143m ago)   37h
pod-with-dnspolicy               1/1     Running   3 (148m ago)    2d14h

找一客户端使用curl命令去访问
[root@K8s-master01 ~]#kubectl run client-$RANDOM --image=ikubernetes/admin-box:v1.2 --restart=Never -it --command -- /bin/bash
If you don't see a command prompt, try pressing enter.
进行访问
root@client-12530 /# curl -k https://10.0.0.100:6443/
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
  "reason": "Forbidden",        #用户被识别成匿名账号,不能请求核心资源群中的所有资源
  "details": {},
  "code": 403

访问具体的pod资源,获取资源详情(get resource)被认证为匿名账号
root@client-12530 /# curl -k https://10.0.0.100:6443/api/v1/namespaces/default/pods/daemonset-demo-wj4bq
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods \"daemonset-demo-wj4bq\" is forbidden: User \"system:anonymous\" cannot get resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {                     #没有权限,因为被认证成匿名账号
    "name": "daemonset-demo-wj4bq",
    "kind": "pods"
  },
  "code": 403

列出来这个类别下所有的资源列表(cannot list resource),被认证为匿名账号
root@client-12530 /# curl -k https://10.0.0.100:6443/api/v1/namespaces/default/pods/
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"system:anonymous\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
  
如果想非匿名,就得拿着账号进行访问
第一步:在/etc/kubernetes/创建quth组
[root@K8s-master01 ~]#cd /etc/kubernetes/
[root@K8s-master01 kubernetes]#mkdir auth
[root@K8s-master01 kubernetes]#cd auth/
第二步:生成三个token
[root@K8s-master01 ~]#echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
0c0e00.f6b62a779a84abac
[root@K8s-master01 ~]#echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
05bf30.51bbd4a043e059c6
[root@K8s-master01 ~]#echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
308ef3.e5dcd15c5f715119
第三步:生成static token文件,输入token信息、用户、用户ID、用户组
[root@K8s-master01 auth]#cat token.csv
0c0e00.f6b62a779a84abac,tom,1001,kubeusers
05bf30.51bbd4a043e059c6,jerry,1002,kubeusers
308ef3.e5dcd15c5f715119,obama,999,kubeadmin

让kubernetes能使用该配置文件中所表示的用户账号,应该编辑/etc/kubernetes/manifests/目录下的
kube-apiserver.yaml文件加上--token-auth-file来加载。
但不能直接编辑原文件,可能会导致kube-apiserver.yaml文件加载失败

拷贝kube-apiserver.yaml文件到/root/目录下
[root@K8s-master01 manifests]#cp kube-apiserver.yaml /root/
[root@K8s-master01 ~]#ls
kube-apiserver.yaml

把关于token账户信息的token.csv文件写入kube-apiserver.yaml中的command字段下的随意位置
[root@K8s-master01 ~]#vim kube-apiserver.yaml
- --token-auth-file=/etc/kubernetes/auth/token.csv

但该文件并不在该容器的文件系统上,使用卷的形式让其关联到当前pod的文件系统上(加到kube-apiserver.yaml文件最后)
挂载
- mountPath: /etc/kubernetes/auth/
      name: static-auth-token
      readOnly: true
      
定义
- hostPath:
      path: /etc/kubernetes/auth
      type: DirectoryOrCreate
    name: static-auth-token
把修改过后的/root/目录下的kube-apiserver.yaml文件替换/etc/kubernetes/manifests/目录下的kube-apiserver.yaml文件
[root@K8s-master01 ~]#cp kube-apiserver.yaml /etc/kubernetes/manifests/
[root@K8s-master01 ~]#kubectl get pods -n kube-system
The connection to the server kubeapi.magedu.com:6443 was refused - did you specify the right host or port?
提示访问被拒绝,因为pod正在被重建,如果文件有问题,就连接不上去了

没问题会显示pod正常运行
[root@K8s-master01 ~]#kubectl get pods -n kube-system
NAME                                   READY   STATUS    RESTARTS          AGE
kube-apiserver-k8s-master01            1/1     Running   0                 29s



请求列出default名称空间下的所有Pod资源:可以识别出tom账号,但仍无法列出default名称空间下的pod,但认证是通过了的,但没有获得资源权限
方法一:客户端进行访问测试
root@client-16659 /# curl -k -H "Authorization: Bearer 0c0e00.f6b62a779a84abac" https://10.0.0.100:6443/api/v1/namespaces/default/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"tom\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403

方法二:kubectl进行访问测试(在工作节点进行访问)
[root@K8s-node02 ~]#kubectl -s https://10.0.0.100:6443 --token="0c0e00.f6b62a779a84abac" --insecure-skip-tls-verify=true get pods -n default
Error from server (Forbidden): pods is forbidden: User "tom" cannot list resource "pods" in API group "" in the namespace "default" 

用户账号就没有保存在kubernetes之上,而是保存在外部的某一个配置文件或者某一个认证服务上

kubeconfig(用文件来加载认证信息)

kubeconfig是YAML格式的文件,用于存储身份认证信息,以便于客户端加载并认证到API Server
   ◼ kubeconfig保存有认证到一至多个Kubernetes集群的相关配置信息,并允许管理员按需在各配置间灵活切换
      ◆clusters:Kubernetes集群访问端点(API Server)列表
      ◆users:认证到API Server的身份凭据列表
      ◆contexts:将每一个user同可认证到的cluster建立关联的上下文列表
      ◆current-context:当前默认使用的context


客户端程序加载的kubeconfig文件的途径及次序
   ◼ --kubeconfig选项
   ◼ KUBECONFIG环境变量:其值是包含有kubeconfig文件的列表
   ◼ 默认路径:$HOME/.kube/config
设定kubeconfig文件
示例1:为静态令牌认证的用户设定一个自定义的kubeconfig文件
① 定义Cluster
      ◆提供包括集群名称、API Server URL和信任的CA的证书相关的配置;clusters配置段中的各列表项名称需要惟一;
      ◆命令:kubectl config set-cluster kube-test --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --
server="https://kubeapi.magedu.com:6443" --kubeconfig=$HOME/.kube/kubeusers.conf

② 定义User
      ◆添加身份凭据,使用静态令牌文件认证的客户端提供令牌令牌即可
      ◆命令:kubectl config set-credentials jerry --token="$JERRY_TOKEN" --kubeconfig=$HOME/.kube/kubeusers.conf

③ 定义Context
      ◆为用户jerry的身份凭据与kube-test集群建立映射关系
      ◆命令:kubectl config set-context jerry@kube-test --cluster=kube-test --user=jerry --kubeconfig=$HOME/.kube/kubeusers.conf

④ 设定Current-Context
      ◆命令: kubectl config use-context jerry@kube-test --kubeconfig=$HOME/.kube/kubeusers.conf
将静态令牌认证信息保存为kubeconfig文件
第一步:定义Cluster 
提供包括集群名称、API Server URL和信任的CA的证书相关的配置;clusters配置段中的各列表项名称需要惟一(更改集群为mykube、IP可换为主机名,如果主机名要换成别的地址,解析结果更容易映射)
[root@K8s-master01 ~]#cd /etc/kubernetes/pki/
kubectl config set-cluster mykube --embed-certs=true --certificate-authority=./ca.crt --server="https://10.0.0.100:6443" --kubeconfig=$HOME/.kube/mykube.conf
Cluster "mykube" set.

#mykube 集群的名称
#--embed-certs=true 表示集群信息,被base64编码以后的证书文件
#--certificate-authority=./ca.crt ca证书路径
#--server="https://10.0.0.100:6443" 指定server地址
#--kubeconfig=$HOME/.kube/mykube.conf 设定kubeconfig保存地址


显示配置文件中定义的信息
[root@K8s-master01 pki]#kubectl config view --kubeconfig=$HOME/.kube/mykube.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.100:6443
  name: mykube                               #集群mykube
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null

第二步:定义User  添加身份凭据,使用静态令牌文件认证的客户端提供令牌令牌即可
查看token信息
[root@K8s-master01 pki]#cat /etc/kubernetes/auth/token.csv 
0c0e00.f6b62a779a84abac,tom,1001,kubeusers
05bf30.51bbd4a043e059c6,jerry,1002,kubeusers
308ef3.e5dcd15c5f715119,obama,999,kubeadmin
利用信息添加身份凭证
[root@K8s-master01 pki]#kubectl config set-credentials tom --token="0c0e00.f6b62a779a84abac" --kubeconfig=$HOME/.kube/mykube.conf
User "tom" set.

显示配置文件中定义的信息(不仅有了Cluster的定义,也有了User的定义)
[root@K8s-master01 pki]#kubectl config view --kubeconfig=$HOME/.kube/mykube.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.100:6443
  name: mykube
contexts: null
current-context: ""
kind: Config
preferences: {}
users:
- name: tom
  user:
    token: REDACTED

第三步:定义Context   为用户tom的身份凭据与mykube集群建立映射关系 
[root@K8s-master01 pki]#kubectl config set-context tom@mykube --cluster=mykube --user=tom --kubeconfig=$HOME/.kube/mykube.conf
Context "tom@mykube" created.

显示配置文件中定义的信息(Context的定义已完成)
[root@K8s-master01 pki]#kubectl config view --kubeconfig=$HOME/.kube/mykube.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.100:6443
  name: mykube
contexts:
- context:
    cluster: mykube
    user: tom
  name: tom@mykube
current-context: ""
kind: Config
preferences: {}
users:
- name: tom
  user:
    token: REDACTED

第四步:设定Current-Context   选择用哪个Context
[root@K8s-master01 pki]# kubectl config use-context tom@mykube --kubeconfig=$HOME/.kube/mykube.conf
Switched to context "tom@mykube".

显示配置文件中定义的信息(Context的定义已完成 选择"tom@mykube")
[root@K8s-master01 pki]#kubectl config view --kubeconfig=$HOME/.kube/mykube.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.100:6443
  name: mykube
contexts:
- context:
    cluster: mykube
    user: tom
  name: tom@mykube
current-context: tom@mykube
kind: Config
preferences: {}
users:
- name: tom
  user:
    token: REDACTED

第五步:指定基于配置文件加载进行访问测试
[root@K8s-master01 pki]# kubectl get pods --kubeconfig=$HOME/.kube/mykube.conf
Error from server (Forbidden): pods is forbidden: User "tom" cannot list resource "pods" in API group "" in the namespace "default"

人为选定使用哪个context进行访问
[root@K8s-master01 pki]#kubectl get pods --context='tom@mykube' --kubeconfig=$HOME/.kube/mykube.conf
Error from server (Forbidden): pods is forbidden: User "tom" cannot list resource "pods" in API group "" in the namespace "default"

用$HOME/.kube/mykube.conf配置文件把默认的配置文件替换掉,或者把这个文件声明为环境变量,就会在$HOME/.kube/mykube.conf配置文件中加载
声明为环境变量:
[root@K8s-master01 pki]#export KUBECONFIG="$HOME/.kube/mykube.conf"

查看pods信息,就会在$HOME/.kube/mykube.conf配置文件中加载(优先级高于默认的配置文件)
[root@K8s-master01 pki]#kubectl get pods
Error from server (Forbidden): pods is forbidden: User "tom" cannot list resource "pods" in API group "" in the namespace "default"
将数字证书认证的信息保存为kubeconfig文件,以下过程中没有新增集群,只添加用户和context:
第一步:定义User  添加身份凭据,使用数字证书认证的客户端提供私钥和证书
[root@K8s-master01 pki]#kubectl config set-credentials mason --embed-certs=true --client-certificate=./mason.crt --client-key=./mason.key --kubeconfig=$HOME/.kube/mykube.conf
User "mason" set.

显示配置文件中定义的信息(有了两个User  tom和mason)
[root@K8s-master01 pki]#kubectl config view --kubeconfig=$HOME/.kube/mykube.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.100:6443
  name: mykube
contexts:
- context:
    cluster: mykube
    user: tom
  name: tom@mykube
current-context: tom@mykube
kind: Config
preferences: {}
users:
- name: mason
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: tom
  user:
    token: REDACTED
    
第二步: 定义Context   为用户mason的身份凭据与mykube集群建立映射关系 
[root@K8s-master01 pki]#kubectl config set-context mason@mykube --cluster=mykube --user=mason --kubeconfig=$HOME/.kube/mykube.conf
Context "mason@mykube" created.

显示配置文件中定义的信息(Context为两个 mason@mykube和tom@mykube 目前使用的为tom@mykube)
[root@K8s-master01 pki]#kubectl config view --kubeconfig=$HOME/.kube/mykube.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.100:6443
  name: mykube
contexts:
- context:
    cluster: mykube
    user: mason
  name: mason@mykube
- context:
    cluster: mykube
    user: tom
  name: tom@mykube
current-context: tom@mykube
kind: Config
preferences: {}
users:
- name: mason
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: tom
  user:
    token: REDACTED
    
访问资源pods(是由tom进行访问的)
[root@K8s-master01 pki]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "tom" cannot list resource "pods" in API group "" in the namespace "default"

临时切换的mason进行访问
[root@K8s-master01 pki]# kubectl --context='mason@mykube' get pods
Error from server (Forbidden): pods is forbidden: User "mason" cannot list resource "pods" in API group "" in the namespace "default"

让mason成为默认访问的用户   设定Current-Context   选择用哪个Context
[root@K8s-master01 pki]#kubectl config use-context mason@mykube --kubeconfig=$HOME/.kube/mykube.conf
Switched to context "mason@mykube".

再次访问,可知默认访问用户已切换成mason
[root@K8s-master01 pki]#kubectl get pods
Error from server (Forbidden): pods is forbidden: User "mason" cannot list resource "pods" in API group "" in the namespace "default"
目前有两个配置文件可用
[root@K8s-master01 pki]#cd $HOME/   
[root@K8s-master01 ~]#cd .kube/
[root@K8s-master01 .kube]#ls
cache  config  mykube.conf
系统默认安装生成的/etc/kubernetes/admin.conf文件与自己生成的在$HOME/.kube/mykube.conf文件合并起来作为配置文件使用
客户端能够通过多种途径获取到kubeconfig文件时,将遵循如下逻辑进行文件合并
   ◼ 设置了--kubeconfig参数时,则仅使用指定的文件,且不进行合并;该参数只能使用一次;
   ◼ 否则,若设置了KUBECONFIG环境变量,则将其值用作应合并的文件列表;处理规则
      ◆忽略不存的文件
      ◆遇到内容无法反序列化的文件时,将生成错误信息
      ◆文件列表中,第一个设定了特定值或映射键(map key)的文件是为生效文件
         ⚫ 修改某个映射键的值时,将修改列表中第一个出现该键的文件中的内容;
         ⚫ 创建一个键时,其将保存于列表中的第一个文件中;
         ⚫ 若列表中指定的文件均不存在时,则自动创建列表中的最后一个文件;
   ◼ 否则 ,将使用默认的“${HOME}/.kube/config”,且不进行合并

context的判定机制
   ◼ 若使用了--context选项,则加载该选项指定要使用的上下文
   ◼ 否则,将使用合并后的kubeconfig文件中的current-context的设定
合并两个文件作为配置文件使用(mykube.conf和默认配置文件admin.conf)
[root@K8s-master01 .kube]#echo $KUBECONFIG
/root/.kube/mykube.conf
[root@K8s-master01 .kube]#export KUBECONFIG=/root/.kube/mykube.conf:/etc/kubernetes/admin.conf
[root@K8s-master01 .kube]#kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://kubeapi.magedu.com:6443
  name: kubernetes
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.100:6443
  name: mykube
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:
    cluster: mykube
    user: mason
  name: mason@mykube
- context:
    cluster: mykube
    user: tom
  name: tom@mykube
current-context: mason@mykube
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: mason
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: tom
  user:
    token: REDACTED

让kubernetes-admin成为默认访问的用户
[root@K8s-master01 .kube]#echo $KUBECONFIG
/root/.kube/mykube.conf:/etc/kubernetes/admin.conf
[root@K8s-master01 .kube]#export KUBECONFIG=/etc/kubernetes/admin.conf

查看pod
[root@K8s-master01 .kube]#kubectl get pod
NAME                             READY   STATUS    RESTARTS      AGE
client-16659                     1/1     Running   0             4h20m
daemonset-demo-k4mmx             1/1     Running   2 (10h ago)   33h
daemonset-demo-nn96h             1/1     Running   1 (10h ago)   33h
daemonset-demo-wj4bq             1/1     Running   2 (10h ago)   33h
deployment-demo-8dcb44cb-fjt2t   1/1     Running   4 (9h ago)    47h
deployment-demo-8dcb44cb-j4pg5   1/1     Running   4 (9h ago)    45h
deployment-demo-8dcb44cb-lcdg5   1/1     Running   7 (9h ago)    45h
deployment-demo-8dcb44cb-nzqmz   1/1     Running   22 (9h ago)   45h
pod-with-dnspolicy               1/1     Running   3 (10h ago)   2d21h
回顾
API Server, etcd 
        Watch 

安全体系:
        禁用匿名
        认证:
            “或”逻辑
            插件:
                token
                    OIDC (KeyCloak动态令牌,需要对接外部的认证中心)
                    静态令牌 
                数字证书:
                    证书:(Subject证书主体)
                        CN, O 
                webhook
            账号:
                User Account: 委托给信任的外部认证机制;账号隶属范围为集群全局;
                Service Account:名称空间级别的资源类型;账号隶属范围为名称空间;
                    专用的认证令牌:ServiceAccount Token 
        鉴权:
            “或”逻辑
            插件: 
                RBAC 
                ABAC: OpenPolicyAgent 
                Node
        准入控制:
            仅对“写”操作生效
            “与”逻辑
            类型: 
                validation
                mutation

Service Account

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

在Pod上使用Service Account
   ◼ 自动设定:Service Account通常由API Server自动创建并通过 ServiceAccount准入控制器自动关联到集群中创建的每个Pod上
   ◼ 自定义:在Pod规范上,使用serviceAccountName指定要使用的特定ServiceAccount
ServiceAccount资源类型
ServiceAccount是Kubernetes API上的标准资源类型
   ◼ 基于资源对象保存ServiceAccount的数据
   ◼ 认证信息保存于ServiceAccount对象专用的Secret中
   ◼ 隶属名称空间级别,专供集群上的Pod中的进程访问API Server时使用
      ◆Kubernetes基于三个组件完成Pod上serviceaccount的自动化
         ⚫ ServiceAccount Admission Controller
         ⚫ Token Controller
         ⚫ ServiceAccount Controller
   ◼ 需要用到特殊权限时,可为Pod指定要使用的自定义ServiceAccount资源对象
ServiceAccount专用的Secret类型
ServiceAccount使用专用的Secret类型存储相关的敏感信息
   ◼ 类型标识为“kubernetes.io/serviceaccount”
   ◼ 有三个固定的数据项,键名称分别为
      ◆ca.crt:Kubernetes CA的数字证书
      ◆namespace:该ServiceAccount可适用的名称空间
      ◆token:认证到API Server的令牌
      信息存放于容器的:/var/run/secrets/kubernetes.io/serviceaccount $ ls
                    ca.crt   namespace  token
      因为安全起见,新版的kubernetes当中,这一功能不在提供了,而且也不会以Secret的方式来对接并为各pod内部注入使用ServiceAccount时提供信息,而分别借助于当wordAPI和project来完成   

ServiceAccount Admission Controller负责完成Pod上的ServiceAccount的自动化
   ◼ 为每个名称空间生成一个默认的default ServiceAccount及其依赖到的Secret对象;
   ◼ 为未定义serviceAccountName的Pod资源自动附加名称空间下的serviceaccounts/default;
   ◼ 为定义了serviceAccountName的Pod资源检查其引用的目标对象是否存在
创建和使用ServiceAccount
创建ServiceAccount
   ◼ 命令式命令
      ◆命令:kubectl create serviceaccount NAME [--dry-run=server|client|none] 
   ◼ 资源配置
apiVersion: v1
kind: ServiceAccount
metadata:
name: …
namespace: …
imagePullSecrets <[]Object>
secrets <[]Object>
automountServiceAccountToken <boolean>


Pod上引用ServiceAccount对象
   ◼ 仅支持引用同一名称空间下的对象
apiVersion: v1
kind: Pod
metadata:
name: …
namespace: …
spec:
serviceAccountName <string>
automountServiceAccountToken <boolean>
…
新版本获取token信息:Secret中的三个键存放位置(ca.crt namespace token)
其token的信息可作为认证凭据来使用
如:把对应的serviceaccount账号的token信息保存为kubeconfig,拿给另外一个进程写脚本自动与API-Server对接时使用
分页查看pod的详细信息可知
[root@K8s-master01 ~]#kubectl get pods daemonset-demo-k4mmx -o yaml |less
Secret中的三个键存放位置在/var/run/secrets/kubernetes.io/serviceaccount

进入交互式接口查看三个键的具体信息
[root@K8s-master01 ~]#kubectl exec -it daemonset-demo-k4mmx -- /bin/sh
/ $ cd /var/run/secrets/kubernetes.io/serviceaccount
/var/run/secrets/kubernetes.io/serviceaccount $ ls
ca.crt     namespace  token

查看token
/var/run/secrets/kubernetes.io/serviceaccount $ cat token
eyJhbGciOiJSUzI1NiIsImtpZCI6InlJSWJiUDFHY2NsMEs4SFNHd0NXcGwzRW1CaXFrdUhXbEcyOW11elBRc2MifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzAwMzE2NzU5LCJpYXQiOjE2Njg3ODA3NTksImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJkYWVtb25zZXQtZGVtby1rNG1teCIsInVpZCI6IjBkZDlmMTYzLTQxOGQtNGMwZi1hNTRhLTJiNzE5MjM1OWMwOCJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6ImE1YjMyM2EyLTliZTItNDM0NS1hOTE0LTNhYjYxN2RkOWE4MyJ9LCJ3YXJuYWZ0ZXIiOjE2Njg3ODQzNjZ9LCJuYmYiOjE2Njg3ODA3NTksInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.jkU4b8lu-CoVTcN8rzTy_ASOZKKSm5MI3v3oKfVb-6XMjqRfzWVQKL4hJoZnQm7mlcqI6l84jVflFexel0f4xMX3YQf44wUTv583fi9hRFpNOl7rvNC9pZCRo_XYApYpnw4o5nkdzc9k8tjF8cCthQ-r_HVw7jFNMqJgE7XJTgeUmdpQUZ3bu9ri2tDvhIXgi4BaNopX1Epb6ni_cOyA-x2QWn83O2Mym8-EYasgDht-5Qp_UCzfRhh2M3kHLuDWu7FkE-xi9JctmmyVg_lCXdOmqdxN3sa1d5NS90MUTSFTtxEkQlZgGvrbftY5YGuqrqx8Mh7NcWsXMBCjgZMuCg

在工作节点上用token信息进行访问
正常情况下是认证不过去的
[root@K8s-node02 pki]#kubectl get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?

把token的信息定义变量
[root@K8s-node02 pki]#TOKEN="eyJhbGciOiJSUzI1NiIsImtpZCI6InlJSWJiUDFHY2NsMEs4SFNHd0NXcGwzRW1CaXFrdUhXbEcyOW11elBRc2MifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzAwMzE2NzU5LCJpYXQiOjE2Njg3ODA3NTksImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJkYWVtb25zZXQtZGVtby1rNG1teCIsInVpZCI6IjBkZDlmMTYzLTQxOGQtNGMwZi1hNTRhLTJiNzE5MjM1OWMwOCJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6ImE1YjMyM2EyLTliZTItNDM0NS1hOTE0LTNhYjYxN2RkOWE4MyJ9LCJ3YXJuYWZ0ZXIiOjE2Njg3ODQzNjZ9LCJuYmYiOjE2Njg3ODA3NTksInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.jkU4b8lu-CoVTcN8rzTy_ASOZKKSm5MI3v3oKfVb-6XMjqRfzWVQKL4hJoZnQm7mlcqI6l84jVflFexel0f4xMX3YQf44wUTv583fi9hRFpNOl7rvNC9pZCRo_XYApYpnw4o5nkdzc9k8tjF8cCthQ-r_HVw7jFNMqJgE7XJTgeUmdpQUZ3bu9ri2tDvhIXgi4BaNopX1Epb6ni_cOyA-x2QWn83O2Mym8-EYasgDht-5Qp_UCzfRhh2M3kHLuDWu7FkE-xi9JctmmyVg_lCXdOmqdxN3sa1d5NS90MUTSFTtxEkQlZgGvrbftY5YGuqrqx8Mh7NcWsXMBCjgZMuCg"

进行访问(认证通过,但没有权限获取资源信息)
[root@K8s-node02 pki]#kubectl --insecure-skip-tls-verify=true -s https://10.0.0.100:6443 --token=${TOKEN} get pods -n default
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:default" cannot list resource "pods" in API group "" in the namespace "default"
如果是旧版本的kubernetes(v1.23-)如何获取token信息?
每一个serviceaccount都有与之匹配的对应的专用的Secret资源,作为管理员而言,直接拿到Secret资源,找到其中的token字段,把里面内容取出来,使用“base64 -d” 反解一下就可以了
命令
[root@K8s-master01 ~]#kubectl describe secret bootstrap-token-2gewz0 -n kube-system
为pod配置认证从私有Registry下载Image(配置认证凭据)的方法,有两种:
imagePullSecrets 
 (1) pods.spec.imagePullSecrets 
 (2) pods.spec.serviceAccountName 
                (a) serviceaccounts.imagePullSecrets
                指明要加载哪个Secrets,而该Secrets中保存有认证至私有Registry的认证凭据
第二种解释:#间接引用,由pod指定特有的serviceAccount,不能是默认default,人为的手动去创建这个serviceAccount,并在serviceAccount上指明imagePullSecrets字段引用事先创建好的imagePullSecrets
第二种方式间接但相对而言不是直接暴露使用的是哪一个Secrets

Kubernetes的鉴权体系

访问API Server
API Server内置了一个有着三级别的访问控制机制
   ◼ 认证:核验请求者身份的合法性
   ◼ 鉴权:核验请求的操作是否获得许可
   ◼ 准入控制:检查操作内容是否合规

插件化机制,每种访问控制机制均有一组专用的插件栈
   ◼ 认证:身份核验过程遵循“或”逻辑,且任何一个插件核验成功后都将不再进行后续的插件验证
      ◆均不成功,则失败,或以“匿名者”身份访问
      ◆建议禁用“匿名者”
   ◼ 鉴权:鉴权过程遵循“或”逻辑,且任何一个插件对操作的许可授权后都将不再进行后续的插件验证
      ◆均未许可,则拒绝请求的操作
   ◼ 准入控制:内容合规性检查过程遵循“与”逻辑,且无论成败,每次的操作请求都要经由所有插件的检验
      ◆将数据写入etcd前,负责检查内容的有效性,因此仅对“写”操作有效
      ◆分两类:validating(校验)和 mutating(补全或订正)
Kubernetes鉴权体系(生产环境默认使用Node和RBAC,增强功能结合第三方使用ABAC)
API Server中的鉴权框架及启用的鉴权模块负责鉴权
   ◼ 支持的鉴权模块
      ◆Node:专用的授权模块,它基于kubelet将要运行的Pod向kubelet进行授权;
      ◆ABAC:通过将属性(包括资源属性、用户属性、对象和环境属性等)组合 在一起的策略,将访问权限授予用户;
      ◆RBAC:基于企业内个人用户的角色来管理对计算机或网络资源的访问的鉴权方法;
      ◆Webhook:用于支持同Kubernetes外部的授权机制进行集成;
   ◼ 另外两个特殊的鉴权模块是AlwaysDeny(无论什么请求都拒绝)和AlwaysAllow(无论什么请求都放行);

配置方法
   ◼ 在kube-apiserver上使用 --authorization-mode 选项进行定义
      ◆kubeadm部署的集群,默认启用了Node和RBAC
   ◼ 多个模块彼此间以逗号分隔
   
[root@K8s-master01 ~]#cd /etc/kubernetes/manifests/
[root@K8s-master01 manifests]#less kube-apiserver.yaml
command字段下
- --authorization-mode=Node,RBAC  #没有明确被授权的统统被拒绝,先定义管理员所有权限再启用
RBAC鉴权模型
RBAC基础
RBAC基础概念
   ◼ 实体(Entity):在RBAC也称为Subject,通常指的是User、Group或者是ServiceAccount;
   ◼ 角色(Role):承载资源操作权限的容器;
   ◼ 资源(Resource):在RBAC中也称为Object,指代Subject期望操作的目标,例如Secret、Pod及Service对象等;
      ◆仅限于/api/v1/…及/apis/<group>/<version>/…起始的路径;
      ◆其它路径对应的端点均被视作“非资源类请求(Non-Resource Requests)”,例如/api或/healthz等端点;
   ◼ 动作(Actions):Subject可以于Object上执行的特定操作,具体的可用动作取决于Kubernetes的定义;
      ◆资源型对象
         ⚫ 只读操作:get、list、watch等
         ⚫ 读写操作:create、update、patch、delete、deletecollection等
      ◆非资源型端点仅支持get操作
   ◼ 角色绑定(Role Binding):将角色关联至实体上,它能够将角色具体的操作权限赋予给实体;
   

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

角色绑定的类型:(让账号useraccount和serviceaccount与角色绑定)
   ◼ Cluster级别:称为ClusterRoleBinding,可以将实体(User、Group或ServiceAccount)关联至ClusterRole;
   ◼ Namespace级别:称为RoleBinding,可以将实体关联至ClusterRole或Role;
      ◆ 即便将Subject使用RoleBinding关联到了ClusterRole上,该角色赋予到Subject的权限也会降级到RoleBinding所属的Namespace范围之内;
RBAC总结
RBAC:
    动作的发出者:
        User Account 
        Service Account 
        Group  

    鉴权体系:
        角色:许可权限的容器
            Role:名称空间
            ClusterRole:集群级别、名称空间

        角色扮演:角色绑定,权限生效范围取决于Binding自身的级别
            RoleBinding:
                授予Subject名称空间级别的权限

                RoleBinding --> Role (同一名称空间)

                RoleBinding --> ClusterRole (降级使用)

            ClusterRoleBinding:
                授予Subject集群级别的权限

                ClusterRoleBinding --> ClusterRole 

Role、ClusterRole、RoleBinding、ClusterRoleBinding都是标准的API资源类型,支持声明式创建
          但Role和RoleBindg:名称空间级别的资源类型 
            ClusterRoleBinding和ClusterRole:集群级别的资源类型

许可权限:action resource (什么权限操作什么资源)
action(权限): get list watch delete update patch deletecollection, ...

resource:(资源)
obejct: 任何操作类型、  no-resource端点:仅支持get操作
示例:创建名称空间级别的role,然后把role与default名称空间进行关联,其role便有了default名称空间下所有的pod、service资源的get,list,watch权限
[root@K8s-master01 manifests]#kubectl create --help
Available Commands:
clusterrole
clusterrolebinding
role
rolebinding

查看创建角色帮助
[root@K8s-master01 manifests]#kubectl create role --help
Usage:
  kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename]
[--dry-run=server|client|none] [options]
--verb=verb(定义操作)
--resource(定义操作被授予哪些资源上)
通过以上方式来定义,很不灵活,无法定义出非常精准的模型,此命令能帮助我们快速生成定义配置定义的框架
用--dry-run生成框架,再进行修改

如:创建个角色,让他能够读default名称空间下的所有pod和service
[root@K8s-master01 manifests]#kubectl create role reader --verb=get,list,watch --resource=pods,service -o yaml --dry-run=client
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - services
  verbs:
  - get
  - list
  - watch
把这个角色的定义保存下来
[root@K8s-master01 manifests]#kubectl create role reader --verb=get,list,watch --resource=pods,service -o yaml --dry-run=client > role-pod-and-service-reader.yaml
创建角色并与default名称空间进行绑定
[root@K8s-master01 manifests]#kubectl apply -f role-pod-and-service-reader.yaml -n default 
role.rbac.authorization.k8s.io/reader created
创建一个clusterrole
[root@K8s-master01 manifests]#kubectl create clusterrole cluster-reader --verb=get,list,watch --resource=storageclass,persistentvolumes,namespaces,deployments -o yaml --dry-run=client
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: null
  name: cluster-reader
rules:
- apiGroups:
  - ""
  resources:
  - persistentvolumes
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - deployments
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - storage.k8s.io
  resources:
  - storageclasses
  verbs:
  - get
  - list
  - watch
把这个集群角色的定义保存下来
[root@K8s-master01 manifests]#kubectl create clusterrole cluster-reader --verb=get,list,watch --resource=storageclass,persistentvolumes,namespaces,deployments -o yaml --dry-run=client > clusterrole-cluster-reader.yaml  
创建集群角色
[root@K8s-master01 manifests]#kubectl apply -f clusterrole-cluster-reader.yaml 
clusterrole.rbac.authorization.k8s.io/cluster-reader created
查看集群角色
[root@K8s-master01 manifests]#kubectl get clusterrole cluster-reader
NAME             CREATED AT
cluster-reader   2022-11-19T07:33:53Z
默认的ClusterRole及ClusterRoleBinding
查看集群角色
[root@K8s-master01 manifests]#kubectl get clusterrole

启用RBAC鉴权模块时,API Server会自动创建一组ClusterRole和ClusterRoleBinding对象
   ◼ 多数都以“system:”为前缀,也有几个面向用户的ClusterRole未使用该前缀,如cluster-admin、admin等
   ◼ 它们都默认使用“kubernetes.io/bootstrapping: rbac-defaults”这一标签

默认的ClusterRole大体可以分为如下5个类别
   ◼ API发现相关的角色
      ◆包括system:basic-user、system:discovery和system:public-info-viewer
   ◼ 面向用户的角色
      ◆包括cluster-admin、admin、edit和view
   ◼ 核心组件专用的角色
      ◆包括system:kube-scheduler、system:volume-scheduler、system:kube-controller-manager、system:node和system:node-proxier等
   ◼ 其它组件专用的角色
      ◆包括system:kube-dns、system:node-bootstrapper、system:node-problem-detector和system:monitoring等
   ◼ 内置控制器专用的角色
   
面向以上内置的集群角色,可以删除,但是删除之后只要重启集群它会自动重建
剩下的用户自己定义的,或其他组件创建时自动定义的clusterrole,删除不会重建
四个面向用户但却是系统内置的集群角色
用于交互式用户授权目的的几个角色
[root@K8s-master01 manifests]#kubectl get clusterrole

默认的ClusterRole

默认的 ClusterRoleBinding

描述

cluster-admin

system:masters 组

允许用户在目标范围内的任意资源上执行任意操作;

admin


管理员权限,主要用于结合RoleBinding为特定名称空间快速授权生成管理员用户,但不支持对ResourceQuota及Namespace本身进行操作;

edit


接近于admin的权限,支持对名称空间内的大多数对象进行读/写操作,包括Secret,但不允许查看或修改Role及RoleBinding;

view


允许以只读方式访问名称空间中的大多数对象,但不包括Role、RoleBinding和Secret;

cluster-admin主要在集群级别使用,其他的都在名称空间级别使用,但也是集群角色,用roelbinding来绑定他们。

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

引用ClusterRole
   ◼ 命令:kubectl create rolebinding jerry-attachto-cluster-admin --clusterrole=cluster-admin --user=jerry --namespace=test
   ◼ 而后可测试jerry用户对test及其它名称空间中的资源对象的访问权限
rolebinding绑定角色
把原来创建的配置文件拷贝到node01节点上测试使用
[root@K8s-master01 ~]#scp .kube/mykube.conf 10.0.0.103:/root/

在node01上使用kubectl get pods默认不加载任何配置文件
[root@K8s-node01 ~]#kubectl get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?

声明环境变量,把拷贝过来的配置文件让node01使用(发现认证完成了,但授权没通过)
[root@K8s-node01 ~]#kubectl get pods
Error from server (Forbidden): pods is forbidden: User "mason" cannot list resource "pods" in API group "" in the namespace "default"

把mason这个账号绑定到此前创建的default名称空间下的role,其就具有了default名称空间下查看pods和service的权限
[root@K8s-master01 ~]#kubectl get role
NAME     CREATED AT
reader   2022-11-19T03:07:24Z

创建rolebinding
[root@K8s-master01 ~]#kubectl create rolebinding mason-and-reader-role --role=reader --user=mason -n default
rolebinding.rbac.authorization.k8s.io/mason-and-reader-role created
[root@K8s-master01 ~]#kubectl create rolebinding mason-and-reader-role --role=reader --user=mason -n default -o yaml --dry-run=client
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: mason-and-reader-role
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: mason


现在mason就具有了default名称空间下的pods和service的获取权限(在node01上查看)
[root@K8s-node01 ~]#kubectl get pods
NAME                             READY   STATUS    RESTARTS        AGE
client-16659                     0/1     Error     0               25h
daemonset-demo-k4mmx             1/1     Running   3 (7h7m ago)    2d6h
daemonset-demo-nn96h             0/1     Running   2 (7h7m ago)    2d6h
daemonset-demo-wj4bq             1/1     Running   4 (7h4m ago)    2d6h
deployment-demo-8dcb44cb-fjt2t   1/1     Running   6 (7h3m ago)    2d20h
deployment-demo-8dcb44cb-j4pg5   1/1     Running   6 (7h2m ago)    2d18h
deployment-demo-8dcb44cb-lcdg5   1/1     Running   9 (7h2m ago)    2d18h
deployment-demo-8dcb44cb-nzqmz   1/1     Running   24 (7h2m ago)   2d18h
pod-with-dnspolicy               1/1     Running   4 (7h8m ago)    3d19h
[root@K8s-node01 ~]#kubectl get service
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
demoapp-svc   ClusterIP   10.101.199.252   <none>        80/TCP    2d23h
kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP   3d4h
rolebinding绑定集群角色cluster-admin在名称空间下降级使用(可以删除自身名称空间)
创建名称空间
[root@K8s-master01 ~]#kubectl create namespace test
namespace/test created
创建rolebinding,绑定集群角色
[root@K8s-master01 ~]#kubectl create rolebinding mason-test-cluster-admin --clusterrole=cluster-admin --user=mason -n test
rolebinding.rbac.authorization.k8s.io/mason-test-cluster-admin created
查看test名称空间下的rolebinding
[root@K8s-master01 ~]#kubectl get rolebinding -n test
NAME                       ROLE                        AGE
mason-test-cluster-admin   ClusterRole/cluster-admin   70s

现在mason对test名称空间具有管理员权限
[root@K8s-node01 ~]#kubectl get pods -n test
No resources found in test namespace.
在test名称空间下创建demoapp
[root@K8s-node01 ~]#kubectl create deployment demoapp --image=ikubernetes/demoapp:v1.0 -n test
deployment.apps/demoapp created
查看pods
[root@K8s-node01 ~]#kubectl get pods -n test
NAME                       READY   STATUS    RESTARTS   AGE
demoapp-55c5f88dcb-d2mgn   1/1     Running   0          11s

虽然绑定的是cluster-admin,但依然没有权限删除其他名称空间下的资源
[root@K8s-node01 ~]#kubectl get pods 
NAME                             READY   STATUS    RESTARTS         AGE
client-16659                     0/1     Error     0                26h
daemonset-demo-k4mmx             1/1     Running   3 (7h31m ago)    2d7h
daemonset-demo-nn96h             0/1     Running   2 (7h31m ago)    2d7h
daemonset-demo-wj4bq             1/1     Running   4 (7h28m ago)    2d7h
deployment-demo-8dcb44cb-fjt2t   1/1     Running   6 (7h27m ago)    2d20h
deployment-demo-8dcb44cb-j4pg5   1/1     Running   6 (7h26m ago)    2d19h
deployment-demo-8dcb44cb-lcdg5   1/1     Running   9 (7h26m ago)    2d19h
deployment-demo-8dcb44cb-nzqmz   1/1     Running   24 (7h26m ago)   2d19h
pod-with-dnspolicy               1/1     Running   4 (7h31m ago)    3d19h
[root@K8s-node01 ~]#kubectl delete pods client-16659
Error from server (Forbidden): pods "client-16659" is forbidden: User "mason" cannot delete resource "pods" in API group "" in the namespace "default"

当删除自身的名称空间时,其绑定的角色也会被删除。
[root@K8s-node01 ~]#kubectl delete namespace test
namespace "test" deleted
rolebinding绑定集群角色admin在名称空间下的使用(删除不了名称空间自身)
创建名称空间
[root@K8s-master01 ~]#kubectl create namespace test
namespace/test created
创建rolebinding,绑定集群角色
[root@K8s-master01 ~]#kubectl create rolebinding mason-test-cluster-admin --clusterrole=admin --user=mason -n test
rolebinding.rbac.authorization.k8s.io/mason-test-cluster-admin created
在test名称空间下创建demoapp
[root@K8s-node01 ~]#kubectl create deployment demoapp --image=ikubernetes/demoapp:v1.0 -n test
deployment.apps/demoapp created
查看pods
[root@K8s-node01 ~]#kubectl get pods -n test
NAME                       READY   STATUS    RESTARTS   AGE
demoapp-55c5f88dcb-d2mgn   1/1     Running   0          11s
删除deployment
[root@K8s-node01 ~]#kubectl delete deployment --all -n test
deployment.apps "demoapp" deleted

但是他删除不了名称空间自身(不具备名称空间自身的管理权限)
[root@K8s-node01 ~]#kubectl delete namespace -n test
error: resource(s) were provided, but no name was specified
edit和view就不再一一验证,知道以上表格中逻辑即可
以上实验,mason账号只具备绑定后的名称空间下的权限,期望mason账号具备整个集群的管理权限
用clusterrolebinding绑定内置的集群角色cluster-admin、admin、edit、view,就立刻扩展到了所有的名称空间上
[root@K8s-node01 ~]#kubectl create clusterrolebinding --help
Usage:
  kubectl create clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname]
[--serviceaccount=namespace:serviceaccountname] [--dry-run=server|client|none] [options]
其中cluster-admin具有一切资源的定义
[root@K8s-master01 ~]#kubectl get clusterrole cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2022-11-07T02:23:21Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
  resourceVersion: "74"
  uid: 4b94617d-87e4-4cf3-99f1-b43aea0d744f
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'
让mason账号具备整个集群的管理权限
创建clusterrolebinding
[root@K8s-master01 ~]#kubectl create clusterrolebinding mason-cluster-admin --clusterrole=cluster-admin --user=mason
clusterrolebinding.rbac.authorization.k8s.io/mason-cluster-admin created
查看
[root@K8s-master01 ~]#kubectl create clusterrolebinding mason-cluster-admin --clusterrole=cluster-admin --user=mason -o yaml --dry-run=client
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: null
  name: mason-cluster-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: mason

去node01节点上查验,发现mason账号具备整个集群的所有管理权限,和默认的用户账号一样
[root@K8s-node01 ~]#kubectl get pods -n kube-system
NAME                                   READY   STATUS    RESTARTS       AGE
coredns-565d847f94-ql7cb               1/1     Running   4 (8h ago)     3d22h
coredns-565d847f94-sr27n               1/1     Running   9 (8h ago)     12d
csi-nfs-controller-65cf7d587-5sxvg     3/3     Running   21 (8h ago)    6d2h
csi-nfs-controller-65cf7d587-z9nn5     3/3     Running   23 (8h ago)    6d2h
csi-nfs-node-8xw66                     3/3     Running   27 (8h ago)    6d2h
创建名称空间
[root@K8s-node01 ~]#kubectl create namespace hello
namespace/hello created
总结
鉴权体系: 
    鉴权模块:
        Node 
        RBAC: Role-Based Access Controller  (基于角色的访问控制)
        ABAC: Attribute-Base AC  
            OpenPolicyAgent, ...
        Webhook 

    RBAC: 
        主谓宾
            主:认证
            谓:操作
                GET, PUT, POST, HEAD, DELETE, ...
                get, create, edit, patch, ...
            宾:操作的承受者
                /api/v1/...
                /apis/<GROUP>/<VERSION/...
                    名称空间:namespaces/<NS_NAME>/<Kind>/<OBJECT_NAME>

        谓宾:
            角色...

        API Server: 
            HTTP Server 
                curl 
                kubectl 

    RBAC功能的承载组件:
        Role:名称空间 
        ClusterRole: 集群级别的资源,生效范围亦是集群范围

        RoleBinding: 名称空间
            RoleBinding --> Role: 二者要在同一名称空间,主语的操作权限亦被限定在同一名称空间;

            RoleBinding --> ClusterRole: RoleBinding所在的名称空间,即为生效的名称空间,ClusterRole上定义的所有权限,仅覆盖到的RoleBinding所在的名称空间这个子集生效;

        ClusterRoleBinding

            ClusterRoleBinding --> ClusterRole: 权限的作用范围,以及授予的权限范围都是整个集群; 
                ServiceAccount,UserAccount, Group:得到的操作权限是整个集群范围; 
    
    命令:
        kubectl create role|clusterrole 
            --verb=VERB --resource= --resource-name=

        kubectl create rolebinding|clusterrolebinding
            --user --serviceaccount --group --role --clusterrole