Kubernetes 身份驗證確保只有授權使用者和服務才能存取叢集資源。文章詳細介紹 OIDC 和 Webhook 兩種驗證方法,並解析其運作流程與組態引數。OIDC 透過第三方身份提供者驗證使用者,Webhook 則透過外部服務驗證 Token。理解這兩種機制有助於提升 Kubernetes 叢集的安全性。

Kubernetes 身份驗證機制詳解:OIDC 與 Webhook 認證流程

Kubernetes 提供了多種身份驗證機制,其中 OpenID Connect(OIDC)與 Webhook 認證是兩種常見且重要的驗證方式。本文將探討這兩種機制的運作原理、組態方法及其在實際應用中的考量。

OIDC 身份驗證流程

OIDC 是一種根據 OAuth 2.0 的身份驗證協定,它允許使用者透過第三方身份提供者進行身份驗證。以下是 OIDC 認證流程的詳細步驟:

  1. 使用者身份驗證:使用者向 Kubernetes API 伺服器發起身份驗證請求,並被重定向到身份提供者進行驗證。
  2. 取得授權碼:使用者在身份提供者處完成驗證後,獲得一個授權碼。
  3. 交換令牌:使用者使用授權碼向身份提供者請求身份令牌(ID Token)和重新整理令牌(Refresh Token)。
  4. 組態 kubeconfig:使用者將獲得的身份令牌新增到 kubeconfig 組態檔案中。
  5. API 請求認證:當使用者使用 kubectl 發起 Kubernetes API 請求時,kubectl 會自動將身份令牌作為 Bearer Token 新增到請求中。
  6. 令牌驗證:Kubernetes API 伺服器接收到請求後,會向身份提供者驗證令牌的有效性。
  7. 請求處理:如果令牌驗證成功,API 伺服器會允許請求繼續執行。

OIDC 組態引數

要啟用 OIDC 身份驗證,需要在 Kubernetes API 伺服器上組態以下引數:

  • --oidc-issuer-url:身份提供者的 URL。
  • --oidc-client-id:客戶端 ID。
  • --oidc-username-claim(可選):用於指定使用者名稱的 Claim,預設為 sub
  • --oidc-group-claim(可選):用於指定使用者群組的 Claim,預設為 groups
# 示例命令列引數
--oidc-issuer-url=https://auth.example.com
--oidc-client-id=dTBlg7xO7dks1uG6Op976jC7TjUZDCDz
--oidc-username-claim=username
--oidc-group-claim=groups

JWT 令牌結構解析

OIDC 使用 JSON Web Token(JWT)作為身份令牌。JWT 包含多個 Claim,用於描述使用者的屬性。以下是一個 JWT 令牌的示例:

{
  "iss": "https://auth.example.com",
  "sub": "Ch5hdXRoMHwMTYzOTgzZTdjN2EyNWQxMDViNjESBWF1N2Q2",
  "aud": "dTBlg7xO7dks1uG6Op976jC7TjUZDCDz",
  "exp": 1517266346,
  "iat": 1517179946,
  "at_hash": "OjgZQ0vauibNVcXP52CtoQ",
  "username": "user",
  "email": "user@example.com",
  "email_verified": true,
  "groups": [
    "qa",
    "infrastructure"
  ]
}

內容解密:

此 JWT 令牌包含了多個重要的 Claim,如 iss(發行者)、sub(主體)、exp(過期時間)、usernamegroups。這些 Claim 用於描述使用者的身份和屬性,並在 Kubernetes API 伺服器進行身份驗證時使用。

Webhook 認證流程

Webhook 認證是一種允許 Kubernetes API 伺服器與外部認證服務進行互動的機制。以下是 Webhook 認證的詳細步驟:

  1. 提取 Bearer Token:API 伺服器從收到的請求中提取 Bearer Token。
  2. 傳送 TokenReview 請求:API 伺服器向認證服務傳送一個包含 Bearer Token 的 TokenReview 請求。
  3. 驗證 Token:認證服務驗證 Bearer Token 的有效性。
  4. 傳回驗證結果:認證服務傳回一個 TokenReview 回應,指示 Token 是否有效。

TokenReview 請求與回應

以下是 TokenReview 請求和回應的示例:

# 請求
{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "spec": {
    "token": "some-bearer-token-string"
  }
}

# 成功回應
{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "status": {
    "authenticated": true,
    "user": {
      "username": "janedoe@example.com",
      "uid": "42",
      "groups": [
        "developers",
        "qa"
      ]
    }
  }
}

# 失敗回應
{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "status": {
    "authenticated": false
  }
}

內容解密:

Webhook 認證允許 Kubernetes 與外部認證服務進行整合,提供更大的靈活性。在 TokenReview 請求中,API 伺服器將 Bearer Token 傳送給認證服務。認證服務驗證 Token 後,傳回一個指示 Token 是否有效的回應。如果 Token 有效,回應中還會包含使用者的詳細資訊,如使用者名稱、UID 和所屬群組。

Kubernetes 驗證與使用者管理深度解析

Kubernetes 的驗證機制是確保叢集安全性的關鍵組成部分。API 伺服器負責處理所有請求,而驗證服務則提供指導,決定是否允許或拒絕 Kubernetes API 請求。

Token-Based 驗證機制的效能瓶頸

大多數根據 token 的驗證機制都需要額外的請求和回應來驗證 token。例如,OIDC 和 webhook 驗證都需要額外的往返時間來驗證 token。如果身份提供者回應不及時,這可能會成為 API 請求的效能瓶頸。因此,選擇低延遲和高效能的提供者至關重要。

Dex:Kubernetes 的 OIDC 代理

當現有的驗證服務無法滿足需求時,Dex 是一個值得考慮的解決方案。Dex 是 CoreOS 的一個專案,提供了一個標準的 OIDC 前端,支援多種常見的後端,包括 LDAP、Active Directory、SQL、SAML 和 SaaS 提供者,如 GitHub、GitLab 和 LinkedIn。Dex 使得將 Kubernetes 與現有的身份管理系統整合變得更加容易。

多重驗證機制的組態

Kubernetes 叢集可以同時啟用多個驗證機制。這種組態在除錯失敗的次要 API 驗證機制時非常有用。例如,可以同時組態 TLS 使用者端憑證和 OIDC 驗證。當多個驗證外掛程式同時啟用時,第一個成功驗證使用者的外掛程式將會短路驗證程式。

kubeconfig:Kubernetes 的組態檔案

kubeconfig 檔案記錄瞭如何驗證 Kubernetes API 請求的詳細資訊。kubectl 使用這個組態檔案來決定傳送請求到 API 伺服器的位置和方法。這個檔案通常位於 ~/.kube/config,但也可以透過 --kubeconfig 引數或 KUBECONFIG 環境變數來指定。

kubeconfig 的結構

kubeconfig 檔案有三個頂層結構:usersclusterscontexts

  • users 定義了使用者名稱和驗證機制。
  • clusters 提供了連線到叢集所需的資訊,包括 API 伺服器的 IP 或完整網域名稱。
  • contexts 將使用者與叢集關聯起來,形成一個單一的命名實體。

管理 kubeconfig

可以使用 kubectl 命令來管理 kubeconfig 檔案。以下是一些範例命令:

$ export KUBECONFIG=mykubeconfig
$ kubectl config set-credentials cluster-admin --username=admin --password=somepassword
$ kubectl config set-credentials regular-user --username=user --password=someotherpassword
$ kubectl config set-cluster cluster1 --server=https://10.1.1.3
$ kubectl config set-cluster cluster2 --server=https://192.168.1.50
$ kubectl config set-context cluster1-admin --cluster=cluster1 --user=cluster-admin
$ kubectl config set-context cluster1-regular --cluster=cluster1 --user=regular-user
$ kubectl config set-context cluster2-regular --cluster=cluster2 --user=regular-user
$ kubectl config view

kubeconfig 的內容

apiVersion: v1
clusters:
- cluster:
    server: https://10.1.1.3
  name: cluster1
- cluster:
    server: https://192.168.1.50
  name: cluster2
contexts:
- context:
    cluster: cluster1
    user: cluster-admin
  name: cluster1-admin
- context:
    cluster: cluster1
    user: regular-user
  name: cluster1-regular
- context:
    cluster: cluster2
    user: regular-user
  name: cluster2-regular
current-context: ""
kind: Config
preferences: {}
users:
- name: cluster-admin
  user:
    password: somepassword
    username: admin
- name: regular-user
  user:
    password: someotherpassword
    username: user

重點解析

  • Kubernetes 的驗證機制對於確保叢集安全性至關重要。
  • Token-Based 驗證機制需要額外的請求和回應來驗證 token,可能會成為效能瓶頸。
  • Dex 提供了一個標準的 OIDC 前端,支援多種常見的後端,是整合 Kubernetes 與現有身份管理系統的一個好選擇。
  • 可以同時啟用多個驗證機制,以提高除錯的便利性。
  • kubeconfig 檔案記錄了驗證 Kubernetes API 請求的詳細資訊,是 kubectl 的重要組態檔案。

Kubernetes 身份驗證與服務帳戶管理

Kubernetes 提供了靈活的身份驗證機制,讓使用者能夠安全地與叢集互動。在本章中,我們將探討 Kubernetes 的身份驗證機制,包括使用者身份驗證和服務帳戶的管理。

使用者身份驗證與 Context 設定

Kubernetes 允許使用者透過多種方式進行身份驗證,例如 X.509 使用者端憑證、靜態權杖檔案和認證代理等。為了簡化叢集管理,Kubernetes 引入了 context 的概念,將叢集、使用者和名稱空間的組態進行組合,從而實作快速切換。

$ kubectl config use-context cluster2-regular
Switched to context "cluster2-regular".

這使得在不同叢集之間切換,或者在同一個叢集中模擬不同使用者變得非常簡單。使用者可以根據自己的需求建立多個 context,並透過簡單的命令進行切換。

服務帳戶(Service Accounts)

除了使用者身份驗證外,Kubernetes 還提供了服務帳戶(Service Accounts)來管理 Pod 內部程式對 API 的存取。服務帳戶是一種名稱空間級別的使用者帳戶,用於為 Pod 提供身份驗證。

建立服務帳戶

$ kubectl create sa testsa
$ kubectl get sa testsa -oyaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: testsa
  namespace: default
secrets:
- name: testsa-token-nr6md

當建立服務帳戶時,Kubernetes 會自動建立一個 Secret,其中包含用於身份驗證的權杖。這個權杖會被掛載到 Pod 中的一個已知位置,供 Kubernetes 使用者端使用。

服務帳戶的應用

每個 Pod 都會關聯一個服務帳戶,如果在 Pod 清單中沒有指定,則會使用預設的服務帳戶。預設服務帳戶在名稱空間建立時自動建立。

apiVersion: v1
kind: Pod
metadata:
  name: testpod
spec:
  serviceAccountName: testpod-sa

JWT 權杖解析

服務帳戶使用的 JWT 權杖包含了多個 Claims,用於識別服務帳戶的相關資訊。

{
  "iss": "kubernetes/serviceaccount",
  "kubernetes.io/serviceaccount/namespace": "default",
  "kubernetes.io/serviceaccount/secret.name": "testsa-token-nr6md",
  "kubernetes.io/serviceaccount/service-account.name": "testsa",
  "kubernetes.io/serviceaccount/service-account.uid": "23fe204f-0f66-11e8-85d0-080027da173d",
  "sub": "system:serviceaccount:default:testsa"
}

安全考量

雖然服務帳戶為 Pod 提供了存取 Kubernetes API 的能力,但在某些場景下,從安全的角度來看,為 Pod 提供 API 存取許可權可能並不合適。我們將在後續章節中探討如何對這些使用案例進行安全強化。

Kubernetes 授權機制

在 Kubernetes 中,API 請求的安全驗證包含三個主要步驟:驗證(Authentication)、授權(Authorization)和准入控制(Admission Control)。本章將重點介紹授權機制的運作原理及其在 Kubernetes 中的重要性。

RESTful API 與資源操作

Kubernetes API 是一個 RESTful API,其設計簡單且具擴充套件性。RESTful API 的核心概念是透過動詞(Verbs)來操作資源(Resources)。例如,當我們請求取得一個 Pod 的資訊時,實際上是發送了一個 GET 請求到特定的資源路徑。

kubectl 請求分析

透過增加 -v 選項來提高日誌級別,我們可以觀察到 kubectl 在背後傳送的 API 請求細節:

$ kubectl -v=6 get po testpod
I0202 00:28:31.933993 17487 loader.go:357] Config loaded from file /home/ubuntu/.kube/config
I0202 00:28:31.994930 17487 round_trippers.go:436] GET https://10.0.0.1:6443/api/v1/namespaces/default/pods/testpod 200 OK

在這個例子中,kubectl 發送了一個 GET 請求來取得 testpod 的資訊。這裡的 GET 是動詞,而 pods/testpod 是資源。

RESTful 動詞與 Kubernetes 資源操作

RESTful API 中常見的四個基本動詞是:Create、Read、Update 和 Delete(CRUD),分別對應到 HTTP 的 POSTGETPUTDELETE 方法。在 Kubernetes 中,除了這四個基本動詞外,還支援 listwatchproxyredirectdeletecollection 等動詞來操作資源。

授權機制

驗證使用者身份後,下一步是授權,即判斷使用者是否有許可權執行特定的操作。Kubernetes 的授權機制由 API 伺服器負責,並透過 --authorization-mode 引數來組態不同的授權模組。

授權模組

目前 Kubernetes 支援多個授權模組,包括:

  1. AlwaysAllow 和 AlwaysDeny:這兩個模組分別無條件允許或拒絕所有請求,主要用於測試環境。
  2. Node:該模組負責限制工作節點(kubelet)對 API 伺服器的存取許可權,確保 kubelet 只能執行必要的操作。
  3. RBAC(Role-Based Access Control):根據角色的存取控制,是目前最為靈活和強大的授權機制,能夠在執行時動態定義存取控制策略。

RBAC 詳解

RBAC 允許管理員透過定義角色(Roles)和角色繫結(RoleBindings)來精細控制使用者對 Kubernetes 資源的存取許可權。這種機制避免了粗粒度許可權控制的問題,使得安全性和靈活性得到了提升。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Kubernetes 身份驗證與授權機制詳解

package "Kubernetes Cluster" {
    package "Control Plane" {
        component [API Server] as api
        component [Controller Manager] as cm
        component [Scheduler] as sched
        database [etcd] as etcd
    }

    package "Worker Nodes" {
        component [Kubelet] as kubelet
        component [Kube-proxy] as proxy
        package "Pods" {
            component [Container 1] as c1
            component [Container 2] as c2
        }
    }
}

api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2

note right of api
  核心 API 入口
  所有操作經由此處
end note

@enduml

此圖示展示了 Kubernetes 中一個請求的處理流程,從驗證到授權再到准入控制的完整過程。

內容解密:

此圖表闡述了 Kubernetes 處理 API 請求的流程。首先,使用者發出請求到 Kubernetes API。接著,系統進行驗證,確認使用者的身份。如果驗證透過,則進入授權階段。在授權階段,RBAC 模組檢查使用者的角色和許可權。如果允許,則進入准入控制階段;如果拒絕,則傳回 HTTP 403 Forbidden 錯誤。