OpenAI API mTLS 與 X.509 Workload Identity Federation 設定
如果 CI、Kubernetes workload 或內部服務需要呼叫 OpenAI API,卻不希望把長期 API key 放進部署環境,OpenAI 現在提供一條以 X.509 client certificate 驗證 workload 的路徑。X.509 Workload Identity Federation 會把已驗證的憑證身分交換成短效 access token,再用 token 加上 client certificate 呼叫 mTLS API endpoint。
最容易搞錯的是:這個流程取代的是 API key,不是 client certificate。API request 仍然需要 bearer token 和受信任的 client certificate;只有憑證,或只有 token,都不足以授權一次 OpenAI API 呼叫。
OpenAI 官方文件目前把這項能力限定在 OpenAI API,Codex 不支援這個 X.509 流程。若你的目標是 Codex,應改看 OIDC 或 SPIFFE JWT-SVID 的 workload identity 方案。
先看完整的五段流程
可以把一次 X.509 登入拆成:
- Organization 在既有 Mutual TLS 設定中上傳並啟用 trusted root。
- X.509 Workload Identity Provider 從通過 TLS 驗證的 client certificate 推導 openai.* attributes。
- Provider 必須產生非空的 openai.subject,再由 service account mapping 將它對應到 project 裡的 service account。
- Workload 把 client certificate 帶到 mtls.auth.openai.com 的 token endpoint,換取短效 bearer token。
- Workload 以 bearer token 加上 client certificate 呼叫 mtls.api.openai.com 的 API route。
Token exchange 的 request body 不放 subject_token;憑證身分來自 TLS connection。另一方面,API request 仍要把 token 放在 Authorization header,並再次提供 client certificate。
開始前要準備什麼
你需要:
- 管理 organization Mutual TLS certificate 與 Workload Identity Provider 的權限。
- 一個 project 和供 workload 使用的 service account。
- client certificate、private key,以及建立到 trusted root 所需的 intermediate certificates。
- 已啟用、且作用於 organization 或 project 的 trusted root。
certificate chain 檔案要把 leaf certificate 放在最前面,再接 intermediate certificates。OpenAI 不會透過 AIA URL 自動抓缺少的 intermediate;若只把 leaf 傳出去,TLS handshake 可能在 production 才失敗。
private key、certificate content 和 access token 都不能進 source control 或 log。部署時以 secret manager 或工作負載的安全檔案注入,並限制只有需要呼叫 API 的 workload 可以讀取。
步驟一:設定 Mutual TLS trust
X.509 provider 會重用 organization 現有的 Mutual TLS certificate 設定,不會建立另一個獨立 trust store。先到 OpenAI Platform 的 organization settings → Security → Mutual TLS:
- 以 PEM 格式上傳 trusted root certificate。
- 啟用它到 organization,或只啟用到要使用 X.509 federation 的 project。
- 確認 client certificate 的 issuer chain 能連到這個 root。
- 準備給 request 的 chain 檔案,排列成 leaf → intermediate。
trusted root 的責任是回答「這張 client certificate 是否被信任」;它還沒有回答「這個 workload 能使用哪個 project service account」。後面的 provider 和 mapping 會處理身分到權限的關係。
步驟二:建立 X.509 Workload Identity Provider
在 organization settings → Security → Workload Identity Provider 建立 provider:
- 選 Create identity provider,Provider type 選 X.509。
- 填寫名稱與描述。X.509 provider 不使用 OIDC issuer、audience、discovery 或 JWKS;建立後不能再改 provider type。
- 若要先拒絕某些 certificate,於 Advanced 設定 Attribute conditions CEL expression。
- 在 Attribute transformations 設定必填的 openai.subject。
- openai.subject 要選穩定且能識別 workload 的 certificate attribute;例如以 certificate common name 作為 subject。
- 可選擇加入其他 openai.* attribute,例如 organizational unit,供後續 mapping 或治理使用。
- 建立後記錄 provider ID。
最小的 transformation 概念如下:
[ { "attribute": "openai.subject", "expression": "assertion.subject.common_name" }, { "attribute": "openai.environment", "expression": "assertion.subject.organizational_unit" }]不要把 raw JWT 的 sub、iss 或 aud 當成 X.509 mapping key;X.509 mapping 使用的是 provider 推導出的 openai.* attributes。
步驟三:建立 service account mapping
從 X.509 provider 詳情頁建立 mapping:
- 選擇 target project 和 service account。
- 只授予 workload 需要的 API permissions。
- 在 Key 填 openai.subject,Value 填一個精確的 subject,例如 payments-service-prod。
- 建立 mapping,並記錄 mapping 所指向的 service account ID。
這個 mapping 的概念可以表示為:
| Provider attribute | 精確值 | 授權結果 |
|---|---|---|
| openai.subject | payments-service-prod | 允許使用指定 project service account |
每個 workload 使用自己的 subject 和 mapping,會比把整個 organization 的 certificate 都映射到同一個高權限 service account 容易撤銷和稽核。若同一張 certificate 被多個服務共用,也要先確認 subject 是否仍能代表你想授權的最小邊界。
步驟四:用 curl 做 token exchange
先把 certificate chain、private key、provider ID 和 service account ID 放入安全的環境變數:
export OPENAI_MTLS_CERT_CHAIN="/secure/path/client-chain.pem"export OPENAI_MTLS_KEY="/secure/path/client-key.pem"export OPENAI_IDENTITY_PROVIDER_ID="idp_example"export OPENAI_SERVICE_ACCOUNT_ID="svc_acct_example"再把 certificate 帶到 token endpoint:
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 和有效時間。request body 不要自行加入 subject_token,也不要把 PEM 內容塞進 JSON;憑證應只由 TLS client authentication 提供。
Token 最長一小時,而且不會超過 client certificate 的剩餘有效時間。這個流程沒有 refresh token;token 快過期時,workload 要重新做 exchange。production code 應以安全的 memory/secret handling 保存 token,並在錯誤時避免把整段回應寫進 log。
步驟五:帶 token 與 certificate 呼叫 Responses API
把上一步取得的 token 放到安全的環境變數,再呼叫 mTLS API endpoint:
export OPENAI_WIF_ACCESS_TOKEN="short_lived_token"export OPENAI_MODEL="gpt-5.6-terra"
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"這裡的兩個認證要素缺一不可:
- client certificate 讓 mTLS endpoint 驗證連線端的 certificate trust。
- bearer token 代表 provider 與 service account mapping 已授權的 API 身分。
若要在應用程式中使用 SDK,OpenAI 官方 Node.js 範例會以 x509-transport 建立 credential,讓 SDK 處理 token exchange、mTLS request 和短效 token renewal:
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("Missing X.509 workload identity settings");}
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();}SDK 的可用版本、runtime 和 transport 依賴要以 OpenAI 當前文件為準。若你正在從舊 API 遷移,Responses API 的物件與 tool loop 仍需要另外盤點,可參考 Assistants API 到 Responses API 的遷移檢查表。
依錯誤類型排查
| 錯誤線索 | 優先檢查 |
|---|---|
| 403 或 method/path 相關錯誤 | token endpoint 是否用 POST、API 是否使用 mtls host、URL 是否完整 |
| invalid_subject_token | leaf/intermediate 順序、certificate validity、trusted root activation、admission 條件 |
| invalid_grant | provider ID、service account mapping、openai.subject 精確值、CEL conditions、root scope |
| API 呼叫被拒絕 | 是否同時帶 bearer token 與 client certificate,以及 mapping 的 service account 是否有必要 API 權限 |
不要用一般 api.openai.com 的 endpoint 測試這個流程,也不要在遇到 mTLS 錯誤時退回把長期 API key 寫入 workload。先確認 certificate chain、host、provider 和 mapping,再決定是否需要更新 SDK。
限制與輪替策略
目前要把幾個邊界寫進 runbook:
- X.509 WIF 只支援 OpenAI API,不支援 Codex。
- bearer token 不是 certificate-bound token;API 仍會獨立驗證 token 和 certificate,不能只保存其中一個。
- OpenAI 不會自動取得缺少的 intermediate certificate。
- X.509 provider 不支援用 raw JWT claims 做 mapping,也不能在建立後把 provider type 改成 OIDC。
- rotation 時讓 workload 提供完整的 leaf+intermediate chain;若 trusted root 不變,可以只輪替 leaf 或 intermediate。
- certificate、private key 和短效 token 都要從 log、source control、錯誤追蹤與 artifact 排除。
結論:把 API key 換成短效、可撤銷的 workload 身分
X.509 Workload Identity Federation 的核心不是「用憑證直接打 API」,而是用 trusted root 驗證 client certificate,再以 openai.subject 對應到最小權限 service account,換取短效 bearer token。最後的 Responses API request 還是要同時帶 token 與 certificate。
實作時依序驗證 trust、provider、mapping、token endpoint 和 API endpoint;先用 curl 在隔離環境確認完整 chain,再交給 SDK 管理 renewal。這樣長期 API key 不必進入 CI 或 workload,但身分、憑證輪替和最小權限仍然有清楚的管理邊界。
常見問題
Q: 有 client certificate 就可以直接呼叫 OpenAI API 嗎?
A: 不行。X.509 certificate 用於 mTLS 與 workload identity exchange;API request 還需要 exchange 得到的 bearer token。OpenAI 文件明確指出 certificate 單獨不足以授權 API 呼叫。
Q: token 過期後可以用 refresh token 更新嗎?
A: 這個流程沒有 refresh token。Token 最長一小時,且不能超過 certificate 剩餘效期;workload 應重新帶 certificate 做 token exchange。
Q: X.509 WIF 可以拿來驗證 Codex 嗎?
A: 目前不行。OpenAI 文件把 X.509 workload identity federation 限定在 OpenAI API;Codex 應使用 OIDC token 或 SPIFFE JWT-SVID 的方案。
參考資料:
OpenAI API Docs:Configure workload identity federation with X.509 certificates
回報錯字、失效連結,或告訴我你想看的延伸主題。