Repository navigation
Oracle Cloud Infrastructure support: OCI GenAI provider profile, OCI request signing, principal refresh #3879
Description
User Story
As a platform engineer running agents on Oracle Cloud Infrastructure (OCI),
I want OpenShell sandboxes to reach OCI Generative AI and other OCI services through OpenShell's normal provider and policy model,
so that agents on OCI get the same "credential never enters the sandbox, endpoint-bound injection, hot-reloadable policy" guarantees that AWS and Google Cloud users already get.
Problem Statement
OpenShell ships example provider profiles, gateway credential refresh, and proxy-side request signing for AWS (aws, aws-s3, aws-bedrock, aws_sts_assume_role, SigV4) and Google Cloud (google-cloud, google-vertex-ai, google_service_account_jwt, GCE metadata emulation). There is no OCI coverage anywhere: no profile, no docs page, no refresh strategy, no signing scheme. Every "OCI" string in the repository refers to the Open Container Initiative.
OCI clients authenticate through five transports, and none of them is representable in OpenShell today except the first, which only works because it happens to be a bearer token:
| OCI transport | How it authenticates | OpenShell gap |
|---|---|---|
| Generative AI API key | Authorization: Bearer sk-... on the OpenAI-compatible /openai/v1 endpoint; key is compartment-scoped |
None once an example profile exists (implementation ready on a fork branch, see below) |
| API key (user principal) | RSA-SHA256 HTTP Signature header over (request-target) host date plus body hash headers, keyId=tenancy/user/fingerprint |
No proxy-side signing scheme; credential_signing accepts only sigv4* |
| Security token (session) | Same signature, keyId=ST$<token> with a short-lived token and ephemeral key |
Same signing gap, plus token refresh from a file (external) |
| Instance principal / resource principal | Same signature with a federated short-lived token | Same signing gap, plus a gateway refresh strategy that performs the federation |
| OKE workload identity | Same signature with a token obtained from the OKE proxymux using the pod's service-account token | Same signing gap, plus a Kubernetes-aware refresh strategy |
Impact / Why This Matters
Without this, OCI users must either hand the sandbox a long-lived OCI API key and private key as plain environment values (defeating the point of OpenShell), or run a signing bridge per service and grant the sandbox egress to the bridge. Both are the workarounds the aws-bedrock profile header already warns against. Oracle Cloud Infrastructure is named as an infrastructure partner in the Open Agent Safety Platform launch, and OCI hosts a growing share of NVIDIA GPU capacity, so this is a real adoption barrier rather than a corner case.
Proposed Design
Phase 1 (this issue; implementation ready at https://github.com/fede-kamel/OpenShell/tree/feat/oci-genai-provider, PR to follow once vouched): an example oci-genai inference profile plus a docs page. The profile declares the regional inference host pattern, restricts the credential to /openai/v1, and documents the OCI-side least-privilege setup (policy before key, one compartment, request.principal.type='generativeaiapikey'). It follows the deepinfra precedent: YAML example, telemetry bucket, overview table row, docs page. No new mechanism.
Phase 2: a credential_signing: oci scheme in the sandbox proxy, a sibling of sigv4. The profile declares oci_key_id and oci_private_key credentials; the proxy signs outbound requests to declared OCI hosts with the OCI HTTP Signature profile and the sandbox never holds the private key. This unlocks the native /20231130 Generative AI API, Object Storage, and every other OCI service with the API-key transport.
Phase 3: gateway refresh strategies oci_instance_principal, oci_resource_principal, and oci_oke_workload_identity that mint the short-lived token and ephemeral key pair the same way aws_sts_assume_role co-mints three AWS values, so principal-based transports work without any long-lived secret at the gateway either.
Happy to write the RFC for phases 2 and 3 if maintainers want one.
Acceptance Criteria
-
openshell provider profile import -f providers/oci-genai.yamllints and imports; a sandbox with the provider attached can callhttps://inference.generativeai.<region>.oci.oraclecloud.com/openai/v1/chat/completionswithOCI_GENAI_API_KEYand the real key never appears inside the sandbox. - A docs page under Providers explains the OCI transport matrix, the policy-before-key ordering, and the least-privilege IAM statement.
- (Phase 2) An endpoint with
credential_signing: ociis signed by the proxy and accepted by OCI for the native Generative AI API and Object Storage. - (Phase 3) A provider configured with an instance-principal or resource-principal refresh strategy rotates its token without operator action.
Alternatives Considered
- Reuse the
openaiprofile with a different host: rejected by the providers overview itself; each host needs its own profile so the credential cannot leak toapi.openai.com. - Bridge-fronted profile like
aws-bedrock: works today for the signed transports but moves the OCI credential into another workload the operator must secure and grants sandbox egress to it. Documented as the interim path. - Sandbox-side signing with injected key material: OpenShell delivers env credentials as placeholders resolved by the proxy, so an in-sandbox SDK cannot sign with them; this is by design and should stay that way.
Agent Investigation
Verified on the fork branch above against main at cf1bbb9: openshell provider profile lint passes, cargo test -p openshell-core --lib telemetry and cargo test -p openshell-server --lib grpc::provider::tests pass (167 tests), clippy with -D warnings, rustfmt, license headers, markdownlint, and fern check are clean. A sandbox with the provider attached receives only a placeholder in OCI_GENAI_API_KEY; the proxy forwards /openai/v1 requests to the regional OCI host and denies the native /20231130 path and other hosts.
Feasibility notes for phases 2 and 3:
- Refresh strategies are a closed proto enum (
ProviderCredentialRefreshStrategy) dispatched incrates/openshell-server/src/provider_refresh.rs; adding OCI principals is about five in-tree files. - Request signing is a closed enum (
CredentialSigning) incrates/openshell-supervisor-network/src/l7/mod.rswith the only implementation insigv4.rs; OCI signing would be a sibling module of similar size. - Compute and credential-store drivers are open gRPC boundaries, so an OCI Vault credential driver and an OKE-aware compute driver need no upstream change and are out of scope here.
Activity
fede-kamel commentedon Sep 29, 2026
Verification with a real OCI Generative AI API key (us-chicago-1), through an OpenShell 0.1.2 Docker gateway with the
oci-genaiprofile from https://github.com/fede-kamel/OpenShell/tree/feat/oci-genai-provider attached to aquay.io/curl/curlsandbox:POST /openai/v1/chat/completions,meta.llama-3.3-70b-instruct200, reply"OK from OCI"POST /openai/v1/responses,openai.gpt-oss-120b200GET /openai/v1/models404from OCI (documented; not a health check)POST /20231130/actions/chaton the same host403policy_deniedfrom the sandbox L7 proxyhttps://api.openai.comOCI_GENAI_API_KEYinside the sandboxUnit suites on the branch:
openshell-core,openshell-providers,openshell-policy,openshell-cli,openshell-server(lib) — 3409 passed, 0 failed, 14 ignored. Clippy-D warnings, rustfmt, license headers, markdownlint andfern checkare clean.fede-kamel commentedon Sep 29, 2026
Follow-up: full OpenAI-compatible surface exercised through the sandbox proxy with the
oci-genaiprofile (real key,us-chicago-1,quay.io/curl/curlsandbox):stream: true200, 12 SSEdata:frames,[DONE]marker, tokens reassembled correctly200,tool_calls[0].function.name = get_weather,finish_reason = tool_callsdata:URL200onmeta.llama-4-maverick-17b-128e-instruct-fp8("Red.") andgoogle.gemini-2.5-flash("Red")200, body forwarded unchanged (sent=262911B)openai.text-embedding-3-small200,object: listcohere.embed-multilingual-v3.0400 Unsupported OpenAI operationfrom OCI (documented)stream: true200, 62 SSE frames,response.created…response.incompleteGET/DELETE /openai/v1/responses/{id}400asking for a conversation storePUT /openai/v1/responses/{id}403 policy_deniedfrom the proxy (not in the profile rules)meta.llama-3.2-90b-vision-instruct,xai.grok-4404 Entity with key … not foundfrom OCI (not exposed on this endpoint; documented)Docs page updated with a Verified Capabilities section and the two OCI error messages above.
fede-kamel commentedon Sep 29, 2026
Phase 1 implementation is now open as #3904 (supersedes #3885, which was auto-closed before the vouch landed).
fede-kamel commentedon Sep 30, 2026
Phase 1 landed: #3904 merged 2026-09-29.
providers/oci-genai.yamlis importable frommain. Phases 2 (proxy-side OCI request signing) and 3 (principal-based refresh) remain open for maintainer disposition here.fede-kamel commentedon Sep 30, 2026
Split the remaining phases into focused issues, following the SigV4 (#1631) and STS (#1576) precedent: #3960 proxy-side OCI request signing (
credential_signing: oci), #3961 OCI principal refresh strategies. This issue stays as the umbrella.fede-kamel commentedon Sep 30, 2026
Closing to remove redundancy: phase 1 (bearer
oci-genaiprofile) merged in #3904; phase 2 (proxy-side OCI request signing) is tracked in #3960 with implementation in #3962; phase 3 (principal-based refresh strategies) is tracked in #3961. Design discussion belongs on those two focused issues.