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 consiste à appeler 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 nécessite 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.
aws ou un SDK AWS disponible dans la charge de travail.L'API AWS STS GetWebIdentityToken renvoie un jeton OIDC signé par AWS qui atteste de 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.
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 avec OutboundWebIdentityFederationDisabledException.
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, instance EC2 ou 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 avec une valeur de la forme https://<uuid>.tokens.sts.global.api.aws. Cette URL est unique à 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())"Suivez le guide de configuration pour enregistrer un émetteur de fédération, créer un compte de service Anthropic et créer une règle de fédération dans la Claude Console. Utilisez ces valeurs spécifiques à STS.
É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_source": "discovery"
}Règle de fédération : Faites correspondre l'audience que vous passez à 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 passés ; vous pouvez faire correspondre ces éléments avec la map 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 spécifique 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.
Appelez GetWebIdentityToken avec https://api.anthropic.com comme audience, puis passez le résultat aux identifiants de fédération du SDK. Le fournisseur de jeton est un callable, de sorte que le SDK réinvoque STS à chaque actualisation.
GetWebIdentityToken n'est disponible que sur les points de terminaison STS régionaux. Si vous recevez 'STS' object has no attribute 'get_web_identity_token' ou une erreur similaire, fixez votre client STS à une région (par exemple, boto3.client("sts", region_name="us-east-1")) et assurez-vous que votre SDK AWS est suffisamment récent pour inclure l'API.
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)Depuis l'intérieur de la charge de travail, échangez directement un jeton émis par STS et inspectez 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. En cas de 400 invalid_grant, consultez Dépanner un échange échoué ; la cause la plus courante côté AWS est une incompatibilité de iss (l'URL de l'émetteur STS propre au compte doit correspondre exactement à l'issuer_url enregistrée).
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, donc aucun callable fournisseur de jeton n'est requis. 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.
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 :
aws 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-arn et projette automatiquement un jeton avec aud: sts.amazonaws.com, exposant son chemin sous AWS_WEB_IDENTITY_TOKEN_FILE. Ce jeton sert à l'assomption de rôle AWS. Pour l'échange Anthropic, projetez un second jeton avec audience: https://api.anthropic.com et 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 sub suit la convention Kubernetes 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
}La projection serviceAccountToken définit aud sur https://api.anthropic.com. Le jeton distinct injecté par IRSA à AWS_WEB_IDENTITY_TOKEN_FILE porte aud: sts.amazonaws.com et sert aux appels d'API AWS, pas à cet échange.
Suivez le guide de configuration pour enregistrer un émetteur de fédération, créer un compte de service Anthropic et créer une règle de fédération dans la Claude Console. Utilisez ces valeurs spécifiques à EKS.
É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_source": "discovery"
}Règle de fédération : Faites correspondre la revendication Kubernetes sub 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 spécifique que la charge de travail le permet. N'assouplissez subject_prefix à system:serviceaccount:inference:* (le * final en fait une correspondance de préfixe) que si chaque compte de service du namespace doit correspondre au même compte de service Anthropic.
À 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). Passez 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-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from EKS"}],
)
print(message.content[0].text)La spécification du Pod définit déjà ANTHROPIC_IDENTITY_TOKEN_FILE, ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et ANTHROPIC_WORKSPACE_ID, vous pouvez donc construire le client sans arguments et le SDK lit automatiquement les variables d'environnement de fédération.
Depuis l'intérieur du pod, échangez directement le jeton projeté et inspectez 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. En cas de 400 invalid_grant, consultez Dépanner un échange échoué ; la cause la plus courante 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 le sts.amazonaws.com par défaut d'IRSA).
Un subject_prefix de arn:aws:iam::123456789012:role/* correspond à tous les rôles IAM du compte. Tout principal capable d'assumer n'importe quel rôle correspondant peut obtenir un jeton Anthropic fédéré.
Verrouillez le bloc match de la règle à la portée la plus étroite qui convient à votre cas d'usage :
subject_prefix: "arn:aws:iam::<account>:role/<role-name>" sans * final afin que les autres rôles du compte ne correspondent pas.aws_account de la revendication https://sts.amazonaws.com/ du jeton via la map claims ou une condition CEL comme vérification de défense en profondeur contre un préfixe mal configuré.system:serviceaccount:<namespace>:<name> sans * après le préfixe system:serviceaccount:.Was this page helpful?