Skip to content

feat(k8s): resolve the sandbox account name for driver-injected numeric UIDs on OpenShift #5034

Open

Description

@SeanCondon

User Story

I run OpenShell sandboxes on an OpenShift cluster.
OpenShift's restricted-v2 SCC assigns each namespace an allocated UID range, so every sandbox I create runs as a numeric UID like 1000920000.
I need tools inside the sandbox to resolve that UID to the image's sandbox account so shells, prompts, and scripts that display or match on the account name work as they do on other runtimes.

Problem Statement

The Kubernetes driver resolves the namespace's openshift.io/sa.scc.uid-range annotation and runs sandbox pods, init containers, and the supervisor under that numeric UID (by design, from #1959). But nothing reconciles the account name:

  • The image's /etc/passwd still maps sandbox to its build-time UID, so getpwuid() fails and id, whoami, ls -l, and shell prompts show the bare number.
  • The supervisor sets USER and HOME for the canonical process (session_user_and_home in crates/openshell-sandbox/src/process.rs), which papers over some tools, but LOGNAME is never set and anything consulting passwd directly still fails.
  • The VM driver already solves this by rewriting the guest's /etc/passwd/group/shadow (ensure_sandbox_guest_user in crates/openshell-driver-vm/src/rootfs.rs), but image layers are immutable on Kubernetes, so the Kubernetes driver has no equivalent.
  • The first-party sandbox runtime image is FROM scratch with no passwd file, so the name never resolves there at all.

Impact / Why This Matters

The numeric UID is the SCC working as intended and permissions are unaffected — the breakage is purely in name resolution — but the visible effect is that every OpenShift sandbox presents an anonymous numeric identity.

Workloads and agents that read the account name (shell prompts, dotfile lookup via $HOME-adjacent logic, tooling that logs or matches usernames, and license/entitlement checks as described in #4216) behave differently on OpenShift than on every other OpenShell runtime.

The only current workaround is a per-image entrypoint script that synthesizes a passwd via nss_wrapper (the pattern OpenShift s2i images use), which is per-user burden, cannot cover the first-party scratch image, and does not survive OpenShell's image-entrypoint replacement unless wired in manually.

Proposed Design

When the resolved sandbox identity is numeric, the supervisor should reconcile the account name for the canonical workload process.

Synthesize a passwd/group pair that maps the running UID/GID to the intended account name (defaulting to sandbox, or the image-declared account when the driver knows it), expose it to the workload via the nss_wrapper environment (NSS_WRAPPER_PASSWD/NSS_WRAPPER_GROUP/LD_PRELOAD), and set LOGNAME alongside the existing USER.

The synthesized files belong in the writable runtime-state area, not the image. The environment must apply only to the workload child — the existing LD_PRELOAD sanitization that keeps it away from supervisor and sandbox-runtime processes must be preserved.

Open question for maintainers: always-on when the identity is numeric with no matching passwd entry, or opt-in via driver/gateway configuration.

Acceptance Criteria

  • On an OpenShift cluster with an SCC-assigned UID, id inside a BYO-container sandbox reports uid=1000920000(sandbox) and whoami returns sandbox
  • USER, LOGNAME, and HOME are set consistently for the canonical process
  • Dynamically linked tools resolve the account name; statically linked tools continue to work unchanged (numeric display acceptable and documented)
  • LD_PRELOAD/NSS_WRAPPER_* never appear in the supervisor or sandbox-runtime process environments
  • The first-party FROM scratch runtime image is unaffected (no regression, documented limitation)
  • Non-OpenShift Kubernetes and other runtimes are unchanged

Alternatives Considered

  • Accept the numeric UID — display-only, but leaves OpenShift as the only runtime with an anonymous identity and pushes the workaround onto every user.
  • Per-image nss_wrapper entrypoint scripts — works today (OpenShift s2i pattern) but must be repeated in every image, conflicts with entrypoint replacement, and cannot cover the first-party image.
  • enable_user_namespaces (hostUsers: false) — an isolation feature, not a naming fix; OpenShift's user-namespace support is limited and it does not reconcile passwd.
  • The Optionally expose the host and user identity #4216 authenticated-username proposal — shares the passwd-reconciliation mechanism but sources the name from the authenticated principal for licensing; the two could share infrastructure while remaining separate options.

Agent Investigation

  • crates/openshell-driver-kubernetes/src/config.rs — resolve_sandbox_uid reads openshift.io/sa.scc.uid-range; resolved UID must fall within MIN_SANDBOX_UID..MAX_SANDBOX_UID.
  • crates/openshell-sandbox/src/process.rs:187 — session_user_and_home sets USER/HOME; comment already notes "Numeric identities have no reliable passwd entry."
  • crates/openshell-driver-vm/src/rootfs.rs:1021 — ensure_sandbox_guest_user shows the in-repo precedent for name reconciliation (real passwd rewrite, possible because the VM driver owns the rootfs).
  • crates/openshell-driver-vm/src/driver.rs (build_guest_environment) — LD_PRELOAD is already filtered from control-plane environments while reaching the workload child, so the proposed env injection fits the existing security model.

Checklist

  • I've reviewed existing issues and the published docs
  • This is a design proposal, not a "please build this" request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions