Kubernetes 1.29: SIG-Auth の変更内容

## はじめに
このページではKubernetes v1.29におけるSIG-Authに関連する取り組みについて、ChangelogのChanges By Kindの項目から紹介しています。ここに記載されていないものは別のまとめで記載されていると思いますので、 [Kubernetes 1.29: 変更点まとめ](https://qiita.com/uesyn/items/7768c2adb426e6ad2864) も合わせて参照してみてください。

:pencil2: がついた文章は、CHANGELOGの公式内容ではなく筆者の補足です。

## Changes by Kind
### Deprecation
- N/A
### API Change

- `kube-apiserver`: `AuthenticationConfiguration`ファイルを読み込むための`--authentication-config` フラグを追加しました。`--authentication-config`フラグは`--oidc-*`フラグと相互排他的です。([#119142](https://github.com/kubernetes/kubernetes/pull/119142))
	- :pencil2: 
	- KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/3331-structured-authentication-configuration
	- v1.29でalphaリリースされた`StructuredAuthenticationConfiguration` フィーチャーゲートで有効になる機能です。OIDC認証への機能要求に従い増えていくフラグベースの設定からの脱却がモチベーションのようです。より詳細なマッピングルールやバリデーションルールが定義できるようになったようです。CEL式での記述も可能です。
	- OIDC認証設定のみが対象です。
	- 詳細は https://qiita.com/hiyosi/items/173d8338c742071fe8a1

- `v1alpha1 AuthenticationConfiguration`にCEL式を追加しました。([#121078](https://github.com/kubernetes/kubernetes/pull/121078))
- Pod Security Standardsでユーザ名前空間のサポートを有効にするフィーチャーゲート `UserNamespacesPodSecurityStandards`を追加しました。この機能を有効にすると`spec[.*].securityContext.[runAsNonRoot,runAsUser]`設定を許可するようにPod Security Standarsルールが変更されます。このフィーチャーゲートはクラスタ内の全てのノードがユーザ名前空間をサポートし有効になっている場合のみ有効にしてください。このフィーチャーゲートは将来のKubernetesリリースでデフォルトで有効になったりGAになることはありません。([#118760](https://github.com/kubernetes/kubernetes/pull/118760))
- 新しい`ServiceCIDR`タイプが追加され`ServiceClusterIPs`アドレスの割り当てに使うクラスタレンジを動的に設定できるようになりました。([#116516](https://github.com/kubernetes/kubernetes/pull/116516))
- `v1alpha1 AuthorizationConfiguration`の `webhook.matchConditions`にCEL式のサポートを追加しました。([#121223](https://github.com/kubernetes/kubernetes/pull/121223))
-  `certificates.k8s.io/v1alpha1` ClusterTrustBundle オブジェクトをPodに投影するためのサポートを追加しました。([#113374](https://github.com/kubernetes/kubernetes/pull/113374))
- CRDバリデーションルールのCEL式で文字列、リスト、またはマップを返す関数のコストが誤って高く計算される不具合を修正しました。関数の結果が後続の操作で使われた際に、誤ったコストが明らかになりました。([#119800](https://github.com/kubernetes/kubernetes/pull/119800))
- Go API: `ResourceRequirements` 構造体はボリュームで使用するために`VolumeResourceRequirements`に置き換えられました。([#118653](https://github.com/kubernetes/kubernetes/pull/118653))
- `ValidatingAdmissionPolicy`のタイプチェックはCRDとAPI extentionタイプをサポートしました。([#119109](https://github.com/kubernetes/kubernetes/pull/119109))
- `kube-apiserver`: `apiserver.config.k8s.io/v1alpha1`の`AuthoirzationConfiguration`オブジェクトを含む設定ファイルを読み込むための `--authorization-config`フラグを追加しました。`--authorization-config`フラグは`--authorization-modes`と`--authorization-webhook-*`フラグと相互排他です。`--authorization-config`を指定するにはアルファ版の`StructuredAuthorizationConfiguration` feature flagを有効にしなければなりません。([#120154](https://github.com/kubernetes/kubernetes/pull/120154))
	- :pencil2: 
	- KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/3221-structured-authorization-configuration
	- v1.29でalphaリリースされた`StructedAuthorizationConfiguration` フィーチャーゲートで有効になる機能です。複数Webhookの指定やCEL式によるWebhookサーバへのリクエストのフィルタリングなども可能になっています。
	- 詳細は https://qiita.com/hiyosi/items/7c396ce98ba3ce42833c
### Feature
- data encryption key(DEK)キャッシュのレコード数を計測するために`apiserver_envelope_encryption_dek_cache_filled`を追加しました。([#119878](https://github.com/kubernetes/kubernetes/pull/119878))
- 次のメトリクスにapiserverの識別子を追加しました。
	- `apiserver_envelope_encryption_key_id_hash_total`
	- `apiserver_envelope_encryption_key_id_hash_last_timestamp_seconds`
	- `apiserver_envelope_encryption_key_id_hash_status_last_timestamp_seconds`
	- `apiserver_encryption_config_controller_automatic_reload_failures_total`
	- `apiserver_encryption_config_controller_automatic_reload_success_total`
	- `apiserver_encryption_config_controller_automatic_reload_last_timestamp_seconds`
	次のメトリクスのイベントが表示されない不具合を修正しました。
	- `apiserver_encryption_config_controller_automatic_reload_failures_total`
	- `apiserver_encryption_config_controller_automatic_reload_last_timestamp_seconds`
	- `apiserver_encryption_config_controller_automatic_reload_success_total`
	([#120438](https://github.com/kubernetes/kubernetes/pull/120438))
- `cel-go`を`v0.17.7`に上げて新しいオプションをもつ`ext`ライブラリを導入しました。([#121577](https://github.com/kubernetes/kubernetes/pull/121577))
- OpenAPI `v3`の特定の`requestBody`パラメータが正しく必須とマークされるようになりました。([#120735](https://github.com/kubernetes/kubernetes/pull/120735))
- `KMSv2KDF` フィーチャーゲートがデフォルトで有効になるように変更されました。([#120433](https://github.com/kubernetes/kubernetes/pull/120433))
- KMSv2のencrypt/decrypt操作のトレースを有効にしました。([#121095](https://github.com/kubernetes/kubernetes/pull/121095))
- Keyed listに重複したアイテムを持つオブジェクトを変更のリクエストや重複したアイテムを修正するリクエストは重複した項目を削除し、 server-side applyリクエストに含まれる単一の項目でそれらを置き換えます。([#121575](https://github.com/kubernetes/kubernetes/pull/121575))
- KubernetesはGo `1.21.4`でビルドされます。([#121808](https://github.com/kubernetes/kubernetes/pull/121808))
- KMSのヘルスチェックがkube-apiserverの再起動を引き起こさないようにKMS v1とv2の`/livez`チェックを削除しました。KMSのヘルスチェックはhealthzとreadinessチェックでまだ残っています。([#120583](https://github.com/kubernetes/kubernetes/pull/120583))
- `KMSv2`と`KMSv2KDF`フィーチャーゲートがGAに昇格しました。`KMSv1`フィーチャーゲートはデフォルトで無効になりました。([#121485])
    - :pencil2:
    - see: https://qiita.com/uesyn/items/7768c2adb426e6ad2864#kms-v2-encryption-at-rest-generally-available-sig-auth
- Secretベースのサービスアカウントトークンを使用すろと、使用されたSecretの名前を含む`authentication.k8s.io/legacy-token-autogenerated-secret` or `authentication.k8s.io/legacy-token-manual-secret` auditアノテーションが追加されるようになりました。 ([#118598](https://github.com/kubernetes/kubernetes/pull/118598))
	- :pencil2: 
	- Auditログに上記のアノテーションでEventが書き込まれるようになります
    ``` json
    {"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"deed60a7-d81e-4bac-854b-06ab0b7a3c83","stage":"ResponseComplete","requestURI":"/api/v1/namespaces/default/pods","verb":"list","user":{"username":"system:serviceaccount:default:test","uid":"00439654-e557-4633-a81f-a510f220c95f","groups":["system:serviceaccounts","system:serviceaccounts:default","system:authenticated"]},"sourceIPs":["172.18.0.1"],"userAgent":"curl/8.1.2","objectRef":{"resource":"pods","namespace":"default","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2024-01-10T00:47:05.663263Z","stageTimestamp":"2024-01-10T00:47:05.667018Z","annotations":{"authentication.k8s.io/legacy-token":"system:serviceaccount:default:test","authentication.k8s.io/legacy-token-manual-secret":"test","authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by RoleBinding \"test/default\" of Role \"test\" to ServiceAccount \"test/default\""}}
    ```

- 発行されるサービスアカウントトークンに`jti`(JWT ID)クレームを追加する`ServiceAccountTokenJTI` フィーチャーゲートがalpha版になりました。トークンが発行されたときに監査ログに`authentication.kubernetes.io/credential-id` アノテーションを追加し、トークンが認証に使われたときに追加ユーザ情報に `authentication.kubernetes.io/credential-id`エントリを追加します。([#120780](https://github.com/kubernetes/kubernetes/pull/120780))
	- :pencil2: 
	- この機能により監査ログで特定のトークンを使ってapiserverに行われたリクエストをトレースすることができます。
	- e.g. token payload
    ``` json
    {
      "aud": [
        "https://kubernetes.default.svc.cluster.local"
      ],
      "exp": 1704853017,
      "iat": 1704849417,
      "iss": "https://kubernetes.default.svc.cluster.local",
      "jti": "585c8ab9-5a91-47f1-ad65-c002cbb5a2c3",
      "kubernetes.io": {
        "namespace": "default",
        "serviceaccount": {
          "name": "test",
          "uid": "5e0a0d2d-06db-45b5-8c92-10d9c37b0f7c"
        }
      },
      "nbf": 1704849417,
      "sub": "system:serviceaccount:default:test"
    }
    ```
   	- e.g. audit log
    ``` json
    {"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"b2d29b82-7ff9-4505-87c5-e0d49ed27a31","stage":"ResponseComplete","requestURI":"/api/v1/nodes","verb":"list","user":{"username":"system:serviceaccount:kube-system:kindnet","uid":"f9f3eb4d-95f2-4219-b5a0-8ad4eea38c8c","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"],"extra":{"authentication.kubernetes.io/credential-id":["JTI=06157ace-a898-4074-a6df-7caff816e030"],"authentication.kubernetes.io/pod-name":["kindnet-9d95h"],"authentication.kubernetes.io/pod-uid":["b46b0543-95f7-479e-ac89-92e92a65ea69"]}},"sourceIPs":["172.18.0.2"],"userAgent":"kindnetd/v0.0.0 (linux/amd64) kubernetes/$Format","objectRef":{"resource":"nodes","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2024-01-10T01:22:29.394830Z","stageTimestamp":"2024-01-10T01:22:29.396400Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"kindnet\" of ClusterRole \"kindnet\" to ServiceAccount \"kindnet/kube-system\""}}
    ```
- Podにバインドされて発行されたサービスアカウントトークンの追加クレームとしてノード名(とノードが存在していればuid)を含む`ServiceAccountTokenPodNodeInfo`フィーチャーゲートがalpha版になりました。またトークンが認証に使われたときに `authentication.kubernetes.io/node-name` と `authentication.kubernetes.io/node-uid`を追加のユーザ情報として含みまます。([#120780](https://github.com/kubernetes/kubernetes/pull/120780))
	- :pencil2:
	- Node情報を埋め込むことについて、リプレイ攻撃への軽減策としてのモチベーションがあるようです。トークンに対して特に強い権限を紐付けるような場合など、より強い確認を求めるようなユースケースに対応できます。 (e.g. DaemonSetでデプロイされるPodが使うトークンなど) Special thanks to @tkusumi
	- e.g. `kubectl create token --bound-object-kind=Pod --bound-object-name=test-pod test` で発行したtokenのpayload
    ```json
    	{
      "aud": [
        "https://kubernetes.default.svc.cluster.local"
      ],
      "exp": 1704854045,
      "iat": 1704850445,
      "iss": "https://kubernetes.default.svc.cluster.local",
      "kubernetes.io": {
        "namespace": "default",
        "node": {
          "name": "kind-control-plane",
          "uid": "c96ab082-643a-45c3-b8b6-21f5c59f748b"
        },
        "pod": {
          "name": "test-pod",
          "uid": "f22f3566-707c-4f41-ad9d-06ac2d7d41f7"
        },
        "serviceaccount": {
          "name": "test",
          "uid": "e523bbc5-56bc-405a-99df-1e67985bef64"
        }
      },
      "nbf": 1704850445,
      "sub": "system:serviceaccount:default:test"
    }
    ```
	- e.g. audit log
    ``` json
    {"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"501b643b-d185-4494-b645-19844ab59895","stage":"ResponseComplete","requestURI":"/api/v1/nodes","verb":"list","user":{"username":"system:serviceaccount:kube-system:kindnet","uid":"f33a64e8-51eb-4db4-9b0f-1f104a77ecf6","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"],"extra":{"authentication.kubernetes.io/node-name":["kind-control-plane"],"authentication.kubernetes.io/node-uid":["c96ab082-643a-45c3-b8b6-21f5c59f748b"],"authentication.kubernetes.io/pod-name":["kindnet-hx4qq"],"authentication.kubernetes.io/pod-uid":["291b2214-fad4-4e4c-bf77-459aa33d3e10"]}},"sourceIPs":["172.18.0.2"],"userAgent":"kindnetd/v0.0.0 (linux/amd64) kubernetes/$Format","objectRef":{"resource":"nodes","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2024-01-10T01:37:11.209762Z","stageTimestamp":"2024-01-10T01:37:11.212185Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"kindnet\" of ClusterRole \"kindnet\" to ServiceAccount \"kindnet/kube-system\""}}
    ```
- トークンをノードに直接バインドする`TokenRequest`を許可するための`ServiceAccountTokenNodeBinding`フィーチャーゲートと、トークンが使われているときにノード名とuidがまだ存在していることを検証するための`ServiceAccountTokenNodeBindingValidation`フィーチャーゲートがalpha版で追加されました。([#120780](https://github.com/kubernetes/kubernetes/pull/120780))
	- :pencil2:
	- この機能によりNodeオブジェクトのライフサイクルに特化したトークンを取得できるようになります。(Podには紐付かずNodeに紐付くトークンを発行できる)
	- `ServiceAccountTokenNodeBinding`で発行したトークンは`ServiceAccountTokenNodeBindingValidation`が有効になっていないと検証に失敗するようです。
	- Validationの有効化は、Node オブジェクトを削除して kubelet を再起動して再作成するようなワークフローが壊れる可能性があるので注意が必要です。 k8sでのロールアウトでは、`ServiceAccountTokenNodeBindingValidation`は`ServiceAccountTokenNodeBinding`の1つ前のリリースでデフォルト有効にするようです。

	- e.g. `KUBECTL_NODE_BOUND_TOKENS=true  kubectl create token test --bound-object-kind Node --bound-object-name kind-control-plane` で作成したtokenのpayload
    ``` json
    {
      "aud": [
        "https://kubernetes.default.svc.cluster.local"
      ],
      "exp": 1704854889,
      "iat": 1704851289,
      "iss": "https://kubernetes.default.svc.cluster.local",
      "kubernetes.io": {
        "namespace": "default",
        "node": {
          "name": "kind-control-plane",
          "uid": "a3768866-ea4e-4f8b-beb1-2a3f8bc66eb1"
        },
        "serviceaccount": {
          "name": "test",
          "uid": "f7974a1b-c84b-4bfb-8acc-a2015c3b982c"
        }
      },
      "nbf": 1704851289,
      "sub": "system:serviceaccount:default:test"
    }
    ```
- `kube-controller-manager`: `LegacyServiceAccountTokenCleanUp`フィーチャーゲートがベータ版でデフォルト有効になりました。。有効にすると、`--legacy-service-account-token-clean-up-period` (デフォルト1 年間) で指定された期間にクレデンシャルが使用されておらず、**かつ** ServiceAccount オブジェクトの `.secrets` リストから参照されており、**かつ** pods から参照されていないレガシーで自動生成されたサービスアカウントトークンのシークレットに自動的に `kubernetes.io/legacy-token-invalid-since` ラベルが付けられます。このラベルにより、認証レイヤーは認証情報の使用を拒否します。無効とラベル付けされた後、`--legacy-service-account-token-clean-up-period` (デフォルト 1 年) で指定した時間が経過してもクレデンシャルが使用されない場合、そのシークレットは自動的に削除されます。まだ自動削除されていない無効とラベル付けされたシークレットは、`kubernetes.io/legacy-token-invalid-since` ラベルを削除することで再度有効にすることができます。([#120682](https://github.com/kubernetes/kubernetes/pull/120682))
	- :pencil2: 
	- 異なる処理に同じフラグの値が使われているのでちょっと混乱しそうです。
    - `--legacy-service-account-token-clean-up-period` が24時間より短い値だったとしても、ラベルが付与されるまでには少なくとも1日経過する必要がありそうに見えました。
- `kubelet`: podに`net.ipv2.tcp_keepalive_time`と`net.ipv4.tcp_keepalive_intvl`, `net.ipv4.tcp_keepalive_probes`  sysctlをデフォルトで使用できるようにしました。Pod Security Admissionはこのsysctlを`v1.29+` バージョンで許可します。 ([#121240](https://github.com/kubernetes/kubernetes/pull/121240))
- `kubelet`はデフォルトで`net.ipv4.tcp_keepalive_time`をsysctlを使用することをPodに許可しました。最小のカーネルバージョンは4.5です。Pod Security Admissionはこのsysctlをbaselineとrestricted policiesの`v1.29+`バージョンで許可します。([#118846](https://github.com/kubernetes/kubernetes/pull/118846))
### Documentation
- N/A
### Failing Test
- N/A
### Bug of Regression

- `v1.28`のネガティブインデックスJSONパッチ処理のリグレッションを修正 ([#120327](https://github.com/kubernetes/kubernetes/pull/120327))
- `ClusterTrustBundleAttest`プラグインが有効になっている場合、クラスタトラストバンドルへのno-opおよびGC関連の更新にattest authorizationが不要になりました。([#120779](https://github.com/kubernetes/kubernetes/pull/120779))
- 無効なデフォルトを削除するために`kube-openapi`を更新しました。OpenAPIの仕様では意味のない特定のフィールドの`{}`が含まれなくなりました。([#120757](https://github.com/kubernetes/kubernetes/pull/120757))
	### Other
-  `LegacyServiceAccountTokenNoAutoGeneration` フィーチャーゲートが削除されました。(この機能は安定しており常時有効です)([#120192](https://github.com/kubernetes/kubernetes/pull/120192))