edx-LFS158x Kubernetes學習筆記(第九章)

Chapter 9. Authentication, Authorization, Admission Control


Introduction and Learning Objectives


每個到達API服務器的API請求都必須經過三個不同的階段,然後才會被服務器接受並執行。在本章中,我們將研究Kubernetes API請求的認證、授權和允許控制階段.本章結束之前,您應該能夠:

  • 討論Kubernetes API訪問的認證、授權和訪問控制階段。
  • 瞭解不同類型的Kubernetes用戶。
  • 探索用於身份驗證和授權的不同模塊


Authentication, Authorization, and Admission Control


Authentication, Authorization, and Admission Control - Overview


要訪問和管理集群中的Kubernetes資源或對象,需要訪問API服務器上的特定API端點。每個訪問請求都經過以下三個階段:

  • 身份驗證
    用戶登錄。
  • 授權
    授權登錄用戶添加的API請求。
  • 允許控制
    軟件模塊可以根據一些額外的檢查(如預先設置的配額)修改或拒絕請求。
    下圖描述了上述階段:
    Accessing the API
edx-LFS158x Kubernetes學習筆記(第九章)


Authentication I


Kubernetes沒有一個名為user的對象,也沒有在它的對象存儲中存儲用戶名或其他相關細節。但是,即使沒有這個,Kubernetes也可以使用用戶名進行訪問控制和請求日誌記錄,我們將在本章對此進行探討;Kubernetes有兩種用戶:

  • 普通用戶
    它們在Kubernetes集群之外通過獨立的服務(如用戶/客戶端證書、列出用戶名/密碼的文件、Google帳戶等)進行管理。
  • 服務帳戶
    對於服務帳戶用戶,集群中的進程與API服務器通信以執行不同的操作。大多數服務帳戶用戶是通過API服務器自動創建的,但也可以手動創建。服務帳戶用戶綁定到給定的命名空間,並裝載相應的憑據以作為機密與API服務器通信。
    如果配置正確,Kubernetes可以支持匿名請求,以及來自普通用戶和服務帳戶的請求。還支持用戶模擬,以便用戶能夠充當另一個用戶,這是管理員排除授權策略故障時的一個有用功能。


Authentication II


對於身份驗證,Kubernetes使用不同的身份驗證模塊:

  • 客戶端證書
    要啟用客戶端證書身份驗證,我們需要通過--client-ca-file=SOMEFILE 選項傳遞給API服務器一個或多個證書頒發機構的文件。文件中提到的證書頒發機構將驗證提供給API服務器的客戶端證書。本章末尾還提供了一個涵蓋此主題的演示視頻。
  • 靜態令牌文件
    我們可以使用--token-auth-file=SOMEFILE 選項將預定義的不記名令牌的文件傳遞給API服務器。目前,這些令牌將無限期地持續,如果不重新啟動API服務器,則無法更改它們。
  • Bootstrap Tokens
    此功能當前處於beta狀態,主要用於bootstrapping 新的Kubernetes集群。
  • 靜態密碼文件
    它類似於靜態令牌文件。我們可以使用--basic-auth-file=SOMEFILE 選項傳遞包含基本身份驗證詳細信息的文件。這些憑據將無限期地持續,如果不重新啟動API服務器,則無法更改密碼。
  • 服務帳戶令牌
    這是一個自動啟用的身份驗證器,它使用簽名的不記名令牌來驗證請求。這些令牌使用ServiceAccount Admission Controller連接到Pods,該控制器允許集群內進程與API服務器通信。
  • OpenID連接令牌
    OpenID Connect幫助我們與OAuth2提供商(如Azure Active Directory、Salesforce、Google等)連接,將身份驗證放到外部服務去完成。
  • Webhook令牌身份驗證
    使用基於Webhook的身份驗證,不記名令牌的驗證可以放到遠程服務去完成。
  • 認證代理
    如果我們想編程實現額外的認證邏輯,我們可以使用認證代理。

我們可以啟用多個認證器,第一個成功認證請求的模塊完成認證評估(後續模塊就不用再驗證)。為了保證認證成功,您應該至少啟用兩個方法:服務帳戶令牌身份驗證器和一個用戶身份驗證器。


Authorization I


認證成功後,用戶可以發送API請求來執行不同的操作。然後,這些API請求由Kubernetes使用各種授權模塊進行授權。Kubernetes檢查的一些API請求屬性包括user、group、extra、Resource或Namespace等等。接下來,根據策略評估這些屬性。如果評估成功,則允許請求,否則將被拒絕。與認證步驟類似,授權具有多個模塊/授權器。可以為一個Kubernetes集群配置多個模塊,每個模塊都是按順序簽入的。如果任何授權人批准或拒絕請求,則立即返回該結果。接下來,我們將討論由Kubernetes支持的授權器。


Authorization II


  • 節點授權人
    節點授權是對kubelets提出的API請求進行專門授權的一種專用授權方式。它授權kubelet對服務、端點、節點等的讀取操作,並授權節點、pod、事件等的寫入操作。有關更多詳細信息,請參閱Kubernetes文檔:https://kubernetes.io/docs/reference/access-authn-authz/node/。
  • 基於屬性的訪問控制(ABAC)授權程序
    通過ABAC授權程序,Kubernetes授予對API請求的訪問權,API請求將策略與屬性結合起來。在下面的示例中,用戶student只能讀取名稱空間lfs158中的pod。


<code>{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "student",
"namespace": "lfs158",
"resource": "pods",
"readonly": true
}
}
/<code>

要啟用ABAC授權程序,我們需要使用 --authorization-mode=ABAC選項啟動API服務器。我們還需要使用--authorization-policy-file=PolicyFile.json指定授權策略。有關更多詳細信息,請查看Kubernetes文檔:https://kubernetes.io/docs/reference/access-authn-authz/abac/。

  • Webhook授權人
    通過Webhook授權程序,Kubernetes可以向某些第三方服務提供授權決策,如果授權成功,則返回true,如果授權失敗,則返回false。為了啟用Webhook授權程序,我們需要使用 --authorization-webhook-config-file=SOME_FILENAME 選項啟動API服務器,其中SOME_FILENAME是遠程授權服務的配置。有關更多詳細信息,請參閱Kubernetes文檔:https://kubernetes.io/docs/reference/access-authn-authz/webhook/。


Authorization III


授權模塊(第2部分):基於角色的訪問控制(RBAC)授權程序一般來說,使用RBAC,我們可以根據單個用戶的角色來調節對資源的訪問。在Kubernetes中,我們可以將不同的角色附加到用戶、服務帳戶等主題上。在創建角色時,我們通過特定的操作(如create、get、update、patch等)限制資源訪問。這些操作稱為verbs。在RBAC中,我們可以創建兩種角色:

  • Role
    使用Role,我們可以授予對特定Namespace中資源的訪問權限。
  • ClusterRole
    ClusterRole可用於授予與Role相同的權限,但其作用域是cluster範圍的。
    在本課程中,我們將集中討論第一類角色。下面是一個例子:


<code>kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: lfs158
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
/<code>

如您所見,它創建了一個pod-reader角色,該角色只能讀取lfs158名稱空間的pod。創建角色後,我們可以將用戶與RoleBinding綁定。有兩種RoleBinding:

  • RoleBinding
    它允許我們將用戶綁定到與Role相同的命名空間。我們還可以在RoleBinding中引用ClusterRole,它將授予對RoleBinding的命名空間中ClusterRole中定義的命名空間資源的權限。
  • ClusterRoleBinding
    它允許我們授予對cluster級資源和所有命名空間的訪問權。
    在本課程中,我們將集中討論第一種,RoleBinding。下面是一個例子:


<code>kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pod-read-access
namespace: lfs158

subjects:
- kind: User
name: student
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
/<code>

如您所見,它允許學生用戶讀取lfs158名稱空間的Pods。要啟用RBAC授權程序,我們需要使用--authorization-mode=RBAC選項啟動API服務器。通過RBAC授權器,我們可以動態配置策略。有關更多詳細信息,請查看Kubernetes文檔。


Admission Control


許可控制用於指定粒度訪問控制策略,包括給容器授予特定權限、檢查資源配額等。我們使用不同的許可控制器強制這些策略,如ResourceQuota、DefaultStorageClass、AlwaysPllimages,等等。它們只有在API請求經過身份驗證和授權後才生效。要使用許可控制,我們必須使用--enable-accedition-plugins啟動Kubernetes API服務器,該插件採用逗號分隔的、有序的控制器名稱列表:


<code>--enable-admission-plugins=NamespaceLifecycle,ResourceQuota,PodSecurityPolicy,DefaultStorageClass
/<code>

Kubernetes在默認情況下啟用了一些許可控制器。有關更多詳細信息,請查看Kubernetes文檔。


Authentication and Authorization Exercise Guide


本練習指南假設以下環境(默認情況下使用/var/lib/minikube/certs/中的證書和密鑰)和RBAC模式進行授權:

  • Minikube 1.0.1版
  • Kubernetes 1.14.1版
  • Docker 18.06.3-ce
    本練習指南可與下一頁的視頻演示一起使用,並且已針對上述環境進行了更新,同時視頻呈現了Kubernetes v1.9的舊Minikube發行版。
    啟動Minikube:


<code>$ minikube start
/<code>

查看kubectl客戶端配置文件的內容,觀察默認創建的唯一上下文minikube和唯一用戶minikube:


<code>$ kubectl config view

apiVersion: v1
clusters:
- cluster:
certificate-authority: /home/student/.minikube/ca.crt
server: https://192.168.99.100:8443

name: minikube
contexts:
- context:
cluster: minikube
user: minikube
name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
user:
client-certificate: /home/student/.minikube/client.crt
client-key: /home/student/.minikube/client.key
/<code>

創建lsf158的命名空間:


<code>$ kubectl create namespace lfs158

namespace/lfs158 created
/<code>

創建rbac目錄並進入:


<code>$ mkdir rbac

$ cd rbac/
/<code>

使用openssl工具為學生用戶創建私鑰,然後使用openssl工具為學生用戶創建證書籤名請求:


<code>~/rbac$ openssl genrsa -out student.key 2048

Generating RSA private key, 2048 bit long modulus (2 primes)
.................................................+++++
.........................+++++

e is 65537 (0x010001)

~/rbac$ openssl req -new -key student.key -out student.csr -subj "/CN=student/O=learner"
/<code>

為證書籤名請求對象創建YAML配置文件,並將其保存為請求字段的空值


<code>~/rbac$ vim signing-request.yaml

apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: student-csr
spec:
groups:
- system:authenticated
request: <assign>
usages:
- digital signature
- key encipherment
- client auth
/<assign>/<code>

查看certificate,將其編碼為base64,並將其賦值給 signing-request.yaml文件中的request字段。


<code>~/rbac$ cat student.csr | base64 | tr -d '\\n'

LS0tLS1CRUd...1QtLS0tLQo=

~/rbac$ vim signing-request.yaml

apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: student-csr
spec:
groups:
- system:authenticated
request: LS0tLS1CRUd...1QtLS0tLQo=

usages:
- digital signature
- key encipherment
- client auth
/<code>

創建certificate signing request對象,然後列出證書籤名請求對象。它顯示一個掛起狀態:


<code>~/rbac$ kubectl create -f signing-request.yaml

certificatesigningrequest.certificates.k8s.io/student-csr created

~/rbac$ kubectl get csr

NAME AGE REQUESTOR CONDITION
student-csr 27s minikube-user Pending
/<code>

批准certificate signing request 對象,然後再次列出證書籤名請求對象。它同時顯示了approved 和issued的狀態:


<code>~/rbac$ kubectl certificate approve student-csr

certificatesigningrequest.certificates.k8s.io/student-csr approved

~/rbac$ kubectl get csr

NAME AGE REQUESTOR CONDITION
student-csr 77s minikube-user Approved,Issued
/<code>

從certificate signing request中提取已批准的certificate ,用base64對其進行解碼,並將其保存為 certificate file。然後查看新創建的證書文件中的證書:


<code>~/rbac$ kubectl get csr student-csr -o jsonpath='{.status.certificate}' | base64 --decode > student.crt

~/rbac$ cat student.crt

-----BEGIN CERTIFICATE-----
MIIDGzCCA...
...
...NOZRRZBVunTjK7A==
-----END CERTIFICATE-----
/<code>

通過分配密鑰和證書來配置學生用戶的憑據:


<code>~/rbac$ kubectl config set-credentials student --client-certificate=student.crt --client-key=student.key

User "student" set.
/<code>

在kubectl客戶機的配置文件中為學生用戶創建一個新的上下文條目,該條目與minikube集群中的lfs158名稱空間相關聯


<code>~/rbac$ kubectl config set-context student-context --cluster=minikube --namespace=lfs158 --user=student

Context "student-context" created.
/<code>

再次查看kubectl客戶機配置文件的內容,觀察新的上下文條目student-context和新的用戶條目student


<code>apiVersion: v1
clusters:
- cluster:
certificate-authority: /home/student/.minikube/ca.crt
server: https://192.168.99.100:8443

name: minikube
contexts:
- context:
cluster: minikube
user: minikube
name: minikube
- context:
cluster: minikube
namespace: lfs158
user: student
name: student-context
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
user:
client-certificate: /home/student/.minikube/client.crt
client-key: /home/student/.minikube/client.key
- name: student
user:
client-certificate: /home/student/rbac/student.crt
client-key: /home/student/rbac/student.key
/<code>

在默認的minikube上下文中,在lfs158命名空間中創建一個新的deployment :


<code>~/rbac$ kubectl -n lfs158 create deployment nginx --image=nginx:alpine

deployment.apps/nginx created
/<code>

從新的context student-context 試著列出Pods。因為student 用戶沒有為 student-context配置權限,所以嘗試失敗:


<code>~/rbac$ kubectl --context=student-context get pods

Error from server (Forbidden): pods is forbidden: User "student" cannot list resource "pods" in API group "" in the namespace "lfs158"
/<code>

以下步驟將在student-context中為student用戶分配一組有限的權限。為一個pod-reader role對象創建一個YAML配置文件,該文件只允許對pod對象使用lfs158名稱空間中的get、watch和list操作。然後創建role對象,並從默認的minikube context(但從lfs158名稱空間)列出它:


<code>~/rbac$ vim role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: lfs158
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]

~/rbac$ kubectl create -f role.yaml

role.rbac.authorization.k8s.io/pod-reader created

~/rbac$ kubectl -n lfs158 get roles

NAME AGE
pod-reader 57s
/<code>

為rolebinding對象創建YAML配置文件,該對象將pod-reader角色的權限分配給student用戶。然後創建rolebinding對象,並從默認的minikube上下文(但從lfs158名稱空間)列出它


<code>~/rbac$ vim rolebinding.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-read-access
namespace: lfs158
subjects:
- kind: User
name: student
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io


~/rbac$ kubectl create -f rolebinding.yaml

rolebinding.rbac.authorization.k8s.io/pod-read-access created

~/rbac$ kubectl -n lfs158 get rolebindings

NAME AGE
pod-read-access 23s
/<code>

現在我們已經為student用戶分配了權限,我們可以成功地列出來自新 context student-context的pods:


<code>~/rbac$ kubectl --context=student-context get pods

NAME READY STATUS RESTARTS AGE
nginx-77595c695-f2xmd 1/1 Running 0 7m4
/<code>


Authentication and Authorization (Demo)

https://edx-video.net/LINIKLFS2017-V001100_DTH.mp4


分享到:


相關文章: