AWS-Workloads können sich ohne statische API-Keys bei der Claude API authentifizieren, indem sie ein von AWS signiertes OIDC-Identitäts-Token austauschen. Der empfohlene Weg ruft die AWS STS GetWebIdentityToken API auf, die überall dort funktioniert, wo der Workload über AWS-Anmeldeinformationen verfügt: Lambda, EC2, ECS und EKS. EKS-Workloads können alternativ den Kubernetes-Projected-Token-Weg verwenden, der weniger Konfigurationsschritte erfordert, aber nur innerhalb eines Pods funktioniert.
Diese Anleitung zeigt beide Wege. Für die zugrunde liegenden Konzepte (Service-Accounts, Federation-Issuer und Federation-Regeln) siehe Workload Identity Federation.
aws-CLI oder ein AWS-SDK, das im Workload verfügbar ist.Die AWS STS GetWebIdentityToken API gibt ein von AWS signiertes OIDC-Token zurück, das die IAM-Identität des Aufrufers bestätigt. Da sie die vorhandenen AWS-Anmeldeinformationen des Workloads verwendet, deckt dieselbe Integration Lambda, EC2, ECS und EKS ab.
Outbound Web Identity Federation für das Konto aktivieren
Dies ist ein kontoweites Flag, das standardmäßig deaktiviert ist. Öffne in der AWS-Konsole IAM, wähle Account settings und aktiviere Outbound web identity federation. Um es programmatisch zu aktivieren:
python3 -c "import boto3; boto3.client('iam').enable_outbound_web_identity_federation()"Wenn dies nicht aktiviert ist, schlagen Aufrufe von GetWebIdentityToken mit OutboundWebIdentityFederationDisabledException fehl.
Der IAM-Rolle des Workloads die Berechtigung zum Aufrufen der API erteilen
Hänge diese Policy an die IAM-Rolle an, unter der deine Lambda-Funktion, EC2-Instanz oder dein ECS-Task ausgeführt wird:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["sts:GetWebIdentityToken"],
"Resource": "*"
}
]
}Die STS-Issuer-URL deines Kontos ermitteln
Nach dem Aktivieren der Outbound Federation zeigt die Seite IAM > Account settings ein Feld Get Token Issuer URL mit einem Wert der Form https://<uuid>.tokens.sts.global.api.aws. Diese URL ist eindeutig für dein AWS-Konto; kopiere sie für den nächsten Schritt. Um sie programmatisch abzurufen:
python3 -c "import boto3; print(boto3.client('iam').get_outbound_web_identity_federation_info())"Öffne in der Claude Console Settings → Workload identity, klicke auf Connect workload und wähle die AWS-Kachel aus. Der Assistent führt dich durch die Registrierung des Issuers, das Erstellen eines Service-Accounts und das Erstellen einer Federation-Regel.
Der Assistent erstellt diese Ressourcen für dich. Verwende die folgenden Werte, unabhängig davon, ob du sie im Assistenten eingibst oder an die Admin API sendest:
Federation-Issuer: Registriere die kontospezifische STS-Issuer-URL, die du im vorherigen Schritt kopiert hast. Sie stellt einen öffentlichen JWKS-Endpunkt bereit, verwende also den Discovery-Modus.
{
"name": "aws-sts",
"issuer_url": "https://<uuid>.tokens.sts.global.api.aws",
"jwks": { "type": "discovery" }
}Federation-Regel: Matche die Audience, die du an GetWebIdentityToken übergibst, und die IAM-Rollen-ARN der aufrufenden Rolle im sub-Claim. Der sub-Wert ist die IAM-Rollen-ARN des Workloads, der die API aufgerufen hat, in der Form arn:aws:iam::<account>:role/<role-name>. Das Token enthält außerdem einen https://sts.amazonaws.com/-Claim mit aws_account, org_id, principal_id und allen request_tags, die du übergeben hast; du kannst diese mit der claims-Map der Regel oder einer CEL-condition für eine feinere Steuerung matchen.
{
"name": "prod-inference",
"issuer_id": "fdis_...",
"match": {
"subject_prefix": "arn:aws:iam::123456789012:role/inference-worker",
"audience": "https://api.anthropic.com"
},
"target": { "type": "service_account", "service_account_id": "svac_..." },
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}Sei so spezifisch, wie es der Workload erlaubt. Matche die exakte Rollen-ARN und erweitere subject_prefix nur dann (zum Beispiel auf arn:aws:iam::123456789012:role/*), wenn mehrere IAM-Rollen demselben Anthropic-Service-Account zugeordnet werden sollen.
Rufe GetWebIdentityToken mit https://api.anthropic.com als Audience auf und übergib das Ergebnis dann an die Federation-Credentials des SDK. Der Token-Provider ist ein Callable, sodass das SDK STS bei jedem Refresh erneut aufruft.
GetWebIdentityToken ist nur auf regionalen STS-Endpunkten verfügbar. Wenn du 'STS' object has no attribute 'get_web_identity_token' oder einen ähnlichen Fehler erhältst, binde deinen STS-Client an eine Region (zum Beispiel boto3.client("sts", region_name="us-east-1")) und stelle sicher, dass dein AWS-SDK aktuell genug ist, um die API zu enthalten.
import os
import anthropic
import boto3
from anthropic import WorkloadIdentityCredentials
def get_sts_web_identity_token() -> str:
sts = boto3.client("sts", region_name="us-east-1")
resp = sts.get_web_identity_token(
Audience=["https://api.anthropic.com"],
SigningAlgorithm="RS256",
DurationSeconds=900,
)
return resp["WebIdentityToken"]
client = anthropic.Anthropic(
credentials=WorkloadIdentityCredentials(
identity_token_provider=get_sts_web_identity_token,
federation_rule_id=os.environ["ANTHROPIC_FEDERATION_RULE_ID"],
organization_id=os.environ["ANTHROPIC_ORGANIZATION_ID"],
service_account_id=os.environ["ANTHROPIC_SERVICE_ACCOUNT_ID"],
workspace_id=os.environ.get("ANTHROPIC_WORKSPACE_ID"),
),
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from AWS"}],
)
print(message.content[0].text)Tausche von innerhalb des Workloads ein von STS ausgestelltes Token direkt aus und prüfe die Antwort:
JWT=$(aws sts get-web-identity-token \
--region us-east-1 \
--audience "https://api.anthropic.com" \
--signing-algorithm RS256 \
--duration-seconds 900 \
--query WebIdentityToken --output text)
curl -sS https://api.anthropic.com/v1/oauth/token \
-H "content-type: application/json" \
-d "{
\"grant_type\": \"urn:ietf:params:oauth:grant-type:jwt-bearer\",
\"assertion\": \"$JWT\",
\"federation_rule_id\": \"fdrl_...\",
\"organization_id\": \"00000000-0000-0000-0000-000000000000\",
\"service_account_id\": \"svac_...\",
\"workspace_id\": \"wrkspc_...\"
}" | jqEin erfolgreicher Austausch gibt ein access_token zurück, das mit sk-ant-oat01- beginnt, sowie einen expires_in-Wert in Sekunden. Bei 400 invalid_grant siehe Fehlerbehebung bei einem fehlgeschlagenen Austausch; die häufigste Ursache auf AWS-Seite ist eine iss-Nichtübereinstimmung (die kontospezifische STS-Issuer-URL muss exakt mit der registrierten issuer_url übereinstimmen).
Wenn dein Workload in einem EKS-Pod läuft, kannst du den STS-Aufruf überspringen und ein von Kubernetes projiziertes Service-Account-Token direkt von der Festplatte lesen. Kubernetes projiziert nativ ein OIDC-kompatibles Token in den Pod, und das SDK kann es aus einem Dateipfad lesen, sodass kein Token-Provider-Callable erforderlich ist. Dieser Weg hat zwei AWS-Konfigurationsschritte weniger als der STS-Weg, funktioniert aber nur innerhalb eines Pods; der zugrunde liegende Mechanismus ist derselbe wie bei der generischen Kubernetes-Integration.
Dieser Weg erfordert zusätzlich einen EKS-Cluster mit einem aktivierten IAM-OIDC-Provider und kubectl-Zugriff auf den Cluster.
Die OIDC-Issuer-URL deines Clusters ermitteln
Jeder EKS-Cluster hat einen eindeutigen OIDC-Issuer. Rufe ihn mit der AWS-CLI ab:
aws eks describe-cluster \
--name <cluster-name> \
--query "cluster.identity.oidc.issuer" \
--output textDie Ausgabe sieht aus wie https://oidc.eks.us-west-2.amazonaws.com/id/6FA42E7BFDE8549CB.... Du registrierst diese URL im nächsten Abschnitt als Federation-Issuer.
Den Service-Account erstellen und ein Token mit Anthropic-Audience projizieren
Der EKS-Pod-Identity-Webhook erkennt die Annotation eks.amazonaws.com/role-arn und projiziert automatisch ein Token mit aud: sts.amazonaws.com, dessen Pfad als AWS_WEB_IDENTITY_TOKEN_FILE bereitgestellt wird. Dieses Token dient der AWS-Rollenübernahme. Für den Anthropic-Austausch projiziere ein zweites Token mit audience: https://api.anthropic.com und mounte es unter einem dedizierten Pfad.
apiVersion: v1
kind: ServiceAccount
metadata:
name: inference-worker
namespace: inference
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/inference-workerapiVersion: v1
kind: Pod
metadata:
name: inference-worker
namespace: inference
spec:
serviceAccountName: inference-worker
volumes:
- name: anthropic-token
projected:
sources:
- serviceAccountToken:
audience: https://api.anthropic.com
expirationSeconds: 3600
path: token
containers:
- name: app
image: your-registry/inference-worker:latest
env:
- name: ANTHROPIC_IDENTITY_TOKEN_FILE
value: /var/run/secrets/anthropic.com/token
- name: ANTHROPIC_FEDERATION_RULE_ID
value: fdrl_...
- name: ANTHROPIC_ORGANIZATION_ID
value: 00000000-0000-0000-0000-000000000000
- name: ANTHROPIC_SERVICE_ACCOUNT_ID
value: svac_...
- name: ANTHROPIC_WORKSPACE_ID # required when the rule covers multiple workspaces
value: wrkspc_...
volumeMounts:
- name: anthropic-token
mountPath: /var/run/secrets/anthropic.com
readOnly: trueDie Claim-Struktur des Tokens beachten
Das projizierte Token ist ein „JSON Web Token" (JWT), das vom OIDC-Issuer deines Clusters signiert wurde. Sein sub-Claim folgt der Kubernetes-Konvention system:serviceaccount:<namespace>:<service-account-name>:
{
"iss": "https://oidc.eks.us-west-2.amazonaws.com/id/6FA42E7BFDE8549CB...",
"sub": "system:serviceaccount:inference:inference-worker",
"aud": ["https://api.anthropic.com"],
"kubernetes.io": {
"namespace": "inference",
"serviceaccount": { "name": "inference-worker", "uid": "..." }
},
"exp": 1775527120,
"iat": 1775523520
}Die serviceAccountToken-Projektion setzt aud auf https://api.anthropic.com. Das separate, von IRSA injizierte Token unter AWS_WEB_IDENTITY_TOKEN_FILE trägt aud: sts.amazonaws.com und ist für AWS-API-Aufrufe gedacht, nicht für diesen Austausch.
Öffne in der Claude Console Settings → Workload identity, klicke auf Connect workload und wähle die AWS-Kachel aus. Der Assistent führt dich durch die Registrierung des Issuers, das Erstellen eines Service-Accounts und das Erstellen einer Federation-Regel.
Der Assistent erstellt diese Ressourcen für dich. Verwende die folgenden Werte, unabhängig davon, ob du sie im Assistenten eingibst oder an die Admin API sendest:
Federation-Issuer: EKS-Issuer stellen einen öffentlichen JWKS-Endpunkt bereit, verwende also den Discovery-Modus. Die Issuer-URL muss exakt mit dem iss-Claim des Tokens übereinstimmen. Registriere einen Issuer pro Cluster.
{
"name": "prod-eks-uswest2",
"issuer_url": "https://oidc.eks.us-west-2.amazonaws.com/id/6FA42E7BFDE8549CB...",
"jwks": { "type": "discovery" }
}Federation-Regel: Matche den Kubernetes-sub-Claim und die Anthropic-Audience https://api.anthropic.com. (Projiziere ein dediziertes Service-Account-Token mit dieser Audience; verwende nicht das IRSA-Standard-Token mit sts.amazonaws.com wieder.)
{
"name": "prod-inference",
"issuer_id": "fdis_...",
"match": {
"subject_prefix": "system:serviceaccount:inference:inference-worker",
"audience": "https://api.anthropic.com"
},
"target": { "type": "service_account", "service_account_id": "svac_..." },
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}Sei so spezifisch, wie es der Workload erlaubt. Lockere subject_prefix nur dann auf system:serviceaccount:inference:* (das abschließende * macht daraus einen Präfix-Match), wenn jeder Service-Account im Namespace demselben Anthropic-Service-Account zugeordnet werden soll.
Innerhalb des Pods befindet sich das projizierte Token unter /var/run/secrets/anthropic.com/token (in der Pod-Spec als ANTHROPIC_IDENTITY_TOKEN_FILE bereitgestellt). Übergib diese Datei an die Federation-Credentials des SDK, und das SDK übernimmt den Austausch und den Refresh.
import os
import anthropic
from anthropic import IdentityTokenFile, WorkloadIdentityCredentials
client = anthropic.Anthropic(
credentials=WorkloadIdentityCredentials(
identity_token_provider=IdentityTokenFile(
os.environ["ANTHROPIC_IDENTITY_TOKEN_FILE"]
),
federation_rule_id=os.environ["ANTHROPIC_FEDERATION_RULE_ID"],
organization_id=os.environ["ANTHROPIC_ORGANIZATION_ID"],
service_account_id=os.environ["ANTHROPIC_SERVICE_ACCOUNT_ID"],
workspace_id=os.environ.get("ANTHROPIC_WORKSPACE_ID"),
),
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from EKS"}],
)
print(message.content[0].text)Die Pod-Spec setzt bereits ANTHROPIC_IDENTITY_TOKEN_FILE, ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID und ANTHROPIC_WORKSPACE_ID, sodass du den Client ohne Argumente erstellen kannst und das SDK die Federation-Umgebungsvariablen automatisch einliest.
Tausche von innerhalb des Pods das projizierte Token direkt aus und prüfe die Antwort:
JWT=$(cat "$ANTHROPIC_IDENTITY_TOKEN_FILE")
curl -sS https://api.anthropic.com/v1/oauth/token \
-H "content-type: application/json" \
-d "{
\"grant_type\": \"urn:ietf:params:oauth:grant-type:jwt-bearer\",
\"assertion\": \"$JWT\",
\"federation_rule_id\": \"$ANTHROPIC_FEDERATION_RULE_ID\",
\"organization_id\": \"$ANTHROPIC_ORGANIZATION_ID\",
\"service_account_id\": \"$ANTHROPIC_SERVICE_ACCOUNT_ID\",
\"workspace_id\": \"$ANTHROPIC_WORKSPACE_ID\"
}" | jqEin erfolgreicher Austausch gibt ein access_token zurück, das mit sk-ant-oat01- beginnt, sowie einen expires_in-Wert in Sekunden. Bei 400 invalid_grant siehe Fehlerbehebung bei einem fehlgeschlagenen Austausch; die häufigste Ursache auf EKS-Seite ist, dass das aud des projizierten Tokens nicht mit der Regel übereinstimmt (projiziere ein Token mit audience: https://api.anthropic.com, nicht das IRSA-Standard-Token mit sts.amazonaws.com).
Ein subject_prefix von arn:aws:iam::123456789012:role/* matcht jede IAM-Rolle im Konto. Jeder Principal, der eine beliebige passende Rolle übernehmen kann, kann ein föderiertes Anthropic-Token erhalten.
Beschränke den match-Block der Regel auf den engsten Bereich, der zu deinem Anwendungsfall passt:
subject_prefix: "arn:aws:iam::<account>:role/<role-name>" ohne abschließendes *, damit andere Rollen im Konto nicht matchen.aws_account des https://sts.amazonaws.com/-Claims des Tokens mit der claims-Map oder einer CEL-condition als zusätzliche Absicherung (Defense-in-Depth) gegen ein falsch konfiguriertes Präfix.system:serviceaccount:<namespace>:<name> ohne * nach dem Präfix system:serviceaccount:.Was this page helpful?