Kubernetes-Pods als Cloud-IdentitÀten: EKS IRSA vs. AKS Workload Identity
Wie ein Kubernetes ServiceAccount zu einer echten Cloud-IdentitÀt wird - die OIDC-Föderations-Vertrauenskette hinter AWS IRSA und Azure AKS Workload Identity, eins zu eins abgebildet, mit den Fallstricken, die Ihre Routine durchbrechen.
Sowohl AWS als auch Azure lösen dasselbe Problem auf dieselbe Weise: Ein Pod authentifiziert sich gegenĂŒber Cloud-APIs als er selbst, mit einem kurzlebigen Token und ohne gespeichertes Secret, indem er seinen Kubernetes ServiceAccount in eine föderierte Cloud-IdentitĂ€t umwandelt. Bei AWS ist die Funktion IRSA (IAM Roles for Service Accounts); bei Azure ist es Microsoft Entra Workload Identity (der Nachfolger der veralteten aad-pod-identity). Im Grunde genommen sind beide derselbe OIDC-Föderationstrick, und die beweglichen Teile stimmen fast eins zu eins ĂŒberein.
Die Kurzversion, falls Sie nur einen Absatz lesen: Der Cluster wird zu einem OpenID Connect Issuer, der ein Token fĂŒr
den ServiceAccount jedes Pods signiert; der Identity Provider der Cloud vertraut diesem Issuer und tauscht das Token gegen echte Cloud-
Credentials aus, die auf eine IdentitĂ€t beschrĂ€nkt sind. AWS nennt die IdentitĂ€t eine IAM role und schĂŒtzt sie mit einer trust policy; Azure nennt sie
eine user-assigned managed identity und schĂŒtzt sie mit einem federated identity credential. Der Subject-String
system:serviceaccount:<namespace>:<name> ist auf beiden der Dreh- und Angelpunkt. Drei Dinge unterscheiden sich ausreichend, um Probleme zu verursachen: Azure teilt
den "OIDC provider" in zwei separate Cluster-Schalter auf, die beide standardmĂ€Ăig deaktiviert sind, Azure erfordert zusĂ€tzlich ein Label am
Pod selbst, und das Pulling Ihres Container-Images ist eine andere IdentitÀt als Ihre Workload Identity auf beiden Clouds.
Das Problem, das beide lösen
Vor der Föderation bedeutete die Vergabe von Cloud-Berechtigungen an einen Pod schlechte Optionen: einen statischen Access Key in das Image oder ein Secret einbacken (Lecks, Rotationsschwierigkeiten), oder die Berechtigung dem gesamten Node erteilen, sodass jeder Pod darauf sie erbt (keine Isolation, stark ĂŒberdimensioniert). Die AWS-seitigen Notlösungen waren Node-IMDS-Interceptors wie kube2iam und kiam; die Azure-seitige war aad-pod-identity. Alle von ihnen haben die IdentitĂ€t des Nodes proxied und waren umstĂ€ndlich und anfĂ€llig fĂŒr Race Conditions.
Die Föderation ersetzt dies durch kryptografisches Vertrauen. Das kubelet projiziert ein signiertes, kurzlebiges OIDC-Token in den Pod, das auf den ServiceAccount des Pods beschrĂ€nkt ist. Der Cloud IdP ĂŒberprĂŒft die Signatur dieses Tokens anhand der veröffentlichten öffentlichen SchlĂŒssel des Clusters und, falls Issuer, Subject und Audience des Tokens mit einer von Ihnen konfigurierten trust rule ĂŒbereinstimmen, gibt er Credentials fĂŒr genau eine Cloud-IdentitĂ€t zurĂŒck. Es wird kein Secret gespeichert; das projizierte Token rotiert automatisch (Standardlebensdauer etwa eine Stunde) und ist auĂerhalb des Clusters nutzlos.
Der gemeinsame Mechanismus: OIDC-Föderation
Jede Workload-Identity-Einrichtung, auf beiden Clouds, ist dasselbe Vertrauensdreieck:
- Der Cluster ist ein OIDC Issuer. Er stellt ein Discovery-Dokument unter
<issuer-url>/.well-known/openid-configurationund einen JWKS-Endpoint mit den öffentlichen SchlĂŒsseln bereit, mit denen er ServiceAccount- Tokens signiert. Diese Issuer-URL ist der Vertrauensanker. - Der Cloud IdP vertraut diesem Issuer fĂŒr ein spezifisches
(subject, audience)-Paar. Das Subject identifiziert, welchen ServiceAccount, und die Audience identifiziert, fĂŒr wen das Token bestimmt ist. - Die Workload tauscht das projizierte Token gegen Cloud-Credentials aus. Das SDK liest die vom kubelet projizierte Token-Datei, prĂ€sentiert sie dem Token-Endpoint der Cloud und erhĂ€lt kurzlebige Credentials fĂŒr eine einzelne Cloud- IdentitĂ€t.
Alles andere ist Benennung. Hier ist die Zuordnung, Zeile fĂŒr Zeile.
Die eins-zu-eins-Zuordnung
- Die Kubernetes-Seite. Bei AWS annotieren Sie den ServiceAccount mit
eks.amazonaws.com/role-arn: <role arn>. Bei Azure annotieren Sie ihn mitazure.workload.identity/client-id: <managed identity client id>und versehen den Pod mit dem Labelazure.workload.identity/use: "true". Beide verweisen den Pod auf eine Cloud-IdentitÀt; Azure benötigt das zusÀtzliche Pod-Label (mehr dazu weiter unten). - Der "OIDC provider". Bei AWS ist dies der OIDC Issuer des EKS-Clusters, der einmal in IAM als OIDC identity
provider registriert wird. Bei Azure sind es zwei Cluster-Einstellungen: der OIDC issuer (
oidcIssuerProfile.enabled), der die Issuer-URL und die SignierschlĂŒssel veröffentlicht, und das workload-identity add-on (securityProfile.workloadIdentity.enabled), ein mutating admission webhook. Beide mĂŒssen aktiviert sein. - Die IdentitĂ€t. AWS: eine IAM role. Azure: eine user-assigned managed identity (UAMI). Dies ist das Objekt, das der Pod wird.
- Die trust rule. AWS: die trust policy der IAM role föderiert den OIDC provider und pinnt
sub = system:serviceaccount:<ns>:<sa>undaud = sts.amazonaws.com. Azure: ein federated identity credential auf der UAMI mitissuer = <cluster OIDC issuer url>,subject = system:serviceaccount:<ns>:<sa>undaudience = api://AzureADTokenExchange. Dieselben drei Felder, unterschiedliche Orte. - Die Berechtigungen. AWS: eine IAM policy, die an die role angehÀngt ist (diesen S3 bucket lesen, von diesem ECR repo pullen). Azure: RBAC role assignments auf den Zielressourcen (Key Vault Secrets User, Storage Blob Data Reader, AcrPull, ...). Dies ist die tiefere philosophische Trennung - AWS heftet eine policy an die IdentitÀt; Azure vergibt eine role im Scope der Ressource.
- Der Austausch. AWS: Das SDK ruft
sts:AssumeRoleWithWebIdentitymit dem projizierten Token auf. Azure: Das SDK fĂŒhrt einen Entra-Token-Austausch ĂŒberDefaultAzureCredential/WorkloadIdentityCredentialdurch, wobei das projizierte Token als client assertion prĂ€sentiert wird. Beide liefern kurzlebige Credentials, beide benötigen keinerlei Secret-Material in Ihrem Code.
Der Rest dieses Beitrags beschreibt jede Cloud von Anfang bis Ende und geht dann auf die Unterschiede ein, die tatsĂ€chlich zu Problemen fĂŒhren.
Walk-through: AWS EKS IRSA, Ende zu Ende
Die Komponenten, in der Reihenfolge des Vertrauensflusses:
1. Der Cluster OIDC Issuer. Jeder EKS-Cluster hat einen, unter einer URL wie
https://oidc.eks.<region>.amazonaws.com/id/<hash>. Sie registrieren ihn einmal in IAM als OIDC identity provider, damit IAM
Tokens vertraut, die er signiert.
2. Die IAM role und ihre trust policy. Die trust policy ist das, was die role fĂŒr einen spezifischen ServiceAccount und nichts anderes annehmbar macht:
{
"Effect": "Allow",
"Principal": { "Federated": "arn:aws:iam::<account>:oidc-provider/oidc.eks.<region>.amazonaws.com/id/<hash>" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.<region>.amazonaws.com/id/<hash>:sub": "system:serviceaccount:apps:checkout",
"oidc.eks.<region>.amazonaws.com/id/<hash>:aud": "sts.amazonaws.com"
}
}
}
Pinnen Sie sowohl :sub als auch :aud. Nur den Issuer zu pinnen, wĂŒrde es jedem ServiceAccount im Cluster ermöglichen, die role anzunehmen - ein
klassischer Over-Trust-Bug.
3. Die IAM policy. Eine normale identitÀtsbasierte policy, die an die role angehÀngt ist, gewÀhrt, was die App tatsÀchlich benötigt
(s3:GetObject auf einem Bucket, ecr:GetDownloadUrlForLayer und so weiter).
4. Der ServiceAccount. Ein einfacher ServiceAccount mit einer Annotation:
apiVersion: v1
kind: ServiceAccount
metadata:
name: checkout
namespace: apps
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<account>:role/checkout
5. Die Projektion. EKS liefert den Pod Identity Webhook im Cluster integriert. Wenn ein Pod einen annotierten
ServiceAccount verwendet, mutiert der Webhook ihn: Er injiziert die Umgebungsvariablen AWS_ROLE_ARN und AWS_WEB_IDENTITY_TOKEN_FILE und mountet
ein projiziertes Token-Volume (Audience sts.amazonaws.com, automatisch rotiert). Sie labeln den Pod nicht; die SA-Annotation ist
ausreichend.
6. Der Austausch. Die Standard-Credential-Kette des AWS SDK bemerkt AWS_WEB_IDENTITY_TOKEN_FILE, ruft
sts:AssumeRoleWithWebIdentity mit dem Token auf und cached die zurĂŒckgegebenen kurzlebigen Credentials. Ihr Code ist einfach
boto3.client("s3") - keinerlei Credential-Handhabung.
Neuere Alternative: EKS Pod Identity (2023) erledigt dieselbe Aufgabe ĂŒber einen On-Cluster-Agenten und eine Association API anstelle eines pro-Cluster IAM OIDC provider und einer pro-role trust policy. Es ist einfacher im groĂen MaĂstab zu betreiben, ist aber AWS-spezifische Implementierung; das oben beschriebene OIDC-Föderationsmodell ist dasjenige, das sauber auf Azure abgebildet werden kann, daher ist es dasjenige, das man fĂŒr einen Cloud-ĂŒbergreifenden Vergleich im Kopf behalten sollte.
Walk-through: Azure AKS Workload Identity, Ende zu Ende
Derselbe Vertrauensfluss, Azure-Begriffe:
1. Zwei Cluster-Schalter. Aktivieren Sie den OIDC issuer (oidcIssuerProfile.enabled = true), der eine Issuer-
URL wie https://<region>.oic.prod-aks.azure.com/<tenant>/<guid>/ veröffentlicht, und das workload-identity add-on
(securityProfile.workloadIdentity.enabled = true), das den mutating webhook installiert. Beide sind standardmĂ€Ăig deaktiviert auf einem neuen
Cluster, und die oidcIssuerUrl des Clusters ist null, bis der erste aktiviert wird. Die Aktivierung ist ein In-Place-Update, keine
Neuerstellung.
2. Die managed identity. Erstellen Sie eine user-assigned managed identity. (Federated credentials werden nur an user-assigned identities angehÀngt, nicht an system-assigned ones.) Ihre client id ist das, worauf der ServiceAccount verweisen wird.
3. Das federated identity credential. Dies ist die trust rule, ein untergeordnetes Objekt auf der UAMI:
issuer: https://<region>.oic.prod-aks.azure.com/<tenant>/<guid>/
subject: system:serviceaccount:apps:checkout
audience: api://AzureADTokenExchange
Beachten Sie dieselbe Subject-Grammatik wie bei AWS und eine andere feste Audience.
4. Das RBAC. GewÀhren Sie dem Principal der UAMI die roles, die sie auf den Zielressourcen benötigt: Key Vault Secrets User auf einem
Vault, Storage Blob Data Reader auf einem Storage Account, AcrPull auf einer Registry, wenn die App die Registry-Data Plane
selbst aufruft. Es gibt kein policy document auf der IdentitĂ€t; der Zugriff erfolgt ĂŒber role assignments im Scope jeder Ressource.
5. Der ServiceAccount und das Pod-Label. Der ServiceAccount trÀgt die client-id annotation, und - dies ist der Teil, den AWS-Benutzer vergessen - der Pod muss ebenfalls gelabelt sein:
apiVersion: v1
kind: ServiceAccount
metadata:
name: checkout
namespace: apps
annotations:
azure.workload.identity/client-id: <uami-client-id>
---
# in the Deployment's pod template:
metadata:
labels:
azure.workload.identity/use: "true" # required on the POD, not just the SA
spec:
serviceAccountName: checkout
6. Die Projektion. Der Webhook des Add-ons mutiert nur Pods, die das Label azure.workload.identity/use: "true" tragen.
Wenn er ausgelöst wird, injiziert er AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_FEDERATED_TOKEN_FILE und
AZURE_AUTHORITY_HOST und projiziert ein Token mit Audience api://AzureADTokenExchange.
7. Der Austausch. DefaultAzureCredential() (oder die explizite WorkloadIdentityCredential) liest diese Umgebungsvariablen,
prĂ€sentiert das projizierte Token Entra ID als client assertion und erhĂ€lt ein Access Token fĂŒr die Zielressource zurĂŒck.
Ein Key Vault-Lesevorgang ist azure.identity.DefaultAzureCredential() plus SecretClient in Python, oder
new DefaultAzureCredential() plus @azure/keyvault-secrets in TypeScript - und wiederum kein Secret irgendwo im Code.
Der Subject-String ist der Dreh- und Angelpunkt (auf beiden Clouds)
Der einzige Wert, der auf beiden Clouds exakt ĂŒbereinstimmen muss, ist das Token Subject:
system:serviceaccount:<namespace>:<serviceaccount-name>
Das kubelet stempelt dies basierend auf dem tatsÀchlichen Namespace und ServiceAccount des Pods in das Token. Die trust rule (IAM trust
policy auf AWS, federated credential auf Azure) pinnt den String, den sie akzeptiert. Wenn die App im Namespace apps unter
ServiceAccount checkout lĂ€uft, muss die trust rule system:serviceaccount:apps:checkout lauten - Zeichen fĂŒr Zeichen. Der
hĂ€ufigste Fehler "es authentifiziert sich als niemand" ist eine NichtĂŒbereinstimmung hier: Der Chart wurde in einem anderen Namespace deployed, der
ServiceAccount erhielt den Release-Namen anstelle des App-Namens, oder jemand nahm den default ServiceAccount an. Wenn die
Föderation stillschweigend fehlschlĂ€gt, ĂŒberprĂŒfen Sie zuerst das Subject.
Die Audience ist das andere gepinnte Feld, und es ist eine feste Konstante pro Cloud: sts.amazonaws.com auf AWS,
api://AzureADTokenExchange auf Azure. Sie Ă€ndern es selten, aber die trust rule und das projizierte Token mĂŒssen sich darauf
einigen.
Vier Unterschiede, die Sie tatsÀchlich stolpern lassen werden
1. Azure teilt den "OIDC provider" in zwei Schalter auf, und beide sind standardmĂ€Ăig deaktiviert. Bei EKS ist der Pod-Identity-Webhook
im Cluster integriert, und der einzige einmalige Schritt ist die Registrierung des OIDC provider in IAM. Bei AKS mĂŒssen Sie separat
den OIDC issuer und das workload-identity add-on aktivieren; vergessen Sie das Add-on, veröffentlicht der Issuer weiterhin Tokens, aber nichts
projiziert sie in Pods, sodass die App keine AZURE_*-Umgebungsvariablen sieht und DefaultAzureCredential stillschweigend auf die
nĂ€chste Credential-Quelle zurĂŒckfĂ€llt. Aktivieren Sie beide, und denken Sie daran, dass das federated credential erst erstellt werden kann, wenn die Issuer-URL existiert.
2. Azure benötigt ein Label am Pod, nicht nur eine Annotation am ServiceAccount. Der AKS-Webhook reagiert auf das
Label azure.workload.identity/use: "true" am Pod (die ServiceAccount-Annotation allein ist nicht ausreichend). Der Webhook von IRSA
reagiert auf die ServiceAccount-Annotation und benötigt kein Pod-Label. Dies ist der hÀufigste Azure-seitige
Stolperstein: Der ServiceAccount sieht perfekt aus, aber die Pod-Vorlage hat das Label vergessen, sodass kein Token projiziert wird.
3. Das Pulling des Images ist eine andere IdentitÀt als die Workload Identity - auf beiden Clouds. Das Image-Pulling ist die Aufgabe der
Node/kubelet-IdentitÀt: Bei AKS besitzt die kubelet-IdentitÀt AcrPull; bei EKS besitzt die Instance role der Node-Gruppe
AmazonEC2ContainerRegistryReadOnly (oder Sie verwenden pull secrets). Workload Identity wird nur benötigt, wenn der App-
Code eine Cloud-API aufruft (ein Secret lesen, einen Bucket auflisten, die Data Plane der Registry aufrufen). Ein reiner HTTP-Dienst, der niemals
mit einem Cloud-SDK kommuniziert, benötigt ĂŒberhaupt keine Workload Identity - und umgekehrt bewirkt die Zuweisung von AcrPull zu einer Workload Identity
nichts fĂŒr das Image-Pulling, da das Pulling stattfindet, bevor die App (und ihr föderiertes Token) ĂŒberhaupt lĂ€uft.
4. Berechtigungen werden unterschiedlich angehĂ€ngt. AWS heftet eine IAM policy an die role - die Berechtigung reist mit der IdentitĂ€t. Azure vergibt RBAC role assignments im Scope der Zielressource - die Berechtigung befindet sich auf dem Objekt, auf das zugegriffen wird, nicht auf der IdentitĂ€t. Derselbe Endzustand (dieser Pod kann diesen Vault lesen), aber Sie suchen an verschiedenen Stellen, um dies zu ĂŒberprĂŒfen: Bei AWS lesen Sie die angehĂ€ngten policies der role; bei Azure listen Sie die role assignments auf der Ressource (oder die Zuweisungen der IdentitĂ€t ĂŒber Scopes hinweg) auf. Dies spiegelt den breiteren IAM-vs-RBAC-Unterschied zwischen den beiden Clouds wider.
Wie die injizierte Umgebung aussieht
Beide Webhooks ĂŒbergeben dem SDK alles, was es benötigt, ĂŒber Umgebungsvariablen und eine projizierte Datei, sodass der App-Code keine Secrets und keine Cloud-spezifische Credential-Logik referenziert:
- AWS:
AWS_ROLE_ARN,AWS_WEB_IDENTITY_TOKEN_FILE,AWS_REGION. Die Standard-Credential-Kette ruftAssumeRoleWithWebIdentityfĂŒr Sie auf. - Azure:
AZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_FEDERATED_TOKEN_FILE,AZURE_AUTHORITY_HOST.DefaultAzureCredentialfĂŒhrt den Entra-Austausch fĂŒr Sie durch.
In beiden FÀllen ist die projizierte Token-Datei kurzlebig und wird vom kubelet automatisch rotiert; das SDK liest sie erneut und aktualisiert die Cloud-Credentials transparent. Es gibt nichts zu rotieren, nichts zu speichern und nichts, das geleakt werden könnte.
Eine Debugging-Checkliste, die auf beiden Clouds funktioniert
Wenn ein Pod "sich nicht authentifizieren kann", gehen Sie die Vertrauenskette der Reihe nach durch:
- Cluster Issuer an? BestÀtigen Sie, dass die OIDC Issuer-URL existiert (AKS: beide Schalter auf true; EKS: der IAM OIDC provider ist registriert). Kein Issuer, kein Vertrauensanker.
- Projektion findet statt? FĂŒhren Sie exec in den Pod aus und prĂŒfen Sie, ob die Token-Datei und die Umgebungsvariablen vorhanden sind
(
AWS_WEB_IDENTITY_TOKEN_FILE/AZURE_FEDERATED_TOKEN_FILE). Fehlen diese bei Azure, bedeutet dies normalerweise, dass das Pod-Label fehlt oder das Add-on deaktiviert ist. - Subject-Ăbereinstimmung? Vergleichen Sie das Subject der trust rule mit
system:serviceaccount:<actual-namespace>:<actual-sa>. Dies ist der hĂ€ufigste Fehler. - Audience-Ăbereinstimmung?
sts.amazonaws.com/api://AzureADTokenExchange, auf beiden Seiten ĂŒbereinstimmend. - Berechtigungen? Erst nachdem die IdentitĂ€t aufgelöst wurde: die IAM policy auf der role oder die RBAC role assignment auf der Zielressource. Ein leeres Ergebnis hier ist ein Autorisierungsfehler, kein Authentifizierungsfehler - eine nĂŒtzliche Unterscheidung, da sie Ihnen sagt, dass die Föderation selbst funktioniert.
Welche Zertifizierungen dies behandeln
Workload Identity befindet sich genau an der Schnittstelle von Kubernetes, Cloud IAM und OIDC-Föderation, daher taucht es in drei PrĂŒfungs- Tracks auf. Wenn Sie bereits eine Cloud-Credential besitzen, ist dasselbe Konzept auf der anderen Cloud nur ein kleiner Schritt.
Auf der AWS-Seite:
- AWS Certified Solutions Architect - Associate (SAA-C03) - IAM roles, EKS und wie IdentitÀten Cloud-Berechtigungen erhalten.
- AWS Certified Security - Specialty (SCS-C03) - IAM trust policies, OIDC-Föderation und Least-Privilege-Scoping (genau die IRSA trust chain).
Auf der Azure-Seite:
- Microsoft Azure Administrator Associate (AZ-104) - AKS, managed identities und RBAC role assignments.
- Microsoft Azure Security Engineer Associate (AZ-500) - Entra ID, managed identities, federated credentials und RBAC-Tiefe.
Auf der Kubernetes-Seite:
- CNCF Certified Kubernetes Administrator (CKA) - ServiceAccounts, projected tokens und Pod- Spezifikationen.
- CNCF Certified Kubernetes Security Specialist (CKS) - ServiceAccount token security, Least Privilege und Reduzierung der Exposition statischer Secrets.
Fazit
IRSA und AKS Workload Identity sind dieselbe Idee in unterschiedlicher Terminologie: Der Cluster signiert ein kurzlebiges OIDC-
Token fĂŒr einen ServiceAccount, der Cloud IdP vertraut diesem Issuer fĂŒr ein (subject, audience), und der Pod tauscht das
Token gegen Credentials aus, die auf eine einzelne Cloud-IdentitÀt beschrÀnkt sind - eine IAM role bei AWS, eine managed identity bei Azure. Lernen Sie das
Vertrauensdreieck einmal, und die Ăbersetzung ist mechanisch: role wird zu managed identity, trust policy wird zu federated
credential, attached policy wird zu RBAC assignment, AssumeRoleWithWebIdentity wird zu einem Entra token exchange. Behalten Sie
drei Dinge im Auge - Azures zwei Cluster-Schalter, Azures erforderliches Pod-Label und die Tatsache, dass das Image-Pulling eine
ganz andere IdentitĂ€t ist - und die Ablehnungen, die frĂŒher zufĂ€llig aussahen, lesen sich nun als kohĂ€rentes, bewusstes Design.