kubernetes-身份與許可權認證(十四)
Kubernetes的安全框架
https://kubernetes.io/docs/reference/access-authn-authz/rbac/
•訪問K8S叢集的資源需要過三關:認證、鑑權、准入控制
•普通使用者若要安全訪問叢集API Server,往往需要證書、Token或者使用者名稱+密碼;Pod訪問,需要ServiceAccount
•K8S安全控制框架主要由下面3個階段進行控制,每一個階段都支援外掛方式,通過API Server配置來啟用外掛。
1.Authentication
2.Authorization
3.Admission Control
三種客戶端身份認證:
•HTTPS 證書認證:基於CA證書籤名的數字證書認證
•HTTP Token認證:通過一個Token來識別使用者
•HTTP Base認證:使用者名稱+密碼的方式認證
授權:RBAC(Role-Based Access Control,基於角色的訪問控制):負責完成授權(Authorization)工作。
准入控制:AdminssionControl實際上是一個准入控制器外掛列表,傳送到APIServer的請求都需要經過這個列表中的每個准入控制器外掛的檢查,檢查不通過,則拒絕請求。
使用RBAC授權
RBAC(Role-Based Access Control,基於角色的訪問控制),允許通過Kubernetes API動態配置策略。
角色
•Role:授權特定名稱空間的訪問許可權
•ClusterRole:授權所有名稱空間的訪問許可權
角色繫結
•RoleBinding:將角色繫結到主體(即subject)
•ClusterRoleBinding:將叢集角色繫結到主體
主體(subject)
•User:使用者
•Group:使用者組
•ServiceAccount:服務賬號
使用RBAC授權對pod讀取許可權示例
建立角色
[[email protected] ~]# vim role-demo.yaml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: developent name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] [[email protected]-master1 ~]# kubectl apply -f role-demo.yaml role.rbac.authorization.k8s.io/pod-reader created [[email protected]-master1 ~]# kubectl get role -n developent NAME AGE pod-reader 50s
建立角色繫結
[[email protected] ~]# vim rolebinding-demo.yaml kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: dev-read-pods namespace: developent subjects: - kind: User name: jane apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io [[email protected]-master1 ~]# kubectl get rolebinding -n developent NAME AGE dev-read-pods 3s [[email protected]-master1 ~]# kubectl describe rolebinding dev-read-pods -n developent Name: dev-read-pods Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"name":"dev-read-pods","namespace":"develop... Role: Kind: Role Name: pod-reader Subjects: Kind Name Namespace ---- ---- --------- User jane
基於證書配置客戶端身份認證
建立證書
[[email protected] ~]# vim jane-csr.json { "CN": "jane", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing" } ] } [[email protected]-master1 ~]# cfssl gencert -ca=/opt/kubernetes/ssl/ca.pem -ca-key=/opt/kubernetes/ssl/ca-key.pem -config=/opt/kubernetes/ssl/ca-config.json -profile=kubernetes jane-csr.json | cfssljson -bare jane
建立kubeconfig檔案
kubectl config set-cluster kubernetes \ --certificate-authority=/opt/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=https://192.168.0.130:6443 \ --kubeconfig=jane-kubeconfig kubectl config set-credentials jane \ --client-key=jane-key.pem \ --client-certificate=jane.pem \ --embed-certs=true \ --kubeconfig=jane-kubeconfig kubectl config set-context default \ --cluster=kubernetes \ --user=jane \ --kubeconfig=jane-kubeconfig kubectl config use-context default --kubeconfig=jane-kubeconfig
測試僅對developent名稱空間檢視pod許可權
[[email protected] ~]# kubectl get pod -n developent NAME READY STATUS RESTARTS AGE nginx-7cdbd8cdc9-5dd7x 1/1 Running 0 16s nginx-7cdbd8cdc9-dthp7 1/1 Running 0 16s nginx-7cdbd8cdc9-lwzjf 1/1 Running 0 16s [[email protected]-master1 ~]# kubectl --kubeconfig=jane-kubeconfig get pod -n developent NAME READY STATUS RESTARTS AGE nginx-7cdbd8cdc9-5dd7x 1/1 Running 0 2m13s nginx-7cdbd8cdc9-dthp7 1/1 Running 0 2m13s nginx-7cdbd8cdc9-lwzjf 1/1 Running 0 2m13s [[email protected]-master1 ~]# kubectl --kubeconfig=jane-kubeconfig get pod Error from server (Forbidden): pods is forbidden: User "jane" cannot list resource "pods" in API group "" in the namespace "default"
使用RBAC授權UI許可權示例
serviceAccount
當建立 pod 的時候,如果沒有指定一個 service account,系統會自動在與該pod 相同的 namespace 下為其指派一個default service account。而pod和apiserver之間進行通訊的賬號,稱為serviceAccountName。如下:
[[email protected] ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nfs-client-provisioner-f69cd5cf-rfbdb 1/1 Running 0 4h31m web-0 1/1 Running 0 4h16m web-1 1/1 Running 0 4h16m [[email protected] ~]# kubectl get pod/web-0 -o yaml |grep "serviceAccountName" serviceAccountName: default [[email protected] ~]# kubectl describe pod web-0 Name: web-0 Namespace: default . . . . . Volumes: www: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: www-web-0 ReadOnly: false default-token-7vs6s: Type: Secret (a volume populated by a Secret) SecretName: default-token-7vs6s Optional: false
從上面可以看到每個Pod無論定義與否都會有個儲存卷,這個儲存卷為default-token-*** token令牌,這就是pod和serviceaccount認證資訊。通過secret進行定義,由於認證資訊屬於敏感資訊,所以需要儲存在secret資源當中,並以儲存卷的方式掛載到Pod當中。從而讓Pod內執行的應用通過對應的secret中的資訊來連線apiserver,並完成認證。每個 namespace 中都有一個預設的叫做 default 的 service account 資源。進行檢視名稱空間內的secret,也可以看到對應的default-token。讓當前名稱空間中所有的pod在連線apiserver時可以使用的預製認證資訊,從而保證pod之間的通訊。
[[email protected] ~]# kubectl get sa NAME SECRETS AGE default 1 9d nfs-client-provisioner 1 4h37m [[email protected] ~]# kubectl get secret NAME TYPE DATA AGE default-token-7vs6s kubernetes.io/service-account-token 3 9d nfs-client-provisioner-token-glqhl kubernetes.io/service-account-token 3 4h38m registry-pull-secret kubernetes.io/dockerconfigjson 1 8d
而預設的service account 僅僅只能獲取當前Pod自身的相關屬性,無法觀察到其他名稱空間Pod的相關屬性資訊。如果想要擴充套件Pod,假設有一個Pod需要用於管理其他Pod或者是其他資源物件,是無法通過自身的名稱空間的serviceaccount進行獲取其他Pod的相關屬性資訊的,此時就需要進行手動建立一個serviceaccount,並在建立Pod時進行定義。那麼serviceaccount該如何進行定義呢???實際上,service accout也屬於一個k8s資源。如下檢視service account的定義方式:
[[email protected] ~]# kubectl explain sa
service account的建立
[[email protected] ~]# kubectl create sa devsa -o yaml -n developent --dry-run #不執行檢視定義方式
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: devsa
namespace: developent
[[email protected] ~]# kubectl create sa devsa -o yaml -n developent --dry-run > sa.yaml #匯出yaml檔案
[[email protected] ~]# kubectl apply -f sa.yaml #建立 serviceaccount/devsa created [[email protected] ~]# kubectl get sa -n developent #檢視 NAME SECRETS AGE default 1 5m46s devsa 1 28s [[email protected] ~]# kubectl get sa devsa -n developent -o yaml apiVersion: v1 kind: ServiceAccount metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"creationTimestamp":null,"name":"devsa","namespace":"developent"}} creationTimestamp: "2018-12-28T07:01:01Z" name: devsa namespace: developent resourceVersion: "780489" selfLink: /api/v1/namespaces/developent/serviceaccounts/devsa uid: 56125cdc-0a6e-11e9-b58a-000c298a2b5f secrets: - name: devsa-token-krgp7
建立角色繫結
[[email protected] ~]# vim sa-rolebinding-demo.yaml kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: sa-read-pods namespace: developent subjects: - kind: ServiceAccount name: devsa roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io [[email protected]-master1 ~]# kubectl apply -f sa-rolebinding-demo.yaml rolebinding.rbac.authorization.k8s.io/sa-read-pods created
獲取token
[[email protected] ~]# kubectl get secret -n developent NAME TYPE DATA AGE default-token-2zhxk kubernetes.io/service-account-token 3 148m devsa-token-pktnh kubernetes.io/service-account-token 3 2m20s [[email protected]-master1 ~]# kubectl describe secret devsa-token-pktnh -n developent Name: devsa-token-pktnh Namespace: developent Labels: <none> Annotations: kubernetes.io/service-account.name: devsa kubernetes.io/service-account.uid: f69d0ff3-0a81-11e9-b58a-000c298a2b5f Type: kubernetes.io/service-account-token Data ==== ca.crt: 1359 bytes namespace: 10 bytes token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXZlbG9wZW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRldnNhLXRva2VuLXBrdG5oIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRldnNhIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZjY5ZDBmZjMtMGE4MS0xMWU5LWI1OGEtMDAwYzI5OGEyYjVmIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRldmVsb3BlbnQ6ZGV2c2EifQ.tkA8I8zHF0yjAS4aitd2NhltvASCx8KTug_cdAs3ImYe-5QkxgeO9VTck6L5F6SlMewg8keMYQ9hhgE89aQC4Vs1t89U_ftZ8lo725SrNxIBqhucPUHpvBWfc4OWc96p7PGYNH59AnudXVIKEXuYZyL-KLoQeAjddPRrYXPqUtBpxpQStLWe6qvl-hXY2yj-FyMXAbYRH516ZCMGetRJbYjla7JAPdPt9nAqZoJe00NvOUfw0xXVp_8H7tcvp0tQbQ5GE06zuCRHMfDV9RWj6XUoXKvKirk1yd2nSNJdygTp-1q5JGKxYY2a_tuq2NSCurNBI28Rpj7dV7eIkehkTw
訪問dashboard,僅對developent名稱空間讀取pod的許可權