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

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

GitHub が発行した OIDC トークンを有効期間の短い OpenAI アクセストークンと交換すると、GitHub Actions をワークロード ID プロバイダーとして使用できます。これにより、有効期間の長い API キーを GitHub のシークレットに保存せずに、ワークフローから 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 をリクエストできます。この権限ではリポジトリの内容に書き込むことはできません。contents: read 権限は actions/checkout に必要です。

トークンをリクエストするときは、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-audience や https://api.openai.com/v1 など、リクエスト時に指定する値との完全一致を求めるように OpenAI を設定します。
  • sub:トークンの主体を表す文字列です。GitHub は、リポジトリ、ブランチ、タグ、pull request、環境などのワークフローメタデータからこの文字列を生成します。
  • repository:ワークフローを実行するリポジトリです。たとえば my-org/my-repo のような値です。
  • repository_owner:リポジトリを所有する組織またはユーザーです。たとえば my-org のような値です。
  • ref:ワークフローの実行をトリガーした Git ref です。例として refs/heads/main や refs/tags/v1.0.0 があります。
  • workflow:ワークフローを表すクレームです。GitHub が実際に出力した値を使用します。たとえば、ジョブのワークフロークレームの値が deploy なら、その値を使用します。
  • workflow_ref:ワークフローファイルのパスと ref を組み合わせた値です。たとえば my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main のような形式です。
  • environment:ジョブが GitHub 環境を使用する場合の環境名です。たとえば production のような値です。
  • run_id、run_number、run_attempt、job_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 に設定した発行者、オーディエンス、マッピングの値と照合します。設定上の問題の多くは、トークンを交換する前に iss、aud、repository、ref、workflow_ref の各クレームを確認すると見つかります。

ワークロード ID フェデレーションの設定

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

まずワークロード ID プロバイダーを設定し、次にサービスアカウントマッピングを作成します。

ワークロード ID プロバイダーの設定

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

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

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

  4. マッピングに派生属性が必要な場合のみ、属性変換を追加します。 repository、ref、workflow などの 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_ref を workflow より優先してください。通常、管理者が信頼の対象とするのは、特定のワークフローファイルのパスと ref の組み合わせです。ワークフロー名は変更でき、複数のワークフローファイルに同じ名前を付けることもできます。

    マッピング画面では、各条件のキーと値を 1 行ずつ入力します。たとえば、キー 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-actions-prod-deploy など、GitHub ワークフローが使用できる OpenAI サービスアカウントを指定します。

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

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

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

ワークフローでは、id-token: write 権限を付与し、ワークロード ID フェデレーションの設定を SDK を使用するコードに渡す必要があります。SDK は、GitHub がジョブに提供する環境変数 ACTIONS_ID_TOKEN_REQUEST_URL と ACTIONS_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_AUDIENCE、OPENAI_IDENTITY_PROVIDER_ID、OPENAI_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 リソースにアクセスする前に承認を必須とするか、アクセスできるブランチを制限してください。
  • マッピングの対象をリポジトリ単位で制限します。組織内のすべてのリポジトリにアクセスを許可せず、可能な限りリポジトリ固有のクレームを照合してください。
  • マッピングの対象をブランチまたはワークフロー単位で制限します。トークンの発行対象を絞るために、repository、ref、environment、workflow_ref などのクレームを照合することを検討してください。
  • CI/CD と本番ワークロードには別々の OpenAI サービスアカウントを使用します。ビルドパイプラインとデプロイ済みのアプリケーションでは、必要な権限が異なることがよくあります。
  • 信頼できないフォークからの pull requests にアクセス権を付与しないでください。フォークからの pull requests では攻撃者が用意したコードが実行される可能性があるため、本番環境の認証情報を渡さないでください。
  • 有効期間の短いアクセストークンと交換します。GitHub OIDC トークンは一時的な認証用なので、必要なときだけ交換してください。
  • リポジトリの所有者変更を監査します。リポジトリの移管、名前変更、権限変更は、既存のマッピングが前提とするセキュリティ条件に影響する可能性があります。
  • クレームの完全一致を優先します。組織全体を対象とする信頼関係に依存せず、repository、ref、environment などのクレームを照合してください。