Para usar a Oracle Cloud Infrastructure (OCI) como provedor de identidade de cargas de trabalho, troque um token de acesso do Oracle Identity Cloud Service (IDCS) por um token de acesso de curta duração da OpenAI. Um principal de instância da OCI assina a solicitação de troca de token enviada a um domínio de identidade na mesma tenancy. A OpenAI valida o token obtido e autoriza a carga de trabalho da OCI a atuar como a conta de serviço da OpenAI definida no mapeamento.
Essa configuração dispensa o uso de uma chave de API da OpenAI, a criação de um aplicativo de recursos OAuth personalizado na Oracle e a concessão de permissões a grupos dinâmicos para acessar um aplicativo personalizado.
Configure a carga de trabalho da OCI
Execute a carga de trabalho em uma instância do OCI Compute com um principal de instância. Se você usa o Oracle Kubernetes Engine (OKE), confirme qual identidade assina a solicitação. O assinador padrão do principal de instância geralmente identifica o node de trabalho, e não um pod específico do Kubernetes.
O assinador obtém as credenciais do serviço de metadados de instância da OCI. Verifique se a carga de trabalho consegue acessar o endpoint de metadados pelo endereço link-local:
curl --fail --silent \
--header "Authorization: Bearer Oracle" \
http://169.254.169.254/opc/v2/instance/id
A carga de trabalho também precisa conseguir enviar solicitações HTTPS ao domínio de identidade da sua tenancy. O acesso ao endpoint de metadados em si dispensa o uso de um gateway NAT ou de uma conexão com a internet.
Solicite um token de identidade da Oracle
Use InstancePrincipalsSecurityTokenSigner do SDK da OCI para Python para assinar uma solicitação OAuth de troca de token destinada ao seu domínio de identidade:
POST https://<identity-domain>/oauth2/v1/token
Content-Type: application/x-www-form-urlencoded;charset=utf-8
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
scope=urn:opc:idm:__myscopes__
requested_token_type=urn:ietf:params:oauth:token-type:access_token
O escopo urn:opc:idm:__myscopes__ usa a autorização que o principal de instância já tem. Use o token de acesso retornado pelo IDCS como token do sujeito na federação de identidades de cargas de trabalho da OpenAI. Não substitua o público do token da Oracle por https://api.openai.com/v1. Configure o provedor da OpenAI com um público presente no token emitido pela Oracle.
Verifique o token
Atribua a TOKEN um token de acesso gerado pela própria carga de trabalho da OCI. Em seguida, use o decodificador JWT local existente para examinar as declarações do token:
const parts = process.env.TOKEN?.split(".") ?? [];
if (parts.length !== 3) {
throw new Error("Expected a compact JWT with three segments");
}
if (!/^[A-Za-z0-9_-]+$/.test(parts[1]) || parts[1].length % 4 === 1) {
throw new Error("JWT payload is not valid Base64URL");
}
const bytes = Buffer.from(parts[1], "base64url");
if (bytes.toString("base64url") !== parts[1]) {
throw new Error("JWT payload is not valid Base64URL");
}
const decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
const claims = JSON.parse(decoded);
if (claims === null || Array.isArray(claims) || typeof claims !== "object") {
throw new Error("JWT payload is not a JSON object");
}
console.log(decoded);O decodificador examina o token sem verificar a assinatura. Trate os tokens originais como dados sensíveis. Não os registre em logs nem cole tokens de produção em decodificadores JWT de terceiros.
Um token de acesso da Oracle, depois de decodificado, pode conter as seguintes declarações:
{
"iss": "https://identity.oraclecloud.com/",
"aud": [
"https://idcs-example.us-phoenix-1.identity.oraclecloud.com",
"https://idcs-example.identity.oraclecloud.com"
],
"sub_type": "instance",
"ipst_instance": "ocid1.instance.oc1.phx.<instance-id>",
"ipst_compartment": "ocid1.compartment.oc1..<compartment-id>",
"domain_id": "ocid1.domain.oc1..<domain-id>",
"ca_ocid": "ocid1.tenancy.oc1..<tenancy-id>",
"tenant": "idcs-example",
"exp": 1782369434,
"iat": 1782365834
}
Use o token emitido pelo seu próprio domínio de identidade como referência. Configure o valor exato de iss e um dos valores de aud desse token. Ao autorizar uma carga de trabalho, dê preferência às declarações imutáveis ipst_instance, ipst_compartment, domain_id e ca_ocid.
Configure a federação de identidades de cargas de trabalho
Crie um provedor de identidade de cargas de trabalho para o seu domínio de identidade da Oracle. Em seguida, adicione um mapeamento para a instância ou o compartimento da OCI que poderá usar a conta de serviço de destino da OpenAI.
Configure o provedor de identidade de cargas de trabalho
-
Crie o provedor de identidade de cargas de trabalho. Em Nome, informe um valor exclusivo, como
oracle-cloud-prod. Use o campo Descrição para identificar a carga de trabalho confiável, por exemplo,Production OCI instance principal. -
Defina o emissor e o público. Em URL do emissor OIDC, informe o valor da declaração
issdo token, por exemplo,https://identity.oraclecloud.com/. Em Público, informe um dos valores deauddo mesmo token. -
Configure a descoberta OIDC específica do tenant, se disponível. Se a opção Usar URL personalizada para descoberta OIDC aparecer em Avançado, ative-a. Em URL personalizada de descoberta OIDC, informe a URL do domínio de identidade do seu tenant, como
https://idcs-example.identity.oraclecloud.com. A OpenAI consultahttps://idcs-example.identity.oraclecloud.com/.well-known/openid-configuratione usa ojwks_urido documento de descoberta para obter as chaves públicas de assinatura do tenant. Se a opção de descoberta personalizada não aparecer, ative Usar JWKS enviado para verificação de tokens e faça upload do JWKS público obtido emhttps://<identity-domain>/admin/v1/SigningCert/jwk. -
Adicione transformações de atributos somente se precisar de atributos derivados. Você pode usar declarações originais da Oracle como
ipst_instance,ipst_compartment,domain_ideca_ociddiretamente nas asserções de mapeamento da conta de serviço. Para derivar explicitamente um atributo de instância, insirainstancecom a expressãoassertion.ipst_instancepara criaropenai.instance.
A documentação da Oracle sobre descoberta OpenID Connect explica a importância da descoberta personalizada. O documento de descoberta pode declarar o emissor global https://identity.oraclecloud.com/ e, ao mesmo tempo, publicar o endpoint de token e o jwks_uri no domínio de identidade específico do tenant. Mantenha o emissor global em URL do emissor OIDC e use o domínio do tenant em URL personalizada de descoberta OIDC.
Se o seu domínio de identidade publicar os metadados de descoberta na URL do emissor do token,
deixe a descoberta personalizada desativada e use a descoberta OIDC padrão. Se a OpenAI
não conseguir acessar o documento de descoberta ou o endpoint de chaves de assinatura do tenant,
desative a descoberta personalizada, ative Usar JWKS enviado para verificação de tokens e
faça upload do JWKS público do tenant obtido em
https://<identity-domain>/admin/v1/SigningCert/jwk. Não é possível usar a descoberta personalizada e
o JWKS enviado ao mesmo tempo. Atualize as chaves enviadas quando a Oracle fizer a rotação dos
certificados de assinatura.
Configure o mapeamento da conta de serviço
-
Crie um mapeamento de conta de serviço. Em Nome, informe um valor exclusivo, como
oracle-instance-prod, e adicione uma descrição que identifique a carga de trabalho confiável da OCI. -
Use a identidade estável da OCI com o escopo mais restrito possível. Para conceder acesso a uma única instância, defina Chave como
ipst_instancee, em Valor, informe o OCID exato da instância que consta no token verificado. Para conceder acesso às instâncias de um compartimento, defina Chave comoipst_compartmente, em Valor, informe o OCID exato do compartimento. -
Restrinja o domínio e a tenancy quando necessário. Adicione linhas ao mapeamento para
domain_idouca_ocidpara restringir a carga de trabalho a um domínio de identidade ou a uma tenancy específica da Oracle. Adicionesub_typecom o valorinstancese o token contiver essa declaração e você quiser exigir um principal de instância. O token precisa atender aos critérios de todas as linhas do mapeamento. -
Escolha a conta de destino na OpenAI. Em Projeto, selecione o projeto ao qual a conta de serviço pertence. Em seguida, selecione a Conta de serviço que a carga de trabalho confiável da OCI poderá usar.
-
Restrinja as permissões da API, se necessário. Selecione apenas as Permissões de que a carga de trabalho precisa. O mapeamento pode restringir as permissões da conta de serviço selecionada, mas não pode conceder permissões que a conta ainda não tenha.
Uma carga de trabalho do OKE que usa o assinador padrão do principal de instância herda a identidade do node de trabalho. Um mapeamento no nível da instância autoriza o node inteiro, e não apenas um pod. Se precisar isolar pods que compartilham um node de trabalho, use uma identidade de carga de trabalho mais específica que a OCI aceite.
Use o token no código
Instale os pacotes Python da OpenAI e da OCI, além do Requests:
pip install openai oci requests
Para Ruby, instale as gems da OpenAI e da OCI:
gem install openai oci
Defina OCI_IDENTITY_DOMAIN_URL como a URL base do domínio de identidade que está na mesma tenancy da carga de trabalho. Atribua a OPENAI_IDENTITY_PROVIDER_ID e OPENAI_SERVICE_ACCOUNT_ID os IDs do provedor da OpenAI e da conta de serviço associada no mapeamento, respectivamente.
O exemplo a seguir usa o principal de instância da OCI para assinar uma solicitação de troca de token da Oracle e retorna o token de acesso do IDCS ao SDK da OpenAI. Quando necessário, o SDK troca esse token por um token de acesso de curta duração da OpenAI:
import os
import oci
import requests
from openai import OpenAI
from openai.auth import SubjectTokenProvider
def oracle_instance_principal_token_provider(
identity_domain_url: str,
) -> SubjectTokenProvider:
def get_token() -> str:
signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
response = requests.post(
f"{identity_domain_url.rstrip('/')}/oauth2/v1/token",
data={
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"scope": "urn:opc:idm:__myscopes__",
"requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
},
headers={
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
},
auth=signer,
timeout=30,
)
response.raise_for_status()
token = response.json().get("access_token")
if not isinstance(token, str) or not token:
raise RuntimeError("Oracle IDCS did not return an access token.")
return token
return {"token_type": "jwt", "get_token": get_token}
client = OpenAI(
workload_identity={
"identity_provider_id": os.environ["OPENAI_IDENTITY_PROVIDER_ID"],
"service_account_id": os.environ["OPENAI_SERVICE_ACCOUNT_ID"],
"provider": oracle_instance_principal_token_provider(
os.environ["OCI_IDENTITY_DOMAIN_URL"]
),
},
)
response = client.responses.create(
model="gpt-5.6-terra",
input="Say hello from Oracle Cloud Infrastructure workload identity federation.",
)
print(response.output_text)O provedor de tokens do sujeito solicita um novo token da Oracle quando o SDK da OpenAI precisa renovar a credencial de identidade da carga de trabalho. Nunca imprima nem armazene de forma persistente o token do sujeito da Oracle ou o token de acesso da OpenAI obtido na troca.
Recomendações de segurança para a OCI
- Mapeie uma única instância com
ipst_instancequando apenas uma carga de trabalho deve ter acesso. - Use
ipst_compartmentsomente quando todas as instâncias elegíveis desse compartimento devem compartilhar o mapeamento. - Adicione
domain_idouca_ocidpara aplicar as restrições de domínio de identidade e de tenancy. - Use uma conta de serviço da OpenAI separada para cada aplicativo e ambiente.
- Antes de contar com o isolamento no nível do pod, verifique se o token do OKE representa um node de trabalho.
- Use o público presente no token emitido pela Oracle. Não presuma que o público seja específico da OpenAI.
- Se o seu domínio de identidade não puder usar a descoberta OIDC, substitua as chaves públicas enviadas sempre que a Oracle fizer a rotação das chaves de assinatura.