Skip to content

Latest commit

 

History

History
184 lines (156 loc) · 11.1 KB

openshell-oauth.md

File metadata and controls

184 lines (156 loc) · 11.1 KB

Test experimental OpenShell OAuth

Verify the experimental Codex OAuth source with upstream OpenShell components and dedicated Codex. Use an owned, disposable environment; this procedure does not establish production support.

Prepare images and trust

Select official OpenShell v0.1.5, source commit bdb956f2cd65a635f1294fccf1d138d263bf650f, for the gateway, supervisor, and static sandbox launcher. Use the immutable digests of the stable 0.1.5 image tags and gateway/Workspace Helm charts from that version. The stable release rebuilds its images, so the source-commit image tags select different digests. This release includes operator GetProviderCredentials from OpenShell #4357 and the alias resolver correction in #4390.

Component Immutable image
Gateway ghcr.io/nvidia/openshell/gateway@sha256:ca0bc15a045017ee20bfab682f1a561eca6e6c6ed7d021d20641da24aaa6dfb6
Supervisor ghcr.io/nvidia/openshell/supervisor@sha256:fabcd01f656e9d23df4386f82e80b4f48b90f3452d7d5c58889007643a069161
Static sandbox launcher ghcr.io/nvidia/openshell/sandbox@sha256:e9adf9ecde328122414ad2ee8c6fc5d5b389e4cf168daf4357c46f5a77d55851

OCE keeps its JWT wrapper: Codex needs the local account claims, while the supervisor replaces the whole alias with the live credential. Stable-handle aliases already worked upstream across rotation. #4390 fixes version-alias resolution after cache eviction and corrects EndpointMismatch reporting for disallowed endpoints; it does not add JWT parsing or change refresh ownership.

The development launcher imports these same pins. When installing separately, select all three immutable references through gateway.image, supervisor.image, and sandboxRuntime.image. Selecting local charts alone does not select those binaries. Record actual launched versions. Earlier dev.8 and dev.47 evidence remains bound to its tested pins; neither qualifies v0.1.5. The release update does not establish a fix for the known provider-environment disconnect or a successful restart/withdrawal proof.

The previous selection was v0.1.4, source commit 5a7728c304b5528e954e9ae900cf21f84e1a12b1.

Configure the shared OpenShell Backend with its selected credential_refresh member, ordinary bearer authentication, the gateway CA, and separate operatorTls certificate/key paths. Enable the gateway's default-off operator authentication in its Helm values:

gatewayConfig:
  openshell.gateway.mtls_auth:
    operator_enabled: true

Issue the client certificate from its trusted client CA with exact OU=operator; use a direct TLS endpoint without termination or forwarded identity. The ordinary bearer keeps its Workspace/provider permissions. Credential export uses only the operator certificate. Do not put both identities on one request.

rootCertificatePath trusts OCC-to-OpenShell gRPC only. The dedicated Agent Gateway also needs to trust the private CA for OpenShell's advertised wss Harness endpoint.

Build the base OCE image using the OpenClaw, Codex, and Node versions pinned by the runtime Dockerfile and follow the runtime recipe. Keep its frozen lockfile, source checksum, and native filesystem checks. Record the tested source commit and actual launched versions with each proof; earlier runtime evidence does not qualify a newer pin.

Set BASE_RUNTIME_IMAGE to that locally available immutable image reference and OPENSHELL_PUBLIC_CA to the gateway's public PEM CA certificate. Build a deployment-specific derivative in a separate directory:

export RUNTIME_CONTEXT="$(mktemp -d)"
cp "$OPENSHELL_PUBLIC_CA" "$RUNTIME_CONTEXT/openshell-ca.crt"
cat > "$RUNTIME_CONTEXT/Dockerfile" <<'DOCKERFILE'
ARG BASE_RUNTIME_IMAGE
FROM ${BASE_RUNTIME_IMAGE}
USER root
COPY openshell-ca.crt /usr/local/share/ca-certificates/openshell.crt
RUN chmod 0644 /usr/local/share/ca-certificates/openshell.crt && update-ca-certificates
ENV NODE_USE_SYSTEM_CA=1
USER node
DOCKERFILE
docker build --build-arg BASE_RUNTIME_IMAGE="$BASE_RUNTIME_IMAGE" \
  --tag openclaw-enterprise-runtime:openshell-oauth "$RUNTIME_CONTEXT"

Include only the public certificate in this build context, never CA signing keys, operator credentials, or OAuth material. NODE_USE_SYSTEM_CA=1 makes Node use the augmented system trust store while retaining normal certificate and hostname verification. A CA change requires rebuilding and selecting the image.

For the Compose control-plane profile, select this local image through OCC_KUBERNETES_RUNTIME_IMAGE before dev-up; the launcher imports it and records an immutable reference. For real-runtime tests, follow the Kubernetes image import procedure and set OCC_TEST_KUBERNETES_GATEWAY_IMAGE and OCC_TEST_KUBERNETES_AGENT_IMAGE to the imported digest reference.

When OpenShell's ordinary OIDC issuer uses a private CA, retain the chart adjustment that preserves the gateway image's public roots; the selected upstream chart still needs it. server.oidc.caConfigMapName selects the issuer bundle through SSL_CERT_FILE, alongside SSL_CERT_DIR=/etc/ssl/certs. An issuer-only file without the public roots can allow OIDC login while breaking refresh at a public OAuth token endpoint. This is separate from the Agent Gateway's trust above; retain TLS verification on both paths.

Run the synthetic refresh proof

The manually selected openshell-oauth lane runs openshell-oauth-credentials-real.test.mjs against the real upstream gateway and a synthetic HTTPS OAuth issuer. It is outside ci and full, enables OCE_OPENSHELL_OAUTH_REAL=1, and requires these inputs in a private environment file:

Variable Required input
OCE_OPENSHELL_OAUTH_GATEWAY_ENDPOINT Direct HTTPS gateway endpoint with operator authentication enabled.
OCE_OPENSHELL_OAUTH_CA_FILE Public gateway CA file.
OCE_OPENSHELL_OAUTH_ADMIN_TOKEN_FILE Ordinary OIDC admin token for Workspace/provider operations.
OCE_OPENSHELL_OAUTH_OPERATOR_CERT_FILE Trusted client certificate with exact OU=operator.
OCE_OPENSHELL_OAUTH_OPERATOR_KEY_FILE Matching private key file, readable only by the test process.
OCE_OPENSHELL_OAUTH_DENIED_TOKEN_FILE Ordinary OIDC admin token without an operator certificate.
OCE_OPENSHELL_OAUTH_TEST_TOKEN_URL Synthetic issuer's HTTPS token endpoint.
OCE_OPENSHELL_OAUTH_KUBECONFIG Dedicated disposable cluster kubeconfig.
OCE_OPENSHELL_OAUTH_KUBERNETES_CONTEXT k3d-occ-dev-oce-oauth-poc; the test enforces this context and a loopback API.
OCE_OPENSHELL_OAUTH_WORKSPACE_CHART Matching OpenShell Workspace chart path.

The synthetic issuer must accept unique oauth-poc-refresh-initial-<UUID> grants, return a new access token and rotating refresh token with a one-hour lifetime, and reject reused refresh tokens. Use fresh fixture identities and state; never point this lane at an existing user's deployment.

node --env-file="$TEST_ENV_FILE" scripts/ci/run-tests.mjs run openshell-oauth \
  --state /tmp/oce-openshell-oauth-state.json \
  --results /tmp/oce-openshell-oauth-results.json

Missing prerequisites fail before execution. No real model credential is needed. The case uses the real Backend's ordinary and operator channels. A seeded token has four minutes remaining, below upstream's five-minute retrieval requirement; the fixture's shorter background-refresh margin puts scheduled refresh beyond the operation deadline. Retrieval must refresh it, a subsequent read must reuse it, and another explicit rotation must use the stored successor refresh token. The case also checks unchanged attachments and rejects ordinary bearer export and refresh-material export. It proves neither real ChatGPT login nor Harness injection/model execution. A TLS handshake or ready source does not prove those outcomes either.

For real-provider proof, use the Console for fresh device login, select the resulting source on a dedicated Codex Agent, and verify initial workspace files, an active deployment, a real model response, and a subsequent version using the same source. Select codex-plugin with catalogSource: hosted to verify directory discovery. Selected runtime plugins remain unsupported; discovery does not prove plugin execution. The remaining qualification boundaries are below.

Receiver fixtures and full-stack qualification

tests/integration/device-authorization-api.test.mjs exercises real Fastify, OCC, IAM and credential-source storage through login, Agent creation/version admission and plugin discovery. The external credential services and provider HTTP are simulated. It verifies session fencing, source grants, configuration discovery after session closure/expiry, and rejection of credential leakage. The Console OAuth browser case exercises those routes through the actual controls; Storybook is separate simulated UI evidence. Neither proves external token refresh or injection.

tests/conformance/kubernetes-compute.test.mjs exercises the real Compute preparation path with Driver transport fixtures. It checks source matching, Harness-only placeholder/metadata delivery, and refusal before provisioning on invalid attachments. tests/integration/codex-model-probe.test.mjs runs the emitted launcher in Docker with a substituted Codex executable, checking the generated auth file at both the probe and app-server boundaries. Select its immutable Node image with OCC_TEST_CODEX_PROBE_IMAGE.

The external ChatGPT receiving contract does not establish OAuth injection or refresh through OpenShell. The bundled real-runtime suite uses an API-key source. Qualifying an OAuth source requires the external Token Service and paired gateway: verify native Codex startup, inference and hosted app/MCP requests, access-token rotation without a Harness restart, restart, and refusal after source withdrawal. Receiver fixtures alone cannot prove those provider and gateway behaviors or native account checks that require real access-token claims.