Repository navigation
feat(sandbox): proxy-side OCI request signing for CONNECT tunnels (credential_signing: oci) #3960
Description
Problem Statement
OpenShell replaces real secrets with opaque placeholders in sandbox environment variables and resolves them in HTTP headers (Bearer, Basic) before forwarding upstream. That is enough for the OCI Generative AI OpenAI-compatible endpoint, which is why the oci-genai example profile (#3904) works today.
Every other OCI API is signed, not bearer-authenticated. OCI request signing is an RSA-SHA256 HTTP Signature over date (request-target) host, plus content-length content-type x-content-sha256 for requests with a body, with keyId either <tenancy>/<user>/<fingerprint> (API key) or ST$<security-token> (session, instance, resource, or workload principal). Like SigV4 (#1631), a placeholder value produces an invalid signature that header replacement cannot fix. Sandboxed agents therefore cannot reach the native Generative AI API (/20231130), Object Storage, or any other OCI service through the credential proxy.
Proposed Design
Add proxy-side OCI signing in the sandbox supervisor's CONNECT tunnel path, as a sibling of SigV4. When credential_signing: oci is set on a REST endpoint (policy YAML or provider profile endpoint), the proxy:
- Terminates TLS as usual for
protocol: rest. - Strips the client's
authorization,date,x-date, andx-content-sha256headers before the fail-closed placeholder scan. - Resolves
OCI_KEY_IDandOCI_PRIVATE_KEY(PEM, optionalOCI_PRIVATE_KEY_PASSPHRASE) from theSecretResolver.OCI_KEY_IDis either the API-key triple or anST$token, so the same code path serves all OCI principals once the token is minted. - Sets
date(RFC 7231) if absent, computesx-content-sha256as base64 SHA-256 of the body for POST, PUT, and PATCH, and signs the header string with RSA PKCS#1 v1.5 SHA-256.ringis banned bydeny.toml;aws-lc-rsalready in the tree provides the primitive. - Injects
Authorization: Signature version="1",keyId="...",algorithm="rsa-sha256",headers="...",signature="..."and forwards.
No signing_service or region parsing is needed: OCI signatures are host-independent, which makes this simpler than SigV4.
endpoints:
- host: "inference.generativeai.*.oci.oraclecloud.com"
port: 443
protocol: rest
credential_signing: oci
rules:
- allow: { method: POST, path: "/20231130/actions/chat" }
- host: "objectstorage.*.oraclecloud.com"
port: 443
protocol: rest
credential_signing: oci
access: read-writeEdge cases to cover: header casing and duplicate host; requests without content-type (OCI accepts application/json default only for JSON bodies; sign what is sent); streaming or chunked bodies must be buffered or rejected because x-content-sha256 needs the full body; OCI rejects date skew beyond five minutes; passphrase-protected keys; non-commercial realms use other domains and need no code change.
Impact / Why This Matters
Without this, OCI users must inject a long-lived API key and private key as plain values, run a signing bridge per service (the workaround the aws-bedrock profile header warns against), or stay on the bearer-only Generative AI endpoint. Oracle Cloud Infrastructure is named as an infrastructure partner of the Open Agent Safety Platform and hosts a growing share of NVIDIA GPU capacity; agents running there need the same governed path AWS got with SigV4.
Acceptance Criteria
-
credential_signing: ociis accepted by policy and profile validation alongside thesigv4*values. - A sandbox holding only placeholders can
POST /20231130/actions/chaton the Generative AI native API andGET/PUTobjects on Object Storage, with the real key never present in the sandbox. - Signatures verify against the OCI Python SDK signer for fixed test vectors (generic headers, body headers,
ST$key ids). - Client-supplied
authorization,date,x-date, andx-content-sha256are stripped before signing and never leak upstream. - Example profiles for the native Generative AI API and Object Storage are added under
providers/with header notes, following Remove the inference provider table and provider profile telemetry buckets #3906. - Docs for the
credential_signingfield listocinext tosigv4.
Alternatives Considered
- Bridge-fronted profile like
aws-bedrock: works today but moves the OCI credential into another workload and grants the sandbox egress to it. Documented as the interim path, not the goal. - Sandbox-side signing with injected key material: OpenShell delivers env credentials as proxy-resolved placeholders by design, so an in-sandbox SDK cannot sign with them.
- Reuse
sigv4: different algorithm (RSA vs HMAC), different canonical string, different header set. A sibling module is cleaner than a shared abstraction over two schemes.
Agent Investigation
Checked against main at 5acaaba:
| Component | Key files | Role |
|---|---|---|
| Signing scheme enum | crates/openshell-supervisor-network/src/l7/mod.rs:83 (CredentialSigning) |
Add Oci variant |
| Policy validation | crates/openshell-policy/src/lib.rs:1222, :1529 |
Accept oci alongside sigv4, sigv4:body, sigv4:no_body |
| Profile schema | crates/openshell-providers/src/profiles.rs:360-361, :420-422 (credential_signing, signing_service) |
signing_service stays optional and unused for oci |
| Proxy wiring | crates/openshell-supervisor-network/src/l7/rest.rs:907 (strip), :985 (resolve keys), :1083, :1102 (apply) |
Mirror the SigV4 branches |
| Signer | new crates/openshell-supervisor-network/src/oci_signature.rs, sibling of sigv4.rs (585 lines) |
Canonical string, body hash, RSA-SHA256, header assembly |
| Example profiles | providers/oci-genai-native.yaml, providers/oci-object-storage.yaml |
Reviewable YAML only, per #3906 |
Related: #3879 (umbrella), #3904 (bearer profile, merged), #1631 / #1638 (SigV4 precedent). Principal-based minting of the ST$ token and session key is a separate follow-up, filed alongside this issue, and consumes this signing path unchanged.
Activity
fede-kamel commentedon Sep 30, 2026
Companion issue for the principal-based minting of the
ST$token and session key that this signing path consumes: #3961.fede-kamel commentedon Sep 30, 2026
Implementation: #3962. Live interop verified against Object Storage and the native Generative AI API in us-chicago-1 with an API-key principal; details in the PR.
purp commentedon Oct 1, 2026
purp commentedon Oct 1, 2026
Thanks for proposing this, @fede-kamel, and #3961 as well. While I'm favorably inclined, we like this sort of provider-specific addition to be brought to the community for acceptance, either in CNCF Slack
#openshell-devor in the weekly community meeting (Tue 9a Pacific/noon Eastern). Can you please bring them to either venue for discussion?I'm going to note this on #3961 as well, and move the attached PRs on both to draft with a linked note.
github-actions commentedon Oct 16, 2026
This issue has had no activity for 14 days and is now marked stale. It may be closed in 14 days if there is no further activity. Comment or remove the state:stale label to keep it open.