AWS 工作負載可以透過交換由 AWS 簽署的 OIDC 身分權杖,在不使用靜態 API 金鑰的情況下向 Claude API 進行驗證。建議的路徑是呼叫 AWS STS GetWebIdentityToken API,只要工作負載擁有 AWS 憑證,此方式在任何地方都適用:Lambda、EC2、ECS 和 EKS。EKS 工作負載也可以改用 Kubernetes 投射權杖路徑,其設定步驟較少,但僅能在 Pod 內運作。
本指南說明這兩種路徑。關於基礎概念(服務帳戶、聯合發行者和聯合規則),請參閱 Workload Identity Federation。
aws CLI 或 AWS SDK。AWS STS GetWebIdentityToken API 會回傳由 AWS 簽署的 OIDC 權杖,用以聲明呼叫者的 IAM 身分。由於它使用工作負載的環境 AWS 憑證,同一個整合方式即可涵蓋 Lambda、EC2、ECS 和 EKS。
為帳戶啟用對外 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())"在 Claude Console 中,開啟 Settings → Workload identity,點擊 Connect workload,然後選擇 AWS 圖塊。精靈會引導您完成註冊發行者、建立服務帳戶和建立聯合規則。
精靈會為您建立這些資源。無論您是在精靈中輸入這些值,還是將其傳送至 Admin API,請使用以下值:
聯合發行者: 註冊您在上一步複製的帳戶專屬 STS 發行者 URL。它會公開一個公用的 JWKS 端點,因此請使用探索模式。
{
"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 作為 audience 呼叫 GetWebIdentityToken,然後將結果傳遞給 SDK 的聯合憑證。權杖提供者是一個可呼叫物件,因此 SDK 會在每次重新整理時重新呼叫 STS。
GetWebIdentityToken 僅在區域性 STS 端點上可用。如果您收到 'STS' object has no attribute 'get_web_identity_token' 或類似的錯誤,請將您的 STS 用戶端固定到某個區域(例如 boto3.client("sts", region_name="us-east-1")),並確保您的 AWS SDK 版本夠新,已包含此 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-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 值。若出現 400 invalid_grant,請參閱疑難排解失敗的交換;AWS 端最常見的原因是 iss 不符(帳戶專屬的 STS 發行者 URL 必須與註冊的 issuer_url 完全相符)。
如果您的工作負載在 EKS Pod 中執行,您可以跳過 STS 呼叫,直接從磁碟讀取 Kubernetes 投射的服務帳戶權杖。Kubernetes 原生會將一個與 OIDC 相容的權杖投射到 Pod 中,而 SDK 可以從檔案路徑讀取它,因此不需要權杖提供者可呼叫物件。此路徑比 STS 路徑少兩個 AWS 設定步驟,但僅能在 Pod 內運作;其底層機制與通用 Kubernetes 整合相同。
此路徑另外需要一個已啟用 IAM OIDC 提供者的 EKS 叢集,以及對該叢集的 kubectl 存取權限。
找到您叢集的 OIDC 發行者 URL
每個 EKS 叢集都有一個唯一的 OIDC 發行者。使用 AWS 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 註冊為聯合發行者。
建立服務帳戶並投射一個以 Anthropic 為 audience 的權杖
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 呼叫,而非此交換。
在 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 audience https://api.anthropic.com。(請投射一個具有該 audience 的專用服務帳戶權杖;不要重複使用 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 規格已設定 ANTHROPIC_IDENTITY_TOKEN_FILE、ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID 和 ANTHROPIC_WORKSPACE_ID,因此您可以不帶任何引數建構用戶端,SDK 會自動讀取聯合環境變數。
在 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 值。若出現 400 invalid_grant,請參閱疑難排解失敗的交換;EKS 端最常見的原因是投射權杖的 aud 與規則不符(請投射 audience: https://api.anthropic.com 的權杖,而非 IRSA 預設的 sts.amazonaws.com)。
subject_prefix 為 arn:aws:iam::123456789012:role/* 會比對帳戶中的每個 IAM 角色。任何可以擔任任一相符角色的主體都可以取得聯合的 Anthropic 權杖。
將規則的 match 區塊鎖定到符合您使用情境的最窄範圍:
subject_prefix: "arn:aws:iam::<account>:role/<role-name>" 且結尾不加 *,這樣帳戶中的其他角色就不會相符。claims 對應表或 CEL condition 比對權杖的 https://sts.amazonaws.com/ 宣告中的 aws_account 欄位,作為防範前綴設定錯誤的縱深防禦檢查。system:serviceaccount:<namespace>:<name> 值,且在 system:serviceaccount: 前綴之後不加 *。Was this page helpful?