For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegação principal

Configuração da federação de identidades de cargas de trabalho para SPIFFE

Use o SPIFFE como provedor de identidade de cargas de trabalho trocando um JWT-SVID do SPIFFE por um token de acesso da OpenAI de curta duração. Isso permite que cargas de trabalho autenticadas pelo SPIRE ou por outro provedor de identidade compatível com SPIFFE chamem a API da OpenAI sem armazenar chaves de API de longa duração.

Para o Codex, use esta página para obter e inspecionar o JWT-SVID. Depois, configure a identidade de cargas de trabalho do Codex para gravar esse token em um arquivo e indicar sua localização ao Codex. O mapeamento de contas de serviço e os exemplos de SDK desta página se aplicam à API da OpenAI.

A OpenAI oferece suporte a JWT-SVIDs do SPIFFE que podem ser validados como tokens de sujeito JWT com emissor, público-alvo, expiração, data e hora de emissão e assinatura verificável por JWKS. A OpenAI não oferece suporte a X.509-SVIDs do SPIFFE como tokens de sujeito para a federação de identidades de cargas de trabalho.

A especificação JWT-SVID exige as declarações sub, aud e exp. Para usar um JWT-SVID com a OpenAI, o token também deve incluir as declarações iss e iat e um cabeçalho kid, para que a OpenAI possa validar o token com base na configuração do provedor de identidade de cargas de trabalho.

Um JWT-SVID não é um token de ID do OpenID Connect. O SPIRE OIDC Discovery Provider fornece metadados de descoberta e chaves JWKS para que a OpenAI possa validar o JWT-SVID; ele não altera a semântica SPIFFE do token nem exige um fluxo de login OIDC.

Para conhecer a terminologia do SPIFFE e os requisitos dos tokens, consulte a especificação JWT-SVID e a especificação Workload API do SPIFFE.

Configuração do SPIFFE

Configure seu provedor SPIFFE para emitir JWT-SVIDs para cargas de trabalho que precisam chamar a API da OpenAI. Estas instruções usam a terminologia do SPIRE, mas a mesma configuração da OpenAI se aplica a qualquer provedor compatível com SPIFFE que emita JWT-SVIDs com um emissor e material de assinatura JWKS que a OpenAI possa validar.

Sua configuração do SPIFFE deve fornecer:

  • Um ID SPIFFE estável para a carga de trabalho, como spiffe://example.org/ns/production/sa/openai-wif.
  • Um único público-alvo de JWT-SVID dedicado ao acesso à OpenAI, como https://api.openai.com/v1 ou outro valor opaco de sua escolha.
  • Uma URL do emissor JWT que apareça na declaração iss do JWT-SVID para validação pela OpenAI.
  • Um JWKS público para as chaves de assinatura dos JWT-SVIDs, disponibilizado por descoberta OIDC ou por upload de um JWKS.
  • Uma forma de a carga de trabalho buscar novos JWT-SVIDs na SPIFFE Workload API.

O público-alvo é um identificador que exige correspondência exata, não necessariamente um endpoint que recebe o JWT-SVID. Você pode usar https://api.openai.com/v1 ou outro valor específico do serviço, desde que os valores na solicitação à SPIFFE Workload API e na configuração do provedor na OpenAI sejam iguais.

Quando possível, exponha o emissor SPIFFE por meio do seu SPIRE OIDC Discovery Provider. Configure jwt_issuer no SPIRE Server e jwt_issuer no OIDC Discovery Provider com a mesma URL HTTPS do emissor que você configurará na OpenAI.

Na configuração do SPIRE Server:

server {
  trust_domain = "example.org"
  jwt_issuer   = "https://spire-oidc.example.org"
}

Na configuração separada do SPIRE OIDC Discovery Provider:

# Relevant issuer fields only
domains    = ["spire-oidc.example.org"]
jwt_issuer = "https://spire-oidc.example.org"

A configuração do OIDC Discovery Provider também precisa de uma fonte de material de chaves, como server_api, workload_api ou file, e de um mecanismo para disponibilizar o serviço, como ACME, um certificado TLS ou um socket Unix. Consulte a documentação do SPIRE OIDC Discovery Provider para ver todas as opções de configuração.

O domínio de confiança do SPIFFE e o emissor JWT são conceitos diferentes. Neste exemplo, o sujeito do JWT-SVID é um ID SPIFFE no domínio de confiança example.org, enquanto o emissor é a URL HTTPS do emissor:

{
  "sub": "spiffe://example.org/ns/production/sa/openai-wif",
  "iss": "https://spire-oidc.example.org"
}

O SPIRE OIDC Discovery Provider disponibiliza um documento de descoberta OIDC e um endpoint JWKS que a OpenAI pode usar quando a opção Usar JWKS enviado para verificação de tokens está desativada.

Se a OpenAI não conseguir acessar o endpoint de descoberta do seu emissor, use o modo de JWKS enviado. Nesse modo, a OpenAI continua comparando o emissor do provedor de identidade de cargas de trabalho com a declaração iss do JWT-SVID, mas verifica as assinaturas com base no JSON do JWKS que você salva no provedor de identidade de cargas de trabalho.

Observação: A especificação JWT-SVID do SPIFFE torna o cabeçalho JWT kid opcional, mas a OpenAI exige que os tokens de sujeito JWT incluam um cabeçalho kid para poder selecionar a chave de assinatura no JWKS configurado. Se o seu provedor SPIFFE puder omitir kid, configure-o para incluir esse cabeçalho ao usar a federação de identidades de cargas de trabalho da OpenAI.

Para inspecionar um JWT-SVID de uma carga de trabalho que pode chamar a SPIFFE Workload API, solicite um token para o mesmo público-alvo que você configurará na OpenAI. Execute este comando no mesmo contexto de carga de trabalho do aplicativo, pois a autorização da Workload API depende da identidade do processo que faz a chamada.

TOKEN=$(spire-agent api fetch jwt \
  -socketPath /run/spire/sockets/agent.sock \
  -audience "https://api.openai.com/v1" | sed -n '2p')
export TOKEN

Se a sua carga de trabalho tiver mais de um ID SPIFFE, solicite a identidade específica:

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

Verifique o token

Antes de configurar a federação de identidades de cargas de trabalho, exporte o JWT-SVID como TOKEN e execute um destes exemplos localmente para inspecionar seu cabeçalho e suas declarações:

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 exemplo decodifica o JWT sem verificar a assinatura do token. Use um decodificador local para tokens de produção e evite colá-los em ferramentas de terceiros.

Um JWT-SVID do SPIFFE decodificado terá uma estrutura semelhante a esta:

{
  "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
}

Use o token decodificado para comparar o token recebido com a configuração da OpenAI antes de trocá-lo. Verifique alg e kid no cabeçalho e iss, aud, sub, iat e exp no payload. O valor exato de alg depende da configuração da chave de assinatura JWT do seu SPIRE Server.

Configuração da federação de identidades de cargas de trabalho

Crie um provedor de identidade de cargas de trabalho na OpenAI para o emissor dos JWT-SVIDs do SPIFFE e adicione um mapeamento de conta de serviço que corresponda aos IDs SPIFFE em que você confia.

Configure o provedor de identidade de cargas de trabalho

  1. Crie o provedor de identidade de cargas de trabalho. Defina Nome com um valor exclusivo, como spiffe-prod. Use Descrição, com um valor como Production SPIFFE workloads, para ajudar os administradores a identificar o provedor.

  2. Defina o emissor e o público-alvo. Defina URL do emissor OIDC com o valor exato da declaração iss do JWT-SVID, como https://spire-oidc.example.org. Defina Público-alvo com o valor do público-alvo solicitado à SPIFFE Workload API. Neste exemplo, esse valor é https://api.openai.com/v1.

  3. Escolha a fonte do JWKS. Deixe a opção Usar JWKS enviado para verificação de tokens desativada quando a OpenAI puder acessar seu SPIRE OIDC Discovery Provider. A OpenAI usa a descoberta OIDC e o JWKS encontrado para verificar as assinaturas dos JWT-SVIDs.

    Se a OpenAI não puder acessar o emissor, ative Usar JWKS enviado para verificação de tokens e preencha JSON do JWKS com o conjunto de chaves públicas correspondente às chaves de assinatura dos JWT-SVIDs. Envie o objeto JWKS público completo, incluindo o array keys que contém as chaves. Não inclua material de chaves privadas.

  4. Adicione transformações de atributos somente se precisar de atributos derivados para o mapeamento. As transformações de atributos não são necessárias ao mapear diretamente a partir de sub. Use-as somente quando precisar derivar um valor de mapeamento de uma ou mais declarações do token. Consulte o guia principal de federação de identidades de cargas de trabalho para entender o comportamento das transformações.

Configure o mapeamento de conta de serviço

  1. Crie um mapeamento de conta de serviço. Defina Nome com um valor exclusivo dentro do provedor de identidade de cargas de trabalho, como production-openai-wif. Use Descrição, com um valor como Production SPIFFE workload for OpenAI API access, para explicar qual carga de trabalho pode usar o mapeamento.

  2. Configure a correspondência com o ID SPIFFE. Defina Chave como sub e Valor como o ID SPIFFE da carga de trabalho, como spiffe://example.org/ns/production/sa/openai-wif.

    Prefira a correspondência exata de IDs SPIFFE para cargas de trabalho privilegiadas. Use um curinga no final somente quando todos os IDs SPIFFE com esse prefixo devam poder gerar tokens de acesso da OpenAI. Por exemplo, spiffe://example.org/ns/production/sa/* permite qualquer caminho de conta de serviço de produção que corresponda a esse padrão.

  3. Escolha o destino na OpenAI. Defina Projeto como o projeto da OpenAI ao qual pertence a conta de serviço de destino. Defina Conta de serviço como a conta de serviço da OpenAI que a carga de trabalho SPIFFE pode usar, como spiffe-prod-openai-wif. Marque Create a new service account in this project se quiser criar uma nova conta de serviço para esse mapeamento em vez de reutilizar uma existente.

  4. Restrinja as permissões da API, se necessário. Selecione as Permissões apropriadas, como api.model.request e api.vector_store.read, para restringir ainda mais os tokens de acesso gerados a partir desse mapeamento. Deixe as permissões em branco para não adicionar uma restrição de escopo específica de WIF; o token continua autorizando o acesso como a conta de serviço mapeada.

Uso do token no código

Configure seu cliente do OpenAI SDK para trocar um novo JWT-SVID do SPIFFE por um token de acesso emitido pela OpenAI.

Os exemplos de SDK abaixo pressupõem que sua integração SPIFFE renova um JWT-SVID e o grava em /var/run/spiffe/openai.jwt. Restrinja a leitura do arquivo à carga de trabalho. Como os JWT-SVIDs têm curta duração, atualize o arquivo antes que o token expire. Como alternativa, quando possível, use uma biblioteca SPIFFE específica da linguagem no provedor de tokens de sujeito para buscar o JWT-SVID diretamente na SPIFFE Workload API e evitar arquivos de token desatualizados.

Defina OPENAI_IDENTITY_PROVIDER_ID e OPENAI_SERVICE_ACCOUNT_ID no ambiente da carga de trabalho. O arquivo de token contém o token de sujeito externo. OPENAI_IDENTITY_PROVIDER_ID identifica o provedor de identidade de cargas de trabalho da OpenAI, e OPENAI_SERVICE_ACCOUNT_ID identifica a conta de serviço de destino da OpenAI. Em seguida, a OpenAI encontra um mapeamento correspondente para esse provedor e essa conta de serviço com base nas declarações do token.

Autentique-se com um JWT-SVID do SPIFFE
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áticas recomendadas para SPIFFE

  • Use JWT-SVIDs para a federação de identidades de cargas de trabalho da OpenAI. Os X.509-SVIDs são úteis para TLS mútuo, mas não são aceitos pelo endpoint de troca de tokens da OpenAI.
  • Use um único público-alvo dedicado ao acesso à OpenAI. Evite públicos-alvo amplos, como um domínio de confiança inteiro ou o nome de um ambiente.
  • Use correspondência exata de IDs SPIFFE sempre que possível. Use mapeamentos com curingas somente para limites de confiança compartilhados intencionalmente.
  • Mantenha curtos os prazos de validade dos JWT-SVIDs para reduzir o risco de ataques de repetição com tokens de portador. Os tokens de acesso da OpenAI nunca permanecem válidos por mais tempo que o token de sujeito externo usado na troca.
  • Faça a rotação das chaves de assinatura com cuidado. Publique tanto as chaves públicas antigas quanto as novas por meio da descoberta OIDC durante a janela de rotação, ou atualize o JWKS público enviado antes de emitir JWT-SVIDs com um novo kid.
  • Mantenha sincronizados os relógios do SPIRE Server e das cargas de trabalho. Uma diferença significativa entre os relógios pode fazer com que JWT-SVIDs válidos nos demais aspectos sejam rejeitados por ainda não serem válidos, serem antigos demais ou estarem expirados.
  • Proteja o socket da SPIFFE Workload API. Um processo capaz de buscar o JWT-SVID de uma carga de trabalho pode tentar trocá-lo por acesso à OpenAI.
  • Alinhe os limites das contas de serviço da OpenAI aos limites de permissão dos seus aplicativos e ambientes. Não compartilhe uma conta de serviço com privilégios elevados entre cargas de trabalho SPIFFE sem relação entre si.
  • Monitore falhas na troca de tokens para identificar divergências de emissor, público-alvo, chave de assinatura e mapeamento.