在 AWS 上使用 WIF
使用 Workload Identity Federation 和 STS 签发的身份令牌,将 Lambda、EC2、ECS 或 EKS 上的 AWS 工作负载认证到 Claude API。
AWS 工作负载可以通过交换 AWS 签名的 OIDC 身份令牌来向 Claude API 进行身份认证,而无需使用静态 API 密钥。推荐的路径是调用 AWS STS GetWebIdentityToken API,该 API 在工作负载拥有 AWS 凭证的任何地方都可以使用:Lambda、EC2、ECS 和 EKS。EKS 工作负载也可以选择使用 Kubernetes 投射令牌路径,该路径配置步骤更少,但只能在 pod 内部使用。
本指南展示了这两种路径。有关底层概念(服务账户、联合签发者和联合规则),请参阅 Workload Identity Federation。
前提条件
- 熟悉 WIF 概念:服务账户(service accounts)、联合签发者(federation issuers)和联合规则(federation rules)。
- 一个附加了 IAM 角色的 AWS 工作负载(EKS pod、ECS 任务、Lambda 函数或 EC2 实例)。
- 工作负载中可用的
awsCLI 或 AWS SDK。 - 在 Claude Console 中为您的 Anthropic 组织创建服务账户、联合签发者和联合规则的权限。
使用 STS Web 身份令牌(推荐)
AWS STS GetWebIdentityToken API 返回一个由 AWS 签名的 OIDC 令牌,用于断言调用者的 IAM 身份。由于它使用工作负载的环境 AWS 凭证,因此同一集成可覆盖 Lambda、EC2、ECS 和 EKS。
配置 AWS
为账户启用出站 Web 身份联合
这是一个账户级别的标志,默认关闭。在 AWS 控制台中,打开 IAM,选择 Account settings,然后启用 Outbound web identity federation。要以编程方式启用它:
python3 -c "import boto3; boto3.client('iam').enable_outbound_web_identity_federation()"如果未启用此功能,对
GetWebIdentityToken的调用将失败并返回OutboundWebIdentityFederationDisabledException。授予工作负载的 IAM 角色调用该 API 的权限
将此策略附加到您的 Lambda 函数、EC2 实例或 ECS 任务所使用的 IAM 角色:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["sts:GetWebIdentityToken"], "Resource": "*" } ] }查找您账户的 STS 签发者 URL
启用出站联合后,IAM > Account settings 页面会显示一个 Get Token Issuer URL 字段,其值的形式为
https://<uuid>.tokens.sts.global.api.aws。此 URL 对您的 AWS 账户是唯一的;请复制它以供下一步使用。要以编程方式获取它:python3 -c "import boto3; print(boto3.client('iam').get_outbound_web_identity_federation_info())"
配置 Anthropic
在 Claude Console 中,打开 Settings → Workload identity,点击 Connect workload,然后选择 AWS 磁贴。向导将引导您完成注册签发者、创建服务账户和创建联合规则的过程。
向导会为您创建这些资源。无论您是在向导中输入这些值,还是将它们发送到 Admin API,都请使用以下值:
联合签发者: 注册您在上一步中复制的每账户 STS 签发者 URL。它公开了一个公共 JWKS 端点,因此请使用发现模式(discovery mode)。
{
"name": "aws-sts",
"issuer_url": "https://<uuid>.tokens.sts.global.api.aws",
"jwks": { "type": "discovery" }
}联合规则: 匹配您传递给 GetWebIdentityToken 的受众(audience)以及 sub 声明中调用角色的 IAM 角色 ARN。sub 值是调用该 API 的工作负载的 IAM 角色 ARN,形式为 arn:aws:iam::<account>:role/<role-name>。该令牌还携带一个 https://sts.amazonaws.com/ 声明,其中包含 aws_account、org_id、principal_id 以及您传递的任何 request_tags;您可以使用规则的 claims 映射或 CEL condition 对这些内容进行匹配,以实现更精细的控制。
{
"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
}请在工作负载允许的范围内尽可能具体。匹配确切的角色 ARN,并且仅当多个 IAM 角色应映射到同一个 Anthropic 服务账户时,才放宽 subject_prefix(例如,放宽为 arn:aws:iam::123456789012:role/*)。
获取并使用令牌
以 https://api.anthropic.com 作为受众调用 GetWebIdentityToken,然后将结果传递给 SDK 的联合凭证。令牌提供者是一个可调用对象,因此 SDK 会在每次刷新时重新调用 STS。
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"))验证设置
在工作负载内部,直接交换 STS 签发的令牌并检查响应:
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_...\"
}" | jq成功的交换会返回一个以 sk-ant-oat01- 开头的 access_token 和一个以秒为单位的 expires_in 值。如果交换失败并返回不透明的 401 authentication_error 响应(消息为 Authentication failed),请查看认证历史页面以了解拒绝原因,并参阅排查失败的交换;AWS 端最常见的原因是 iss 不匹配(每账户 STS 签发者 URL 必须与注册的 issuer_url 完全匹配)。
使用 EKS 投射服务账户令牌
如果您的工作负载运行在 EKS pod 中,您可以跳过 STS 调用,直接从磁盘读取 Kubernetes 投射的服务账户令牌。Kubernetes 原生地将一个兼容 OIDC 的令牌投射到 pod 中,SDK 可以从文件路径读取它,因此不需要令牌提供者可调用对象。与 STS 路径相比,此路径少了两个 AWS 配置步骤,但只能在 pod 内部使用;其底层机制与通用 Kubernetes 集成相同。
此路径还需要一个启用了 IAM OIDC 提供者的 EKS 集群,以及对该集群的 kubectl 访问权限。
配置您的 EKS 集群
查找您集群的 OIDC 签发者 URL
每个 EKS 集群都有一个唯一的 OIDC 签发者。使用 AWS CLI 获取它:
CLIaws eks describe-cluster \ --name <cluster-name> \ --query "cluster.identity.oidc.issuer" \ --output text输出类似于
https://oidc.eks.us-west-2.amazonaws.com/id/6FA42E7BFDE8549CB...。您将在下一节中将此 URL 注册为联合签发者。创建服务账户并投射一个 Anthropic 受众令牌
EKS pod 身份 webhook 会检测
eks.amazonaws.com/role-arn注解,并自动投射一个aud: sts.amazonaws.com的令牌,将其路径公开为AWS_WEB_IDENTITY_TOKEN_FILE。该令牌用于 AWS 角色代入。对于 Anthropic 交换,请投射第二个audience: https://api.anthropic.com的令牌,并将其挂载到专用路径。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: true注意令牌的声明结构
投射的令牌是由您集群的 OIDC 签发者签名的 JSON Web Token(JWT)。其
sub声明遵循 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 }serviceAccountToken投射将aud设置为https://api.anthropic.com。位于AWS_WEB_IDENTITY_TOKEN_FILE的另一个由 IRSA 注入的令牌携带aud: sts.amazonaws.com,用于 AWS API 调用,而非此交换。
配置 Anthropic
在 Claude Console 中,打开 Settings → Workload identity,点击 Connect workload,然后选择 AWS 磁贴。向导将引导您完成注册签发者、创建服务账户和创建联合规则的过程。
向导会为您创建这些资源。无论您是在向导中输入这些值,还是将它们发送到 Admin API,都请使用以下值:
联合签发者: EKS 签发者公开了一个公共 JWKS 端点,因此请使用发现模式。签发者 URL 必须与令牌的 iss 声明完全匹配。每个集群注册一个签发者。
{
"name": "prod-eks-uswest2",
"issuer_url": "https://oidc.eks.us-west-2.amazonaws.com/id/6FA42E7BFDE8549CB...",
"jwks": { "type": "discovery" }
}联合规则: 匹配 Kubernetes sub 声明和 Anthropic 受众 https://api.anthropic.com。(请投射一个具有该受众的专用服务账户令牌;不要重用 IRSA 默认的 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
}请在工作负载允许的范围内尽可能具体。仅当命名空间中的每个服务账户都应映射到同一个 Anthropic 服务账户时,才将 subject_prefix 放宽为 system:serviceaccount:inference:*(末尾的 * 使其成为前缀匹配)。
获取并使用令牌
在 pod 内部,投射的令牌位于 /var/run/secrets/anthropic.com/token(在 Pod 规范中公开为 ANTHROPIC_IDENTITY_TOKEN_FILE)。将该文件传递给 SDK 的联合凭证,SDK 会处理交换和刷新。
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"))验证设置
在 pod 内部,直接交换投射的令牌并检查响应:
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\"
}" | jq成功的交换会返回一个以 sk-ant-oat01- 开头的 access_token 和一个以秒为单位的 expires_in 值。如果交换失败并返回不透明的 401 authentication_error 响应(消息为 Authentication failed),请查看认证历史页面以了解拒绝原因,并参阅排查失败的交换;EKS 端最常见的原因是投射令牌的 aud 与规则不匹配(请投射一个 audience: https://api.anthropic.com 的令牌,而不是 IRSA 默认的 sts.amazonaws.com)。
限定规则范围
将规则的 match 块锁定到适合您用例的最窄范围:
- 固定完整的角色 ARN: 使用
subject_prefix: "arn:aws:iam::<account>:role/<role-name>",末尾不带*,这样账户中的其他角色就不会匹配。 - 固定账户 ID: 使用
claims映射或 CELcondition匹配令牌https://sts.amazonaws.com/声明中的aws_account字段,作为针对前缀配置错误的纵深防御检查。 - 在 EKS 上固定命名空间和服务账户: 使用确切的
system:serviceaccount:<namespace>:<name>值,在system:serviceaccount:前缀之后不带*。 - 为每个环境使用单独的规则: 为生产、预发布和开发工作负载创建不同的规则,而不是放宽一个前缀来覆盖所有环境。
后续步骤
- 查看 WIF 参考,了解完整的凭证优先级、配置文件配置和规则匹配参考。
- 对于不在 EKS 上的自管理 Kubernetes 集群,请参阅在 Kubernetes 上使用 WIF。
Was this page helpful?