For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
主导航

为 Google Cloud 配置工作负载身份联合

在以下任一场景中,可将 Google Cloud 用作工作负载身份提供方:

  • Google 工作负载身份: 将签发给已关联的 Google 服务账户、由 Google 签名的 OIDC Token 交换为短期 OpenAI 访问令牌。
  • Google Kubernetes Engine: 将投射的 GKE 服务账户 Token 交换为短期 OpenAI 访问令牌。

如果您使用 Codex,请按照本页说明获取并检查 Google Token。然后配置 Codex 工作负载身份,将该 Token 写入文件,并让 Codex 使用该文件。本页的服务账户映射和 SDK 示例适用于 OpenAI API。

Google 工作负载身份

Google Cloud 工作负载可以向 Google 元数据服务器请求已签名的 OIDC 身份 Token,而无需存储长期有效的服务账户密钥。在 OpenAI 工作负载身份联合中,Google 身份 Token 是主体 Token,OpenAI 会先验证它,再签发 OpenAI 访问令牌。此流程适用于 Compute Engine、Cloud Run、使用已关联的 Google 服务账户的 GKE 工作负载,以及提供元数据服务器身份端点的其他 Google 托管运行时。

设置 Google 工作负载身份

为需要调用 OpenAI API 的工作负载创建 Google 服务账户。有关完整的设置流程,请参阅 Google 的创建服务账户指南。

例如,使用 Google Cloud CLI 创建服务账户:

gcloud iam service-accounts create openai-wif \
  --description="Service account for OpenAI workload identity federation" \
  --display-name="OpenAI workload identity federation"

创建 Compute Engine 虚拟机并关联该服务账户,或将该服务账户关联到运行您应用的 Google Cloud 资源。该资源必须能够在运行时调用 Google 元数据服务器。有关虚拟机设置的详细信息,请参阅 Google 的创建使用用户管理的服务账户的虚拟机指南。

请勿为此流程创建或下载服务账户密钥。工作负载会使用已关联的服务账户和元数据服务器来请求短期 OIDC Token。

获取 Google 身份 Token

从已关联服务账户的 Google Cloud 资源中,使用配置的受众向元数据服务器请求 OIDC 身份 Token。此 Token 是主体 Token,OpenAI 会将其交换为 OpenAI 签发的访问令牌。

AUDIENCE="https://api.openai.com/v1"

TOKEN=$(curl -sS -G -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity" \
  --data-urlencode "audience=${AUDIENCE}")
export TOKEN

元数据服务器会返回由 Google 签名的 JWT。有关元数据服务器身份端点的更多信息,请参阅 Google 的验证虚拟机身份指南。

验证 Token

配置工作负载身份联合之前,请将 Google 身份 Token 导出为 TOKEN,然后在本地运行此脚本以检查其声明:

const parts = process.env.TOKEN?.split(".") ?? [];
if (parts.length !== 3) {
  throw new Error("Expected a compact JWT with three segments");
}
if (!/^[A-Za-z0-9_-]+$/.test(parts[1]) || parts[1].length % 4 === 1) {
  throw new Error("JWT payload is not valid Base64URL");
}

const bytes = Buffer.from(parts[1], "base64url");
if (bytes.toString("base64url") !== parts[1]) {
  throw new Error("JWT payload is not valid Base64URL");
}
const decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
const claims = JSON.parse(decoded);
if (claims === null || Array.isArray(claims) || typeof claims !== "object") {
  throw new Error("JWT payload is not a JSON object");
}
console.log(decoded);

此命令会解码 JWT 载荷,但不会验证 Token 签名。对于生产环境 Token,请使用本地解码器,避免将生产环境 Token 粘贴到第三方工具中。

解码后的 Google 元数据服务器身份 Token 类似如下:

{
  "iss": "https://accounts.google.com",
  "aud": "https://api.openai.com/v1",
  "azp": "110123456789012345678",
  "sub": "110123456789012345678",
  "email": "openai-wif@my-project.iam.gserviceaccount.com",
  "email_verified": true,
  "iat": 1716235422,
  "exp": 1716239022
}

使用解码后的载荷,将收到的 Token 与 OpenAI 中配置的签发方、受众和映射值进行比较。在交换 Token 之前,通过检查 issaudemailsub 声明即可发现大多数配置问题。

设置工作负载身份联合

在 OpenAI 中为 Google 签发的身份 Token 创建工作负载身份提供方,然后添加服务账户映射,以匹配 Token 中的稳定声明。

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

设置工作负载身份提供方

  1. 创建工作负载身份提供方。名称 设置为唯一值,例如 google-workload-identity-prod。填写 描述(例如 Production Google Cloud workloads),帮助管理员识别该提供方。

  2. 设置签发方和受众。OIDC 签发方 URL 设置为 https://accounts.google.com。将 受众 设置为工作负载向 Google 元数据服务器请求 Token 时指定的自定义受众,例如 https://api.openai.com/v1。此值必须与 Token 的 aud 声明一致。

  3. 使用 Google OIDC 发现机制。 保持 使用上传的 JWKS 验证 Token 处于禁用状态。OpenAI 会使用 Google 的 OIDC 发现元数据和 JWKS 来验证由 Google 签名的身份 Token。

  4. 如果需要派生的映射属性,请添加属性转换。 例如,输入 subject 并使用表达式 assertion.sub,即可根据主体声明创建 openai.subject。控制台会自动添加 openai. 前缀。对于 openai. 映射键,系统会忽略原始 Token 中已以 openai. 开头的声明,除非配置了相应的转换。

设置服务账户映射

  1. 创建服务账户映射。名称 设置为该工作负载身份提供方内的唯一值,例如 compute-openai-wif。填写 描述(例如 Production Compute Engine OpenAI API workload),说明哪些工作负载可以使用此映射。

  2. 匹配稳定的 Google 服务账户声明。 为每个必须匹配的声明添加一行 。使用 sub 作为主要身份绑定依据,因为它稳定且唯一。您也可以额外匹配 email,以提高可读性。

  3. 选择 OpenAI 目标。项目 设置为目标服务账户所属的 OpenAI 项目。将 服务账户 设置为 Google Cloud 工作负载可以使用的 OpenAI 服务账户,例如 google-workload-identity-prod-openai-wif

  4. 根据需要缩小 API 权限范围。 选择适当的 权限 ,例如 api.model.requestapi.vector_store.read,以进一步限制通过此映射签发的访问令牌的权限范围。将权限留空则不会添加 WIF 专属的范围限制;Token 仍以映射的服务账户身份进行授权。

在代码中使用 Token

配置您的 OpenAI SDK 客户端,使其向元数据服务器请求 Google 身份 Token,并将其交换为 OpenAI 签发的访问令牌。

OPENAI_WIF_AUDIENCE 设置为工作负载身份提供方中配置的自定义受众。SDK 会请求面向该受众的 Google 身份 Token,将其交换为 OpenAI 签发的访问令牌,并使用该 OpenAI Token 对 API 请求进行身份验证。

使用 Google 元数据服务器身份 Token 进行身份验证
import OpenAI from "openai";

const metadataEndpoint =
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity";

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

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

function googleMetadataIdentityTokenProvider(audience) {
  return {
    tokenType: "jwt",
    getToken: async () => {
      const url = new URL(metadataEndpoint);
      url.searchParams.set("audience", audience);
      url.searchParams.set("format", "full");

      const response = await fetch(url, {
        headers: { "Metadata-Flavor": "Google" },
      });

      if (!response.ok) {
        throw new Error(
          `Google metadata token request failed with status ${response.status}.`
        );
      }

      const token = (await response.text()).trim();
      if (!token) {
        throw new Error(
          "Google metadata server did not return an identity token."
        );
      }

      return token;
    },
  };
}

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

const response = await client.responses.create({
  model: "gpt-5.6-terra",
  input: "Say hello from Google Cloud workload identity federation.",
});

console.log(response.output_text);

Google Cloud 最佳实践

  • 为每个工作负载使用专用的 Google 服务账户。避免在不相关的服务或环境之间共享服务账户。
  • 使用工作负载身份流程来替代长期有效的服务账户密钥。对于能够使用元数据服务器身份令牌或 GKE 工作负载身份的工作负载,请避免分发和轮换 JSON 密钥文件。
  • 将身份的适用范围限制在实际可行的最小工作负载边界内。为各个应用使用独立的服务账户,可以让审计更清晰,并实现最小权限访问。
  • 谨慎使用基于属性的映射。尽可能优先使用服务账户主体声明等稳定标识符,而非可变元数据。
  • 将生产环境项目与非生产环境项目分开。使用不同的项目可以降低意外共享权限的风险,并简化审计。
  • 仅授予必需的 IAM 权限。将 Google 身份的权限限制为工作负载所需的权限。
  • 监控服务账户的使用情况。非预期的令牌交换可能表明配置发生偏移,或工作负载已遭入侵。