Utiliser WIF avec AWS
Authentifiez les charges de travail AWS sur Lambda, EC2, ECS ou EKS auprès de l'API Claude avec Workload Identity Federation et des jetons d'identité émis par STS.
Les charges de travail AWS peuvent s'authentifier auprès de l'API Claude sans clés API statiques en échangeant un jeton d'identité OIDC signé par AWS. La méthode recommandée appelle l'API AWS STS GetWebIdentityToken, qui fonctionne partout où la charge de travail dispose d'identifiants AWS : Lambda, EC2, ECS et EKS. Les charges de travail EKS peuvent également utiliser la méthode du jeton projeté Kubernetes, qui comporte moins d'étapes de configuration mais ne fonctionne qu'à l'intérieur d'un pod.
Ce guide présente les deux méthodes. Pour les concepts sous-jacents (comptes de service, émetteurs de fédération et règles de fédération), consultez Workload Identity Federation.
Prérequis
- Une familiarité avec les concepts WIF : comptes de service, émetteurs de fédération et règles de fédération.
- Une charge de travail AWS (pod EKS, tâche ECS, fonction Lambda ou instance EC2) avec un rôle IAM attaché.
- La CLI
awsou un SDK AWS disponible dans la charge de travail. - L'autorisation de créer des comptes de service, des émetteurs de fédération et des règles de fédération dans la Claude Console pour votre organisation Anthropic.
Utiliser les jetons d'identité web STS (recommandé)
L'API AWS STS GetWebIdentityToken renvoie un jeton OIDC signé par AWS qui atteste l'identité IAM de l'appelant. Comme elle utilise les identifiants AWS ambiants de la charge de travail, la même intégration couvre Lambda, EC2, ECS et EKS.
Configurer AWS
Activer la fédération d'identité web sortante pour le compte
Il s'agit d'un indicateur au niveau du compte, désactivé par défaut. Dans la console AWS, ouvrez IAM, choisissez Account settings et activez Outbound web identity federation. Pour l'activer par programmation :
python3 -c "import boto3; boto3.client('iam').enable_outbound_web_identity_federation()"Si cette option n'est pas activée, les appels à
GetWebIdentityTokenéchouent avecOutboundWebIdentityFederationDisabledException.Accorder au rôle IAM de la charge de travail l'autorisation d'appeler l'API
Attachez cette politique au rôle IAM sous lequel s'exécute votre fonction Lambda, votre instance EC2 ou votre tâche ECS :
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["sts:GetWebIdentityToken"], "Resource": "*" } ] }Trouver l'URL de l'émetteur STS de votre compte
Après avoir activé la fédération sortante, la page IAM > Account settings affiche un champ Get Token Issuer URL dont la valeur a la forme
https://<uuid>.tokens.sts.global.api.aws. Cette URL est propre à votre compte AWS ; copiez-la pour l'étape suivante. Pour la récupérer par programmation :python3 -c "import boto3; print(boto3.client('iam').get_outbound_web_identity_federation_info())"
Configurer Anthropic
Dans la Claude Console, ouvrez Settings → Workload identity, cliquez sur Connect workload et sélectionnez la tuile AWS. L'assistant vous guide dans l'enregistrement de l'émetteur, la création d'un compte de service et la création d'une règle de fédération.
L'assistant crée ces ressources pour vous. Utilisez les valeurs suivantes, que vous les saisissiez dans l'assistant ou que vous les envoyiez à l'Admin API :
Émetteur de fédération : enregistrez l'URL de l'émetteur STS propre au compte que vous avez copiée à l'étape précédente. Elle expose un point de terminaison JWKS public, utilisez donc le mode découverte.
{
"name": "aws-sts",
"issuer_url": "https://<uuid>.tokens.sts.global.api.aws",
"jwks": { "type": "discovery" }
}Règle de fédération : faites correspondre l'audience que vous transmettez à GetWebIdentityToken et l'ARN du rôle IAM appelant dans la revendication sub. La valeur sub est l'ARN du rôle IAM de la charge de travail qui a appelé l'API, sous la forme arn:aws:iam::<account>:role/<role-name>. Le jeton contient également une revendication https://sts.amazonaws.com/ avec aws_account, org_id, principal_id et tous les request_tags que vous avez transmis ; vous pouvez établir une correspondance sur ceux-ci avec la table claims de la règle ou une condition CEL pour un contrôle plus fin.
{
"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
}Soyez aussi précis que la charge de travail le permet. Faites correspondre l'ARN exact du rôle et n'élargissez subject_prefix (par exemple, à arn:aws:iam::123456789012:role/*) que si plusieurs rôles IAM doivent correspondre au même compte de service Anthropic.
Obtenir et utiliser le jeton
Appelez GetWebIdentityToken avec https://api.anthropic.com comme audience, puis transmettez le résultat aux identifiants de fédération du SDK. Le fournisseur de jeton est un objet appelable, de sorte que le SDK réinvoque STS à chaque actualisation.
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-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from AWS"}],
)
print(next(block.text for block in message.content if block.type == "text"))Vérifier la configuration
Depuis l'intérieur de la charge de travail, échangez directement un jeton émis par STS et examinez la réponse :
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_...\"
}" | jqUn échange réussi renvoie un access_token commençant par sk-ant-oat01- et une valeur expires_in en secondes. Si l'échange échoue avec la réponse opaque 401 authentication_error (message Authentication failed), consultez la page d'historique d'authentification pour connaître le motif du refus et reportez-vous à Dépanner un échange en échec ; la cause la plus fréquente côté AWS est une non-correspondance de iss (l'URL de l'émetteur STS propre au compte doit correspondre exactement à l'issuer_url enregistrée).
Utiliser les jetons de compte de service projetés EKS
Si votre charge de travail s'exécute dans un pod EKS, vous pouvez ignorer l'appel STS et lire directement depuis le disque un jeton de compte de service projeté par Kubernetes. Kubernetes projette nativement un jeton compatible OIDC dans le pod, et le SDK peut le lire à partir d'un chemin de fichier, de sorte qu'aucun fournisseur de jeton appelable n'est nécessaire. Cette méthode comporte deux étapes de configuration AWS de moins que la méthode STS mais ne fonctionne qu'à l'intérieur d'un pod ; le mécanisme sous-jacent est le même que celui de l'intégration Kubernetes générique.
Cette méthode nécessite en outre un cluster EKS avec un fournisseur OIDC IAM activé et un accès kubectl au cluster.
Configurer votre cluster EKS
Trouver l'URL de l'émetteur OIDC de votre cluster
Chaque cluster EKS possède un émetteur OIDC unique. Récupérez-le avec la CLI AWS :
CLIaws eks describe-cluster \ --name <cluster-name> \ --query "cluster.identity.oidc.issuer" \ --output textLa sortie ressemble à
https://oidc.eks.us-west-2.amazonaws.com/id/6FA42E7BFDE8549CB.... Vous enregistrerez cette URL comme émetteur de fédération dans la section suivante.Créer le compte de service et projeter un jeton avec l'audience Anthropic
Le webhook d'identité de pod EKS détecte l'annotation
eks.amazonaws.com/role-arnet projette automatiquement un jeton avecaud: sts.amazonaws.com, en exposant son chemin sousAWS_WEB_IDENTITY_TOKEN_FILE. Ce jeton sert à l'endossement de rôle AWS. Pour l'échange Anthropic, projetez un second jeton avecaudience: https://api.anthropic.comet montez-le à un chemin dédié.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: trueNoter la forme des revendications du jeton
Le jeton projeté est un « JSON Web Token » (jeton web JSON), ou JWT, signé par l'émetteur OIDC de votre cluster. Sa revendication
subsuit la convention Kubernetessystem: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 }La projection
serviceAccountTokendéfinitaudsurhttps://api.anthropic.com. Le jeton distinct injecté par IRSA à l'emplacementAWS_WEB_IDENTITY_TOKEN_FILEporteaud: sts.amazonaws.comet sert aux appels d'API AWS, pas à cet échange.
Configurer Anthropic
Dans la Claude Console, ouvrez Settings → Workload identity, cliquez sur Connect workload et sélectionnez la tuile AWS. L'assistant vous guide dans l'enregistrement de l'émetteur, la création d'un compte de service et la création d'une règle de fédération.
L'assistant crée ces ressources pour vous. Utilisez les valeurs suivantes, que vous les saisissiez dans l'assistant ou que vous les envoyiez à l'Admin API :
Émetteur de fédération : les émetteurs EKS exposent un point de terminaison JWKS public, utilisez donc le mode découverte. L'URL de l'émetteur doit correspondre exactement à la revendication iss du jeton. Enregistrez un émetteur par cluster.
{
"name": "prod-eks-uswest2",
"issuer_url": "https://oidc.eks.us-west-2.amazonaws.com/id/6FA42E7BFDE8549CB...",
"jwks": { "type": "discovery" }
}Règle de fédération : faites correspondre la revendication sub Kubernetes et l'audience Anthropic https://api.anthropic.com. (Projetez un jeton de compte de service dédié avec cette audience ; ne réutilisez pas le jeton IRSA par défaut sts.amazonaws.com.)
{
"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
}Soyez aussi précis que la charge de travail le permet. N'assouplissez subject_prefix en system:serviceaccount:inference:* (le * final en fait une correspondance par préfixe) que si chaque compte de service de l'espace de noms doit correspondre au même compte de service Anthropic.
Obtenir et utiliser le jeton
À l'intérieur du pod, le jeton projeté se trouve à /var/run/secrets/anthropic.com/token (exposé sous ANTHROPIC_IDENTITY_TOKEN_FILE dans la spécification du Pod). Transmettez ce fichier aux identifiants de fédération du SDK et le SDK gère l'échange et l'actualisation.
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-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from EKS"}],
)
print(next(block.text for block in message.content if block.type == "text"))Vérifier la configuration
Depuis l'intérieur du pod, échangez directement le jeton projeté et examinez la réponse :
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\"
}" | jqUn échange réussi renvoie un access_token commençant par sk-ant-oat01- et une valeur expires_in en secondes. Si l'échange échoue avec la réponse opaque 401 authentication_error (message Authentication failed), consultez la page d'historique d'authentification pour connaître le motif du refus et reportez-vous à Dépanner un échange en échec ; la cause la plus fréquente côté EKS est que l'aud du jeton projeté ne correspond pas à la règle (projetez un jeton avec audience: https://api.anthropic.com, et non la valeur IRSA par défaut sts.amazonaws.com).
Délimiter votre règle
Verrouillez le bloc match de la règle sur la portée la plus étroite qui convient à votre cas d'utilisation :
- Fixer l'ARN complet du rôle : utilisez
subject_prefix: "arn:aws:iam::<account>:role/<role-name>"sans*final afin que les autres rôles du compte ne correspondent pas. - Fixer l'ID du compte : faites correspondre le champ
aws_accountde la revendicationhttps://sts.amazonaws.com/du jeton avec la tableclaimsou uneconditionCEL comme vérification de défense en profondeur contre un préfixe mal configuré. - Fixer l'espace de noms et le compte de service sur EKS : utilisez la valeur exacte
system:serviceaccount:<namespace>:<name>sans*après le préfixesystem:serviceaccount:. - Utiliser une règle distincte par environnement : créez des règles distinctes pour les charges de travail de production, de préproduction et de développement plutôt que d'élargir un seul préfixe pour toutes les couvrir.
Étapes suivantes
- Consultez la référence WIF pour la référence complète sur l'ordre de priorité des identifiants, la configuration des profils et la correspondance des règles.
- Pour les clusters Kubernetes autogérés qui ne sont pas sur EKS, consultez Utiliser WIF avec Kubernetes.
Was this page helpful?