返回文章列表

Kubernetes ServiceAccount 與 JWT 驗證機制

本文探討 Kubernetes 中 ServiceAccount 與 JWT 的驗證機制,說明如何建立和管理 ServiceAccount,以及如何使用 JWT Token 進行 kubectl 驗證。文章涵蓋了從 Kubernetes 1.22 版本開始的改進,例如短暫有效 Token 和自動掛載,並示範瞭如何建立

容器技術 資安

Kubernetes 提供 ServiceAccount 作為 Pod 與 Kubernetes API 互動的憑證機制。早期版本使用靜態 Token 存在安全風險,而自 1.22 版本起,Kubernetes 匯入 TokenRequest API,提供短暫有效且自動掛載的 Token,提升安全性。本文將逐步說明如何建立和管理 ServiceAccount,包含設定 RBAC 許可權,並示範如何使用產生的 JWT Token 設定 kubeconfig,以便透過 kubectl 進行驗證。同時,文章也將探討如何建立 Namespace、ServiceAccount、Role 和 RoleBinding,以及如何設定 kubeconfig 以使用 JWT Token 進行驗證,確保 Pod 能夠安全地存取 Kubernetes API。

Kubernetes 安全機制中的 ServiceAccount 與 JWT 驗證

在 Kubernetes 中,ServiceAccount 是用於提供 Pod 與 Kubernetes API 互動的身份憑證。在 1.22 版本之前,Kubernetes 會自動為 ServiceAccount 生成包含靜態 Token 的 Secret。然而,這種方法存在安全風險,因為靜態 Token 可能會被洩露,並且難以管理 Token 的生命週期和許可權。

從 1.22 版本開始的改進

從 Kubernetes 1.22 版本開始,系統改用更安全的 TokenRequest API 為 Pod 提供 Token。這些 Token 具有以下特性:

  • 短暫有效: Token 的生命週期有限,減少了 Token 被洩露的風險。
  • 自動掛載: Token 會自動掛載到 Pod 中,無需預先儲存 Secret。

雖然自動掛載是預設行為,但仍然可以手動建立 Secret 以取得較長生命週期的 Token。然而,在大多數情況下,建議優先使用自動掛載以提高安全性。

建立和管理 ServiceAccount

以下示範如何建立和管理 ServiceAccount,以及如何使用 JWT Token 進行 kubectl 驗證。

步驟 1: 建立 Namespace 和 ServiceAccount

首先,建立一個新的 Namespace 和一個 ServiceAccount,並設定 RBAC,使其只能讀取該 Namespace 中的 Pod。

# 01_serviceaccount/example-sa-ns.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: example-ns
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: example-sa
  namespace: example-ns

#### 內容解密:

此 YAML 檔案定義了一個新的 Namespace example-ns 和一個 ServiceAccount example-sa。ServiceAccount 被設定在 example-ns Namespace 中。

步驟 2: 建立 Role 和 RoleBinding

接下來,建立一個 Role 物件 pod-reader,允許讀取 example-ns Namespace 中的 Pod。

# 01_serviceaccount/pod-reader-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: example-ns
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

#### 內容解密:

此 Role 物件定義了對 Pod 資源的 getwatchlist 操作許可權,允許 ServiceAccount 讀取 Pod 資訊。

然後,建立一個 RoleBinding,將 pod-reader Role 繫結到 example-sa ServiceAccount。

# 01_serviceaccount/read-pods-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: example-ns
subjects:
- kind: ServiceAccount
  name: example-sa
  namespace: example-ns
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

#### 內容解密:

此 RoleBinding 將 pod-reader Role 繫結到 example-sa ServiceAccount,使其具有讀取 Pod 的許可權。

步驟 3: 建立 Token 和設定 kubeconfig

建立一個 Token 給 example-sa ServiceAccount。

$ kubectl create token example-sa -n example-ns

收集輸出的 JWT Token,並使用它來設定 kubeconfig。

$ kubectl config set-credentials example-sa --token=<your-token>

建立一個新的 context,使用剛才建立的使用者和叢集。

$ kubectl config set-context example-sa-context --user=example-sa --cluster=minikube

#### 內容解密:

此步驟使用 kubectl config 命令建立了一個新的使用者和 context,以便使用 example-sa ServiceAccount 的身份進行驗證。

切換到新的 context

切換到新的 context,並驗證目前的身份。

$ kubectl config use-context example-sa-context
$ kubectl auth whoami

#### 內容解密:

此步驟切換到新的 context,並使用 kubectl auth whoami 命令驗證目前的身份,確認其為 example-sa ServiceAccount。

Kubernetes 中的身份驗證方法:ServiceAccount 令牌與 X.509 使用者端憑證

Kubernetes 提供了多種身份驗證方法,以確保叢集的安全性和存取控制。在本章中,我們將探討兩種主要的身份驗證方法:ServiceAccount 令牌和 X.509 使用者端憑證。我們將分析它們的優缺點、設定方法和安全性影響。

使用 ServiceAccount 令牌進行身份驗證

ServiceAccount 是 Kubernetes 中的一個重要概念,它為 Pod 中的程式提供了身份和存取控制的能力。ServiceAccount 令牌可以用於身份驗證,但這種方法有一些限制。

設定 ServiceAccount 令牌

  1. 首先,我們需要建立一個 ServiceAccount 和相關的 RBAC 角色繫結。
apiVersion: v1
kind: ServiceAccount
metadata:
  name: example-sa
  namespace: example-ns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: example-sa-rolebinding
  namespace: example-ns
roleRef:
  name: example-role
  kind: Role
subjects:
- kind: ServiceAccount
  name: example-sa
  namespace: example-ns

內容解密:

  • 上述 YAML 檔案定義了一個名為 example-sa 的 ServiceAccount 和一個 RoleBinding,將 example-sa 繫結到 example-role 角色。
  • 這樣,example-sa 就具有了 example-role 定義的許可權。
  1. 然後,我們需要取得 ServiceAccount 的令牌,並使用它來設定 kubectl 的上下文。
$ kubectl get secret example-sa-token -n example-ns -o jsonpath='{.data.token}' | base64 --decode
$ kubectl config set-credentials example-sa --token=<token-value>
$ kubectl config set-context --current --user=example-sa

內容解密:

  • 第一行命令取得 example-sa 的令牌值。
  • 第二行命令使用取得的令牌值設定 kubectl 的使用者憑證。
  • 第三行命令將目前的上下文切換到使用 example-sa 使用者。
  1. 驗證身份驗證是否成功。
$ kubectl get po -n example-ns
NAME          READY   STATUS    RESTARTS   AGE
nginx-pod     1/1     Running   0          18m

內容解密:

  • 此命令列出 example-ns 名稱空間中的 Pod,驗證了 example-sa 的讀取許可權。

ServiceAccount 令牌的優缺點

優點:

  • 易於設定和使用。
  • 由 Kubernetes 叢集管理,無需外部身份驗證提供者。
  • ServiceAccount 是名稱空間範圍的。

缺點:

  • ServiceAccount 主要用於 Pod 中的程式,不建議用於外部身份驗證。
  • 在生產環境中,由於安全問題,不是最佳選擇。

使用 X.509 使用者端憑證進行身份驗證

X.509 使用者端憑證是一種行業標準的身份驗證方法。在 Kubernetes 中,可以使用 X.509 使用者端憑證進行身份驗證。

設定 X.509 使用者端憑證

  1. Kubernetes API 伺服器需要設定 --client-ca-file 引數,以提供憑證授權單位(CA)資訊。
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=192.168.59.154
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/var/lib/minikube/certs/ca.crt

內容解密:

  • 上述 YAML 檔案片段顯示了 kube-apiserver 的設定,其中 --client-ca-file 引數指定了 CA 憑證檔案的位置。
  1. 使用者需要從 CA 請求 X.509 使用者端憑證,並在身份驗證過程中出示該憑證。
$ kubectl config set-credentials minikube --client-certificate=/path/to/client.crt --client-key=/path/to/client.key

內容解密:

  • 此命令設定 kubectl 的使用者憑證,使用指定的使用者端憑證和私鑰。

X.509 使用者端憑證身份驗證流程

此圖示說明瞭 X.509 使用者端憑證身份驗證在 Kubernetes 中的流程:

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title X.509 使用者端憑證身份驗證流程

rectangle "請求憑證" as node1
rectangle "簽發憑證" as node2
rectangle "出示憑證" as node3
rectangle "驗證憑證" as node4

node1 --> node2
node2 --> node3
node3 --> node4

@enduml

此圖示說明瞭使用者端如何從 CA 請求和取得憑證,並在與 Kubernetes API 伺服器進行身份驗證時出示該憑證。

Kubernetes 安全機制:證書基身份驗證與 OpenID Connect

在 Kubernetes 中,安全性和身份驗證是至關重要的。本篇文章將探討證書基身份驗證和 OpenID Connect(OIDC)兩種主要的身份驗證方法,並分析其優缺點。

證書基身份驗證

證書基身份驗證是一種安全且廣泛使用的身份驗證方法。以下是如何生成和組態證書基身份驗證的步驟:

  1. 生成私鑰:使用 openssl 命令生成私鑰。

    $ openssl genrsa -out iamgini.key 2048
    

    此步驟生成一個 2048 位的 RSA 私鑰,儲存在 iamgini.key 檔案中。

  2. 生成 CertificateSigningRequest (CSR):使用私鑰生成 CSR。

    $ openssl req -new -key iamgini.key -out iamgini.csr -subj "/CN=iamgini/O=web1/O=frontend"
    

    此步驟生成一個 CSR 檔案 iamgini.csr,包含使用者的身份資訊。

  3. 編碼 CSR:將 CSR 內容進行 base64 編碼。

    $ cat iamgini.csr | base64 -w 0
    

    此步驟將 CSR 內容編碼為 base64 格式,以便在下一步中使用。

  4. 建立 CertificateSigningRequest 資源:建立一個 csr.yaml 檔案,包含編碼後的 CSR 內容。

    # csr.yaml
    apiVersion: certificates.k8s.io/v1
    kind: CertificateSigningRequest
    metadata:
      name: iamgini
    spec:
      request: <your encoded CSR content here>
      signerName: kubernetes.io/kube-apiserver-client
      usages:
        - client auth
    

    <your encoded CSR content here> 替換為步驟 3 中生成的 base64 編碼內容。

  5. 應用 CSR 資源:使用 kubectl 命令應用 csr.yaml 檔案。

    $ kubectl apply -f csr.yaml
    
  6. 批准 CSR:管理員需要批准 CSR 請求。

    $ kubectl certificate approve iamgini
    
  7. 取得證書:從批准的 CSR 資源中提取證書內容。

    $ kubectl get csr iamgini -o json | jq -r '.status.certificate' | base64 --decode > iamgini.crt
    
  8. 組態 kubeconfig:將新使用者和上下文新增到 kubeconfig 檔案中。

    $ kubectl config set-credentials iamgini --client-key=/full-path/iamgini.key --client-certificate=/full-path/iamgini.crt
    $ kubectl config set-context iamgini --cluster=minikube --user=iamgini
    
  9. 測試存取:切換到新上下文並驗證身份。

    $ kubectl config use-context iamgini
    $ kubectl auth whoami
    

證書基身份驗證的優缺點

優點

  • 比使用 ServiceAccount 令牌或靜態令牌檔案更安全。
  • 證書可以被復原,這在安全事件發生時非常重要。

缺點

  • 證書有過期日期,需要定期更新。
  • 需要監控證書過期、復原和輪換。

OpenID Connect (OIDC) 令牌

OIDC 是根據 OAuth 2.0 的身份驗證層,提供單點登入(SSO)體驗。以下是 OIDC 的基本流程:

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title OpenID Connect (OIDC) 令牌

rectangle "認證請求" as n1
rectangle "重定向到 OIDC 提供者" as n2
rectangle "認證使用者" as n3
rectangle "取得授權碼" as n4
rectangle "發放 ID 令牌" as n5
rectangle "使用 ID 令牌存取" as n6

n1 --> n2
n2 --> n3
n3 --> n4
n4 --> n5
n5 --> n6

@enduml

OIDC 的優點

  • 提供單點登入體驗。
  • 與雲端服務提供商的 OpenID 提供者整合方便。

OIDC 的缺點

  • 需要依賴外部 OIDC 提供者。
  • 組態和管理可能較為複雜。

Kubernetes 中的 OIDC 認證機制

在 Kubernetes 中,OpenID Connect (OIDC) 是一種重要的認證機制,能夠提供單一登入(SSO)體驗並與外部身分提供者(IdP)整合。本章將探討 OIDC 在 Kubernetes 中的應用、優勢、挑戰以及相關組態。

OIDC 認證流程

OIDC 認證的核心在於 OpenID 提供者負責 SSO 體驗和管理 Bearer Token。此外,Kubernetes API 伺服器必須驗證收到的 Bearer Token 是否合法。

OIDC 的優勢

  • 提供單一登入(SSO)體驗,能夠與組織內的其他服務整合
  • 大多數雲端服務提供商都有自己的 OpenID 提供者,能夠輕鬆與其管理的 Kubernetes 服務整合
  • 可用於非雲端佈署,雖然需要額外的組態
  • 提供安全且可擴充套件的解決方案

OIDC 的挑戰

  • Kubernetes 沒有內建的 Web 介面來觸發認證流程,需要手動從 IdP 取得憑證
  • OIDC Token 可以被 IdP 復原,但不是所有 IdP 都支援 Token 復原功能,且 Kubernetes 本身不處理 Token 復原

在 Kubernetes 中使用 OIDC

Kubernetes 不提供內建的 OIDC 身分提供者,因此需要依賴外部的身分提供者。流行的雲端環境如 AWS、GCP 和 Azure 都原生支援 OIDC 整合,使得啟用 SSO 變得簡單。對於非雲端或自管理的 Kubernetes 叢集,可以使用 Dex、Keycloak、UAA 或 OpenUnison 等工具來設定身分提供者。

身分提供者的需求

要讓 OIDC 身分提供者與 Kubernetes 協同工作,需要滿足以下條件:

  • 支援 OIDC Discovery,以簡化組態工作
  • 符合 Transport Layer Security (TLS) 規範,處理敏感的認證資料
  • 使用具有 CA 標誌的憑證,以便 Kubernetes 能夠信任身分提供者的憑證

流行的 OIDC 身分提供者

  • Dex:輕量級、開源的身分提供者,支援 OIDC 和外部 IdP(如 LDAP、GitHub 和 Google)
  • Keycloak:功能強大的開源 IdP,支援 OIDC 和 SAML,具有企業級功能如使用者聯盟和 RBAC
  • OpenUnison:針對 Kubernetes 最佳化的 IdP,具有原生整合 Kubernetes RBAC 和身分聯盟的功能
  • Cloud Foundry User Account and Authentication (UAA):多用途的開源 IdP,支援 OIDC 和雲端平台及企業認證系統整合

組態 OIDC 與 Kubernetes API 伺服器

要在 Kubernetes 中啟用 OIDC,需要組態 Kubernetes API 伺服器並使用相關的 OIDC 旗標。主要組態包括:

  • oidc-issuer-url:OIDC 提供者的 URL,用於驗證 Token 的真實性
  • oidc-client-id:當 Kubernetes 作為客戶端時,用於向 IdP 進行認證的客戶端 ID
  • oidc-username-claim:指定 Token 中的哪個 Claim 應該對映到 Kubernetes 使用者名稱
  • oidc-groups-claim:將 IdP 中的群組對映到 Kubernetes 群組,以便管理 RBAC 角色

其他認證方法

除了 OIDC 之外,Kubernetes 還提供了其他認證方法,如:

  • 認證代理:在 Kubernetes API 伺服器前面使用認證代理,可以組態 API 伺服器從 HTTP 標頭中提取使用者資訊
  • Webhook Token 認證:Kubernetes API 伺服器使用外部服務來驗證 Bearer Token,外部服務接收 TokenReview 物件並傳回驗證結果

這些方法主要用於進階使用案例,例如與 LDAP 或 Kerberos 整合。詳細資訊可以參考官方檔案。