# Kubelet 認証と認可

{{#include ../../../banners/hacktricks-training.md}}

## Kubelet 認証 <a href="#kubelet-authentication" id="kubelet-authentication"></a>

[**From the docss:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)

デフォルトでは、他の設定された認証方法によって拒否されない kubelet の HTTPS エンドポイントへのリクエストは匿名リクエストとして扱われ、**ユーザー名 `system:anonymous`** と **グループ `system:unauthenticated`** が与えられます。

認証の **3** つの **方法** は次のとおりです:

- **Anonymous** (デフォルト): パラメータ **`--anonymous-auth=true`** または設定で有効にします:
```json
"authentication": {
"anonymous": {
"enabled": true
},
```
- **Webhook**: これにより kubectl の **API bearer tokens** を認証として**有効にします**（有効なトークンはどれでも認証されます）。次のように許可します：
- API サーバーで `authentication.k8s.io/v1beta1` API グループが有効になっていることを確認する
- kubelet を **`--authentication-token-webhook`** と **`--kubeconfig`** フラグで起動するか、次の設定を使用する：
```json
"authentication": {
"webhook": {
"cacheTTL": "2m0s",
"enabled": true
},
```
> [!NOTE]
> kubelet は設定された API server 上の **`TokenReview` API`** を呼び出し、bearer tokens から**ユーザー情報を判定します**

- **X509 client certificates:** X509 client certs を使用して認証できます
- see the [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) for more details
- kubelet を `--client-ca-file` フラグで起動し、クライアント証明書を検証するための CA バンドルを指定します。あるいは設定で:
```json
"authentication": {
"x509": {
"clientCAFile": "/etc/kubernetes/pki/ca.crt"
}
}
```
## Kubelet 認可 <a href="#kubelet-authentication" id="kubelet-authentication"></a>

正常に認証された（匿名リクエストを含む）すべてのリクエストは、**その後認可されます**。**デフォルト**の認可モードは**`AlwaysAllow`**で、**すべてのリクエストを許可します**。

ただし、もう一つの可能な値は**`webhook`**（現場で**主に見かける**のはこちら）です。このモードは、アクションを許可するか拒否するかを決めるために、**認証済みユーザーの権限をチェックします**。

> [!WARNING]
> **匿名認証が有効になっている**場合でも、**匿名アクセス**は操作を実行するための権限を**持たない場合があります**。

webhookによる認可は、**param `--authorization-mode=Webhook`** を使用するか、設定ファイルで次のように設定できます：
```json
"authorization": {
"mode": "Webhook",
"webhook": {
"cacheAuthorizedTTL": "5m0s",
"cacheUnauthorizedTTL": "30s"
}
},
```
The kubelet は構成された API サーバー上の **`SubjectAccessReview`** API を呼び出して、各リクエストが **許可されているかどうか** を **判定** します。

kubelet は apiserver と同じ [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) アプローチを使って API リクエストを認可します:

- **アクション**

| HTTP verb | request verb                                                                                                                                                  |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| POST      | create                                                                                                                                                        |
| GET, HEAD | get (for individual resources), list (for collections, including full object content), watch (for watching an individual resource or collection of resources) |
| PUT       | update                                                                                                                                                        |
| PATCH     | patch                                                                                                                                                         |
| DELETE    | delete (for individual resources), deletecollection (for collections)                                                                                         |

- Kubelet api に対して話す **resource** は **常に** **nodes** で、**subresource** は受信リクエストのパスから **決定されます**:

| Kubelet API  | resource | subresource |
| ------------ | -------- | ----------- |
| /stats/\*    | nodes    | stats       |
| /metrics/\*  | nodes    | metrics     |
| /logs/\*     | nodes    | log         |
| /spec/\*     | nodes    | spec        |
| _all others_ | nodes    | proxy       |

> [!NOTE]
> WebSocket ベースの `/exec`, `/run`, `/attach`, `/portforward` はデフォルトの **proxy** subresource に分類され、初回 HTTP **GET** ハンドシェイクで認可されます。`nodes/proxy` **GET** のみを持つ主体でも、WebSockets 経由で `https://<node_ip>:10250` に直接接続すればコンテナを exec できてしまいます。詳細は [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) を参照してください。

例えば、次のリクエストは権限なしに kubelet の pods 情報へアクセスしようとしました:
```bash
curl -k --header "Authorization: Bearer ${TOKEN}" 'https://172.31.28.172:10250/pods'
Forbidden (user=system:node:ip-172-31-28-172.ec2.internal, verb=get, resource=nodes, subresource=proxy)
```
- **Forbidden** を受け取ったので、リクエストは **認証チェックを通過している**。もしそうでなければ、単に `Unauthorised` メッセージを受け取っていただろう。
- **username** が確認できる（この場合はトークンから）
- **resource** が **nodes**、**subresource** が **proxy** になっているのを確認（前の情報と一致する）

## References

- [https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
- [nodes/proxy GET -> kubelet exec via WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce)

{{#include ../../../banners/hacktricks-training.md}}
