码迷,mamicode.com
首页 > Web开发 > 详细

Kubernetes进阶之基于RBAC授权安全框架

时间:2019-09-08 09:23:19      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:node节点   host   count   ice   tcp   ase   reader   rsa   jin   

K8S 安全机制

  1. Kubernetes的安全框架
  2. 传输安全,认证,授权,准入控制
  3. 使用RBAC授权,我们作为一个用户如何去授权不同的同事去访问集群的权限,比如开发同事,可以访问哪个资源,哪个命名空间,测试同事可以访问哪些,通过这方面我们怎么去限制。

一、K8S的安全框架

? 访问K8S集群的资源需要过三关:认证、鉴权、准入控制
? 普通用户若要安全访问集群API Server,往往需要证书、Token或者用户名+密码;Pod访问,比如ingress控制器Ui的Dashboard都需要ServiceAccount,主要是让这个容器能够访问这个API,也就是所有的交互都是通过API的,这可能通过一个人去通过kubectl去交互,也有可能你的程序去调用API,但这些都是需要授权的

? K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过API Server配置来启用插件。

  1. Authentication 认证
  2. Authorization 鉴权
  3. Admission Control 准入控制

说在前面的话,也就是每个阶段都是插件化的设计,可以自己开发插件,把这些集成到步骤里面,来实现相关的访问控制,这样的话你就不需要去修改原有的代码去增加了,所以k8s设计原则有很多都是以扩展性去设计的,都尽可能的让用户自定义一些东西,集成到里面。

接下来看一张图,这是访问API经历的一些阶段
技术图片
从上面kubectl、API、UI,访问的是k8sAPI,k8s的API提供了很多的接口
技术图片

这些都是Apiserver去提供的,也支持不同的功能,来完成相关的处理的,相关的认证,再往下就是API内置有三层的授权,第一层就是认证,第二层就是鉴权,第三层就是准入控制,然后通过之后就可以访问相关的资源了,这些资源都是从ETCD中去调用的,一些存储状态的信息

传输安全:
现在k8s都已经改成https进行访问,也就是不管你是kubeadm部署还是二进制部署,他都是建议你使用https进行全栈的通信,告别8080,使用6443

认证:
API收到用户发送的请求之后,他会先认证,认证它这边有三个可以做到
三种客户端身份认证:

? HTTPS 证书认证:基于CA证书签名的数字证书认证,也就是k8s,CA签出来的证书可以作为你客户端访问携带的证书,它会帮你认证,这是一种方式,从这个证书里面去提取你有没有权限去访问。
? HTTP Token认证:通过一个Token来识别用户。
? HTTP Base认证:用户名+密码的方式认证,这是基于http自身的一个认证,不过这个很少人去用,因为安全系数比较低。

第一关就是标识你是用哪个证书进来的,还是token标识进来的,看看我这里是不是可信任的,看看我这个token我这里有没有相关的授权,也就是我这里有没有这个token,如果没有就不允许通过,然后下面就不会再进行了,如果通过的话,就比如本地已经创建这个token了,有的话就给你放行,进行下一个判断,也就是第二关授权。

授权:
RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。也就是会查看你的访问符不符合权限,所以它会在这个地方去给你判断,如果你来的这个身份,虽然有这个身份,但是没有这个权限访问这个资源,也会不允许你通过。

授权的资源有很多类型的支持
技术图片
准入控制:
简单讲就是开发将一些高级的功能,直接插件化的去设计,也就是准入控制器就是一个插件的集合,集合里面就有一些高级的特性,都是以插件去实现的,如果不启用这些插件的话,那你就使用不了这个功能,这也就是第三关,也就是你的请求会经过你的插件准入控制,准入控制呢会给你效验请求的实现的这个方法,到底这个插件有没有启用这一块,不过大多数的方式默认的插件都是启用的,启动之后来请求相关的资源,才会被允许,因为它启用插件了,如果没启动的话也会不通过

Adminssion Control实际上是一个准入控制器插件列表,发送到API Server的请求都需要经过这个列表中的每个准入控制器,插件的检查,检查不通过,则拒绝请求。

1.11版本以上推荐使用的插件:
--enable-admission-plugins= \
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota

使用RBAC授权
RBAC(Role-Based Access Control,基于角色的访问控制),允许通过Kubernetes API动态配置策略。也就是即使配置,即时生效,不需要重启服务
技术图片
角色
? Role:授权特定命名空间的访问权限
? ClusterRole:授权所有命名空间的访问权限

角色绑定
? RoleBinding:将角色绑定到主体(即subject)
? ClusterRoleBinding:将集群角色绑定到主体

主体(subject)
? User:用户
? Group:用户组
? ServiceAccout: 服务账号
要做一个权限的管理系统,有两块,第一块就是对象是谁,创建的用户,第二就是权限组,比如创建一个开发组,开发组有哪些权限,可以访问这个系统,这也是为了方便去管理这些权限,来划分这个权限组,每个用户都给他创建一个权限很麻烦,有这个组的话,直接将用户加入这个组里面就可以了,比如来一个开放,并给他设置权限,他是一个来宾用户的组,这个组里面只能查看一些东西,但是他是一个开发组的,对一些项目有一些开发权限,管理员进去呢,在这个管理页面去再去加一个开发组,这样的话他就有开发组的权限了

K8s和刚才说的其实都是一样的,用户就是这个主体,就是谁来访问,然后权限组呢就是角色,定义了一组权限的集合,用户要想将用户与权限集合做一个附加,将开发附加一个权限组,就称为角色绑定,角色里面又分为了,角色及集群角色,集群角色是授权集群命名空间的,
也就是k8s有命名空间这一说,所以有分为了单个命名空间和所有命名空间,这个权限集合的设置,ClusterRole也就是授权所有命名空间,也就是说将某个用户加入这个权限角色里,那就意味着它可以访问所有命名空间,相关的一些权限。

示例:为zhaocheng用户授权default命名空间Pod读取权限
比如就是只能查看pod默认的空间的运行的一些资源,像svc,日志是没有权限查看的,当你试用期过了之后,再给你加一些权限,再做一些相关的操作
实现这个目标需要完成以下三步

  1. 用K8S CA签发客户端证书
  2. 生成kubeconfig授权文件
  3. 创建RBAC权限策略
    Ca.crt 和 Ca.key就是这两个需要签发的证书

    [root@k8s-master ~]# ls /etc/kubernetes/pki/
    apiserver.crt              apiserver.key                 ca.crt  front-proxy-ca.crt      front-proxy-client.key
    apiserver-etcd-client.crt  apiserver-kubelet-client.crt  ca.key  front-proxy-ca.key      sa.key
    apiserver-etcd-client.key  apiserver-kubelet-client.key  etcd    front-proxy-client.crt  sa.pub
  4. 用K8S CA签发客户端证书
    [root@k8s-master ~]# cd demo/
    [root@k8s-master demo]# mkdir rbac
    [root@k8s-master demo]# cd rbac/
    [root@k8s-master rbac]# rz -E
    rz waiting to receive.
    [root@k8s-master rbac]# ls
    cert.sh  cfssl.sh  config.sh  rbac.yaml
    [root@k8s-master rbac]# cat cfssl.sh 
    wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
    wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
    wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
    chmod +x cfssl*
    mv cfssl_linux-amd64 /usr/bin/cfssl
    mv cfssljson_linux-amd64 /usr/bin/cfssljson
    mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
    [root@k8s-master rbac]# sh cfssl.sh 

然后这里我们把我们证书签发的脚本拿过来,这里注意的是签发用户的CN这里是指签发用户的用户名,就是说k8s拿这个CA来认证,它不单效验是不是我颁发的证书,还要效验里面的用户名,就是CN这个字段是不是授权过的,相当于鉴权那一块,O是用户组,也可以基于这个用户组去做这个权限限制

[root@k8s-master rbac]# chmod +x cert.sh 
[root@k8s-master rbac]# vim cert.sh 
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
EOF

cat > zhaocheng-csr.json <<EOF
{
  "CN": "zhaocheng",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes zhaocheng-csr.json | cfssljson -bare zhaocheng

[root@k8s-master rbac]# bash cert.sh 

主要生成的就是zhaocheng-key.pem zhaocheng.pem

[root@k8s-master rbac]# ls
ca-config.json  cert.sh  cfssl.sh  config.sh  rbac.yaml  zhaocheng.csr  zhaocheng-csr.json  zhaocheng-key.pem  zhaocheng.pem

需要用这两个证书来对客户端做请求认证,写到客户端授权文件里,用这个授权文件就能请求这个k8s集群了
比如公司有多个集群,那么这个开发需要登录这个集群,需要这个config证书,到时候可以拿这个来回切换登录不同的集群
--kubeconfig=zhaocheng.kubeconfig

[root@k8s-master rbac]# vim config.sh 
kubectl config set-cluster kubernetes   --certificate-authority=/etc/kubernetes/pki/ca.crt   --embed-certs=true   --server=https://192.168.30.21:6443   --kubeconfig=zhaocheng.kubeconfig

设置客户端认证
kubectl config set-credentials zhaocheng   --client-key=zhaocheng-key.pem   --client-certificate=zhaocheng.pem   --embed-certs=true   --kubeconfig=zhaocheng.kubeconfig

设置默认上下文
kubectl config set-context kubernetes   --cluster=kubernetes   --user=zhaocheng   --kubeconfig=zhaocheng.kubeconfig

设置当前使用配置
kubectl config use-context kubernetes --kubeconfig=zhaocheng.kubeconfig

[root@k8s-master rbac]# bash config.sh 
[root@k8s-master rbac]# cat zhaocheng.kubeconfig 

现在就可以拿这个kubeconfig去访问集群了
到这呢其实是到认证这个地方给打回去了,node节点是没有访问权限的,已经识别出来是zhaocheng用户了,但是鉴权这块没有相关的授权,所以现在要为这个用户授权

[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig node
Error from server (Forbidden): nodes is forbidden: User "zhaocheng" cannot list resource "nodes" in API group "" at the cluster scope

如果有一个组的命名空间,权限比较大,就是可以访问所有命名空间,比如运维来讲,有很多的运维,可以创建集群的角色,这样它是管控所有命名空间的角色,这个角色就是针对于特定的命名空间的,比如开发,测试,它只能访问命名空间的项目,它负责的项目,然后可以使用这个指定命名空间,然后就是集群的绑定,然后绑定到zhaocheng这个用户身上,这里我定义的是user,也可以是group组。

pod也是不能访问的

[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig pod
Error from server (Forbidden): pods is forbidden: User "zhaocheng" cannot list resource "pods" in API group "" in the namespace "default"
[root@k8s-master rbac]# vim rbac.yaml 
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: zhaocheng
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

[root@k8s-master rbac]# kubectl create -f rbac.yaml 

然后现在就可以进行访问了

[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig pod
NAME                                     READY   STATUS             RESTARTS   AGE
my-pod                                   1/1     Running            0          10h
nfs-744d977b46-dh9xj                     1/1     Running            0          29h
nfs-744d977b46-kcx6h                     1/1     Running            0          29h
nfs-744d977b46-wqhc6                     1/1     Running            0          29h
nfs-client-provisioner-fbc77b9d4-kkkll   1/1     Running            0          11h
nginx-797db8dc57-tdd5s                   1/1     Running            0          8h
nginx-a1-6d5fd7b8dd-w647x                1/1     Running            0          4h55m
nginx-statefulset-0                      1/1     Running            0          7h7m
nginx-statefulset-1                      1/1     Running            0          7h6m
nginx-statefulset-2                      1/1     Running            0          7h6m
web-0                                    1/1     Running            0          4h55m
web-1                                    1/1     Running            0          4h53m
web-2                                    1/1     Running            0          4h52m

但是svc是没有定义的所以还不能访问

[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig svc
Error from server (Forbidden): services is forbidden: User "zhaocheng" cannot list resource "services" in API group "" in the namespace "default"

比如我们加一个别的访问权限,比如service,deployment
在刚才我们的rbac的策略里面加上这些权限

- apiGroups: [""]
  resources: ["pods","services"]
  verbs: ["get", "watch", "list"]

再来测试一下,已经可以正常去访问svc了

[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig service
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.1.0.1      <none>        443/TCP        30h
my-service   ClusterIP   None          <none>        80/TCP         7h22m
nginx        ClusterIP   None          <none>        80/TCP         4h59m
service      NodePort    10.1.207.32   <none>        80:30963/TCP   8h
zhao         ClusterIP   10.1.75.232   <none>        80/TCP         7h31m
zhaocheng    ClusterIP   10.1.27.206   <none>        80/TCP         7h33m

像其他的授权可以查看官方提供
https://kubernetes.io/docs/reference/access-authn-authz/rbac/

Kubernetes进阶之基于RBAC授权安全框架

标签:node节点   host   count   ice   tcp   ase   reader   rsa   jin   

原文地址:https://blog.51cto.com/14143894/2436500

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!