Usa SPIFFE como proveedor de identidad de cargas de trabajo. Para ello, intercambia un JWT-SVID de SPIFFE por un token de acceso de OpenAI de corta duración. Así, las cargas de trabajo autenticadas por SPIRE u otro proveedor de identidad compatible con SPIFFE pueden llamar a la API de OpenAI sin almacenar claves de API de larga duración.
Si usas Idira Secure Workload Access, sigue la guía de configuración de Idira para configurar el agente y la entrega de tokens.
OpenAI admite los JWT-SVID de SPIFFE que se pueden validar como tokens de sujeto JWT con un emisor, una audiencia, una fecha de vencimiento, una marca de tiempo de emisión y una firma verificable mediante un JWKS. OpenAI no admite los X.509-SVID de SPIFFE como tokens de sujeto para la federación de identidades de cargas de trabajo.
La especificación JWT-SVID exige las declaraciones sub, aud y exp. Para usar un JWT-SVID con OpenAI, el token también debe incluir las declaraciones iss e iat y el campo kid en el encabezado. Así, OpenAI puede validar el token según la configuración del proveedor de identidad de cargas de trabajo.
Un JWT-SVID no es un token de identidad de OpenID Connect. El proveedor de descubrimiento OIDC de SPIRE proporciona los metadatos de descubrimiento y las claves del JWKS que OpenAI necesita para validar el JWT-SVID. Esto no cambia la semántica del token definida por SPIFFE ni requiere un flujo de inicio de sesión OIDC.
Para conocer la terminología de SPIFFE y los requisitos de los tokens, consulta la especificación JWT-SVID y la especificación de la Workload API de SPIFFE.
Configurar SPIFFE
Configura tu proveedor SPIFFE para que emita JWT-SVID para las cargas de trabajo que necesiten llamar a la API de OpenAI. Estas instrucciones usan la terminología de SPIRE, pero la misma configuración de OpenAI se aplica a cualquier proveedor compatible con SPIFFE que emita JWT-SVID y proporcione un emisor y las claves de firma de un JWKS que permitan a OpenAI validar los tokens.
Tu configuración de SPIFFE debe proporcionar lo siguiente:
- Un ID de SPIFFE estable para la carga de trabajo, como
spiffe://example.org/ns/production/sa/openai-wif. - Una sola audiencia de JWT-SVID dedicada al acceso a OpenAI, como
https://api.openai.com/v1u otro valor opaco que elijas. - Una URL del emisor de JWT que figure en la declaración
issdel JWT-SVID para que OpenAI pueda validarlo. - Un JWKS público con las claves de firma de los JWT-SVID, disponible mediante el descubrimiento OIDC o mediante la carga de un JWKS.
- Un mecanismo que permita a la carga de trabajo obtener JWT-SVID nuevos de la Workload API de SPIFFE.
La audiencia es un identificador que debe coincidir exactamente. No tiene que ser un punto de acceso que reciba el JWT-SVID. Puedes usar https://api.openai.com/v1 u otro valor específico del servicio, siempre que la audiencia indicada en la solicitud a la Workload API de SPIFFE coincida con la que configures para el proveedor en OpenAI.
Siempre que sea posible, publica la información del emisor de SPIFFE a través de tu proveedor de descubrimiento OIDC de SPIRE. Asigna al parámetro jwt_issuer de SPIRE Server y al parámetro jwt_issuer del proveedor de descubrimiento OIDC la misma URL HTTPS del emisor que configurarás en OpenAI.
En la configuración de SPIRE Server:
server {
trust_domain = "example.org"
jwt_issuer = "https://spire-oidc.example.org"
}
En la configuración independiente del proveedor de descubrimiento OIDC de SPIRE:
# Relevant issuer fields only
domains = ["spire-oidc.example.org"]
jwt_issuer = "https://spire-oidc.example.org"
La configuración del proveedor de descubrimiento OIDC también requiere una fuente de claves, como server_api, workload_api o file, y un mecanismo para ofrecer el servicio, como ACME, un certificado TLS o un socket Unix. Consulta la documentación del proveedor de descubrimiento OIDC de SPIRE para ver todas las opciones de configuración.
El dominio de confianza de SPIFFE y el emisor de JWT son conceptos distintos. En este ejemplo, el sujeto del JWT-SVID es un ID de SPIFFE del dominio de confianza example.org, mientras que el emisor se identifica mediante su URL HTTPS:
{
"sub": "spiffe://example.org/ns/production/sa/openai-wif",
"iss": "https://spire-oidc.example.org"
}
El proveedor de descubrimiento OIDC de SPIRE ofrece un documento de descubrimiento OIDC y un punto de acceso JWKS que OpenAI puede usar cuando la opción Usar el JWKS cargado para verificar tokens está desactivada.
Si OpenAI no puede acceder al punto de acceso de descubrimiento de tu emisor, usa el modo de JWKS cargado. En ese modo, OpenAI sigue comparando el emisor configurado en el proveedor de identidad de cargas de trabajo con la declaración iss del JWT-SVID, pero verifica las firmas con el JWKS que guardes en formato JSON en la configuración del proveedor.
Nota: la especificación JWT-SVID de SPIFFE considera opcional el campo
kiddel encabezado JWT, pero OpenAI exige que los tokens de sujeto JWT incluyan el campokiden el encabezado para poder seleccionar la clave de firma del JWKS configurado. Si tu proveedor SPIFFE puede omitirkid, configúralo para que lo incluya cuando uses la federación de identidades de cargas de trabajo de OpenAI.
Para inspeccionar un JWT-SVID desde una carga de trabajo que pueda llamar a la Workload API de SPIFFE, solicita uno para la misma audiencia que configurarás en OpenAI. Ejecuta este comando en el mismo contexto de carga de trabajo que la aplicación, ya que la autorización de la Workload API depende de la identidad del proceso que la llama.
TOKEN=$(spire-agent api fetch jwt \
-socketPath /run/spire/sockets/agent.sock \
-audience "https://api.openai.com/v1" | sed -n '2p')
export TOKEN
Si tu carga de trabajo tiene más de un ID de SPIFFE, especifica la identidad en la solicitud:
TOKEN=$(spire-agent api fetch jwt \
-socketPath /run/spire/sockets/agent.sock \
-spiffeID "spiffe://example.org/ns/production/sa/openai-wif" \
-audience "https://api.openai.com/v1" | sed -n '2p')
export TOKEN
Verificar el token
Antes de configurar la federación de identidades de cargas de trabajo, exporta el JWT-SVID como TOKEN y ejecuta uno de estos ejemplos localmente para inspeccionar el encabezado y las declaraciones del token:
const parts = process.env.TOKEN?.split(".") ?? [];
if (parts.length !== 3) {
throw new Error("Expected a compact JWT with three segments");
}
const decode = (segment) => {
if (!/^[A-Za-z0-9_-]+$/.test(segment) || segment.length % 4 === 1) {
throw new Error("JWT segment is not valid Base64URL");
}
const bytes = Buffer.from(segment, "base64url");
if (bytes.toString("base64url") !== segment) {
throw new Error("JWT segment is not valid Base64URL");
}
const decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
const value = JSON.parse(decoded);
if (value === null || Array.isArray(value) || typeof value !== "object") {
throw new Error("JWT segment is not a JSON object");
}
return decoded;
};
console.log("Header:");
console.log(decode(parts[0]));
console.log("\nPayload:");
console.log(decode(parts[1]));Cada ejemplo decodifica el JWT sin verificar la firma del token. Usa un decodificador local para los tokens de producción y evita pegarlos en herramientas de terceros.
Un JWT-SVID de SPIFFE decodificado tendrá un aspecto similar al de este ejemplo:
{
"alg": "ES256",
"kid": "jwt-svid-key-1"
}
{
"iss": "https://spire-oidc.example.org",
"aud": ["https://api.openai.com/v1"],
"sub": "spiffe://example.org/ns/production/sa/openai-wif",
"iat": 1716235422,
"exp": 1716235722
}
Antes de intercambiar el token que recibiste, compara los valores del token decodificado con la configuración de OpenAI. Revisa alg y kid en el encabezado, y iss, aud, sub, iat y exp en la carga útil. El valor exacto de alg depende de la configuración de la clave de firma de JWT en SPIRE Server.
Configurar la federación de identidades de cargas de trabajo
Crea un proveedor de identidad de cargas de trabajo en OpenAI para el emisor de JWT-SVID de SPIFFE. Luego, agrega una asignación de cuenta de servicio que coincida con los ID de SPIFFE en los que confías.
Configurar el proveedor de identidad de cargas de trabajo
-
Crea el proveedor de identidad de cargas de trabajo. En Nombre, ingresa un valor único, como
spiffe-prod. En Descripción, escribe un texto comoProduction SPIFFE workloadspara que los administradores puedan identificar el proveedor. -
Configura el emisor y la audiencia. En URL del emisor OIDC, ingresa el valor exacto de la declaración
issdel JWT-SVID, por ejemplo,https://spire-oidc.example.org. En Audiencia, ingresa el valor de audiencia que indicaste en la solicitud a la Workload API de SPIFFE. En este ejemplo, el valor eshttps://api.openai.com/v1. -
Elige la fuente del JWKS. Deja desactivada la opción Usar el JWKS cargado para verificar tokens si OpenAI puede acceder a tu proveedor de descubrimiento OIDC de SPIRE. OpenAI usa el descubrimiento OIDC y el JWKS que obtiene por ese medio para verificar las firmas de los JWT-SVID.
Si OpenAI no puede acceder al emisor, activa Usar el JWKS cargado para verificar tokens y, en JSON del JWKS, ingresa el conjunto de claves públicas correspondiente a las claves de firma de los JWT-SVID. Carga el objeto JWKS público completo, incluido el arreglo
keysque contiene las claves. No incluyas datos de claves privadas. -
Agrega transformaciones de atributos solo si necesitas atributos derivados para la asignación. Si creas la asignación directamente a partir de
sub, no necesitas transformar los atributos. Usa transformaciones solo si necesitas derivar un valor para la asignación a partir de una o más declaraciones del token. Consulta la guía principal de federación de identidades de cargas de trabajo para saber cómo funcionan las transformaciones.
Configurar la asignación de cuenta de servicio
-
Crea una asignación de cuenta de servicio. En Nombre, ingresa un valor único dentro del proveedor de identidad de cargas de trabajo, como
production-openai-wif. En Descripción, escribe un texto comoProduction SPIFFE workload for OpenAI API accesspara indicar qué carga de trabajo puede usar la asignación. -
Configura la coincidencia con el ID de SPIFFE. En Clave, ingresa
suby, en Valor, ingresa el ID de SPIFFE de la carga de trabajo, por ejemplo,spiffe://example.org/ns/production/sa/openai-wif.Para las cargas de trabajo con privilegios, da preferencia a la coincidencia exacta del ID de SPIFFE. Usa un comodín al final solo si todos los ID de SPIFFE con ese prefijo deben poder generar tokens de acceso de OpenAI. Por ejemplo,
spiffe://example.org/ns/production/sa/*permite cualquier ruta de cuenta de servicio de producción que coincida con ese patrón. -
Elige el destino en OpenAI. En Proyecto, selecciona el proyecto de OpenAI al que pertenece la cuenta de servicio de destino. En Cuenta de servicio, selecciona la cuenta de servicio de OpenAI que puede usar la carga de trabajo de SPIFFE, por ejemplo,
spiffe-prod-openai-wif. MarcaCreate a new service account in this projectsi quieres crear una cuenta de servicio para esta asignación en lugar de reutilizar una existente. -
Limita los permisos de la API si es necesario. En Permisos, selecciona los que correspondan, como
api.model.requestyapi.vector_store.read, para restringir aún más el alcance de los tokens de acceso que se generen con esta asignación. Deja el campo de permisos en blanco si quieres evitar una restricción de alcance específica de WIF. El token seguirá otorgando acceso con los permisos de la cuenta de servicio asignada.
Usar el token en el código
Configura tu cliente del SDK de OpenAI para que intercambie un JWT-SVID de SPIFFE nuevo por un token de acceso emitido por OpenAI.
Los siguientes ejemplos del SDK suponen que tu integración con SPIFFE renueva el JWT-SVID y lo guarda en /var/run/spiffe/openai.jwt. Asegúrate de que solo la carga de trabajo pueda leer el archivo. Como los JWT-SVID tienen una vigencia breve, actualiza el archivo antes de que venza el token. Como alternativa, si es posible, usa una biblioteca SPIFFE de tu lenguaje en el proveedor de tokens de sujeto para obtener el JWT-SVID directamente de la Workload API de SPIFFE. Así evitas usar archivos con tokens desactualizados.
Configura OPENAI_IDENTITY_PROVIDER_ID y OPENAI_SERVICE_ACCOUNT_ID en el entorno de la carga de trabajo. El archivo del token contiene el token de sujeto externo. OPENAI_IDENTITY_PROVIDER_ID identifica al proveedor de identidad de cargas de trabajo de OpenAI y OPENAI_SERVICE_ACCOUNT_ID identifica la cuenta de servicio de OpenAI de destino. OpenAI usa las declaraciones del token para encontrar una asignación que coincida con ese proveedor y esa cuenta de servicio.
import { readFile } from "node:fs/promises";
import OpenAI from "openai";
const tokenPath = "/var/run/spiffe/openai.jwt";
const identityProviderId = process.env.OPENAI_IDENTITY_PROVIDER_ID;
const serviceAccountId = process.env.OPENAI_SERVICE_ACCOUNT_ID;
if (!identityProviderId || !serviceAccountId) {
throw new Error(
"Set OPENAI_IDENTITY_PROVIDER_ID and OPENAI_SERVICE_ACCOUNT_ID"
);
}
function spiffeJwtSvidProvider(path) {
return {
tokenType: "jwt",
getToken: async () => {
const token = (await readFile(path, "utf8")).trim();
if (!token) {
throw new Error("The SPIFFE JWT-SVID file is empty.");
}
return token;
},
};
}
const client = new OpenAI({
workloadIdentity: {
identityProviderId,
serviceAccountId,
provider: spiffeJwtSvidProvider(tokenPath),
},
});
const response = await client.responses.create({
model: "gpt-5.6-terra",
input: "Say hello from SPIFFE workload identity federation.",
});
console.log(response.output_text);Prácticas recomendadas para SPIFFE
- Usa JWT-SVID para la federación de identidades de cargas de trabajo de OpenAI. Los X.509-SVID sirven para TLS mutuo, pero el punto de acceso de intercambio de tokens de OpenAI no los acepta.
- Usa una sola audiencia dedicada al acceso a OpenAI. Evita audiencias amplias, como un dominio de confianza completo o el nombre de un entorno.
- Siempre que sea posible, exige coincidencias exactas con los ID de SPIFFE. Usa asignaciones con comodines solo cuando las identidades deban compartir el mismo límite de confianza por diseño.
- Asigna períodos de vigencia breves a los JWT-SVID para reducir el riesgo de ataques de repetición con tokens al portador. Los tokens de acceso de OpenAI nunca vencen después del token de sujeto externo utilizado en el intercambio.
- Rota las claves de firma con cuidado. Durante el período de rotación, publica tanto las claves públicas anteriores como las nuevas mediante el descubrimiento OIDC, o actualiza el JWKS público cargado antes de emitir JWT-SVID con un nuevo
kid. - Mantén sincronizados los relojes de SPIRE Server y de las cargas de trabajo. Un desfase considerable puede hacer que se rechacen JWT-SVID que de otro modo serían válidos, porque se consideran aún no vigentes, demasiado antiguos o vencidos.
- Protege el socket de la Workload API de SPIFFE. Un proceso que pueda obtener el JWT-SVID de una carga de trabajo puede intentar intercambiarlo para obtener acceso a OpenAI.
- Ajusta los límites de acceso de las cuentas de servicio de OpenAI a los permisos de tus aplicaciones y entornos. Evita compartir una cuenta de servicio con privilegios elevados entre cargas de trabajo de SPIFFE que no estén relacionadas.
- Supervisa los intercambios de tokens fallidos para detectar discrepancias en el emisor, la audiencia, la clave de firma o la asignación.