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/

相關文章
相關標籤/搜索