k8s安全認證

訪問控制概述

Kubernetes作爲一個分佈式集羣的管理工具,保證集羣的安全性是其一個重要的任務。所謂的安全性其實就是保證對Kubernetes的各種客戶端進行認證和鑑權操作。

客戶端

在Kubernetes集羣中,客戶端通常有兩類:

  • User Account:一般是獨立於kubernetes之外的其他服務管理的用戶賬號。
  • Service Account:kubernetes管理的賬號,用於爲Pod中的服務進程在訪問Kubernetes時提供身份標識。

img

認證、授權與准入控制

ApiServer是訪問及管理資源對象的唯一入口。任何一個請求訪問ApiServer,都要經過下面三個流程:

  • Authentication(認證):身份鑑別,只有正確的賬號才能夠通過認證
  • Authorization(授權): 判斷用戶是否有權限對訪問的資源執行特定的動作
  • Admission Control(准入控制):用於補充授權機制以實現更加精細的訪問控制功能。

img

認證管理

Kubernetes集羣安全的最關鍵點在於如何識別並認證客戶端身份,它提供了3種客戶端身份認證方式:

  • HTTP Base認證:通過用戶名+密碼的方式認證

        這種認證方式是把“用戶名:密碼”用BASE64算法進行編碼後的字符串放在HTTP請求中的Header Authorization域裏發送給服務端。服務端收到後進行解碼,獲取用戶名及密碼,然後進行用戶身份認證的過程。
    
  • HTTP Token認證:通過一個Token來識別合法用戶

        這種認證方式是用一個很長的難以被模仿的字符串--Token來表明客戶身份的一種方式。每個Token對應一個用戶名,當客戶端發起API調用請求時,需要在HTTP Header裏放入Token,API Server接到Token後會跟服務器中保存的token進行比對,然後進行用戶身份認證的過程。
    
  • HTTPS證書認證:基於CA根證書籤名的雙向數字證書認證方式

        這種認證方式是安全性最高的一種方式,但是同時也是操作起來最麻煩的一種方式。
    

img

HTTPS認證大體分爲3個過程:

  1. 證書申請和下發

      HTTPS通信雙方的服務器向CA機構申請證書,CA機構下發根證書、服務端證書及私鑰給申請者
    
  2. 客戶端和服務端的雙向認證

      1> 客戶端向服務器端發起請求,服務端下發自己的證書給客戶端,
         客戶端接收到證書後,通過私鑰解密證書,在證書中獲得服務端的公鑰,
         客戶端利用服務器端的公鑰認證證書中的信息,如果一致,則認可這個服務器
      2> 客戶端發送自己的證書給服務器端,服務端接收到證書後,通過私鑰解密證書,
         在證書中獲得客戶端的公鑰,並用該公鑰認證證書信息,確認客戶端是否合法
    
  3. 服務器端和客戶端進行通信

      服務器端和客戶端協商好加密方案後,客戶端會產生一個隨機的祕鑰並加密,然後發送到服務器端。
      服務器端接收這個祕鑰後,雙方接下來通信的所有內容都通過該隨機祕鑰加密
    

注意: Kubernetes允許同時配置多種認證方式,只要其中任意一個方式認證通過即可

授權管理

授權策略介紹

授權發生在認證成功之後,通過認證就可以知道請求用戶是誰, 然後Kubernetes會根據事先定義的授權策略來決定用戶是否有權限訪問,這個過程就稱爲授權。

每個發送到ApiServer的請求都帶上了用戶和資源的信息:比如發送請求的用戶、請求的路徑、請求的動作等,授權就是根據這些信息和授權策略進行比較,如果符合策略,則認爲授權通過,否則會返回錯誤。

API Server目前支持以下幾種授權策略:

  • AlwaysDeny:表示拒絕所有請求,一般用於測試
  • AlwaysAllow:允許接收所有請求,相當於集羣不需要授權流程(Kubernetes默認的策略)
  • ABAC:基於屬性的訪問控制,表示使用用戶配置的授權規則對用戶請求進行匹配和控制
  • Webhook:通過調用外部REST服務對用戶進行授權
  • Node:是一種專用模式,用於對kubelet發出的請求進行訪問控制
  • RBAC:基於角色的訪問控制(kubeadm安裝方式下的默認選項)

RBAC(Role-Based Access Control) 基於角色的訪問控制,主要是在描述一件事情:給哪些對象授予了哪些權限

其中涉及到了下面幾個概念:

  • 對象:User、Groups、ServiceAccount
  • 角色:代表着一組定義在資源上的可操作動作(權限)的集合
  • 綁定:將定義好的角色跟用戶綁定在一起

img

RBAC引入了4個頂級資源對象:

  • Role、ClusterRole:角色,用於指定一組權限
  • RoleBinding、ClusterRoleBinding:角色綁定,用於將角色(權限)賦予給對象

Role、ClusterRole

一個角色就是一組權限的集合,這裏的權限都是許可形式的(白名單)。

# Role只能對命名空間內的資源進行授權,需要指定nameapce
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: dev
  name: authorization-role
rules:
- apiGroups: [""]  # 支持的API組列表,"" 空字符串,表示核心API羣
  resources: ["pods"] # 支持的資源對象列表
  verbs: ["get", "watch", "list"] # 允許的對資源對象的操作方法列表
# ClusterRole可以對集羣範圍內資源、跨namespaces的範圍資源、非資源類型進行授權
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
 name: authorization-clusterrole
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

需要詳細說明的是,rules中的參數:

  • apiGroups: 支持的API組列表

    "","apps", "autoscaling", "batch"
    
  • resources:支持的資源對象列表

    "services", "endpoints", "pods","secrets","configmaps","crontabs","deployments","jobs",
    "nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets",
    "horizontalpodautoscalers","replicationcontrollers","cronjobs"
    
  • verbs:對資源對象的操作方法列表

    "get", "list", "watch", "create", "update", "patch", "delete", "exec"
    

RoleBinding、ClusterRoleBinding

角色綁定用來把一個角色綁定到一個目標對象上,綁定目標可以是User、Group或者ServiceAccount。

# RoleBinding可以將同一namespace中的subject綁定到某個Role下,則此subject即具有該Role定義的權限
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: authorization-role-binding
  namespace: dev
subjects:
- kind: User
  name: makalo
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: authorization-role
  apiGroup: rbac.authorization.k8s.io
# ClusterRoleBinding在整個集羣級別和所有namespaces將特定的subject與ClusterRole綁定,授予權限
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
 name: authorization-clusterrole-binding
subjects:
- kind: User
  name: makalo
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: authorization-clusterrole
  apiGroup: rbac.authorization.k8s.io

RoleBinding引用ClusterRole進行授權

RoleBinding可以引用ClusterRole,對屬於同一命名空間內ClusterRole定義的資源主體進行授權。

    一種很常用的做法就是,集羣管理員爲集羣範圍預定義好一組角色(ClusterRole),然後在多個命名空間中重複使用這些ClusterRole。這樣可以大幅提高授權管理工作效率,也使得各個命名空間下的基礎性授權規則與使用體驗保持一致。
# 雖然authorization-clusterrole是一個集羣角色,但是因爲使用了RoleBinding
# 所以makalo只能讀取dev命名空間中的資源
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: authorization-role-binding-ns
  namespace: dev
subjects:
- kind: User
  name: makalo
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: authorization-clusterrole
  apiGroup: rbac.authorization.k8s.io

實戰:創建一個只能管理dev空間下Pods資源的賬號

創建賬號

# 1) 創建證書
cd /etc/kubernetes/pki/

(umask 077;openssl genrsa -out makalo.key 2048)

# 2) 用apiserver的證書去簽署
# 2-1) 簽名申請,申請的用戶是makalo,組是devgroup
openssl req -new -key makalo.key -out makalo.csr -subj "/CN=makalo/O=devgroup"     
# 2-2) 簽署證書
openssl x509 -req -in makalo.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out makalo.crt -days 3650

# 3) 設置集羣、用戶、上下文信息
kubectl config set-cluster kubernetes --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.176.100:6443

kubectl config set-credentials makalo --embed-certs=true --client-certificate=/etc/kubernetes/pki/makalo.crt --client-key=/etc/kubernetes/pki/makalo.key

kubectl config set-context makalo@kubernetes --cluster=kubernetes --user=makalo

# 切換賬戶到devman
kubectl config use-context makalo@kubernetes

# 查看dev下pod,發現沒有權限
kubectl get pods -n dev

# 切換到admin賬戶
kubectl config use-context kubernetes-admin@kubernetes

image-20220531144913855

給用戶授權

創建dev-role.yaml,Role和RoleBinding,爲makalo用戶授權

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: dev
  name: dev-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  
---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: authorization-role-binding
  namespace: dev
subjects:
- kind: User
  name: makalo
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: dev-role
  apiGroup: rbac.authorization.k8s.io
kubectl create -f dev-role.yaml

image-20220531145353193

切換用戶,驗證授權

切換賬戶,再次驗證

# 切換賬戶到makalo
kubectl config use-context makalo@kubernetes

# 再次查看
kubectl get pods -n dev

# 切回admin賬戶
kubectl config use-context kubernetes-admin@kubernetes

image-20220531145433065

准入控制

通過了前面的認證和授權之後,還需要經過准入控制處理通過之後,apiserver纔會處理這個請求。

准入控制是一個可配置的控制器列表,可以通過在Api-Server上通過命令行設置選擇執行哪些准入控制器:

--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,
                      DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds

只有當所有的准入控制器都檢查通過之後,apiserver才執行該請求,否則返回拒絕。

當前可配置的Admission Control准入控制如下:

  • AlwaysAdmit:允許所有請求
  • AlwaysDeny:禁止所有請求,一般用於測試
  • AlwaysPullImages:在啓動容器之前總去下載鏡像
  • DenyExecOnPrivileged:它會攔截所有想在Privileged Container上執行命令的請求
  • ImagePolicyWebhook:這個插件將允許後端的一個Webhook程序來完成admission controller的功能。
  • Service Account:實現ServiceAccount實現了自動化
  • SecurityContextDeny:這個插件將使用SecurityContext的Pod中的定義全部失效
  • ResourceQuota:用於資源配額管理目的,觀察所有請求,確保在namespace上的配額不會超標
  • LimitRanger:用於資源限制管理,作用於namespace上,確保對Pod進行資源限制
  • InitialResources:爲未設置資源請求與限制的Pod,根據其鏡像的歷史資源的使用情況進行設置
  • NamespaceLifecycle:如果嘗試在一個不存在的namespace中創建資源對象,則該創建請求將被拒絕。當刪除一個namespace時,系統將會刪除該namespace中所有對象。
  • DefaultStorageClass:爲了實現共享存儲的動態供應,爲未指定StorageClass或PV的PVC嘗試匹配默認的StorageClass,儘可能減少用戶在申請PVC時所需瞭解的後端存儲細節
  • DefaultTolerationSeconds:這個插件爲那些沒有設置forgiveness tolerations並具有notready:NoExecute和unreachable:NoExecute兩種taints的Pod設置默認的“容忍”時間,爲5min
  • PodSecurityPolicy:這個插件用於在創建或修改Pod時決定是否根據Pod的security context和可用的PodSecurityPolicy對Pod的安全策略進行控制
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章