# Kubelet Authentication & Authorization

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

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

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

By default, requests to the kubelet's HTTPS endpoint that are not rejected by other configured authentication methods are treated as anonymous requests, and given a **username of `system:anonymous`** and a **group of `system:unauthenticated`**.

The **3** authentication **methods** are:

- **Anonymous** (default): Use set setting the param **`--anonymous-auth=true` or the config:**

```json
"authentication": {
    "anonymous": {
      "enabled": true
    },
```

- **Webhook**: This will **enable** the kubectl **API bearer tokens** as authorization (any valid token will be valid). Allow it with:
  - ensure the `authentication.k8s.io/v1beta1` API group is enabled in the API server
  - start the kubelet with the **`--authentication-token-webhook`** and **`--kubeconfig`** flags or use the following setting:

```json
"authentication": {
    "webhook": {
      "cacheTTL": "2m0s",
      "enabled": true
    },
```

> [!NOTE]
> The kubelet calls the **`TokenReview` API** on the configured API server to **determine user information** from bearer tokens

- **X509 client certificates:** Allow to authenticate via X509 client certs
  - see the [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) for more details
  - start the kubelet with the `--client-ca-file` flag, providing a CA bundle to verify client certificates with. Or with the config:

```json
"authentication": {
    "x509": {
      "clientCAFile": "/etc/kubernetes/pki/ca.crt"
    }
}
```

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

Any request that is successfully authenticated (including an anonymous request) **is then authorized**. The **default** authorization mode is **`AlwaysAllow`**, which **allows all requests**.

However, the other possible value is **`webhook`** (which is what you will be **mostly finding out there**). This mode will **check the permissions of the authenticated user** to allow or disallow an action.

> [!WARNING]
> Note that even if the **anonymous authentication is enabled** the **anonymous access** might **not have any permissions** to perform any action.

The authorization via webhook can be configured using the **param `--authorization-mode=Webhook`** or via the config file with:

```json
"authorization": {
    "mode": "Webhook",
    "webhook": {
      "cacheAuthorizedTTL": "5m0s",
      "cacheUnauthorizedTTL": "30s"
    }
},
```

The kubelet calls the **`SubjectAccessReview`** API on the configured API server to **determine** whether each request is **authorized.**

The kubelet authorizes API requests using the same [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) approach as the apiserver:

- **Action**

| 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)                                                                                         |

- The **resource** talking to the Kubelet api is **always** **nodes** and **subresource** is **determined** from the incoming request's path:

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

> [!NOTE]
> WebSocket-based `/exec`, `/run`, `/attach`, and `/portforward` fall into the default **proxy** subresource and are authorized using the initial HTTP **GET** handshake. A principal with only `nodes/proxy` **GET** can still exec containers if it connects directly to `https://<node_ip>:10250` over WebSockets. See the [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) for details.

For example, the following request tried to access the pods info of kubelet without permission:

```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)
```

- We got a **Forbidden**, so the request **passed the Authentication check**. If not, we would have got just an `Unauthorised` message.
- We can see the **username** (in this case from the token)
- Check how the **resource** was **nodes** and the **subresource** **proxy** (which makes sense with the previous information)

## 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}}



