English
主导航

旧版 API

为 AWS 配置工作负载身份联合

在以下任一场景中将 AWS 用作工作负载身份提供商:

  • AWS 出站身份联合: 将 AWS STS 颁发的 OIDC JWT 从 GetWebIdentityToken 兑换为短期 OpenAI 访问令牌。
  • Amazon EKS: 将 Amazon EKS 投射的服务账户令牌兑换为短期 OpenAI 访问令牌。

OpenAI 支持来自出站身份联合的 AWS 颁发 OIDC JWT,以及由 Amazon EKS 颁发的 Kubernetes 投射服务账户令牌。OpenAI 不支持将 SigV4 签名请求或 AWS STS 临时访问密钥凭据作为工作负载身份联合主题令牌。

AWS 出站身份联合

AWS 出站身份联合允许 AWS 主体从 AWS STS 请求签名的 OIDC JWT,并将该令牌提供给外部服务。在 OpenAI 工作负载身份联合中,AWS 颁发的 JWT 是 OpenAI 在颁发 OpenAI 访问令牌之前验证的主题令牌。

设置 AWS 出站身份联合

为将要颁发令牌的 AWS 账户启用出站身份联合。有关设置详情,请参阅 AWS 指南: 出站身份联合入门.

aws iam enable-outbound-web-identity-federation

记录 AWS 返回的特定于账户的颁发者 URL。您需要将此值配置为 OpenAI 工作负载身份提供商的颁发者,并且它必须与 iss AWS 颁发令牌中的声明相匹配。

The AWS STS GetWebIdentityToken 该 API 在 STS 全局端点上不可用。请配置 AWS CLI 或 SDK 以使用区域 STS 端点。

授予工作负载调用权限,最大生命周期为 300 秒: sts:GetWebIdentityToken。请在 IAM 中限制受众和最大令牌生命周期,以便 AWS 主体只能生成专为 OpenAI 预期的令牌。此示例允许以下受众的令牌 https://api.openai.com/v1 请求一个与您将在 OpenAI 工作负载身份提供商上配置的受众相同的 AWS 颁发 OIDC 令牌。请使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:GetWebIdentityToken",
      "Resource": "*",
      "Condition": {
        "ForAllValues:StringEquals": {
          "sts:IdentityTokenAudience": "https://api.openai.com/v1"
        },
        "NumericLessThanEquals": {
          "sts:DurationSeconds": 300
        }
      }
    }
  ]
}

除非您的环境要求 ES384 验证 AWS 颁发的令牌 RS256 compatibility.

1
2
3
4
5
6
7
8
TOKEN=$(aws sts get-web-identity-token \
  --audience "https://api.openai.com/v1" \
  --signing-algorithm ES384 \
  --duration-seconds 300 \
  --tags Key=environment,Value=production \
         Key=workload,Value=batch-ingest \
  --query "WebIdentityToken" \
  --output text)

在配置工作负载身份联合之前,请在本地解码 AWS 颁发的样本令牌并检查其声明:

此命令在不验证令牌签名的情况下解码 JWT 负载。请在本地解码器中解码生产令牌,并避免将生产令牌粘贴到第三方工具中。

1
2
3
4
5
6
7
8
9
TOKEN="$TOKEN" python3 - <<'PY'
import base64
import json
import os

payload = os.environ["TOKEN"].split(".")[1]
payload += "=" * (-len(payload) % 4)
print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))
PY

解码后的 AWS 颁发 OIDC 令牌类似于:

并非每个 AWS 颁发的令牌都包含所有的 AWS 特定声明。位于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
  "iss": "https://abc123-def456-ghi789-jkl012.tokens.sts.global.api.aws",
  "aud": "https://api.openai.com/v1",
  "sub": "arn:aws:iam::123456789012:role/OpenAIWifRole",
  "iat": 1716235422,
  "exp": 1716235722,
  "jti": "jwt-id-example",
  "https://sts.amazonaws.com/": {
    "aws_account": "123456789012",
    "source_region": "us-west-2",
    "org_id": "o-exampleorgid",
    "principal_tags": {
      "environment": "production"
    },
    "request_tags": {
      "environment": "production",
      "workload": "batch-ingest"
    }
  }
}

下的声明取决于调用主体、会话上下文和请求标签。 https://sts.amazonaws.com/ 验证您计划在 OpenAI 中配置的声明:

受众以及 OpenAI 工作负载身份提供商的受众。

  • iss:必须与在 OpenAI 工作负载身份提供商中配置的特定 AWS 账户颁发者 URL 相匹配。
  • aud:必须与 GetWebIdentityToken AWS 特定声明:在匹配账户、组织、主体标签或请求标签值之前,请使用解码后的令牌作为事实来源。
  • sub:标识请求令牌的 IAM 主体 ARN。建议优先匹配精确的角色 ARN。
  • 使用解码后的负载将您收到的令牌与 OpenAI 中配置的颁发者、受众和映射值进行比较。大多数配置问题在您兑换令牌之前即可在

声明中显现。 iss, aud,且 sub 设置工作负载身份联合

在 OpenAI 中为 AWS 账户颁发者创建工作负载身份提供商,然后添加与 AWS 颁发令牌中的稳定声明相匹配的服务账户映射。

请先配置工作负载身份提供商,然后再创建服务账户映射。

设置工作负载身份提供商

创建工作负载身份提供商。

  1. 为一个唯一的值,例如 设置 名称 设置颁发者和受众。 aws-outbound-prod值。使用 描述,例如 Production AWS outbound identity federation workloads,以帮助管理员识别该提供商。

  2. OIDC 颁发者 URL 设置 设置为启用出站身份联合时返回的 AWS 特定于账户的颁发者 URL。此值必须与令牌的 声明相匹配。设置 iss 受众 为传递给 的相同受众。 GetWebIdentityToken。在此示例中,该值为 https://api.openai.com/v1.

  3. 使用 AWS OIDC 发现。 保持禁用 使用上传的 JWKS 进行令牌验证 状态。OpenAI 使用 AWS 颁发者的 OIDC 发现元数据和 JWKS 来验证 AWS 颁发的令牌。

  4. 仅在需要派生映射属性时才添加属性转换。 原始令牌匹配支持来自上述解码令牌示例的顶级标量声明,例如 sub, aud,且 iss。AWS 特定的命名空间声明嵌套在 https://sts.amazonaws.com/之下,因此在使用它们进行映射之前,请使用 CEL 括号表示法创建派生属性。例如,输入 aws_environment with expression assertion["https://sts.amazonaws.com/"]["principal_tags"]["environment"] to create openai.aws_environment 。在使用前,请验证样本令牌中的嵌套声明路径;如果无法评估转换,则映射解析将失败。对于 openai. 映射键,已以 openai. 开头的原始令牌声明将被忽略,除非配置了匹配的转换。

设置服务账户映射

  1. 创建服务账户映射。 设置 名称 为在工作负载身份提供商内唯一的值,例如 aws-role-openai-wif值。使用 描述,例如 Production AWS role for OpenAI API workload,以说明哪个工作负载可以使用此映射。

  2. 匹配 AWS 主体。 设置 to sub and 为解码令牌中的 IAM 主体 ARN,例如 arn:aws:iam::123456789012:role/OpenAIWifRole。对精确的 sub 声明进行匹配,可为 AWS 出站身份联合提供最强的隔离性。

  3. 根据需要添加额外的声明匹配。 您可以匹配任何可用的标量声明或已转换的属性。例如,如果您需要额外的信任边界,可以使用从 AWS 账户、组织、主体标签或请求标签声明派生的已转换属性。

  4. 选择 OpenAI 目标。 设置 项目 指向拥有目标服务账户的 OpenAI 项目。将 服务账户 设置为 AWS 工作负载可使用的 OpenAI 服务账户,例如 aws-outbound-prod-openai-wif.

  5. 根据需要缩小 API 权限范围。 选择适当的 权限 例如 api.model.request and api.vector_store.read 以进一步限制从此映射生成的访问令牌。将权限留空可避免添加特定于 WIF 的范围限制;该令牌仍会以映射的服务账户身份进行授权。

在代码中使用令牌

配置您的 OpenAI SDK 客户端,以向 AWS STS 请求 AWS 颁发的 OIDC 令牌,并将其换取 OpenAI 颁发的访问令牌。

设置 OPENAI_WIF_AUDIENCE 与在 OpenAI 工作负载身份提供者上配置的受众相同。主体令牌提供者将使用该受众调用 AWS STS, GetWebIdentityToken 返回 AWS 签发的 JWT 作为主体令牌,然后由 OpenAI SDK 将其交换为 OpenAI 签发的访问令牌。

使用 AWS 签发的 OIDC 令牌进行身份验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { GetWebIdentityTokenCommand, STSClient } from "@aws-sdk/client-sts";
import OpenAI from "openai";
import type { SubjectTokenProvider } from "openai/auth";

const identityProviderId = process.env.OPENAI_IDENTITY_PROVIDER_ID;
const serviceAccountId = process.env.OPENAI_SERVICE_ACCOUNT_ID;
const audience = process.env.OPENAI_WIF_AUDIENCE;
const awsRegion = process.env.AWS_REGION;

if (!identityProviderId || !serviceAccountId || !audience || !awsRegion) {
  throw new Error(
    "Set OPENAI_IDENTITY_PROVIDER_ID, OPENAI_SERVICE_ACCOUNT_ID, OPENAI_WIF_AUDIENCE, and AWS_REGION"
  );
}

const sts = new STSClient({ region: awsRegion });

function awsOutboundWebIdentityTokenProvider(): SubjectTokenProvider {
  return {
    tokenType: "jwt",
    getToken: async () => {
      const response = await sts.send(
        new GetWebIdentityTokenCommand({
          Audience: [audience],
          SigningAlgorithm: "ES384",
          DurationSeconds: 300,
        })
      );

      if (!response.WebIdentityToken) {
        throw new Error("AWS STS did not return a web identity token.");
      }

      return response.WebIdentityToken;
    },
  };
}

const client = new OpenAI({
  workloadIdentity: {
    identityProviderId,
    serviceAccountId,
    provider: awsOutboundWebIdentityTokenProvider(),
  },
});

const response = await client.responses.create({
  model: "gpt-4.1-mini",
  input: "Say hello from AWS outbound workload identity federation.",
});

console.log(response.output_text);

AWS 最佳实践

  • 为每个工作负载使用专用的 AWS 身份。为 AWS 出站身份联合使用单独的 IAM 角色,并为 EKS 工作负载使用单独的 Kubernetes 服务账号。
  • 为 OpenAI 访问配置专用的受众。在 AWS 颁发或 EKS projected 令牌以及 OpenAI Workload Identity Provider 配置中使用相同的受众值。
  • 保持令牌生命周期合理简短。对于 AWS 出站身份联合,请使用 IAM 条件,例如 sts:DurationSeconds;对于 EKS,请设置合适的投射令牌过期时间。
  • 优先使用精确的主体匹配。对于 AWS 出站令牌,请匹配完整的 IAM 主体 ARN;对于 EKS 令牌,请匹配完整的 Kubernetes 服务账户主体。
  • 将映射范围限定在稳定的边界内。当账户、组织、命名空间或转换后的属性能够在不创建宽泛信任规则的前提下缩减访问权限时,请使用它们。
  • 在交换令牌时重新加载令牌。在需要时请求 AWS 出站令牌,并从挂载文件路径读取 EKS 投射令牌,以便自动获取已轮换的令牌。
  • 仅授予工作负载所需的权限。使用映射级别的权限来进一步收窄目标 OpenAI 服务账户所授予的访问权限。