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

K8S 安全机制 node

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

1、K8S的安全框架linux

• 访问K8S集群的资源须要过三关:认证、鉴权、准入控制
• 普通用户若要安全访问集群API Server,每每须要证书、Token或者用户名+密码;Pod访问,好比ingress控制器Ui的Dashboard都须要ServiceAccount,主要是让这个容器可以访问这个API,也就是全部的交互都是经过API的,这可能经过一我的去经过kubectl去交互,也有可能你的程序去调用API,但这些都是须要受权的nginx

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

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

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

接下来看一张图,这是访问API经历的一些阶段
Kubernetes进阶之基于RBAC受权安全框架
从上面kubectl、API、UI,访问的是k8sAPI,k8s的API提供了不少的接口
Kubernetes进阶之基于RBAC受权安全框架vim

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

传输安全:
如今k8s都已经改为https进行访问,也就是无论你是kubeadm部署仍是二进制部署,他都是建议你使用https进行全栈的通讯,告别8080,使用6443安全

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

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

第一关就是标识你是用哪一个证书进来的,仍是token标识进来的,看看我这里是否是可信任的,看看我这个token我这里有没有相关的受权,也就是我这里有没有这个token,若是没有就不容许经过,而后下面就不会再进行了,若是经过的话,就好比本地已经建立这个token了,有的话就给你放行,进行下一个判断,也就是第二关受权。

受权:
RBAC(Role-Based Access Control,基于角色的访问控制):负责完成受权(Authorization)工做。也就是会查看你的访问符不符合权限,因此它会在这个地方去给你判断,若是你来的这个身份,虽然有这个身份,可是没有这个权限访问这个资源,也会不容许你经过。

受权的资源有不少类型的支持
Kubernetes进阶之基于RBAC受权安全框架
准入控制:
简单讲就是开发将一些高级的功能,直接插件化的去设计,也就是准入控制器就是一个插件的集合,集合里面就有一些高级的特性,都是以插件去实现的,若是不启用这些插件的话,那你就使用不了这个功能,这也就是第三关,也就是你的请求会通过你的插件准入控制,准入控制呢会给你效验请求的实现的这个方法,到底这个插件有没有启用这一块,不过大多数的方式默认的插件都是启用的,启动以后来请求相关的资源,才会被容许,由于它启用插件了,若是没启动的话也会不经过

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

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

使用RBAC受权
RBAC(Role-Based Access Control,基于角色的访问控制),容许经过Kubernetes API动态配置策略。也就是即便配置,即时生效,不须要重启服务
Kubernetes进阶之基于RBAC受权安全框架
角色
• 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/

相关文章
相关标签/搜索