X.509 工作负载身份联合允许工作负载将 TLS 客户端证书中的身份交换为短期 OpenAI 访问令牌。随后,工作负载同时使用访问令牌和受认可的客户端证书调用 OpenAI API。此流程替代的是 API 密钥,而非客户端证书。
OpenAI API 支持 X.509 工作负载身份联合。 Codex 不支持此功能。对于 Codex,请使用 OIDC Token 或 SPIFFE JWT-SVID,并按照 Codex 工作负载身份指南操作。
有关 Token 交换请求和响应的详细信息,请参阅工作负载身份 Token 交换参考资料。有关双向 TLS 权限、证书要求、激活、mTLS 主机和轮换的信息,请参阅双向 TLS 指南。
工作原理
X.509 工作负载身份交换包含五个部分:
- 您的组织在现有的双向 TLS 设置中上传并激活受信任的根证书。
- X.509 工作负载身份提供方从经过验证的客户端证书中派生
openai.*属性。它必须派生出一个非空的openai.subject值。 - 服务账户映射授权派生的身份使用项目中的一个 OpenAI 服务账户。
- 工作负载向
mtls.auth.openai.com上的 X.509 Token 端点出示其证书,并请求短期持有者 Token。证书来自 TLS 连接;请求体中不包含subject_token。 - 工作负载向
mtls.api.openai.com上的 API 路由出示持有者 Token 和客户端证书,以获得 API 授权。
API 请求中的持有者 Token 和证书分别接受独立的授权检查。仅凭证书无法获得 OpenAI API 调用授权。
开始之前
您需要:
- 管理组织的双向 TLS 证书和工作负载身份提供方的权限。
- 供工作负载使用的项目和服务账户。
- 客户端证书、其私钥,以及构建通向受信任根证书的路径所需的所有中间证书。
- 在组织或项目级别处于激活状态的受信任根证书。
请勿将私钥纳入源代码版本控制,并将私钥访问权限限制为仅供使用它们的工作负载访问。请勿在日志中记录私钥、证书内容或返回的访问令牌。
配置双向 TLS 证书信任
X.509 工作负载身份提供方复用您组织现有的双向 TLS 证书配置。它们不会上传证书,也不会维护单独的证书信任库。
请参阅双向 TLS 指南,了解证书要求、 mTLS 主机、证书激活行为、CEL 过滤器和 客户端配置。然后打开组织设置 > 安全 > 双向 TLS,上传 PEM 格式的受信任证书,并为组织或 每个将使用 X.509 工作负载身份联合的项目激活该证书。
如果您的客户端证书通过中间证书构成证书链,请配置稳定的信任锚,并在 TLS 握手期间按顺序出示叶证书和当前的中间证书。OpenAI 使用请求中提供的中间证书,不会从证书 URL 获取缺失的中间证书。
配置 X.509 提供方
要配置 X.509 提供方,请执行以下操作:
- 打开组织设置 > 安全 > 工作负载身份提供方,然后选择 创建身份提供方。
- 将 提供方类型选为 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。请记录这两个标识符;工作负载会在 Token 交换期间发送它们。
通过 SDK 使用 X.509 工作负载身份
为证书链、私钥、提供方和服务账户设置环境变量:
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 会在 Token 交换和 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 版本:JavaScript 7.8.0 或更高版本(需安装 undici 对等依赖项)、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。您也可以改为向 SDK 提供基于 PEM 或硬件的管理器。
手动使用证书进行交换
要直接检查或实现 Token 交换协议,请向 X.509 Token 端点出示证书:
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
交换成功后会返回一个普通的短期持有者 Token:
{
"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 的单位及含义,请参阅 Token 交换响应字段。
从成功响应中读取 access_token 值,并将其存入应用程序的凭据存储或 OPENAI_WIF_ACCESS_TOKEN 等环境变量中。请将其作为机密信息处理,不要打印、记录到日志或提交到代码仓库。
手动调用 OpenAI API
将 OPENAI_MODEL 设置为当前默认模型 gpt-6-astra,或目标项目可用的其他模型。然后,将持有者 Token 和受认可的客户端证书发送到 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"
使用持有者 Token 替代 API 密钥,并继续在 API 请求中出示受认可的客户端证书。
持有者 Token 与证书之间没有密码学绑定。API 请求复用交换时的证书是最直接的配置方式,但也可以使用另一张证书,前提是该证书能独立满足当前相同的 API mTLS 策略。
Token 有效期与续期
X.509 工作负载身份 Token 的有效期最长为一小时,且不会晚于已验证的客户端证书到期。交换操作不会返回刷新 Token。请再次执行证书交换,以获取新的访问 Token。
手动交换时,请将 expires_at 与访问 Token 一同保存,并安排在该时间戳所指的时间之前再次执行交换。请为时钟偏差和请求延迟预留时间。示例请参阅 Token 续期指南。
轮换中间证书无需更改已配置的根证书。请在后续交换和 API 请求中提供新的完整证书链。
排查 Token 交换问题
X.509 Token 交换会返回通用的 OAuth 错误,不会透露证书、根证书、提供方或映射的详细信息。
| 结果 | 常见原因 |
|---|---|
HTTP 403 | 请求使用的方法或路径与 mtls.auth.openai.com 上要求的 POST /oauth/token 不完全一致。 |
invalid_subject_token | TLS 客户端证书缺失或无效,提供的证书链无法追溯到已激活的根证书,证书不在有效期内,或双向 TLS 证书准入规则拒绝了该证书。 |
invalid_grant | 提供方或映射无效或已禁用,提供方的 属性条件 表达式拒绝了该身份,没有已激活的适用根证书,或没有匹配的映射。 |
| 服务器错误 | OpenAI 返回了临时服务器错误。请按照您常用的临时错误处理策略重试。 |
X.509 交换绝不会回退到 OIDC 或常规 OAuth 流程。
限制
- X.509 工作负载身份提供方不会维护单独的证书信任存储。
- 持有者 Token 不与证书绑定,也不使用 DPoP 或
cnf声明。 - 证书交换并不意味着仅凭证书即可获得 API 授权。API 请求仍需提供持有者 Token 和可被接受的客户端证书。
- OpenAI 不会从 AIA URL 获取缺失的中间证书。请在 TLS 协商期间提供完整的证书链。
- OpenAI 在此流程中不会执行证书吊销列表(CRL)或 OCSP 检查。请结合双向 TLS 根证书、提供方和映射的控制措施,以及已签发 Token 有效期较短这一特点,制定证书安全事件响应方案。
- 此流程并未新增对 SPIFFE X.509-SVIDs 的支持。SPIFFE 指南仍使用 JWT-SVIDs。