管理服務賬號

_ServiceAccount_ 為在 Pod 中執行的程序提供身份。

Pod 內部的程序可以使用其關聯服務賬號的身份向叢集的 API 伺服器進行身份驗證。

有關服務賬號的介紹,請閱讀配置服務賬號

此任務指南解釋了 ServiceAccount 背後的一些概念。本指南還解釋瞭如何獲取或撤銷代表 ServiceAccount 的令牌,以及如何(可選地)將 ServiceAccount 的有效性繫結到 API 物件的生命週期。

準備工作

你需要有一個 Kubernetes 叢集,並且 kubectl 命令列工具已配置為與你的叢集通訊。建議在至少有兩個不作為控制平面主機的節點組成的叢集上執行本教程。如果你還沒有叢集,可以使用 minikube 建立一個,或者使用以下 Kubernetes 演練場之一。

為了能夠完全按照這些步驟操作,請確保你有一個名為 `examplens` 的名稱空間。如果沒有,請透過執行以下命令建立一個:

kubectl create namespace examplens

使用者賬號與服務賬號

Kubernetes 基於多種原因區分使用者賬號和服務賬號的概念:

  • 使用者賬號供人類使用。服務賬號供應用程式程序使用,這些程序(對於 Kubernetes)在屬於 Pod 的容器中執行。
  • 使用者賬號旨在具有全域性性:名稱在叢集的所有名稱空間中必須是唯一的。無論你檢視哪個名稱空間,代表使用者的特定使用者名稱都代表同一個使用者。在 Kubernetes 中,服務賬號是名稱空間範圍的:兩個不同的名稱空間可以包含具有相同名稱的 ServiceAccount。
  • 通常,叢集的使用者賬號可能與企業資料庫同步,其中建立新使用者賬號需要特殊許可權並與複雜的業務流程相關聯。相比之下,服務賬號的建立旨在更加輕量級,允許叢集使用者按需為特定任務建立服務賬號。將 ServiceAccount 建立與人類使用者入職步驟分離,使工作負載更容易遵循最小許可權原則。
  • 人類和服務賬號的審計考慮可能不同;這種分離使其更容易實現。
  • 複雜系統的配置包可能包含該系統元件的各種服務賬號定義。由於服務賬號可以在沒有許多限制的情況下建立並具有名稱空間名稱,因此此類配置通常是可移植的。

繫結服務賬號令牌

ServiceAccount 令牌可以繫結到 kube-apiserver 中存在的 API 物件。這可以用於將令牌的有效性與另一個 API 物件的存在關聯起來。支援的物件型別如下:

  • Pod(用於投射型卷掛載,見下文)
  • Secret(可用於透過刪除 Secret 來撤銷令牌)
  • Node(可用於在 Node 被刪除時自動撤銷令牌;建立新的節點繫結令牌在 v1.33+ 中已正式釋出)

當令牌繫結到某個物件時,該物件的 `metadata.name` 和 `metadata.uid` 會作為額外的“私有宣告”儲存在頒發的 JWT 中。

當繫結令牌呈現給 kube-apiserver 時,服務賬號認證器將提取並驗證這些宣告。如果引用的物件或 ServiceAccount 正在等待刪除(例如,由於終結器),那麼在 `metadata.deletionTimestamp` 日期之後 60 秒(或更長時間)的任何時刻,使用該令牌的認證都將失敗。如果引用的物件不再存在(或其 `metadata.uid` 不匹配),則請求將不會透過認證。

Pod 繫結令牌中的額外元資料

特性狀態: Kubernetes v1.32 [stable] (預設啟用:true)

當一個服務賬號令牌繫結到 Pod 物件時,額外元資料也會嵌入到令牌中,該元資料指示繫結 Pod 的 `spec.nodeName` 欄位的值,以及該節點的 UID(如果可用)。

當令牌用於認證時,kube-apiserver **不會**驗證此節點資訊。包含此資訊是為了讓整合商在檢查 JWT 時,無需獲取 Pod 或 Node API 物件來檢查關聯的節點名稱和 UID。

驗證和檢查私有宣告

TokenReview API 可用於驗證和從令牌中提取私有宣告。

  1. 首先,假設你有一個名為 `test-pod` 的 Pod 和一個名為 `my-sa` 的服務賬號。

  2. 建立繫結到此 Pod 的令牌

    kubectl create token my-sa --bound-object-kind="Pod" --bound-object-name="test-pod"
    
  3. 將此令牌複製到一個名為 `tokenreview.yaml` 的新檔案中

    apiVersion: authentication.k8s.io/v1
    kind: TokenReview
    spec:
      token: <token from step 2>
    
  4. 將此資源提交給 apiserver 進行審查

    # use '-o yaml' to inspect the output
    kubectl create -o yaml -f tokenreview.yaml
    

    你應該看到如下輸出:

    apiVersion: authentication.k8s.io/v1
    kind: TokenReview
    metadata:
      creationTimestamp: null
    spec:
      token: <token>
    status:
      audiences:
      - https://kubernetes.default.svc.cluster.local
      authenticated: true
      user:
        extra:
          authentication.kubernetes.io/credential-id:
          - JTI=7ee52be0-9045-4653-aa5e-0da57b8dccdc
          authentication.kubernetes.io/node-name:
          - kind-control-plane
          authentication.kubernetes.io/node-uid:
          - 497e9d9a-47aa-4930-b0f6-9f2fb574c8c6
          authentication.kubernetes.io/pod-name:
          - test-pod
          authentication.kubernetes.io/pod-uid:
          - e87dbbd6-3d7e-45db-aafb-72b24627dff5
        groups:
        - system:serviceaccounts
        - system:serviceaccounts:default
        - system:authenticated
        uid: f8b4161b-2e2b-11e9-86b7-2afc33b31a7e
        username: system:serviceaccount:default:my-sa
    

服務賬號私有宣告的模式

目前,JWT 令牌中 Kubernetes 特定宣告的模式尚未文件化,但可以在 Kubernetes 程式碼庫中 ServiceAccount 包中找到相關程式碼區域。

你可以使用標準的 JWT 解碼工具檢查 JWT。下面是一個 `my-serviceaccount` 服務賬號的 JWT 示例,它繫結到名為 `my-pod` 的 Pod 物件,該 Pod 被排程到 `my-namespace` 名稱空間中的 `my-node` 節點:

{
  "aud": [
    "https://my-audience.example.com"
  ],
  "exp": 1729605240,
  "iat": 1729601640,
  "iss": "https://my-cluster.example.com",
  "jti": "aed34954-b33a-4142-b1ec-389d6bbb4936",
  "kubernetes.io": {
    "namespace": "my-namespace",
    "node": {
      "name": "my-node",
      "uid": "646e7c5e-32d6-4d42-9dbd-e504e6cbe6b1"
    },
    "pod": {
      "name": "my-pod",
      "uid": "5e0bd49b-f040-43b0-99b7-22765a53f7f3"
    },
    "serviceaccount": {
      "name": "my-serviceaccount",
      "uid": "14ee3fa4-a7e2-420f-9f9a-dbc4507c3798"
    }
  },
  "nbf": 1729601640,
  "sub": "system:serviceaccount:my-namespace:my-serviceaccount"
}

在 Kubernetes 外部執行並希望執行 JWT 離線驗證的服務,可以使用此模式,以及配置了來自 API 伺服器的 OpenID Discovery 資訊的相容 JWT 驗證器,來驗證提交的 JWT,而無需使用 TokenReview API。

以這種方式驗證 JWT 的服務**不驗證**JWT 令牌中嵌入的宣告是否是當前的並且仍然有效。這意味著如果令牌繫結到某個物件,並且該物件不再存在,則該令牌仍將被視為有效(直到配置的令牌過期)。

需要確保令牌的繫結宣告仍然有效的客戶端,**必須**使用 TokenReview API 將令牌提交給 `kube-apiserver`,以便它驗證並擴充套件嵌入的宣告,步驟類似於上述驗證和檢查私有宣告部分,但使用支援的客戶端庫。有關 JWT 及其結構的更多資訊,請參閱 JSON Web Token RFC

繫結服務賬號令牌卷機制

特性狀態:`Kubernetes v1.22 [stable]` (預設啟用:true)

預設情況下,Kubernetes 控制平面(特別是 ServiceAccount 准入控制器)會向 Pod 新增一個投射型卷,此捲包含用於 Kubernetes API 訪問的令牌。

以下是已啟動 Pod 的示例:

...
  - name: kube-api-access-<random-suffix>
    projected:
      sources:
        - serviceAccountToken:
            path: token # must match the path the app expects
        - configMap:
            items:
              - key: ca.crt
                path: ca.crt
            name: kube-root-ca.crt
        - downwardAPI:
            items:
              - fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
                path: namespace

該清單片段定義了一個由三個源組成的投射型卷。在本例中,每個源也代表該卷內的一個單一路徑。這三個源是:

  1. 一個 `serviceAccountToken` 源,其中包含 kubelet 從 kube-apiserver 獲取的令牌。kubelet 使用 TokenRequest API 獲取有時效的令牌。TokenRequest 提供的令牌在 Pod 刪除時或在定義的生命週期(預設情況下為 1 小時)後過期。kubelet 也會在令牌過期之前重新整理該令牌。該令牌繫結到特定的 Pod,並將 kube-apiserver 作為其受眾。此機制取代了早期基於 Secret 添加捲的機制,其中 Secret 代表 Pod 的 ServiceAccount,但不會過期。
  2. 一個 `configMap` 源。ConfigMap 包含一個證書頒發機構資料包。Pod 可以使用這些證書來確保它們正在連線到叢集的 kube-apiserver(而不是中間裝置或意外配置錯誤的對等方)。
  3. 一個 `downwardAPI` 源,用於查詢包含 Pod 的名稱空間的名稱,並將該名稱資訊提供給 Pod 中執行的應用程式程式碼。

Pod 中掛載此特定卷的任何容器都可以訪問上述資訊。

ServiceAccount 的手動 Secret 管理

Kubernetes v1.22 之前的版本會自動建立用於訪問 Kubernetes API 的憑據。這種較舊的機制是基於建立令牌 Secret,然後可以將其掛載到執行中的 Pod 中。

在較新版本中,包括 Kubernetes v1.34,API 憑據是使用 TokenRequest API 直接獲取的,並透過投射型卷掛載到 Pod 中。透過此方法獲取的令牌具有有界生命週期,並在其掛載的 Pod 被刪除時自動失效。

你仍然可以手動建立一個 Secret 來儲存服務賬號令牌;例如,如果你需要一個永不過期的令牌。

一旦你手動建立了一個 Secret 並將其連結到 ServiceAccount,Kubernetes 控制平面會自動將令牌填充到該 Secret 中。

自動生成的舊版 ServiceAccount 令牌清理

在 1.24 版本之前,Kubernetes 會為 ServiceAccount 自動生成基於 Secret 的令牌。為了區分自動生成的令牌和手動建立的令牌,Kubernetes 會檢查 ServiceAccount 的 secrets 欄位是否有引用。如果 Secret 被 secrets 欄位引用,則它被視為自動生成的舊版令牌。否則,它被視為手動建立的舊版令牌。例如:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-robot
  namespace: default
secrets:
  - name: build-robot-secret # usually NOT present for a manually generated token

從 1.29 版本開始,自動生成的舊版 ServiceAccount 令牌如果在一定時期內(預設設定為一年)未使用,將被標記為無效。在此定義週期(預設仍為一年)內仍未使用的令牌隨後將被控制平面清除。

如果使用者使用無效的自動生成令牌,令牌驗證器將:

  1. 為鍵值對 `authentication.k8s.io/legacy-token-invalidated: /` 新增審計註解,
  2. 遞增 `invalid_legacy_auto_token_uses_total` 指標計數,
  3. 使用新日期更新 Secret 標籤 `kubernetes.io/legacy-token-last-used`,
  4. 返回一個錯誤,指示令牌已失效。

收到此驗證錯誤時,使用者可以更新 Secret 以移除 `kubernetes.io/legacy-token-invalid-since` 標籤,以暫時允許使用此令牌。

這是一個自動生成的舊版令牌的示例,它已被標記為 `kubernetes.io/legacy-token-last-used` 和 `kubernetes.io/legacy-token-invalid-since` 標籤:

apiVersion: v1
kind: Secret
metadata:
  name: build-robot-secret
  namespace: default
  labels:
    kubernetes.io/legacy-token-last-used: 2022-10-24
    kubernetes.io/legacy-token-invalid-since: 2023-10-25
  annotations:
    kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token

控制平面細節

ServiceAccount 控制器

ServiceAccount 控制器管理名稱空間內的 ServiceAccount,並確保每個活躍名稱空間中都存在一個名為“default”的 ServiceAccount。

令牌控制器

服務賬號令牌控制器作為 `kube-controller-manager` 的一部分執行。此控制器非同步執行。它:

  • 監視 ServiceAccount 刪除,並刪除所有相應的 ServiceAccount 令牌 Secret。
  • 監視 ServiceAccount 令牌 Secret 的新增,並確保引用的 ServiceAccount 存在,並在需要時向 Secret 新增令牌。
  • 監視 Secret 刪除,並在需要時從相應的 ServiceAccount 中移除引用。

你必須使用 `--service-account-private-key-file` 標誌將服務賬號私鑰檔案傳遞給 `kube-controller-manager` 中的令牌控制器。私鑰用於簽署生成的服務賬號令牌。同樣,你必須使用 `--service-account-key-file` 標誌將相應的公鑰傳遞給 `kube-apiserver`。公鑰將用於在身份驗證期間驗證令牌。

特性狀態: Kubernetes v1.34 [beta] (預設啟用:true)

設定 `--service-account-private-key-file` 和 `--service-account-key-file` 標誌的另一種設定是為外部 ServiceAccount 令牌簽名和金鑰管理配置一個外部 JWT 簽名器。請注意,這些設定是互斥的,不能同時配置。

ServiceAccount 准入控制器

Pod 的修改是透過名為准入控制器的外掛實現的。它是 API 伺服器的一部分。該准入控制器同步修改 Pod 建立。當此外掛處於活動狀態(預設在大多數發行版中都處於活動狀態)時,當 Pod 建立時,它會執行以下操作:

  1. 如果 Pod 未設定 `spec.serviceAccountName`,准入控制器會將此傳入 Pod 的 ServiceAccount 名稱設定為 `default`。
  2. 准入控制器確保傳入 Pod 引用的 ServiceAccount 存在。如果沒有具有匹配名稱的 ServiceAccount,准入控制器將拒絕傳入的 Pod。此檢查甚至適用於 `default` ServiceAccount。
  3. 如果 ServiceAccount 的 `automountServiceAccountToken` 欄位和 Pod 的 `automountServiceAccountToken` 欄位都沒有設定為 `false`:
    • 准入控制器修改傳入的 Pod,新增一個額外的,其中包含用於 API 訪問的令牌。
    • 准入控制器會為 Pod 中的每個容器新增一個 `volumeMount`,跳過任何已經為路徑 `/var/run/secrets/kubernetes.io/serviceaccount` 定義了卷掛載的容器。對於 Linux 容器,該卷掛載在 `/var/run/secrets/kubernetes.io/serviceaccount`;在 Windows 節點上,掛載在等效路徑。
  4. 如果傳入 Pod 的規約中尚未包含任何 `imagePullSecrets`,則准入控制器會新增 `imagePullSecrets`,並將其從 `ServiceAccount` 複製過來。

舊版 ServiceAccount 令牌跟蹤控制器

特性狀態:`Kubernetes v1.28 [stable]` (預設啟用: true)

此控制器在 `kube-system` 名稱空間中生成一個名為 `kube-system/kube-apiserver-legacy-service-account-token-tracking` 的 ConfigMap。該 ConfigMap 記錄系統開始監控舊版服務賬號令牌的時間戳。

舊版 ServiceAccount 令牌清理器

特性狀態: Kubernetes v1.30 [stable] (預設啟用:true)

舊版 ServiceAccount 令牌清理器作為 `kube-controller-manager` 的一部分執行,每 24 小時檢查一次是否有自動生成的舊版 ServiceAccount 令牌在_指定時間_內未使用。如果是,清理器將這些令牌標記為無效。

清理器首先檢查控制平面建立的 ConfigMap(前提是啟用了 `LegacyServiceAccountTokenTracking`)。如果當前時間在 ConfigMap 中的日期之後_指定時間_,清理器 then 遍歷叢集中 Secret 列表,並評估每個型別為 `kubernetes.io/service-account-token` 的 Secret。

如果 Secret 滿足以下所有條件,清理器會將其標記為無效:

  • 該 Secret 是自動生成的,這意味著它被 ServiceAccount 雙向引用。
  • 此 Secret 當前未被任何 Pod 掛載。
  • 該 Secret 自建立或上次使用以來已_指定時間_未使用。

清理器透過向 Secret 新增名為 `kubernetes.io/legacy-token-invalid-since` 的標籤並將其值設定為當前日期來將 Secret 標記為無效。如果無效的 Secret 在_指定時間_內未使用,清理器將刪除它。

TokenRequest API

特性狀態:`Kubernetes v1.22 [stable]`

你可以使用 ServiceAccount 的 TokenRequest 子資源來獲取該 ServiceAccount 的有時效的令牌。你不需要呼叫此 API 來獲取在容器內使用的 API 令牌,因為 kubelet 會使用_投射型卷_為你設定好。

如果你想從 `kubectl` 使用 TokenRequest API,請參閱手動為 ServiceAccount 建立 API 令牌

Kubernetes 控制平面(特別是 ServiceAccount 准入控制器)會向 Pod 新增一個投射型卷,並且 kubelet 確保此捲包含一個令牌,允許容器以正確的 ServiceAccount 身份進行身份驗證。

(此機制取代了早期基於 Secret 添加捲的機制,其中 Secret 代表 Pod 的 ServiceAccount,但不會過期。)

以下是已啟動 Pod 的示例:

...
  - name: kube-api-access-<random-suffix>
    projected:
      defaultMode: 420 # decimal equivalent of octal 0644
      sources:
        - serviceAccountToken:
            expirationSeconds: 3607
            path: token
        - configMap:
            items:
              - key: ca.crt
                path: ca.crt
            name: kube-root-ca.crt
        - downwardAPI:
            items:
              - fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
                path: namespace

該清單片段定義了一個投射型卷,它結合了來自三個源的資訊:

  1. 一個 `serviceAccountToken` 源,其中包含 kubelet 從 kube-apiserver 獲取的令牌。kubelet 使用 TokenRequest API 獲取有時效的令牌。TokenRequest 提供的令牌在 Pod 刪除時或在定義的生命週期(預設情況下為 1 小時)後過期。該令牌繫結到特定的 Pod,並將 kube-apiserver 作為其受眾。
  2. 一個 `configMap` 源。ConfigMap 包含一個證書頒發機構資料包。Pod 可以使用這些證書來確保它們正在連線到叢集的 kube-apiserver(而不是中間裝置或意外配置錯誤的對等方)。
  3. 一個 `downwardAPI` 源。此 `downwardAPI` 卷使包含 Pod 的名稱空間的名稱可供 Pod 中執行的應用程式程式碼使用。

Pod 中掛載此卷的任何容器都可以訪問上述資訊。

建立額外的 API 令牌

要為 ServiceAccount 建立一個永不失效的持久 API 令牌,請建立一個型別為 `kubernetes.io/service-account-token` 的 Secret,並帶有一個引用 ServiceAccount 的註解。控制平面隨後會生成一個長期有效的令牌,並用生成的令牌資料更新該 Secret。

以下是此類 Secret 的示例清單:

apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: mysecretname
  annotations:
    kubernetes.io/service-account.name: myserviceaccount

要根據此示例建立 Secret,請執行:

kubectl -n examplens create -f https://k8s.io/examples/secret/serviceaccount/mysecretname.yaml

要檢視該 Secret 的詳細資訊,請執行:

kubectl -n examplens describe secret mysecretname

輸出類似於:

Name:           mysecretname
Namespace:      examplens
Labels:         <none>
Annotations:    kubernetes.io/service-account.name=myserviceaccount
                kubernetes.io/service-account.uid=8a85c4c4-8483-11e9-bc42-526af7764f64

Type:   kubernetes.io/service-account-token

Data
====
ca.crt:         1362 bytes
namespace:      9 bytes
token:          ...

如果你在 `examplens` 名稱空間中啟動一個新 Pod,它可以使用你剛剛建立的 `myserviceaccount` 服務賬號令牌 Secret。

刪除/失效 ServiceAccount 令牌

刪除/失效長期/舊版 ServiceAccount 令牌

如果你知道包含要移除的令牌的 Secret 名稱:

kubectl delete secret name-of-secret

否則,首先找到 ServiceAccount 的 Secret。

# This assumes that you already have a namespace named 'examplens'
kubectl -n examplens get serviceaccount/example-automated-thing -o yaml

輸出類似於:

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"example-automated-thing","namespace":"examplens"}}      
  creationTimestamp: "2019-07-21T07:07:07Z"
  name: example-automated-thing
  namespace: examplens
  resourceVersion: "777"
  selfLink: /api/v1/namespaces/examplens/serviceaccounts/example-automated-thing
  uid: f23fd170-66f2-4697-b049-e1e266b7f835
secrets:
  - name: example-automated-thing-token-zyxwv

然後,刪除你現在知道名稱的 Secret:

kubectl -n examplens delete secret/example-automated-thing-token-zyxwv

刪除/使短期 ServiceAccount 令牌失效

短期 ServiceAccount 令牌在建立時指定的時限後會自動過期。沒有已頒發令牌的中央記錄,因此無法撤銷單個令牌。

如果你必須在短期令牌過期前撤銷它,你可以刪除並重新建立與其關聯的 ServiceAccount。這將改變其 UID,從而使為其建立的**所有** ServiceAccount 令牌失效。

外部 ServiceAccount 令牌簽名和金鑰管理

特性狀態: Kubernetes v1.34 [beta] (預設啟用:true)

kube-apiserver 可以配置為使用外部簽名器進行令牌簽名和令牌驗證金鑰管理。此功能使 Kubernetes 發行版能夠與他們選擇的金鑰管理解決方案(例如,HSM、雲 KMS)整合,以進行服務賬號憑據簽名和驗證。要將 kube-apiserver 配置為使用 external-jwt-signer,請將 `--service-account-signing-endpoint` 標誌設定為檔案系統上 Unix 域套接字(UDS)的位置,或以 @ 符號為字首並命名抽象套接字名稱空間中的 UDS。在配置的 UDS 處應有一個實現 `ExternalJWTSigner` gRPC 服務的 RPC 伺服器。

外部 JWT 簽名器必須是健康的,並準備好為 kube-apiserver 啟動提供支援的服務賬號金鑰。

外部簽名器提供了一個實現 3 種方法的 `v1.ExternalJWTSigner` gRPC 服務:

元資料

Metadata 旨在由 `kube-apiserver` 在啟動時呼叫一次。這使外部簽名器能夠與 kube-apiserver 共享元資料,例如簽名器支援的最大令牌生命週期。

rpc Metadata(MetadataRequest) returns (MetadataResponse) {}

message MetadataRequest {}

message MetadataResponse {
  // used by kube-apiserver for defaulting/validation of JWT lifetime while accounting for configuration flag values:
  // 1. `--service-account-max-token-expiration`
  // 2. `--service-account-extend-token-expiration`
  //
  // * If `--service-account-max-token-expiration` is greater than `max_token_expiration_seconds`, kube-apiserver treats that as misconfiguration and exits.
  // * If `--service-account-max-token-expiration` is not explicitly set, kube-apiserver defaults to `max_token_expiration_seconds`.
  // * If `--service-account-extend-token-expiration` is true, the extended expiration is `min(1 year, max_token_expiration_seconds)`.
  //
  // `max_token_expiration_seconds` must be at least 600s.
  int64 max_token_expiration_seconds = 1;
}

獲取金鑰

FetchKeys 返回一組受信任用於簽署 Kubernetes 服務賬號令牌的公鑰。Kube-apiserver 將呼叫此 RPC:

  • 每次嘗試使用未知金鑰 ID 驗證來自服務賬號頒發者的 JWT 時,以及
  • 定期,以便它可以從 OIDC JWKs 端點提供合理最新的金鑰。
rpc FetchKeys(FetchKeysRequest) returns (FetchKeysResponse) {}

message FetchKeysRequest {}

message FetchKeysResponse {
  repeated Key keys = 1;

  // The timestamp when this data was pulled from the authoritative source of
  // truth for verification keys.
  // kube-apiserver can export this from metrics, to enable end-to-end SLOs.
  google.protobuf.Timestamp data_timestamp = 2;

  // refresh interval for verification keys to pick changes if any.
  // any value <= 0 is considered a misconfiguration.
  int64 refresh_hint_seconds = 3;
}

message Key {
  // A unique identifier for this key.
  // Length must be <=1024.
  string key_id = 1;

  // The public key, PKIX-serialized.
  // must be a public key supported by kube-apiserver (currently RSA 256 or ECDSA 256/384/521)
  bytes key = 2;

  // Set only for keys that are not used to sign bound tokens.
  // eg: supported keys for legacy tokens.
  // If set, key is used for verification but excluded from OIDC discovery docs.
  // if set, external signer should not use this key to sign a JWT.
  bool exclude_from_oidc_discovery = 3;
}

簽名

Sign 接收一個序列化的 JWT 負載,並返回序列化的頭部和簽名。`kube-apiserver` 然後從頭部、負載和簽名組裝 JWT。

rpc Sign(SignJWTRequest) returns (SignJWTResponse) {}

message SignJWTRequest {
  // URL-safe base64 wrapped payload to be signed.
  // Exactly as it appears in the second segment of the JWT
  string claims = 1;
}

message SignJWTResponse {
  // header must contain only alg, kid, typ claims.
  // typ must be “JWT”.
  // kid must be non-empty, <=1024 characters, and its corresponding public key should not be excluded from OIDC discovery.
  // alg must be one of the algorithms supported by kube-apiserver (currently RS256, ES256, ES384, ES512).
  // header cannot have any additional data that kube-apiserver does not recognize.
  // Already wrapped in URL-safe base64, exactly as it appears in the first segment of the JWT.
  string header = 1;

  // The signature for the JWT.
  // Already wrapped in URL-safe base64, exactly as it appears in the final segment of the JWT.
  string signature = 2;
}

清理

如果你建立了 `examplens` 名稱空間進行實驗,你可以將其移除:

kubectl delete namespace examplens

下一步

最後修改時間:2025 年 7 月 29 日下午 2:30(太平洋標準時間):KEP-740:將 grpc 文件移至網站 (c6c320d7d4)