【Kubernetes 018】cfssl创建证书并结合RBAC的RoleBinding配置新用户config文件操作详解

安全性是企业生产环境中的头等大事,对于访问同一集群的不同用户或者用户组来说,将权限分级是很有必要的。和很多云厂商一样,k8s也是采用按照角色和用户绑定的方式来分配权限的,这一节我们就来实际操作下,新建一个用户,并只让他在指定的namespace进行管理。

我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。

文章目录

    • RBAC
      • Role和ClusterRole
      • RoleBinding和ClusterRoleBinding
    • 用户以及认证
      • 一些证书工具
      • config文件
    • 实际操作
      • 创建用户证书
      • 创建用户config文件
      • 添加证书到config文件
      • 设置Context
      • 做RoleBinding
      • 使用config文件
      • 验证效果
    • 总结

RBAC

RBAC,全称Role-based access control,会创建很多Role,每个Role对应着一系列的权限。通过将用户和Role进行绑定来给用户赋予不同类型的权限。

Role和ClusterRole

K8s中的资源要么是在某个namespace下,例如pod和service,要么是全局的,例如node。所有权限也就分为两种,Role下的权限是针对某个namespace的,在定义的时候必须要加上具体namespace;与之相对的ClusterRole下的权限是集群级别的,不用加namespace。

需要注意,所有的权限都是允许类型,而没有拒绝类型,所以赋予权限只能进行添加操作。一个用户绑定了某个Role,就只有Role下赋予的权限。

Role和ClusterRole都是集群中的单独资源,可以用yaml文件来创建。

例如下面是一个Role的声明

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

其中的apiGroupsresources是资源列表,可以参考官方API文档,而verbs是允许对资源的操作动作,可以参考全部操作。

同样下面是一个ClusterRole的声明

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Secret
  # objects is "secrets"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

但是通常来说系统自带的Role和ClusterRole就基本够用了,如下

[root@k8s-master ~]# kubectl get role --all-namespaces
NAMESPACE       NAME                                             AGE
ingress-nginx   ingress-nginx                                    6d19h
ingress-nginx   ingress-nginx-admission                          6d19h
kube-public     kubeadm:bootstrap-signer-clusterinfo             16d
kube-public     system:controller:bootstrap-signer               16d
kube-system     extension-apiserver-authentication-reader        16d
kube-system     kube-proxy                                       16d
kube-system     kubeadm:kubelet-config-1.15                      16d
kube-system     kubeadm:nodes-kubeadm-config                     16d
kube-system     system::leader-locking-kube-controller-manager   16d
kube-system     system::leader-locking-kube-scheduler            16d
kube-system     system:controller:bootstrap-signer               16d
kube-system     system:controller:cloud-provider                 16d
kube-system     system:controller:token-cleaner                  16d
[root@k8s-master ~]# kubectl get clusterrole
NAME                                                                   AGE
admin                                                                  16d
cluster-admin                                                          16d
edit                                                                   16d
flannel                                                                16d
ingress-nginx                                                          6d19h
ingress-nginx-admission                                                6d19h
system:aggregate-to-admin                                              16d
system:aggregate-to-edit                                               16d
system:aggregate-to-view                                               16d
system:auth-delegator                                                  16d
system:basic-user                                                      16d
system:certificates.k8s.io:certificatesigningrequests:nodeclient       16d
system:certificates.k8s.io:certificatesigningrequests:selfnodeclient   16d
system:controller:attachdetach-controller                              16d
system:controller:certificate-controller                               16d
system:controller:clusterrole-aggregation-controller                   16d
system:controller:cronjob-controller                                   16d
system:controller:daemon-set-controller                                16d
system:controller:deployment-controller                                16d
system:controller:disruption-controller                                16d
system:controller:endpoint-controller                                  16d
system:controller:expand-controller                                    16d
system:controller:generic-garbage-collector                            16d
system:controller:horizontal-pod-autoscaler                            16d
system:controller:job-controller                                       16d
system:controller:namespace-controller                                 16d
system:controller:node-controller                                      16d
system:controller:persistent-volume-binder                             16d
system:controller:pod-garbage-collector                                16d
system:controller:pv-protection-controller                             16d
system:controller:pvc-protection-controller                            16d
system:controller:replicaset-controller                                16d
system:controller:replication-controller                               16d
system:controller:resourcequota-controller                             16d
system:controller:route-controller                                     16d
system:controller:service-account-controller                           16d
system:controller:service-controller                                   16d
system:controller:statefulset-controller                               16d
system:controller:ttl-controller                                       16d
system:coredns                                                         16d
system:csi-external-attacher                                           16d
system:csi-external-provisioner                                        16d
system:discovery                                                       16d
system:heapster                                                        16d
system:kube-aggregator                                                 16d
system:kube-controller-manager                                         16d
system:kube-dns                                                        16d
system:kube-scheduler                                                  16d
system:kubelet-api-admin                                               16d
system:node                                                            16d
system:node-bootstrapper                                               16d
system:node-problem-detector                                           16d
system:node-proxier                                                    16d
system:persistent-volume-provisioner                                   16d
system:public-info-viewer                                              16d
system:volume-scheduler                                                16d
view                                                                   16d

这里面带system:前缀的是系统级别的,不建议修改和使用,而面向用户的,例如cluster-adminadmineditview等则可以使用和修改,接下来的例子会看到。

RoleBinding和ClusterRoleBinding

将用户和Role进行绑定的操作就叫做RoleBinding,将用户和ClusterRole进行绑定的操作就叫做ClusterRoleBinding。

官方文档上也可以用yaml文件来进行这两种操作,但是通常直接用命令行即可,例如

kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root

可以参考这里获得更多官方样例

用户以及认证

既然提到了用户,不得不提一下k8s里面的用户以及认证。当然这是一个大的话题,这里先简单了解,后面再专门详细讲解。

k8s中的用户(user)分为两种,一种叫Service Account(SA),由k8s自己管理,一种是普通的user,由第三方来管理。我们这里要关心的就是第二种普通user。所有的API请求都必须跟一个user绑定,这也就意味着,任何API请求都必须先经过用户认证(Authentication)然后经过上面说的权限校验(Authorization)最后才到API

不像Mysql这种集群,k8s自己内部是不保存用户信息的,都是由外部第三方来管理,那么如何进行用户认证呢?这就需要用到HTTPS中的一个概念,叫客户端证书(Client Certificate)。在k8s集群内部有一个权威机构(certificate Authority,CA)专门用来颁发证书,将用户信息提交到CA获得一个k8s认可的证书即可获得集群的信任。

下面的操作我们会详细看到这些步骤。

再次强调,用户认证和证书可以延伸很多,后面再写文章专门详细介绍

对HTTPS感兴趣的朋友,我后面会写一篇TLS1.3的wireshark抓包分析文章,欢迎大家关注我的csdn博客

一些证书工具

在手动生成客户端证书的时候,官方向我们推荐了三款软件,分别是easyrsa,openssl和cfssl。可以在这里查看官方给出的一些简要介绍和脚本示例,下面的实际操作我们会选用CloudFlare家的cfssl来进行操作演示。

config文件

用户在访问k8s集群的时候需要携带自己的的认证信息,例如私钥和证书。于是kuberctl工具规定用户需要将这些信息连同API server的访问地址还有集群域名等等一起汇总填写到~/.kube/config文件中,每次用户使用kubectl进行操作都会使用该文件进行认证。所以创建用户的根本目的就是创建该用户的config文件

同时不管是集群内的还是集群外机器安装的kubectl,只要能读取到用户的config文件就可以正常访问到集群资源。可以参考我的另一篇博客《Kubernetes集群外Windows10机器的kubectl访问集群资源图文详解》。

实际操作

下面以创建一个用户xiaofu,并只允许其到xiaofu-team这个namespace下进行管理为例进行实际操作。

创建用户证书

前面说到需要得到集群内CA的认证才能获得证书,CA的信息都在master节点的/etc/kubernetes/pki目录下

[root@k8s-master certs]# cd /etc/kubernetes/pki
[root@k8s-master pki]# ll
total 56
-rw-r--r--. 1 root root 1224 Apr 28 15:01 apiserver.crt
-rw-r--r--. 1 root root 1090 Apr 28 15:01 apiserver-etcd-client.crt
-rw-------. 1 root root 1671 Apr 28 15:01 apiserver-etcd-client.key
-rw-------. 1 root root 1675 Apr 28 15:01 apiserver.key
-rw-r--r--. 1 root root 1099 Apr 28 15:01 apiserver-kubelet-client.crt
-rw-------. 1 root root 1675 Apr 28 15:01 apiserver-kubelet-client.key
-rw-r--r--. 1 root root 1025 Apr 28 15:01 ca.crt
-rw-------. 1 root root 1675 Apr 28 15:01 ca.key
drwxr-xr-x. 2 root root  162 Apr 28 15:01 etcd
-rw-r--r--. 1 root root 1038 Apr 28 15:01 front-proxy-ca.crt
-rw-------. 1 root root 1675 Apr 28 15:01 front-proxy-ca.key
-rw-r--r--. 1 root root 1058 Apr 28 15:01 front-proxy-client.crt
-rw-------. 1 root root 1679 Apr 28 15:01 front-proxy-client.key
-rw-------. 1 root root 1675 Apr 28 15:01 sa.key
-rw-------. 1 root root  451 Apr 28 15:01 sa.pub

这里有CA以及各个核心组件的证书和私钥,我们创建的用户证书和私钥也可以放在这里。

首先下载cfssl工具,直接根据官方链接下载即可

curl -L https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssl_1.4.1_linux_amd64 -o cfssl
chmod +x cfssl
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssljson_1.4.1_linux_amd64 -o cfssljson
chmod +x cfssljson
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssl-certinfo_1.4.1_linux_amd64 -o cfssl-certinfo
chmod +x cfssl-certinfo

下载后赋予可执行权限并添加到PATH

[root@k8s-master cfssl]# ll
total 35256
-rwxr-xr-x. 1 root root 14842064 May 15 12:43 cfssl
-rwxr-xr-x. 1 root root 11758832 May 15 12:46 cfssl-certinfo
-rwxr-xr-x. 1 root root  9495504 May 15 12:44 cfssljson
[root@k8s-master cfssl]# cp * /usr/local/bin

之后准备以下用户的个人信息,保存为如下json格式的证书请求文件

{
  "CN": "",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
     {
       "C": "",
       "L": "",
       "O": "",
       "OU": "",
       "ST": ""
     }
  ]
}

这里的CN就会作为用户名,而O就为作为用户组名,例如创建xiaofu-crs.json文件如下

{
  "CN": "xiaofu",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
     {
       "C": "CN",
       "L": "Beijing",
       "O": "Beijing",
       "OU": "k8s",
       "ST": "System"
     }
  ]
}

然后到/etc/kubernetes/pki下根据上面的请求信息生成CA认证后的用户证书和私钥

[root@k8s-master pki]# cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /root/users/xiaofu/xiaofu-csr.json | cfssljson -bare xiaofu
2020/05/15 12:55:10 [INFO] generate received request
2020/05/15 12:55:10 [INFO] received CSR
2020/05/15 12:55:10 [INFO] generating key: rsa-2048
2020/05/15 12:55:10 [INFO] encoded CSR
2020/05/15 12:55:10 [INFO] signed certificate with serial number 696211841642757082046062313230328484866400029241
2020/05/15 12:55:10 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
[root@k8s-master pki]# ll xiaofu*
-rw-r--r--. 1 root root  997 May 15 12:55 xiaofu.csr
-rw-------. 1 root root 1679 May 15 12:55 xiaofu-key.pem
-rw-r--r--. 1 root root 1233 May 15 12:55 xiaofu.pem

成功以后会出现xiaofu-key.pem以及xiaofu.pem,分别是CA签名之后的私钥和证书

.pem/.key/.crt/.cer 这些格式都有可能表示证书和密钥,看不同工具的编码方式

创建用户config文件

之后就可以用这两个文件去生成用户专属的认证config文件了,

[root@k8s-master xiaofu]# pwd
/root/users/xiaofu
[root@k8s-master xiaofu]# kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=https://172.29.56.175:6443 --kubeconfig=xiaofu.config
Cluster "kubernetes" set.

kubectl config命令专门用来创建和修改用户的config文件,这里创建了一个叫kubernetes的cluster,并指明了该cluster的地址和CA证书,注意地址不能少了https://

会看到出现config文件,但是只包含集群的一些信息,没有用户的证书和私钥信息

[root@k8s-master xiaofu]# cat xiaofu.config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: xxxxx
    server: https://172.29.56.175:6443
  name: kubernetes
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []

添加证书到config文件

之后设置客户端认证证书

[root@k8s-master xiaofu]# kubectl config set-credentials xiaofu --client-certificate=/etc/kubernetes/pki/xiaofu.pem --client-key=/etc/kubernetes/pki/xiaofu-key.pem --embed-certs=true --kubeconfig=xiaofu.config
User "xiaofu" set.
[root@k8s-master xiaofu]# cat xiaofu.config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: xxxxx
    server: https://172.29.56.175:6443
  name: kubernetes
contexts: []
current-context: ""
kind: Config
preferences: {}
users:
- name: xiaofu
  user:
    client-certificate-data: xxxxx
    client-key-data: xxxxx

可以看到config文件就多了用户的信息,因为太长我这里用xxxxx代替了

设置Context

Context是给一组访问参数起的一个名字,每个context由cluster,namespace,user组成,user和cluster是必须的,namespace可以不指定。同时config文件中还有一个current context字段,kubectl用该字段来和集群进行沟通。如果config中配置了多个context的话,可以切换不同的context到current context。

首先创建一个新的namespace

kubectl create namespace xiaofu-team

然后给xiaofu用户设置context

[root@k8s-master xiaofu]# kubectl config set-context kubernetes --cluster=kubernetes --user=xiaofu --namespace=xiaofu-team --kubeconfig=xiaofu.config
Context "kubernetes" created.
[root@k8s-master xiaofu]# cat xiaofu.config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: xxxxx
    server: https://172.29.56.175:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: xiaofu-team
    user: xiaofu
  name: kubernetes
current-context: ""
kind: Config
preferences: {}
users:
- name: xiaofu
  user:
    client-certificate-data: xxxxx
    client-key-data: xxxxx

可以看到一个名叫kubernetes的context被创建了,但是current-context里面还没有使用

设置下current-context

[root@k8s-master xiaofu]# kubectl config use-context kubernetes --kubeconfig=xiaofu.config
Switched to context "kubernetes".
[root@k8s-master xiaofu]# cat xiaofu.config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: xxxxx
    server: https://172.29.56.175:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: xiaofu-team
    user: xiaofu
  name: kubernetes
current-context: kubernetes
kind: Config
preferences: {}
users:
- name: xiaofu
  user:
    client-certificate-data: xxxxx
    client-key-data: xxxxx

到这里用户的config文件就生成完毕

做RoleBinding

接着做一个rolebinding,对xiaofu用户赋予权限。

这里就不单独创造Role了,将k8s自带的admin角色绑定到xiaofu上,但是限制在xiaofu-team这个namespace里面,这样xiaofu就在xiaofu-team下拥有了管理员权限

[root@k8s-master xiaofu]# kubectl create rolebinding xiaofu-admin-binding --clusterrole=admin --user=xiaofu --namespace=xiaofu-team
rolebinding.rbac.authorization.k8s.io/xiaofu-admin-binding created

使用config文件

这样在任意能访问到API server的机器上,只要将刚才创建的config文件放到~/.kube/目录下,该用户就可以以xiaofu的身份访问到集群了。

在k8s-master机器上创建xiaofu用户,并复制config文件到/home/xiaofu/.kube下,改名为config

[root@k8s-master xiaofu]# useradd xiaofu
[root@k8s-master xiaofu]# mkdir /home/xiaofu/.kube
[root@k8s-master xiaofu]# cp xiaofu.config /home/xiaofu/.kube/config
[root@k8s-master xiaofu]# passwd xiaofu
Changing password for user xiaofu.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.

因为是用root创建的文件,记得修改下config文件的权限

[root@k8s-master xiaofu]# chown xiaofu:xiaofu /home/xiaofu/.kube/config

验证效果

之后切换到xiaofu用户登录k8s-master,会发现看不到别的namespace的信息

[xiaofu@k8s-master ~]$ kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "xiaofu" cannot list resource "pods" in API group "" in the namespace "kube-system"

创建的pod也是在xiaofu-team这个namespace下

[xiaofu@k8s-master ~]$ kubectl run xiaofu-nginx --image=mynginx:v2
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/xiaofu-nginx created
[xiaofu@k8s-master ~]$ kubectl get pod -o wide -n xiaofu-team
NAME                            READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
xiaofu-nginx-6fdc85d5b7-tjd8c   1/1     Running   0          56s   10.244.1.177   k8s-node1              

用root用户可以看到namespace

[root@k8s-master .kube]# kubectl get pod -o wide --all-namespaces
NAMESPACE       NAME                                        READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
ingress-nginx   ingress-nginx-controller-5575c6cd9d-mjncn   1/1     Running   0          47h     10.244.0.24     k8s-master              
kube-system     coredns-5d4dd4b4db-qcknv                    1/1     Running   0          16d     10.244.0.3      k8s-master              
kube-system     coredns-5d4dd4b4db-wr4hh                    1/1     Running   0          16d     10.244.0.2      k8s-master              
kube-system     etcd-k8s-master                             1/1     Running   0          16d     172.29.56.175   k8s-master              
kube-system     kube-apiserver-k8s-master                   1/1     Running   0          16d     172.29.56.175   k8s-master              
kube-system     kube-controller-manager-k8s-master          1/1     Running   0          16d     172.29.56.175   k8s-master              
kube-system     kube-flannel-ds-amd64-q6wf7                 1/1     Running   0          16d     172.29.56.175   k8s-master              
kube-system     kube-flannel-ds-amd64-xdxbh                 1/1     Running   0          45h     172.29.56.176   k8s-node1               
kube-system     kube-proxy-4fw7f                            1/1     Running   0          8d      172.29.56.175   k8s-master              
kube-system     kube-proxy-brgtq                            1/1     Running   0          8d      172.29.56.176   k8s-node1               
kube-system     kube-scheduler-k8s-master                   1/1     Running   0          16d     172.29.56.175   k8s-master              
xiaofu-team     xiaofu-nginx-6fdc85d5b7-tjd8c               1/1     Running   0          2m35s   10.244.1.177    k8s-node1               

总结

总结下这一节的知识点

  • k8s将一系列权限以Role或者ClusterRole的方式划分角色
  • 通过将用户与角色进行绑定达到为用户分配权限的目的
  • k8s本身不保存用户信息,每次用户访问必须要通过自己的config文件携带认证信息
  • 创建用户的config文件分为如下几步
    • 构建证书请求json文件csr.json
    • 结合CA证书生成用户的客户端证书和私钥
    • 创建空的config文件
    • 补充config文件cluster信息和用户信息以及context
    • 将config文件复制到~/.kube/config并设定好权限
  • 集群外部机器想访问集群资源,复制用户config文件即可

你可能感兴趣的:(Devops,-,Kubernetes)