Claude Platform Docs
管理身份提供商

在 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 实例)。
  • 工作负载中可用的 aws CLI 或 AWS SDK。
  • 在 Claude Console 中为您的 Anthropic 组织创建服务账户、联合签发者和联合规则的权限。

AWS STS GetWebIdentityToken API 返回一个由 AWS 签名的 OIDC 令牌,用于断言调用者的 IAM 身份。由于它使用工作负载的环境 AWS 凭证,因此同一集成可覆盖 Lambda、EC2、ECS 和 EKS。

配置 AWS

  1. 为账户启用出站 Web 身份联合

    这是一个账户级别的标志,默认关闭。在 AWS 控制台中,打开 IAM,选择 Account settings,然后启用 Outbound web identity federation。要以编程方式启用它:

    python3 -c "import boto3; boto3.client('iam').enable_outbound_web_identity_federation()"

    如果未启用此功能,对 GetWebIdentityToken 的调用将失败并返回 OutboundWebIdentityFederationDisabledException

  2. 授予工作负载的 IAM 角色调用该 API 的权限

    将此策略附加到您的 Lambda 函数、EC2 实例或 ECS 任务所使用的 IAM 角色:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["sts:GetWebIdentityToken"],
          "Resource": "*"
        }
      ]
    }
  3. 查找您账户的 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_accountorg_idprincipal_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 签发的令牌并检查响应:

cURL
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 集群

  1. 查找您集群的 OIDC 签发者 URL

    每个 EKS 集群都有一个唯一的 OIDC 签发者。使用 AWS CLI 获取它:

    CLI
    aws eks describe-cluster \
      --name <cluster-name> \
      --query "cluster.identity.oidc.issuer" \
      --output text

    输出类似于 https://oidc.eks.us-west-2.amazonaws.com/id/6FA42E7BFDE8549CB...。您将在下一节中将此 URL 注册为联合签发者。

  2. 创建服务账户并投射一个 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-worker
    apiVersion: 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
  3. 注意令牌的声明结构

    投射的令牌是由您集群的 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 内部,直接交换投射的令牌并检查响应:

cURL
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 映射或 CEL condition 匹配令牌 https://sts.amazonaws.com/ 声明中的 aws_account 字段,作为针对前缀配置错误的纵深防御检查。
  • 在 EKS 上固定命名空间和服务账户: 使用确切的 system:serviceaccount:<namespace>:<name> 值,在 system:serviceaccount: 前缀之后不带 *
  • 为每个环境使用单独的规则: 为生产、预发布和开发工作负载创建不同的规则,而不是放宽一个前缀来覆盖所有环境。

后续步骤

  • 查看 WIF 参考,了解完整的凭证优先级、配置文件配置和规则匹配参考。
  • 对于不在 EKS 上的自管理 Kubernetes 集群,请参阅在 Kubernetes 上使用 WIF

Was this page helpful?