For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
メインナビゲーション

GitHub Actions 向けワークロード ID フェデレーションの構成

GitHub が発行した OIDC トークンを有効期間の短い OpenAI アクセストークンに交換することで、GitHub Actions をワークロード ID プロバイダーとして使用できます。これにより、有効期間の長い API キーを GitHub のシークレットに保存せずに、ワークフローから OpenAI API に対して認証できます。

Codex を使用する場合は、このページに従って GitHub トークンを取得し、内容を確認します。その後、Codex のワークロード ID を構成し、そのトークンをファイルに書き込んで、Codex がそのファイルを参照するようにします。このページのサービスアカウントマッピングと SDK の例は、OpenAI API を対象としています。

GitHub は、id-token: write 権限を持ち、ID トークンをリクエストするワークフロージョブに対して、署名付き OIDC JWT を発行できます。OpenAI は、トークンの発行者、オーディエンス、署名、マッピング属性を検証してから、OpenAI アクセストークンを発行します。

GitHub Actions のセットアップ

ワークフローまたはジョブに、GitHub OIDC トークンをリクエストする権限を付与します。

permissions:
  id-token: write
  contents: read

id-token: write 権限により、ジョブは OIDC JWT をリクエストできます。この権限は、リポジトリの内容への書き込みアクセスを付与するものではありません。actions/checkout には contents: read 権限が必要です。

OpenAI のワークロード ID プロバイダーに構成したオーディエンスと完全に一致する値を指定して、トークンをリクエストします。カスタム JavaScript アクションでは core.getIDToken("your-wif-audience") を呼び出せます。シェルステップでは、GitHub の OIDC リクエスト URL を直接呼び出せます。https://api.openai.com/v1 のように URL の予約文字を含むオーディエンス値は、リクエスト 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:トークンの発行者です。GitHub Actions の場合は https://token.actions.githubusercontent.com です。
  • aud:ワークフローがリクエストしたオーディエンス値です。your-wif-audiencehttps://api.openai.com/v1 など、リクエストする値との完全一致を必須とするように OpenAI を構成します。
  • sub:主要なサブジェクト文字列です。GitHub は、リポジトリ、ブランチ、タグ、Pull Request、環境などのワークフローメタデータからこの文字列を生成します。
  • repository:ワークフローを実行するリポジトリ(例:my-org/my-repo
  • repository_owner:リポジトリを所有する組織またはユーザー(例:my-org
  • ref:ワークフローのトリガーとなった Git の参照(例:refs/heads/main または refs/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 リファレンスを参照してください。

トークンの検証

ワークロード ID フェデレーションを構成する前に、GitHub OIDC トークンを環境変数 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 ペイロードをデコードします。本番環境のトークンにはローカルのデコーダーを使用し、サードパーティ製ツールに本番環境のトークンを貼り付けないでください。GitHub OIDC トークンの生の値や、交換して取得した OpenAI アクセストークンをログに記録しないでください。

デコードした GitHub Actions OIDC トークンは、次のようになります。

{
  "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"
}

デコードしたペイロードを使って、受け取ったトークンを、OpenAI に構成した発行者、オーディエンス、マッピングの値と比較します。構成に関する問題の多くは、トークンを交換する前に、issaudrepositoryrefworkflow_ref の各クレームで確認できます。

ワークロード ID フェデレーションのセットアップ

OpenAI で GitHub Actions 用のワークロード ID プロバイダーを作成し、信頼する GitHub ワークフローのクレームに一致するサービスアカウントマッピングを追加します。

まずワークロード ID プロバイダーを構成し、その後でサービスアカウントマッピングを作成します。

ワークロード ID プロバイダーのセットアップ

  1. ワークロード ID プロバイダーを作成します。 名前 には、github-actions-prod などの一意の値を設定します。管理者がプロバイダーを識別しやすいように、 説明には Production GitHub Actions workflows などを入力します。

  2. 発行者とオーディエンスを設定します。 OIDC 発行者 URLhttps://token.actions.githubusercontent.com に設定します。 オーディエンス には、your-wif-audiencehttps://api.openai.com/v1 など、ワークフローがリクエストするオーディエンスと完全に一致する値を設定します。

  3. GitHub の OIDC ディスカバリーを使用します。 アップロードした JWKS をトークン検証に使用 は無効のままにします。OpenAI は GitHub の OIDC ディスカバリーメタデータと JWKS を使用して、GitHub が署名したトークンを検証します。

  4. マッピング用の派生属性が必要な場合にのみ、属性変換を追加します。 repositoryrefworkflow などの GitHub の元のクレームは、マッピングのアサーションで直接使用できます。派生属性を作成すると、ダッシュボードが openai. プレフィックスを自動的に付加します。たとえば、github_repository と式 assertion.repository を入力すると、openai.github_repository が作成されます。元のトークンクレームの名前がすでに openai. で始まっている場合、一致する変換が構成されていない限り、openai. のマッピングキーではそのクレームが無視されます。

サービスアカウントマッピングのセットアップ

  1. サービスアカウントマッピングを作成します。 名前 には、github-actions-main-deploy など、そのワークロード ID プロバイダー内で一意の値を設定します。どのワークフローがマッピングを使用できるかを示すために、 説明には Production deploy workflow on main などを入力します。

  2. クレームの完全一致を求めるアサーションを追加します。 一致を必須とする GitHub クレームごとに、 キー の行を 1 行追加します。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 よりも workflow_ref を優先してください。管理者が信頼の対象として想定しているのは、通常、特定のワークフローファイルのパスと参照だからです。ワークフロー名は変更でき、複数のワークフローファイルで同じ名前を使用することもできます。

    マッピング UI では、これらをキーと値の行として入力します。たとえば、 キーrepositorymy-org/my-repo の行、 キーrefrefs/heads/main の行、 キーworkflow_refmy-org/my-repo/.github/workflows/deploy.yml@refs/heads/main の行を入力します。ジョブが GitHub の環境を使用する場合は、 キーenvironmentproduction の行も追加します。

    注意: 所有者の名前空間にあるすべてのリポジトリに OpenAI アクセストークンの発行を許可する意図がない限り、repository_owner == "my-org" だけを信頼するような、対象範囲が広すぎるマッピングは避けてください。

  3. OpenAI 側の対象を選択します。 プロジェクト には、対象のサービスアカウントを所有する OpenAI プロジェクトを設定します。 サービスアカウント には、github-actions-prod-deploy など、GitHub ワークフローが使用できる OpenAI サービスアカウントを設定します。

  4. 必要に応じて API 権限を絞り込みます。 api.model.requestapi.vector_store.read などの適切な 権限 を選択して、このマッピングから発行されるアクセストークンの権限をさらに制限します。WIF 固有のスコープ制限を追加しない場合は、権限を空欄のままにします。その場合も、トークンはマッピング先のサービスアカウントとして認可されます。

ワークフローでのトークンの使用

GitHub OIDC トークンをリクエストし、OpenAI が発行するアクセストークンに交換するように、OpenAI SDK クライアントを構成します。

ワークフローでは、id-token: write 権限を付与し、ワークロード ID フェデレーションの設定を SDK コードに渡す必要があります。SDK は、GitHub がジョブに提供する環境変数 ACTIONS_ID_TOKEN_REQUEST_URLACTIONS_ID_TOKEN_REQUEST_TOKEN を使って GitHub OIDC トークンをリクエストし、交換して取得した 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 の変数として保存します。これらはプロバイダーとサービスアカウントを識別するものであり、Bearer 認証情報ではありません。

次の例では、カスタムのサブジェクトトークンプロバイダーを使用して OpenAI クライアントを初期化します。このプロバイダーは、構成されたオーディエンス向けの GitHub OIDC トークンをリクエストし、ワークロード ID フェデレーションのサブジェクトトークンとして使用します。

GitHub Actions OIDC トークンによる認証
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 などのクレームによる照合を検討してください。
  • CI/CD と本番環境のワークロードには、それぞれ別の OpenAI サービスアカウントを使用します。ビルドパイプラインには、デプロイ済みのアプリケーションとは異なる権限が必要になることがよくあります。
  • 信頼できないフォークからの Pull Request には、アクセスを付与しないでください。フォークからの Pull Request では、攻撃者が制御するコードが実行される可能性があるため、本番環境の認証情報を渡してはいけません。
  • 有効期間の短いトークンへの交換を利用します。GitHub OIDC トークンは一時的な認証を目的としているため、必要なときにのみ交換してください。
  • リポジトリの所有権の変更を監査します。リポジトリの移管、名前の変更、権限の変更は、既存のマッピングが前提とするセキュリティ条件に影響する可能性があります。
  • クレームの完全一致による照合を優先します。組織全体の信頼関係に依存するのではなく、repositoryrefenvironment などのクレームで照合します。