K8s-RBAC权限管理

发布时间 2023-04-25 16:05:19作者: yuanbangchen
一、RBAC概述
RBAC引入了四个新的顶级资源对象。Role、ClusterRole、RoleBinding、 ClusterRoleBinding。同其他 API 资源对象一样,用户可以使用 kubectl 或者 API 调用等 方式操作这些资源对象。kubernetes集群相关所有的交互都通过apiserver来完成,对于这样集中式管理的系统来说,从1.6版本起,K8S默认启用RBAC访问控制策略,目前RBAC已作为稳定的功能,通过启动文件kube-apiserver.service中的-authorization-mode=RBAC 来启用RABC.


API Server目前支持以下几种授权策略:
    AlwaysDeny:表示拒绝所有请求,一般用于测试。
    AlwaysAllow:允许接收所有请求。如果集群不需要授权流程,则可以采用该策略,这也是Kubernetes的默认配置。
    ABAC(Attribute-Based Access Control):基于属性的访问控制。表示使用用户配置的授权规则对用户请求进行匹配和控制。
    Webhook:通过调用外部REST服务对用户进行授权。
    RBAC:Role-Based Access Control,基于角色的访问控制(本章讲解)。
    Node:是一种专用模式,用于对kubelet发出的请求进行访问控制。
二、用户分类
K8s的用户分两种,一种是普通用户,一种是ServiceAccount(服务账户)。

1、普通用户
普通用户是假定被外部或独立服务管理的。管理员分配私钥。平时常用的kubectl命令都是普通用户执行的。
如果是用户需求权限,则将Role与User(或Group)绑定(这需要创建User/Group),是给用户使用的。

2、ServiceAccount(服务账户)
ServiceAccount(服务帐户)是由KubernetesAPI管理的用户。它们绑定到特定的命名空间,并由API服务器自动创建或通过API调用手动创建。
服务帐户与存储为Secrets的一组证书相关联,这些凭据被挂载到pod中,以便集群进程与Kubernetes API通信。(登录dashboard时我们使用的就是ServiceAccount)
如果是程序需求权限,将Role与ServiceAccount指定(这需要创建ServiceAccount并且在deployment中指定ServiceAccount),是给程序使用的。
三、K8s角色&角色绑定

1.授权介绍
在RABC API中,通过如下的步骤进行授权:
    创建主体:创建用户
    定义角色:在定义角色时会指定此角色对于资源的访问控制的规则。
    绑定角色:将主体与角色进行绑定,对用户进行访问授权。

主体(subject)
    User:用户
    Group:用户组
    ServiceAccount:服务账号

角色(一组权限的集合)
    Role:授权特定命名空间的访问权限
    ClusterRole:授权所有命名空间(集群范围内)的访问权限
    
角色绑定
    RoleBinding:将角色绑定到主体(即subject)
    ClusterRoleBinding:将集群角色绑定到主体



2.角色相关参数(资源和权限)
1、Role和ClsuterRole的Verbs可配置参数(资源)
    get、 list、watch、create、 update、 patch、 delete、 exec、proxy、redirect、 deletecollection

2、Role和ClsuterRole的Resource可配置参数(权限)
    services、 endpoints、pods、secrets、configmaps、crontabs、deployments、jobs、nodes、rolebindings、clusterroles、
daemonsets、replicasets、statefulsets、horizontalpodautoscalers、replicationcontrollers、cronjobs

3、Role和ClsuterRole的APIGroup可配置参数(kubectl api-resources )
    apps、 autoscaling、 batch



主体说明
Kubernetes 有着以下几个内建的用于特殊目的的组:
    system:unauthenticated :未能通过任何一个授权插件检验的账号,即未通过认证测 试的用户所属的组 。
    system :authenticated :认证成功后的用户自动加入的一个组,用于快捷引用所有正常通过认证的用户账号。
    system : serviceaccounts :当前系统上的所有 Service Account 对象。
    system :serviceaccounts :<namespace>:特定命名空间内所有的 Service Account 对象。


1.名称为 “alice@example.com”用户:
subjects:
- kind: User
  name: "alice@example.com"
  apiGroup: rbac.authorization.k8s.io

2.名称为“frontend-admins”的组:
subjects:
- kind: Group
  name: "frontend-admins"
  apiGroup: rbac.authorization.k8s.io

3.在kube-system命名空间中,名称为“default”的服务帐户:
subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

4.在“qa”命名空间中,所有的服务帐户:
subjects:
- kind: Group
  name:system: serviceaccounts:qa
  apiGroup: rbac.authorization.k8s.io

5.所有的服务帐户: 
subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io

6.所有被认证的用户 (version 1.5+):
subjects:
- kind: Group
  name:system: authenticated
  apiGroup: rbac.authorization.k8s.io
实例1:基于Role
1.1:在指定namespace创建账户:
[root@localhost7C role]#  kubectl create serviceaccount laomao -n linux39


1.2:角色:创建role规则:
[root@localhost7C role]# cat linux39-role.yml 
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: linux39
  name: linux39-role     #角色名
rules:
- apiGroups: ["*"]      
  resources: ["pods"]    #资源
  #verbs: ["*"]             #权限
  ##RO-Role
  verbs: ["get", "watch", "list"]
- apiGroups: ["extensions", "apps"]   #允许读/写在 “extensions” 和 “apps” API 组中的 “deployments” 资源:
  resources: ["deployments"]
  #verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  ##RO-Role
  verbs: ["get", "watch", "list"]
  


1.3:角色绑定,将规则与账户进行绑定:
[root@localhost7C role]# cat linux39-bind.yml 
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: role-bind-linux39
  namespace: linux39
subjects:               #主体
- kind: ServiceAccount    #主体类型
  name: laomao          #调用主体名
  namespace: linux39
roleRef:                #角色
  kind: Role            #角色类型
  name: linux39-role    #调用角色名
  apiGroup: rbac.authorization.k8s.io


1.4 查看
[root@localhost7C role]# kubectl apply -f ./ 
[root@localhost7C role]# kubectl get role  -n linux39 
[root@localhost7C role]# kubectl  describe role -n linux39 

[root@localhost7C role]# kubectl  get RoleBinding  -n linux39   
[root@localhost7C role]# kubectl describe  RoleBinding  -n linux39   



1.5:登录dashboard测试(手动输入namespace)
[root@localhost7C role]# kubectl describe secrets  -n linux39  laomao-token-cjxnh 
https://192.168.80.160:30002/#/pod?namespace=linux39
实例2:    基于ClusterRole
[root@localhost7C ClsuterRole]# cat ClsuterRole.yml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-clusterrole
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]


[root@localhost7C ClsuterRole]# cat ClsuterRole-Binding.yml 
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: crb
subjects:
- kind: ServiceAccount
  name: mark          
  namespace: default
roleRef:
  kind: ClusterRole
  name: pod-clusterrole
  apiGroup: rbac.authorization.k8s.io
  
---
#创建用户
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mark
  namespace: default
实战3: 1.基于Role角色创建用户和绑定角色
        2.创建用户的dashboard的登录配置文件,而不是使用token登录。

1.1:在指定namespace创建账户:
# kubectl create serviceaccount laomao -n linux39

1.2:创建role规则:
# cat linux39-role.yml 
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: linux39
  name: linux39-role
rules:
- apiGroups: ["*"]
  resources: ["pods"]
  #verbs: ["*"]
  ##RO-Role
  verbs: ["get", "watch", "list"]
- apiGroups: ["extensions", "apps"]
  resources: ["deployments"]
  #verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  ##RO-Role
  verbs: ["get", "watch", "list"]
  
  

1.3:将规则与账户进行绑定:
# cat linux39-bind.yml 
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: role-bind-linux39
  namespace: linux39
subjects:
- kind: ServiceAccount
  name: laomao
  namespace: linux39
roleRef:
  kind: Role
  name: linux39-role
  apiGroup: rbac.authorization.k8s.io


1.4:获取token名称:
#  kubectl get secret -n  linux39  | grep laomao
laomao-token-cd4b9    kubernetes.io/service-account-token   3      5m37s



1.5:使用base加密: (等同= kubectl describe secrets  -n linux39 laomao-token-cd4b9)
# kubectl get secret laomao-token-cd4b9 -o jsonpath={.data.token} -n linux39 |base64 -d
eyJhbGciOiJSUzI1NiIsImtpZCI6IkR5eEg0ckg0VFlTYkdEcUtTUzFad3R6OEJzOVJHdFRsZ0tGTGVUUFJiTncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJsaW51eDM5Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Imxhb21hby10b2tlbi1jZDRiOSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJsYW9tYW8iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJhNTQyZTlkYy1mMDYyLTQwNmMtOWUwZi05NzA5MjQ2MWNlOTYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6bGludXgzOTpsYW9tYW8ifQ.BK9bv8gqDxeN_ilJiDBm3COf7t2ybE0QM1M56JnGmEnzRRMJCs6uzCds9b9bB-XgVvJwqNi6W8vOj6r2iW4rMdqS9pbJrWOSl9mR756wlMSbLdAUsgHB_ywzy0L20ew13590mor_BPAvTOF5We-_2MwswNgQtUaEU6Yixpg-73Cq1UyZaCILi0h_oLqusEFwxkkunI4dmsUF3QkJ96d_TOerizizWwR716tUm_jGb05izobUjghoL526ngIdzYtND-QQM4_039vzC9WW-yobeNypM-BQADqfvD4g6g_tKiXe61SuegOyobQYQ7jom-dcqVbOU5uVDK_oHg6frHYaLQ

1.6:登录dashboard测试:


二:基于kube-config文件登录dashboard:
2.1:创建csr文件:
# cat laomao-csr.json 
{
  "CN": "jack",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}


2.2:签发证书:
# cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem  -ca-key=/etc/kubernetes/ssl/ca-key.pem -config=/etc/kubernetes/ssl/ca-config.json -profile=kubernetes laomao-csr.json | cfssljson -bare  laomao

# ls laomao*
laomao.csr  laomao-csr.json  laomao-key.pem  laomao.pem

2.3:生成普通用户kubeconfig文件:cluster1群集名(kubectl config  get-clusters)  --server是VIP地址(可以使用本master地址)。参考cat  /root/.kube/config
# kubectl config set-cluster cluster1 --certificate-authority=/etc/kubernetes/ssl/ca.pem --embed-certs=true --server=https://192.168.80.120:6443 --kubeconfig=laomao.kubeconfig

查看config
cat laomao.kubeconfig 



2.4:设置客户端认证参数:
# cp *.pem /etc/kubernetes/ssl/
# kubectl config set-credentials laomao \
--client-certificate=/etc/kubernetes/ssl/laomao.pem \
--client-key=/etc/kubernetes/ssl/laomao-key.pem \
--embed-certs=true \
--kubeconfig=laomao.kubeconfig


2.5:设置上下文参数
kubectl config set-context cluster1 \
--cluster=cluster1 \
--user=laomao \
--namespace=linux39 \
--kubeconfig=laomao.kubeconfig


2.5: 设置默认上下文
kubectl config use-context cluster1 --kubeconfig=laomao.kubeconfig

2.7:获取token:
# kubectl  describe   secrets  laomao-token-cd4b9 -n linux39
Name:         laomao-token-cd4b9
Namespace:    linux39
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: laomao
              kubernetes.io/service-account.uid: a542e9dc-f062-406c-9e0f-97092461ce96

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1350 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IkR5eEg0ckg0VFlTYkdEcUtTUzFad3R6OEJzOVJHdFRsZ0tGTGVUUFJiTncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJsaW51eDM5Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Imxhb21hby10b2tlbi1jZDRiOSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJsYW9tYW8iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJhNTQyZTlkYy1mMDYyLTQwNmMtOWUwZi05NzA5MjQ2MWNlOTYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6bGludXgzOTpsYW9tYW8ifQ.BK9bv8gqDxeN_ilJiDBm3COf7t2ybE0QM1M56JnGmEnzRRMJCs6uzCds9b9bB-XgVvJwqNi6W8vOj6r2iW4rMdqS9pbJrWOSl9mR756wlMSbLdAUsgHB_ywzy0L20ew13590mor_BPAvTOF5We-_2MwswNgQtUaEU6Yixpg-73Cq1UyZaCILi0h_oLqusEFwxkkunI4dmsUF3QkJ96d_TOerizizWwR716tUm_jGb05izobUjghoL526ngIdzYtND-QQM4_039vzC9WW-yobeNypM-BQADqfvD4g6g_tKiXe61SuegOyobQYQ7jom-dcqVbOU5uVDK_oHg6frHYaLQ

2.8:将token写入用户kube-config文件(注意格式):


2.9:dashboard登录测试:
https://172.31.7.201:30002/#/pod?namespace=linux39
实战4:基于角色访问控制(RBAC)子系统会确定用户是否有权针对 某资源执行特定的操作。

普通用户并不是通过k8s来创建和维护,是通过创建证书和切换上下文环境的方式来创建和切换用户。

尽管无法通过 API 调用来添加给kubernetes增加普通用户,Kubernetes 仍然认为能够提供由集群的证书 机构签名的合法证书的用户是通过身份认证的用户。
基于这样的配置,Kubernetes 使用证书中的 ‘subject’ 的通用名称(Common Name)字段(例如,"/CN=devuser")来 确定用户名, 
Kubernetes使用证书中的 ‘subject’ 的单位名称 (Organization Name) 字段(例如,"/O=system:masters")来确定用户组。

说明
--embed-certs=true的作用是不在配置文件中显示证书信息。
--kubeconfig=/root/jenkins.conf 用于创建新的配置文件,如果不加此选项,则内容会"追加"到当前用户家目录下.kube/config文件中。(温馨提示,保存老的~/kube/config)
可以使用use-context来切换不同的用户管理k8s集群。可以不加context简单的理解就是用什么用户来管理哪个集群,即用户和集群的结合。

1、创建证书 创建K8S用户
#创建私钥
$(umask 077;openssl genrsa -out zzhz.key 2048)

#用此私钥创建一个csr(证书签名请求)文件
$openssl req -new -key zzhz.key -subj "/CN=zzhz" -out zzhz.csr

#拿着私钥和请求文件生成证书
$openssl x509 -req -in zzhz.csr -CA /etc/kubernetes/ssl/ca.pem -CAkey /etc/kubernetes/ssl/ca-key.pem -CAcreateserial -out zzhz.crt -days 365


2.集群配置
生成普通用户kubeconfig文件:cluster1群集名(kubectl config  get-clusters)  --server是VIP地址(可以使用本master地址)。参考cat  /root/.kube/config
当--kubeconfig=zzhz.kubeconfig不指定,并且/root/.kube/config已存在,此步可以不用操作。
kubectl config set-cluster cluster1 --certificate-authority=/etc/kubernetes/ssl/ca.pem --embed-certs=true --server=https://192.168.80.120:6443 --kubeconfig=zzhz.kubeconfig


#生成账号和设置客户端认证参数:用户配置
$kubectl config set-credentials zzhz --client-certificate=./zzhz.crt --client-key=./zzhz.key --embed-certs=true  --kubeconfig=zzhz.kubeconfig



3、设置上下文参数, 创建context
#设置上下文, 默认会保存在 $HOME/.kube/config 
$ kubectl config set-context zzhz@cluster1 --cluster=cluster1 --user=zzhz --namespace=linux39  --kubeconfig=zzhz.kubeconfig

#查看
$ kubectl config get-contexts --kubeconfig=zzhz.kubeconfig
CURRENT   NAME            CLUSTER    AUTHINFO   NAMESPACE
*         cluster1        cluster1   admin      
         zzhz@cluster1   cluster1   zzhz       linux39

#切换context
$ kubectl config use-context zzhz@cluster1 --kubeconfig=./zzhz.kubeconfig


#测试
发现使用我们创建的用户查询是失败的,是因为账号还没授权,接下来就是对账号进行授权。这里需要先把用切回来,要不然就无法进行下一步授权了。
$ kubectl get nodes --kubeconfig=./zzhz.kubeconfig
Error from server (Forbidden): nodes is forbidden: User "zzhz" cannot list resource "nodes" in API group "" at the cluster scope


切回管理员用户
kubectl config use-context cluster1



5、对用户授权
上述操作完成后,用户还没有具体的访问权限,创建Role和RoleBinding,为该用户授权,只有linux39名称空间的相关权限
cat /role-pod-reader.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: linux39
  name: pods-reader    
rules: 
- apiGroups: [""] 
  resources: ["pods","services","pods/*"]  
  verbs: ["get","watch","list","create"] 


绑定角色
cat role-binding-zzhz.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: zzhz
  namespace: linux39
subjects:
- kind: User
  name: zzhz
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pods-reader
  apiGroup: rbac.authorization.k8s.io



6、验证

切回管理员用户
kubectl config use-context  zzhz@cluster1 --kubeconfig=./zzhz.kubeconfig


kubectl   get pods -n linux39 
[root@localhost7C zzhz]# kubectl  get pods  -n zzhz   --kubeconfig=./zzhz.kubeconfig
zzhz.crt               zzhz.csr               zzhz.key               zzhz-rolebinding.yaml  zzhz-role.yaml         


[root@localhost7C zzhz]# kubectl  get pods  -n default  --kubeconfig=./zzhz.kubeconfig
Error from server (Forbidden): pods is forbidden: User "zzhz" cannot list resource "pods" in API group "" in the namespace "default"
Group因为跟user类型,这里就不过多文字介绍,直接上命令和配置

# 创建私钥
$ openssl genrsa -out devgroupuser.key 2048
 
# 用此私钥创建一个csr(证书签名请求)文件
$ openssl req -new -key devgroupuser.key -subj "/O=devgroup/CN=devgroupuser" -out devgroupuser.csr
 
# 拿着私钥和请求文件生成证书
$ openssl x509 -req -in devgroupuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out devgroupuser.crt -days 365

# 生成账号
$ kubectl config set-credentials devgroupuser --client-certificate=./devgroupuser.crt --client-key=./devgroupuser.key --embed-certs=true

# 设置上下文参数
$ kubectl config set-context devgroupuser@kubernetes --cluster=kubernetes --user=devgroupuser --namespace=dev

# 查看
$ kubectl config get-contexts

$ cat >devgroup-role-bind.yaml<<EOF
kind: Role  # 角色
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: dev
  name: devgroup-role
rules:
- apiGroups: [""] # ""代表核心api组
  resources: ["services","pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: RoleBinding # 角色绑定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: devgroup-rolebinding
  namespace: dev
subjects:
- kind: Group
  name: devgroup   # 目标用户组
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: devgroup-role  # 角色信息
  apiGroup: rbac.authorization.k8s.io
EOF


执行并验证(命名空间默认dev,而不是系统的default)
$ kubectl apply -f devgroup-role-bind.yaml
#切用户
$ kubectl config use-context devgroupuser@kubernetes
# 查看
$ kubectl config get-contexts
$ kubectl get pods
$ kubectl get svc
$ kubectl get nodes
$ kubectl get jobs


参考文档
https://blog.csdn.net/qq_35745940/article/details/120693490