Files
Taylor Mutch 7a0c444445 refactor!(auth): drop SSH handshake secret (#1274)
* refactor!(auth): drop SSH handshake secret in favor of mTLS

The OPENSHELL_SSH_HANDSHAKE_SECRET / x-sandbox-secret mechanism was
misnamed: it does not authenticate SSH (which flows over the
RelayStream gRPC RPC and is gated by mTLS plus supervisor Unix-socket
permissions). It only gated a small set of sandbox-to-gateway
control-plane RPCs, and production deployments already enforce mTLS
on that channel — so the shared secret was redundant.

Replace the secret check with an mTLS-presence marker. Sandbox-class
methods (ReportPolicyStatus, PushSandboxLogs,
GetSandboxProviderEnvironment, SubmitPolicyAnalysis, GetSandboxConfig,
GetInferenceBundle) accept callers without a Bearer token; the gRPC
mTLS handshake is the trust boundary. Dual-auth methods treat
Bearer-present as full-scope CLI access and Bearer-absent as
sandbox-restricted scope via validate_sandbox_caller_update.

Drops the secret from all drivers (K8s, Podman, VM), the sandbox gRPC
interceptor, the Helm chart (values + pre-install hook + StatefulSet
env), the RPM bootstrap script, the man pages, and the
debug-openshell-cluster skill. Also removes the never-read
ssh_handshake_skew_secs flag and config field.

BREAKING CHANGE: --ssh-handshake-secret / OPENSHELL_SSH_HANDSHAKE_SECRET
and --ssh-handshake-skew-secs / OPENSHELL_SSH_HANDSHAKE_SKEW_SECS are
removed from the gateway, sandbox, and all driver binaries. The
openshell-ssh-handshake K8s Secret is no longer managed by the chart;
operators may delete the orphan. Deployments using
--disable-gateway-auth must enforce caller authentication at the
fronting proxy, since the gateway no longer validates a per-request
secret on sandbox-class methods.

Refs OS-174.

* docs(auth): scrub residual SSH handshake secret references

Sweep across docs, e2e scripts, the Podman driver README/NETWORKING
notes, the RPM/Helm/setup guides, the gateway man page, and RFC 0003
to remove instructions and examples that still referenced
OPENSHELL_SSH_HANDSHAKE_SECRET / --ssh-handshake-secret /
ssh_handshake_skew_secs. The mechanism is gone; nothing should still
suggest setting it. Negative-assertion regression tests are kept so
the env var cannot silently be re-introduced.

* test(drivers): drop SSH handshake secret negative-assertion tests

The supporting code, env vars, CLI flags, and config plumbing are
gone — these tests asserted absence of strings that no longer have
any path to being set. Remove the guards from the Docker, Podman,
Kubernetes, and VM driver test modules.
2026-05-14 13:14:30 -07:00
..

openshell-driver-docker

Docker-backed compute driver for local OpenShell gateways.

The driver manages sandbox containers through the local Docker daemon with the bollard client. It is intended for developer environments where Docker is already available and running Kubernetes would be unnecessary.

Runtime Model

The gateway runs as a host process. The Docker driver creates one container per sandbox and starts the openshell-sandbox supervisor inside that container. The supervisor then creates the nested sandbox namespace for the agent process.

Docker containers currently use host networking. This lets a supervisor reach a gateway bound to 127.0.0.1 without requiring a separate bridge listener, NAT rule, or userland proxy. The container also receives host.openshell.internal -> 127.0.0.1 so local host services have a stable OpenShell-owned name.

Container Contract

The driver-controlled container settings are part of the sandbox security contract:

Setting Purpose
user = "0" The supervisor needs root inside the container to prepare namespaces, mounts, Landlock, and seccomp.
network_mode = "host" Lets the supervisor call back to loopback gateway endpoints.
cap_add Grants supervisor-only capabilities required for namespace setup and process inspection.
apparmor=unconfined Avoids Docker's default profile blocking required mount operations.
restart_policy = unless-stopped Keeps managed sandboxes resumable across daemon or gateway restarts.
CDI GPU request Uses the sandbox gpu_device value when set; otherwise requests all NVIDIA GPUs when the sandbox spec asks for GPU support and daemon CDI support is detected.

The agent child process does not retain these supervisor privileges.

Supervisor Binary Resolution

The Docker driver bind-mounts a host-side Linux openshell-sandbox binary into each sandbox container. Resolution order is:

  1. --docker-supervisor-bin / OPENSHELL_DOCKER_SUPERVISOR_BIN.
  2. A sibling openshell-sandbox next to the running openshell-gateway binary.
  3. A local Linux cargo target build for the Docker daemon architecture.
  4. --docker-supervisor-image / OPENSHELL_DOCKER_SUPERVISOR_IMAGE, or the release-matched default supervisor image, extracting /openshell-sandbox.

Release and Docker-image gateway builds bake the matching supervisor image tag into the binary at compile time. The default Docker supervisor image is not :latest unless a custom build explicitly sets that tag.

Callback and TLS

OPENSHELL_ENDPOINT is injected from the gateway's configured gRPC endpoint without rewriting. Because the container uses host networking, loopback endpoints such as http://127.0.0.1:8080 resolve to the host gateway.

For HTTPS endpoints, the server certificate must include the endpoint host as a subject alternative name. Docker sandboxes also need the client TLS bundle mounted into the container and exposed with:

  • OPENSHELL_TLS_CA
  • OPENSHELL_TLS_CERT
  • OPENSHELL_TLS_KEY

HTTP endpoints reject TLS material because the supervisor would not use it.

Environment Ownership

The driver merges template environment and sandbox spec environment first, then overwrites security-critical keys:

  • OPENSHELL_ENDPOINT
  • OPENSHELL_SANDBOX_ID
  • OPENSHELL_SANDBOX
  • OPENSHELL_SSH_SOCKET_PATH
  • OPENSHELL_SANDBOX_COMMAND
  • TLS path variables when HTTPS is enabled

Do not allow sandbox images or templates to override these values.