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

为 Microsoft Azure 配置工作负载身份联合

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

  • Azure 托管身份: 将为托管身份签发的 Microsoft Entra ID 访问令牌交换为短期 OpenAI 访问令牌。
  • AKS: 将投射的 Azure Kubernetes Service(AKS)服务账户 Token 交换为短期 OpenAI 访问令牌。

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

Azure 托管身份

Azure 托管身份让 Azure 上托管的工作负载无需存储长期密钥,即可请求 Microsoft Entra Token。在 OpenAI 工作负载身份联合中,托管身份 Token 充当主体 Token,OpenAI 会先验证该 Token,再签发 OpenAI 访问令牌。

设置 Azure 托管身份

创建或使用一个 Microsoft Entra 应用注册,用于表示 OpenAI 应信任的 Token 受众。配置其 应用程序 ID URI;此 URI 是您的工作负载向 Azure 实例元数据服务(IMDS)请求 Token 时使用的 resource 值,也会作为已签发 Token 中的 aud 声明。有关 Microsoft 的设置步骤,请参阅 Microsoft Entra 的创建新的 Entra ID 应用程序和服务主体指南。

Microsoft Entra ID 中配置的应用程序 ID URI、IMDS 的 resource 参数、 生成的 Token 中的 aud 声明,以及 OpenAI 工作负载身份提供方的受众 必须全部一致。

创建一个托管身份,然后将其分配给运行您应用程序的 Azure 资源,例如虚拟机。该资源必须能够在运行时调用 IMDS。有关 Azure 设置的详细信息,请参阅 Microsoft 的托管身份概述,以及相关 Azure 资源文档中关于分配身份的说明。

获取 Azure 托管身份 Token

从已分配托管身份的 Azure 资源向 IMDS 请求 Token,并将应用程序 ID URI 用作 resource 参数。此 Token 是主体 Token,OpenAI 会将其交换为由 OpenAI 签发的访问令牌。

APPLICATION_ID_URI="api://<application-client-id>"

TOKEN=$(curl -sS -G -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token" \
  --data-urlencode "api-version=2018-02-01" \
  --data-urlencode "resource=${APPLICATION_ID_URI}" \
  | jq -r .access_token)
export TOKEN

如果资源具有多个用户分配的托管身份,请添加 client_idobject_idmsi_res_id 查询参数,以指定您要使用的托管身份。Microsoft 在使用虚拟机上的托管身份获取访问令牌中介绍了 IMDS Token 请求参数。

验证 Token

配置工作负载身份联合之前,请将 Microsoft Entra 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,请使用本地解码器,避免将其粘贴到第三方工具中。

解码后的 Microsoft Entra ID 托管身份 Token 类似如下:

{
  "iss": "https://login.microsoftonline.com/11111111-2222-3333-4444-555555555555/v2.0",
  "aud": "api://00000000-1111-2222-3333-444444444444",
  "tid": "11111111-2222-3333-4444-555555555555",
  "appid": "22222222-3333-4444-5555-666666666666",
  "oid": "33333333-4444-5555-6666-777777777777",
  "sub": "33333333-4444-5555-6666-777777777777",
  "xms_mirid": "/subscriptions/<subscription-id>/resourcegroups/my-resource-group/providers/Microsoft.Compute/virtualMachines/openai-wif-vm",
  "iat": 1716235422,
  "exp": 1716239022
}

核实您计划在 OpenAI 中配置的声明:

  • iss:使用 Token 中的确切签发者值。签发者可能为 https://login.microsoftonline.com/<tenant-id>/v2.0,但不要假定其一定包含该后缀。
  • aud:必须与应用程序 ID URI、IMDS 的 resource 参数和 OpenAI 工作负载身份提供方的受众一致。
  • tid:Microsoft Entra 租户 ID。
  • appid:如果存在此声明,其值为托管身份的应用程序/客户端 ID。
  • iatexp:检查 Token 的完整有效期,即 exp - iat,单位为秒。

如果您使用 Codex,请将提供方的 max_assertion_lifetime_seconds 设置为经批准的上限, 且该上限应涵盖签发者预期的 Token 有效期范围。不要使用 Token 的剩余有效时间,也不要假定每个 Entra Token 的有效期都是一小时。 Microsoft 文档说明了访问令牌有效期 的可变性, 并且不支持配置托管身份 Token 的有效期。 请参阅管理 API 提供方 示例

托管身份 Token 还可能包含 azpoidsubxms_mirid 等声明。请以解码后的 Token 为准,选择能够准确标识您信任的托管身份及资源边界的声明。

使用解码后的载荷,将您收到的 Token 与 OpenAI 中配置的签发者、受众和映射值进行比较。在交换 Token 之前,通过 issaudtid 和托管身份声明就能发现大多数配置问题。

设置工作负载身份联合

在 OpenAI 中为 Microsoft Entra ID 签发者创建工作负载身份提供方,然后添加服务账户映射,使其匹配托管身份 Token 中的稳定声明。

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

设置工作负载身份提供方

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

  2. 设置签发者和受众。OIDC 签发者 URL 设置为 Token 中 iss 声明的确切值。请先获取一个托管身份 Token 样本,并检查其声明。例如,签发者可能为 https://login.microsoftonline.com/<tenant-id>/v2.0。将 受众 设置为您配置的 Microsoft Entra 应用程序 ID URI,例如 api://<application-client-id>。此值必须与 Token 的 aud 声明一致。

  3. 使用 Microsoft Entra Token 验证。 保持 使用上传的 JWKS 验证 Token 处于禁用状态。OpenAI 使用 Microsoft Entra 签发者元数据和 JWKS 来验证托管身份 Token。

  4. 如果需要派生的映射属性,请添加属性转换。 例如,输入 managed_identity_client_id 并使用表达式 assertion.appid,从托管身份的应用程序/客户端 ID 声明创建 openai.managed_identity_client_id。控制台会自动添加 openai. 前缀。对于 openai. 映射键,除非配置了匹配的转换,否则已带有 openai. 前缀的原始 Token 声明会被忽略。

设置服务账户映射

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

  2. 匹配稳定的托管身份声明。 为每个必须匹配的声明添加一行 。如果 Token 包含 appid,请将 设置为 appid,将 设置为托管身份的客户端 ID。appid 声明标识托管身份的应用程序/客户端 ID,通常是将映射绑定到特定托管身份时最稳定的声明。如果您的 Token 不包含 appid,请使用解码后 Token 中的其他稳定声明,例如 azpoidsubxms_mirid。要将映射绑定到单个租户,还需将 设置为 tid,将 设置为 Microsoft Entra 租户 ID。解码来自 IMDS 的 Token 样本,并使用对您信任的托管身份和资源保持稳定的声明。

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

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

在代码中使用 Token

配置您的 OpenAI SDK 客户端,使其从 IMDS 请求 Azure 托管身份 Token,并将其交换为由 OpenAI 签发的访问令牌。

OPENAI_WIF_AUDIENCE 设置为已配置为工作负载身份提供方受众的 Microsoft Entra 应用程序 ID URI。SDK 会为该受众请求托管身份 Token,将其交换为由 OpenAI 签发的访问令牌,并使用该 OpenAI Token 对 API 请求进行身份验证。

使用 Azure 托管身份 Token 进行身份验证
import OpenAI from "openai";

const imdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token";

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 azureManagedIdentityTokenProvider(resource) {
  return {
    tokenType: "jwt",
    getToken: async () => {
      const url = new URL(imdsEndpoint);
      url.searchParams.set("api-version", "2018-02-01");
      url.searchParams.set("resource", resource);

      const clientId = process.env.AZURE_CLIENT_ID;
      if (clientId) {
        url.searchParams.set("client_id", clientId);
      }

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

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

      const body = await response.json();
      if (!body.access_token) {
        throw new Error("Azure IMDS did not return an access token.");
      }

      return body.access_token;
    },
  };
}

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

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

console.log(response.output_text);

Microsoft Azure 最佳实践

  • 尽可能使用托管身份。与手动分发凭据相比,托管身份提供的身份验证方式更简单、更安全。
  • 为不同的应用和环境使用独立的托管身份、Microsoft Entra 应用和 OpenAI 映射。避免在开发、预发布和生产环境的工作负载之间共用同一个身份。
  • 限制可接受的受众。仅配置 OpenAI 工作负载身份联合所需的受众。
  • 使用专用的 Microsoft Entra ID 应用划分安全边界。独立的应用有助于明确归属,并使审计和访问管理更加清晰。
  • 优先使用针对特定工作负载的映射。根据特定工作负载的声明进行匹配,而不是使用覆盖整个租户的宽泛属性。
  • 定期审查联合凭据配置。陈旧的联合凭据可能会在工作负载停用很久之后,仍意外地授予访问权限。
  • 将生产环境身份与非生产环境身份分开。生产环境工作负载应通过独立的联合身份和 OpenAI 服务账户进行身份验证。