一、kubernetes集群安全架構
用戶使用kubectl、客戶機或通過REST請求訪問API。可以授權用戶和Kubernetes服務帳戶進行API訪問。當一個請求到達API時,它會經歷幾個階段,如下圖所示:
1.訪問K8S集群的資源需要過三關:認證、鑒權、准入控制;
2.普通用戶若要安全訪問集群API Server,往往需要證書、Token或者用戶名+密碼;
3.Pod訪問,需要ServiceAccountK8S安全控制框架主要由下面3個階段進行控制,每一個階段都支持插件方式,通過API Server配置來啟用插件。
- 1. Authentication
- 2. Authorization
- 3. Admission Contro
二、認證
API Server處理請求的過程中,認證插件負責鑒定⽤戶⾝份,授權插件⽤於操作權限許可鑒別,⽽准⼊控制則⽤於在資源對象的創建、刪除、更新或連接(proxy)操作時實現更精細的許可檢查。Kubernetes使⽤⾝份驗證插件對API請求進⾏⾝份驗證,⽀持的認證⽅式包括客戶端證書、承載令牌(bearer tokens)、⾝份驗證代理(authenticating proxy)或HTTP basic認證等。
下面我們基於客戶端證書來做認證:
1.將apiserver的根證書(ca.pem,ca-key.pem,ca-config.json)放到同一個目錄下執行以下腳本:
[root@master hejianlai]# cat rbac-user.sh cat > hejianlai-csr.json <<EOF { "CN": "hejianlai", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing" } ] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes hejianlai-csr.json | cfssljson -bare hejianlai kubectl config set-cluster kubernetes \ --certificate-authority=ca.pem \ --embed-certs=true \ --server=https://172.31.182.140:6443 \ #Master ip --kubeconfig=hejianlai-kubeconfig kubectl config set-credentials hejianlai \ --client-key=hejianlai-key.pem \ --client-certificate=hejianlai.pem \ --embed-certs=true \ --kubeconfig=hejianlai-kubeconfig kubectl config set-context default \ --cluster=kubernetes \ --user=hejianlai \ --kubeconfig=hejianlai-kubeconfig kubectl config use-context default --kubeconfig=hejianlai-kubeconfig
三、RBAC授權
官方地址:https://kubernetes.io/docs/reference/access-authn-authz/rbac/
RBAC是⼀種操作授權機制,⽤於界定“誰”(subject)能夠或不能夠“操作”(verb)哪個或哪類“對象”(object)。動作的發出者即“主體”,通常以“賬號”為載體,它既可以是常規⽤戶(User Account),也可以是服務賬號(Service Account)。“操作”(verb)⽤於表明要執⾏的具體操作,包括創建、刪除、修改和查看等,對應於kubectl來說,它通常由create、apply、delete、update、patch、edit和get等⼦命令來給出。⽽“客體”則是指操作施加於的⽬標實體,對Kubernetes API來說主要是指各類的資源對象以及⾮資源型URL。
Kubernetes 使用 API 服務器授權 API 請求。它根據所有策略評估所有請求屬性來決定允許或拒絕請求。 一個API請求的所有部分必須被某些策略允許才能繼續。這意味着默認情況下拒絕權限。
(盡管 Kubernetes 使用 API 服務器,但是依賴於特定種類對象的特定字段的訪問控制和策略由准入控制器處理。)
配置多個授權模塊時,將按順序檢查每個模塊。 如果任何授權模塊批准或拒絕請求,則立即返回該決定,並且不會與其他授權模塊協商。 如果所有模塊對請求沒有意見,則拒絕該請求。一個拒絕響應返回 HTTP 狀態代碼 403 。
Kubernetes僅審查以下API請求屬性:
- user - 身份驗證期間提供的
user
字符串。 - group - 經過身份驗證的用戶所屬的組名列表。
- extra - 由身份驗證層提供的任意字符串鍵到字符串值的映射。
- API - 指示請求是否針對 API 資源。
- Request path - 各種非資源端點的路徑,如
/api
或/healthz
。 - API request verb - API 動詞
get
,list
,create
,update
,patch
,watch
,proxy
,redirect
,delete
和deletecollection
用於資源請求。要確定資源API端點的請求動詞,請參閱確定請求動詞。 - HTTP request verb - HTTP 動詞
get
,post
,put
和delete
用於非資源請求。 - Resource - 正在訪問的資源的 ID 或名稱(僅限資源請求) - 對於使用
get
,update
,patch
和delete
動詞的資源請求,您必須提供資源名稱。 - Subresource - 正在訪問的子資源(僅限資源請求)。
- Namespace - 正在訪問的對象的名稱空間(僅適用於命名空間資源請求)。
- API group - 正在訪問的 API 組(僅限資源請求)。空字符串表示核心API組。
1、創建role其權限只有簡單的查看pod,我這里指定命名空間pci
[root@master rbac]# cat role.yaml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: pci name: pod-reader rules: - apiGroups: [""] # "" indicates the core API group resources: ["pods"] verbs: ["get", "watch", "list"]
2.創建rolebinding 綁定用戶
[root@master rbac]# cat role-binding.yaml kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: read-pods namespace: pci subjects: - kind: User name: hejianlai # Name is case sensitive apiGroup: rbac.authorization.k8s.io roleRef: kind: Role #this must be Role or ClusterRole name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to apiGroup: rbac.authorization.k8s.io
三、准入控制
Kubernetes系統通過三個獨⽴的組件間的相互協作來實現服務賬戶的⾃動化,三個組件具體為:Service Account准⼊控制器、令牌控制器(token controller)和Service Account賬戶控制器。Service Account控制器負責為名稱空間管理相應的資源,並確保每個名稱空間中都存在⼀個名為“default”的Service Account對象。
[root@master hejianlai]# cat sa.yaml apiVersion: v1 kind: ServiceAccount metadata: name: pod-reader namespace: pci --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: sa-read-pods namespace: pci subjects: - kind: ServiceAccount name: pod-reader roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
這時我們可以看見在pci這個命名中間下有一個默認的defaul和剛創建的pod-reader
這時我們驗證下權限是否有效:
上圖我們可以看到除了該命名空間下除了pod可以訪問,其他的權限都是被拒絕的。
通過查看這個pod-reader生成的token我們就可以訪問:
kubectl describe secret pod-reader -n pci
記住這個token要復制到記事本里取消自動換行!!!
然后我們用這個token去訪問UI時也是只能看到pci這個命名中間下的。