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 對象。設定其 應用程式識別碼 URI;此 URI 是工作負載向 Azure Instance Metadata Service (IMDS) 請求時使用的 resource 值,也會出現在所簽發 Token 的 aud 宣告中。如需 Microsoft 的設定步驟,請參閱 Microsoft Entra 的建立新的 Entra ID 應用程式與服務主體指南。

在 Microsoft Entra ID 中設定的應用程式識別碼 URI、IMDS 的 resource 參數、取得的 Token 中的 aud 宣告,以及 OpenAI 工作負載身分 提供者的對象,必須全部相符。

建立受控識別,然後將該受控識別指派給執行應用程式的 Azure 資源,例如虛擬機器。該資源必須能在執行階段呼叫 IMDS。如需 Azure 設定詳細資訊,請參閱 Microsoft 的受控識別概覽,以及相關 Azure 資源文件中指派識別的說明。

取得 Azure 受控識別 Token

從已指派受控識別的 Azure 資源,使用應用程式識別碼 URI 作為 resource 參數,向 IMDS 請求 Token。這個 Token 就是用來向 OpenAI 交換其所簽發存取權杖的主體 Token。

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,並避免將正式環境的 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:必須與應用程式識別碼 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 應用程式識別碼 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 應用程式識別碼 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 服務帳戶進行身分驗證。