X.509 ワークロード ID フェデレーションでは、ワークロードが TLS クライアント証明書の ID を、有効期間の短い OpenAI アクセストークンと交換できます。その後、ワークロードはアクセストークンと受け入れ可能なクライアント証明書の両方を使用して OpenAI API を呼び出します。このフローは API キーを置き換えるものであり、クライアント証明書を置き換えるものではありません。
X.509 ワークロード ID フェデレーションは OpenAI API で利用できます。 Codex は対応していません。Codex では OIDC トークンまたは SPIFFE JWT-SVID を使用し、 Codex ワークロード ID ガイドに従ってください。
トークン交換のリクエストとレスポンスの詳細は、ワークロード ID トークン交換リファレンスを参照してください。相互 TLS の権限、証明書の要件、有効化、mTLS ホスト、ローテーションについては、相互 TLS ガイドを参照してください。
仕組み
X.509 ワークロード ID の交換は、次の 5 つのステップで構成されます。
- 組織が既存の相互 TLS 設定で、信頼するルート証明書をアップロードし、有効化します。
- X.509 ワークロード ID プロバイダーが、検証済みのクライアント証明書から
openai.*属性を導出します。空でないopenai.subjectの値を 1 つ導出する必要があります。 - サービスアカウントマッピングにより、導出された ID に対して、プロジェクト内の 1 つの OpenAI サービスアカウントの使用が許可されます。
- ワークロードが
mtls.auth.openai.comの X.509 トークンエンドポイントに証明書を提示し、有効期間の短いベアラートークンをリクエストします。証明書は TLS 接続から取得され、リクエスト本文にはsubject_tokenを含めません。 - ワークロードが API の認可を受けるために、
mtls.api.openai.comの API ルートにベアラートークンとクライアント証明書を提示します。
API リクエストでは、ベアラートークンと証明書がそれぞれ独立して認可されます。証明書だけでは OpenAI API の呼び出しは許可されません。
事前準備
次のものが必要です。
- 組織の相互 TLS 証明書とワークロード ID プロバイダーを管理する権限
- ワークロード用のプロジェクトとサービスアカウント
- クライアント証明書、その秘密鍵、および信頼するルートまでのパスの構築に必要な中間証明書
- 組織またはプロジェクトレベルで有効になっている、信頼するルート証明書
秘密鍵はソース管理の対象外に保管し、使用するワークロードだけがアクセスできるように制限してください。秘密鍵、証明書の内容、返されたアクセストークンをログに記録しないでください。
相互 TLS 証明書の信頼設定
X.509 ワークロード ID プロバイダーは、組織の既存の相互 TLS 証明書設定を再利用します。証明書のアップロードや、独立した証明書トラストストアの管理は行いません。
相互 TLS ガイドに従って、証明書の要件、 mTLS ホスト、証明書の有効化の動作、CEL フィルター、 クライアント設定を確認してください。次に、組織設定 > セキュリティ > 相互 TLSを開き、 信頼する証明書を PEM 形式でアップロードします。その証明書を組織全体、または X.509 ワークロード ID フェデレーションを使用する各プロジェクトで有効化してください。
クライアント証明書のチェーンが中間証明書を経由する場合は、安定したトラストアンカーを構成し、TLS ハンドシェイク時にリーフ証明書、現在の中間証明書の順で提示してください。OpenAI はリクエストで提供された中間証明書を使用し、不足している中間証明書を証明書の URL から取得することはありません。
X.509 プロバイダーの構成
X.509 プロバイダーを構成するには、次の手順に従います。
- 組織設定 > セキュリティ > ワークロード ID プロバイダーを開き、 ID プロバイダーを作成を選択します。
- プロバイダーの種類で X.509 を選択し、名前と任意の説明を入力します。X.509 プロバイダーでは、OIDC の発行者、オーディエンス、ディスカバリー、JWKS の設定は使用しません。作成後にプロバイダーの種類を変更することはできません。
- 必要に応じて、 上級の 属性条件 に CEL 式を追加し、マッピングの解決前に証明書を拒否できるようにします。
- 属性変換で、必須の
openai.subject変換に空でない式を入力します。X.509 を選択すると、ダッシュボードにsubject行が追加され、openai.プレフィックスが表示されて適用されます。ワークロードを識別できる、変わりにくい証明書情報を選択してください。 - 必要に応じて、他の一意な
openai.*名を持つ変換を追加し、 作成を選択します。
たとえば、次の構成では証明書のコモンネームを正規のサブジェクトとして使用し、組織単位を追加のマッピング属性として公開します。
[
{
"attribute": "openai.subject",
"expression": "assertion.subject.common_name"
},
{
"attribute": "openai.environment",
"expression": "assertion.subject.organizational_unit"
}
]
証明書情報は assertion.subject と assertion.subject_alt_names で参照できます。マッピングに使用する変換結果は、スカラー値である必要があります。追加の変換には、一意な openai.* 名が必要です。
たとえば、 属性条件 の式を使用して、プロバイダーが受け入れる証明書を本番環境用に制限できます。
assertion.subject.organizational_unit == "Production"
サービスアカウントマッピングの作成
- X.509 プロバイダーの詳細ページで、 マッピングを作成を選択します。
- 対象のプロジェクトとサービスアカウントを選択し、ワークロードに必要な API 権限だけを付与します。
- キー と 値 のフィールドで、
openai.subjectの値の完全一致を条件として指定します。X.509 マッピングでは、空のオブジェクト({})で表すアサーションなしの設定、またはキーがopenai.で始まるアサーションを使用できます。 - 作成を選択します。
例:
| キー | 値 |
|---|---|
openai.subject | payments-service-prod |
X.509 マッピングは、導出された openai.* 属性を使用します。sub、iss、aud などの JWT クレームをそのまま照合することはありません。
プロバイダー一覧にはプロバイダー ID が表示され、マッピングの詳細には選択したサービスアカウントとそのサービスアカウント ID が表示されます。ワークロードがトークン交換時に送信するため、両方の ID を記録してください。
SDK での X.509 ワークロード ID の使用
証明書チェーン、秘密鍵、プロバイダー、サービスアカウントの環境変数を設定します。
export OPENAI_MTLS_CERT_CHAIN="/path/to/client-chain.pem"
export OPENAI_MTLS_KEY="/path/to/client-key.pem"
export OPENAI_IDENTITY_PROVIDER_ID="idp_example"
export OPENAI_SERVICE_ACCOUNT_ID="svc_acct_example"
証明書チェーンファイルには、最初にリーフ証明書を配置し、その後に中間証明書を配置してください。リクエスト本文に証明書データや subject_token を含めないでください。
これらの値を使用して OpenAI SDK クライアントを構成します。SDK は、トークン交換時と API リクエスト時にクライアント証明書を提示し、API リクエストを mTLS エンドポイントに送信して、有効期間の短いアクセストークンを自動的に更新します。
import { readFile } from "node:fs/promises";
import OpenAI from "openai";
import { workloadIdentity } from "openai/auth/x509-transport";
const certificatePath = process.env.OPENAI_MTLS_CERT_CHAIN;
const privateKeyPath = process.env.OPENAI_MTLS_KEY;
const identityProviderId = process.env.OPENAI_IDENTITY_PROVIDER_ID;
const serviceAccountId = process.env.OPENAI_SERVICE_ACCOUNT_ID;
if (
!certificatePath ||
!privateKeyPath ||
!identityProviderId ||
!serviceAccountId
) {
throw new Error(
"Set OPENAI_MTLS_CERT_CHAIN, OPENAI_MTLS_KEY, OPENAI_IDENTITY_PROVIDER_ID, and OPENAI_SERVICE_ACCOUNT_ID"
);
}
const credential = workloadIdentity.fromX509({
certificateChain: await readFile(certificatePath, "utf8"),
privateKey: await readFile(privateKeyPath, "utf8"),
identityProviderId,
serviceAccountId,
});
try {
const client = new OpenAI({ credential });
const response = await client.responses.create({
model: "gpt-5.6-terra",
input: "Say hello from X.509 workload identity federation.",
});
console.log(response.output_text);
} finally {
await credential.close();
}これらの例には、ここに示す X.509 構成に対応した OpenAI SDK が必要です。対象バージョンは、ピア依存関係の undici をインストールした JavaScript 7.8.0 以降、Python 3.6.0 以降、Go 3.54.0 以降、Java 4.55.0 以降、Ruby 0.83.0 以降です。
Java の例では、PKCS12 キーストアを読み込んで X509ExtendedKeyManager を構築し、プラットフォームのデフォルトのトラストストアを使用して X509TrustManager を構築します。この例では、OPENAI_X509_KEYSTORE_PATH、OPENAI_X509_KEYSTORE_PASSWORD、OPENAI_X509_CERTIFICATE_ALIAS を設定してください。代わりに、PEM またはハードウェアを基盤とするマネージャーを SDK に渡すこともできます。
証明書の手動交換
トークン交換プロトコルを直接確認または実装するには、X.509 トークンエンドポイントに証明書を提示します。
curl --cert "$OPENAI_MTLS_CERT_CHAIN" \
--key "$OPENAI_MTLS_KEY" \
--request POST "https://mtls.auth.openai.com/oauth/token" \
--header "Content-Type: application/json" \
--data @- <<JSON
{
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token_type": "urn:openai:params:oauth:token-type:x509",
"identity_provider_id": "${OPENAI_IDENTITY_PROVIDER_ID}",
"service_account_id": "${OPENAI_SERVICE_ACCOUNT_ID}"
}
JSON
交換に成功すると、有効期間の短い通常のベアラートークンが返されます。
{
"access_token": "eyJ...",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"expires_at": 1789045200,
"scope": "api.model.read api.model.request"
}
scope プロパティは、一致するサービスアカウントマッピングに権限がある場合にのみ返されます。
有効期限の値は一例です。検証済みのクライアント証明書が先に期限切れになる場合、返される有効期間は短くなることがあります。expires_in と expires_at の単位と意味については、トークン交換のレスポンスフィールドを参照してください。
成功レスポンスから access_token の値を読み取り、アプリケーションの認証情報ストア、または OPENAI_WIF_ACCESS_TOKEN などの環境変数に保存してください。この値はシークレットとして扱い、表示、ログへの記録、コミットをしないでください。
OpenAI API の手動呼び出し
OPENAI_MODEL を、現在のデフォルトである gpt-6-astra、または対象プロジェクトで利用できる別のモデルに設定します。次に、ベアラートークンと受け入れ可能なクライアント証明書を API の mTLS エンドポイントに送信します。
curl --request POST \
--cert "$OPENAI_MTLS_CERT_CHAIN" \
--key "$OPENAI_MTLS_KEY" \
--header "Authorization: Bearer $OPENAI_WIF_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"model\":\"$OPENAI_MODEL\",\"input\":\"Say hello in one sentence.\"}" \
"https://mtls.api.openai.com/v1/responses"
API キーの代わりにベアラートークンを使用し、API リクエストでは引き続き、受け入れ可能なクライアント証明書を提示してください。
ベアラートークンは証明書に暗号学的にバインドされていません。交換に使用した証明書を API リクエストでも再利用するのが最もシンプルな構成ですが、現在の同じ API mTLS ポリシーを独立して満たす別の証明書を API リクエストで使用することもできます。
トークンの有効期間と更新
X.509 ワークロード ID トークンの有効期間は最長 1 時間で、検証済みのクライアント証明書の有効期限を超えることはありません。この交換ではリフレッシュトークンは返されません。新たなアクセストークンを取得するには、証明書の交換を繰り返します。
手動で交換する場合は、expires_at をアクセストークンとともに保存し、その時刻より前に再度交換を行うようスケジュールしてください。時刻のずれやリクエストの遅延も考慮してください。具体例は、トークン更新のガイダンスを参照してください。
中間証明書をローテーションしても、設定済みのルート証明書を変更する必要はありません。以降の交換と API リクエストでは、新しい完全な証明書チェーンを提示してください。
トークン交換のトラブルシューティング
X.509 トークン交換では汎用的な OAuth エラーが返され、証明書、ルート証明書、プロバイダー、マッピングの詳細は公開されません。
| 結果 | 主な原因 |
|---|---|
HTTP 403 | リクエストで、mtls.auth.openai.com 上の POST /oauth/token と完全には一致しないメソッドまたはパスが使用されています。 |
invalid_subject_token | TLS クライアント証明書が存在しないか無効である、提示されたチェーンが有効なルート証明書につながらない、証明書が有効期間外である、または相互 TLS の証明書受け入れルールによって拒否されています。 |
invalid_grant | プロバイダーまたはマッピングが無効であるか無効化されている、プロバイダーの 属性条件 式によって ID が拒否されている、適用可能なルート証明書がいずれも有効化されていない、または一致するマッピングがありません。 |
| サーバーエラー | OpenAI が一時的なサーバーエラーを返しました。通常の一時的エラー処理ポリシーに従って再試行してください。 |
X.509 の交換が OIDC や通常の OAuth フローにフォールバックすることはありません。
制限事項
- X.509 ワークロード ID プロバイダーは、独立した証明書トラストストアを管理しません。
- ベアラートークンは証明書にバインドされておらず、DPoP や
cnfクレームも使用しません。 - 証明書の交換によって、証明書だけで API の認可を受けられるわけではありません。API リクエストには引き続き、ベアラートークンと受け入れ条件を満たすクライアント証明書が必要です。
- OpenAI は不足している中間証明書を AIA URL から取得しません。TLS ネゴシエーション時に完全な証明書チェーンを提示してください。
- OpenAI は、このフロー中に証明書失効リスト(CRL)や OCSP による確認を行いません。相互 TLS のルート証明書、プロバイダー、マッピングの制御機能と、発行されるトークンの短い有効期間を踏まえて、証明書に関するインシデント対応を計画してください。
- このフローで SPIFFE X.509-SVIDs のサポートが追加されるわけではありません。SPIFFE ガイドでは、引き続き JWT-SVIDs を使用します。