用一个订阅安全接入多套环境:Claude Platform on AWS 权限架构实践

2026-10-02 28 预计阅读时间: 1 分钟
来源: aws.amazon.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

当开发、测试、生产以及 AWS 之外的流水线都要访问 Claude Platform 时,最危险的做法是让它们共享同一把长期 API Key。更稳妥的设计是:在独立的 AI Services AWS 账户中集中订阅和治理 Claude,再通过工作区隔离资源,并根据调用方类型选择跨账户 SigV4、工作区 API Key 或 OIDC 联邦身份。

这套架构的关键不是“所有环境使用同一种认证”,而是“所有环境进入同一个治理边界,但各自使用最合适的身份”。

一个订阅,不等于一个安全边界

可以把 Claude 接入划分为两层:

  • 账户层:建立专用的 AI Services AWS 账户,集中管理订阅、角色、审计和成本。
  • 工作区层:为 development、staging、production 等环境创建独立工作区,分别配置成员、API Key、配额和使用策略。

调用关系可以设计为:

开发者电脑 ---------------- API Key ----------> Development Workspace
应用开发账户 -- AssumeRole + SigV4 ----------> Development Workspace
应用生产账户 -- AssumeRole + SigV4 ----------> Production Workspace
外部 CI/CD -------- OIDC + 临时凭证 ---------> 指定 Workspace
                                      |
                              AI Services Account
                              单一订阅与集中治理

这种设计保留了集中采购和管理的便利,同时避免测试流量、生产权限和开发者凭证混在一起。工作区应该被视为真正的权限与配额边界,而不只是用于展示的标签。

建议至少做到:

调用方 推荐认证 凭证寿命 隔离方式
AWS 应用负载 跨账户 AssumeRole + SigV4 临时 IAM Role + Workspace
本地开发者 工作区级 API Key 可轮换的长期凭证 Workspace + 个人或团队 Key
外部 CI/CD 或云平台 OIDC 联邦 临时 OIDC aud/sub 条件 + Role

AWS 工作负载:跨账户角色配合 SigV4

对于运行在 ECS、EKS、EC2 或 Lambda 上的服务,不要把 API Key写进 Secrets Manager 后让所有应用共享。可以让工作负载先承担 AI Services 账户中的角色,再使用临时凭证对请求执行 SigV4 签名。

下面是一份可改造的角色信任策略。它应配置在 AI Services 账户中的环境角色上。运行前请替换账户 ID 和角色名;生产环境应只信任明确的工作负载角色,而不是整个来源账户。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:role/orders-production"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "orders-production-claude"
        }
      }
    }
  ]
}

来源账户中的 orders-production 角色还需要拥有针对目标角色的 sts:AssumeRole 权限:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::444455556666:role/claude-production-access"
    }
  ]
}

下面的 Python 示例会承担跨账户角色,然后发送一条 SigV4 签名请求。由于实际签名服务名、区域、端点和授权策略取决于 Claude Platform 的账户配置,运行前必须根据平台文档设置四个环境变量。

python -m venv .venv
source .venv/bin/activate
pip install boto3 requests

export CLAUDE_ROLE_ARN="arn:aws:iam::444455556666:role/claude-production-access"
export CLAUDE_EXTERNAL_ID="orders-production-claude"
export CLAUDE_API_URL="https://YOUR_CLAUDE_ENDPOINT/v1/messages"
export CLAUDE_SIGV4_SERVICE="YOUR_SIGNING_SERVICE"
export AWS_REGION="us-east-1"
export CLAUDE_MODEL="YOUR_ENABLED_MODEL_ID"
python sigv4_claude.py

将以下内容保存为 sigv4_claude.py:

import json
import os

import boto3
import requests
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials

required = [
    "CLAUDE_ROLE_ARN",
    "CLAUDE_API_URL",
    "CLAUDE_SIGV4_SERVICE",
    "AWS_REGION",
    "CLAUDE_MODEL",
]
missing = [name for name in required if not os.getenv(name)]
if missing:
    raise SystemExit(f"Missing environment variables: {', '.join(missing)}")

sts = boto3.client("sts", region_name=os.environ["AWS_REGION"])
assume_args = {
    "RoleArn": os.environ["CLAUDE_ROLE_ARN"],
    "RoleSessionName": "claude-example",
}
if os.getenv("CLAUDE_EXTERNAL_ID"):
    assume_args["ExternalId"] = os.environ["CLAUDE_EXTERNAL_ID"]

result = sts.assume_role(**assume_args)["Credentials"]
credentials = Credentials(
    result["AccessKeyId"],
    result["SecretAccessKey"],
    result["SessionToken"],
)

payload = json.dumps({
    "model": os.environ["CLAUDE_MODEL"],
    "max_tokens": 128,
    "messages": [
        {"role": "user", "content": "Return the current environment name."}
    ],
})
headers = {
    "content-type": "application/json",
    "anthropic-version": "2023-06-01",
}

request = AWSRequest(
    method="POST",
    url=os.environ["CLAUDE_API_URL"],
    data=payload,
    headers=headers,
)
SigV4Auth(
    credentials,
    os.environ["CLAUDE_SIGV4_SERVICE"],
    os.environ["AWS_REGION"],
).add_auth(request)

response = requests.post(
    os.environ["CLAUDE_API_URL"],
    data=payload,
    headers=dict(request.headers.items()),
    timeout=60,
)
response.raise_for_status()
print(json.dumps(response.json(), ensure_ascii=False, indent=2))

目标角色本身仍需绑定 Claude Platform 所要求的最小权限,并限制到对应工作区。不要因为签名已经使用临时凭证,就给角色附加管理员权限;SigV4 解决的是身份验证,资源授权仍需单独收紧。

开发者与外部环境:分别使用 API Key 和 OIDC

本地开发通常不适合要求工程师手工维护 AWS 临时凭证。可以为开发工作区创建独立 API Key,并限制它只能访问开发资源。Key 应按人员或团队发放,避免整个部门共用一个值。

以下命令可用于验证工作区 API Key。请把模型 ID替换为该工作区已启用的模型,并避免把 Key 写入 shell 历史或提交到 .env 文件:

read -s -p "Claude API key: " ANTHROPIC_API_KEY
export ANTHROPIC_API_KEY
echo

export CLAUDE_MODEL="YOUR_ENABLED_MODEL_ID"

curl https://api.anthropic.com/v1/messages \
  --fail-with-body \
  --header "x-api-key: ${ANTHROPIC_API_KEY}" \
  --header "anthropic-version: 2023-06-01" \
  --header "content-type: application/json" \
  --data "{
    \"model\": \"${CLAUDE_MODEL}\",
    \"max_tokens\": 128,
    \"messages\": [
      {\"role\": \"user\", \"content\": \"Summarize this test request in one sentence.\"}
    ]
  }"

对于 GitHub Actions、其他云平台或企业 CI/CD,优先使用 OIDC 换取短期 AWS 凭证,而不是保存 Access Key。下面以 GitHub Actions 为例,目标角色位于 AI Services 账户中,并且只允许指定仓库的 production Environment:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::444455556666:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
          "token.actions.githubusercontent.com:sub": "repo:acme/orders:environment:production"
        }
      }
    }
  ]
}

对应的工作流片段如下:

name: claude-production-check
on:
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

jobs:
  call-claude:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::444455556666:role/claude-production-oidc
          aws-region: us-east-1

      - name: Call Claude with SigV4
        env:
          CLAUDE_API_URL: https://YOUR_CLAUDE_ENDPOINT/v1/messages
          CLAUDE_SIGV4_SERVICE: YOUR_SIGNING_SERVICE
          AWS_REGION: us-east-1
          CLAUDE_MODEL: YOUR_ENABLED_MODEL_ID
        run: |
          python -m pip install boto3 requests
          python sigv4_claude.py

如果 OIDC 角色已经是最终调用角色,可让脚本直接使用环境中的 AWS 凭证,而不必再次 AssumeRole。也可以保留第二跳角色,但要明确记录信任链,避免故障排查时分不清是哪一层拒绝了请求。

上线前检查:把环境边界落实到权限和运维

这套方案适合逐步落地,而不必一次迁移所有调用方:

  1. 先建工作区边界:开发、测试、生产分别使用工作区,不以请求参数代替隔离。
  2. 再迁移 AWS 工作负载:为每个环境创建独立角色,采用 SigV4 和短期凭证。
  3. 收紧开发者 Key:按工作区、人员或团队发放,建立轮换和吊销流程。
  4. 外部系统改用 OIDC:限制 issuer、aud、sub、仓库、分支或部署环境。
  5. 验证双向权限:既检查谁能承担角色,也检查该角色能访问哪个工作区。
  6. 分别设置配额与告警:防止开发压测耗尽生产容量或预算。
  7. 记录环境标识:在角色会话名、应用日志和请求元数据中保留调用来源,但不要记录提示词中的敏感内容或完整凭证。
  8. 准备紧急撤销路径:能够快速禁用某个 Key、OIDC Role 或跨账户信任,而不影响其他环境。

最终目标不是消灭所有长期凭证,而是把它们限制在确实需要的开发场景;机器到机器的访问则尽量使用短期身份。单一订阅负责集中治理,工作区负责资源隔离,IAM 与 OIDC 负责证明“谁正在调用”。这三层边界清楚之后,多环境接入才不会演变成一张无法审计的共享密钥网络。


相关推荐