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

為 GitHub Actions 設定工作負載身分聯合

將 GitHub 簽發的 OIDC Token 交換為短效的 OpenAI 存取權杖,即可使用 GitHub Actions 作為工作負載身分提供者。這樣一來,工作流程就能向 OpenAI API 進行身分驗證,無須在 GitHub 密碼中儲存長效 API 金鑰。

若要搭配 Codex 使用,請依照本頁說明取得並檢查 GitHub Token。接著設定 Codex 工作負載身分,將該 Token 寫入檔案,並讓 Codex 指向該檔案。本頁的服務帳戶對應和 SDK 範例適用於 OpenAI API。

當工作流程中的作業具備 id-token: write 權限並請求身分 Token 時,GitHub 就能為該作業產生已簽署的 OIDC JWT。OpenAI 會先驗證 Token 的簽發者、對象、簽章和對應屬性,再簽發 OpenAI 存取權杖。

設定 GitHub Actions

授予工作流程或作業請求 GitHub OIDC Token 的權限:

permissions:
  id-token: write
  contents: read

id-token: write 權限讓作業能夠請求 OIDC JWT,但不會授予程式碼庫內容的寫入權限。actions/checkout 需要 contents: read 權限。

請求 Token 時,請使用與 OpenAI 工作負載身分提供者設定完全相符的對象值。自訂 JavaScript 動作可呼叫 core.getIDToken("your-wif-audience");Shell 步驟則可直接呼叫 GitHub 的 OIDC 請求 URL。若對象值包含 URL 保留字元,例如 https://api.openai.com/v1,應先進行 URL 編碼,再附加至請求 URL:

AUDIENCE="https://api.openai.com/v1"
ENCODED_AUDIENCE=$(jq -rn --arg audience "$AUDIENCE" '$audience | @uri')

TOKEN=$(curl -sSf -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
  "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${ENCODED_AUDIENCE}" | jq -r .value)
export TOKEN

重要的 GitHub OIDC 宣告包括:

  • iss:Token 的簽發者。對 GitHub Actions 而言,此值為 https://token.actions.githubusercontent.com
  • aud:工作流程請求的對象值。請將 OpenAI 設定為要求與請求中完全相符的值,例如 your-wif-audiencehttps://api.openai.com/v1
  • sub:主要的主體字串。GitHub 會根據工作流程中繼資料產生此字串,例如程式碼庫、分支、標籤、Pull Request 或環境。
  • repository:執行工作流程的程式碼庫,例如 my-org/my-repo
  • repository_owner:擁有該程式碼庫的組織或使用者,例如 my-org
  • ref:觸發工作流程的 Git 參照,例如 refs/heads/mainrefs/tags/v1.0.0
  • workflow:工作流程宣告。請使用 GitHub 實際產生的宣告值;例如,若作業中的工作流程宣告值為 deploy,就使用該值。
  • workflow_ref:工作流程的檔案路徑和參照,例如 my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main
  • environment:作業使用環境時的 GitHub 環境名稱,例如 production
  • run_idrun_numberrun_attemptjob_workflow_ref:工作流程執行與作業的識別碼,可協助稽核或設定更進階的信任規則。

如需完整的宣告清單和主體格式,請參閱 GitHub 的 OpenID Connect 參考資料

驗證 Token

設定工作負載身分聯合之前,請將 GitHub OIDC 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,請使用本機解碼器,避免將其貼入第三方工具。切勿將原始 GitHub OIDC Token 或交換取得的 OpenAI 存取權杖寫入記錄。

解碼後的 GitHub Actions OIDC Token 內容如下所示:

{
  "iss": "https://token.actions.githubusercontent.com",
  "aud": "https://api.openai.com/v1",
  "sub": "repo:my-org/my-repo:environment:production",
  "repository": "my-org/my-repo",
  "repository_owner": "my-org",
  "ref": "refs/heads/main",
  "workflow": "deploy",
  "workflow_ref": "my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main",
  "environment": "production",
  "run_id": "1234567890",
  "run_attempt": "1"
}

使用解碼後的承載資料,比較收到的 Token 與 OpenAI 中設定的簽發者、對象和對應值。在交換 Token 之前,就能從 issaudrepositoryrefworkflow_ref 宣告中看出大多數組態問題。

設定工作負載身分聯合

在 OpenAI 中為 GitHub Actions 建立工作負載身分提供者,再新增服務帳戶對應,讓它比對您信任的 GitHub 工作流程宣告。

請先設定工作負載身分提供者,再建立服務帳戶對應。

設定工作負載身分提供者

  1. 建立工作負載身分提供者。名稱 設為唯一的值,例如 github-actions-prod。使用 說明欄位,例如填入 Production GitHub Actions workflows,協助管理員識別此提供者。

  2. 設定簽發者和對象。OIDC 簽發者 URL 設為 https://token.actions.githubusercontent.com。將 對象 設為與工作流程請求完全相符的對象值,例如 your-wif-audiencehttps://api.openai.com/v1

  3. 使用 GitHub OIDC 探索機制。使用上傳的 JWKS 驗證 Token 維持停用。OpenAI 會使用 GitHub 的 OIDC 探索中繼資料和 JWKS,驗證由 GitHub 簽署的 Token。

  4. 只有在需要衍生對應屬性時,才新增屬性轉換。 原始 GitHub 宣告,例如 repositoryrefworkflow,可直接用於對應判斷提示。若建立衍生屬性,儀表板會自動加上 openai. 前置詞;例如,輸入 github_repository 並搭配運算式 assertion.repository,即可建立 openai.github_repository。對於 openai. 對應鍵,除非已設定相符的轉換,否則系統會忽略原本就以 openai. 開頭的原始 Token 宣告。

設定服務帳戶對應

  1. 建立服務帳戶對應。名稱 設為在該工作負載身分提供者內唯一的值,例如 github-actions-main-deploy。使用 說明欄位,例如填入 Production deploy workflow on main,說明哪些工作流程可以使用此對應。

  2. 新增精確的宣告判斷提示。 針對每個必須相符的 GitHub 宣告,新增一列 。所有已設定的列都必須相符,OpenAI 才會簽發存取權杖。對於正式環境部署工作流程,請使用如下的判斷提示:

    iss == "https://token.actions.githubusercontent.com"
    aud == "https://api.openai.com/v1"
    repository == "my-org/my-repo"
    ref == "refs/heads/main"
    workflow_ref == "my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main"

    對於具備特殊權限的對應,建議優先使用 workflow_ref 而非 workflow,因為管理員通常希望信任的是特定的工作流程檔案路徑和參照。工作流程名稱可以變更,而且多個工作流程檔案也可能使用相同名稱。

    在對應介面中,以鍵/值列輸入這些項目,例如將 repository 搭配 my-org/my-repo ref 搭配 refs/heads/main,以及 workflow_ref 搭配 my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main。若作業使用 GitHub 環境,還要新增 environment,搭配 production

    注意: 請避免範圍過廣的對應,例如僅以 repository_owner == "my-org" 作為信任條件,除非該擁有者命名空間中的每個程式碼庫都應該能夠產生 OpenAI 存取權杖。

  3. 選擇 OpenAI 目標。專案 設為目標服務帳戶所屬的 OpenAI 專案。將 服務帳戶 設為 GitHub 工作流程可使用的 OpenAI 服務帳戶,例如 github-actions-prod-deploy

  4. 視需要縮小 API 權限範圍。 選取適當的 權限 ,例如 api.model.requestapi.vector_store.read,進一步限制透過此對應產生的存取權杖。若不想新增 WIF 專屬的範圍限制,請將權限留白;Token 仍會以對應的服務帳戶身分取得授權。

在工作流程中使用 Token

設定 OpenAI SDK 用戶端,讓它請求 GitHub OIDC Token,並交換為 OpenAI 簽發的存取權杖。

工作流程必須授予 id-token: write 權限,並將工作負載身分聯合設定傳遞給 SDK 程式碼。SDK 會使用 GitHub 提供給作業的 ACTIONS_ID_TOKEN_REQUEST_URLACTIONS_ID_TOKEN_REQUEST_TOKEN 環境變數,請求 GitHub OIDC Token,再使用交換取得的 OpenAI 存取權杖,為 API 請求進行身分驗證。

例如,透過如下的工作流程執行應用程式碼:

name: deploy

on:
  push:
    branches:
      - main
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

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

      - name: Run OpenAI SDK code
        env:
          OPENAI_WIF_AUDIENCE: ${{ vars.OPENAI_WIF_AUDIENCE }}
          OPENAI_IDENTITY_PROVIDER_ID: ${{ vars.OPENAI_IDENTITY_PROVIDER_ID }}
          OPENAI_SERVICE_ACCOUNT_ID: ${{ vars.OPENAI_SERVICE_ACCOUNT_ID }}
        run: node ./scripts/call-openai.js

OPENAI_WIF_AUDIENCEOPENAI_IDENTITY_PROVIDER_IDOPENAI_SERVICE_ACCOUNT_ID 儲存為 GitHub Actions 變數。它們用於識別提供者和服務帳戶,並非持有者憑證。

以下範例使用自訂主體 Token 提供者初始化 OpenAI 用戶端。該提供者會針對已設定的對象請求 GitHub OIDC Token,並將其作為工作負載身分聯合的主體 Token。

使用 GitHub Actions OIDC Token 進行身分驗證
import OpenAI from "openai";

const identityProviderId = process.env.OPENAI_IDENTITY_PROVIDER_ID;
const serviceAccountId = process.env.OPENAI_SERVICE_ACCOUNT_ID;
const audience = process.env.OPENAI_WIF_AUDIENCE;
const requestURL = process.env.ACTIONS_ID_TOKEN_REQUEST_URL;
const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;

if (
  !identityProviderId ||
  !serviceAccountId ||
  !audience ||
  !requestURL ||
  !requestToken
) {
  throw new Error(
    "Set OPENAI_IDENTITY_PROVIDER_ID, OPENAI_SERVICE_ACCOUNT_ID, OPENAI_WIF_AUDIENCE, and run inside GitHub Actions with id-token: write"
  );
}

function githubActionsOIDCTokenProvider(requestURL, requestToken, audience) {
  return {
    tokenType: "jwt",
    getToken: async () => {
      const url = new URL(requestURL);
      url.searchParams.set("audience", audience);

      const response = await fetch(url, {
        headers: { Authorization: `bearer ${requestToken}` },
      });

      if (!response.ok) {
        throw new Error(
          `Failed to request GitHub OIDC token: ${response.status} ${response.statusText}`
        );
      }

      const body = await response.json();
      if (!body.value) {
        throw new Error("GitHub OIDC token response did not include a value.");
      }

      return body.value;
    },
  };
}

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

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

console.log(response.output_text);

GitHub Actions 最佳實務

  • 為正式環境部署使用環境保護措施。要求工作流程先取得核准或符合分支限制,才能存取正式環境的 OpenAI 資源。
  • 依程式碼庫限制對應。盡可能比對特定程式碼庫的宣告,避免允許組織內所有程式碼庫存取。
  • 依分支或工作流程限制對應。考慮比對 repositoryrefenvironmentworkflow_ref 等宣告,以限制 Token 的簽發。
  • 為 CI/CD 和正式環境工作負載使用不同的 OpenAI 服務帳戶。建置管線所需的權限通常與已部署的應用程式不同。
  • 避免授予來自不受信任分支的 Pull Request 存取權。來自分支的 Pull Request 可能執行攻擊者控制的程式碼,不應取得正式環境憑證。
  • 採用短效 Token 交換。GitHub OIDC Token 用於短暫的身分驗證,應只在需要時進行交換。
  • 稽核程式碼庫擁有權的變更。程式碼庫的移轉、重新命名和權限變更,都可能影響現有對應所依據的安全性假設。
  • 優先使用精確的宣告比對。比對 repositoryrefenvironment 等宣告,避免依賴涵蓋整個組織的信任關係。