Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions deploy/helm/openshell/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ discovery endpoint or its TLS CA.
| server.policyValidationFailureMode | string | `"fail_closed"` | Posture when a candidate sandbox policy fails validation. `fail_closed` deactivates the previous policy; `retain_last_valid` keeps it active. |
| server.providerTokenGrants.spiffe.enabled | bool | `false` | Mount the SPIFFE Workload API socket into gateway and sandbox pods for dynamic provider token grants. |
| server.providerTokenGrants.spiffe.workloadApiSocketPath | string | `"/spiffe-workload-api/spire-agent.sock"` | Path to the SPIFFE Workload API socket mounted into gateway and sandbox pods. |
| server.sandboxGid | string | `""` | Explicit GID paired with sandboxUid. Empty (default) = omit the field; the driver then reuses the resolved UID as the GID. Setting this without sandboxUid has no effect on UID resolution. Any non-root GID is valid. |
| server.sandboxImage | string | `"ghcr.io/nvidia/openshell-community/sandboxes/base:latest"` | Default sandbox image used when requests do not specify one. |
| server.sandboxImagePullPolicy | string | `""` | Kubernetes imagePullPolicy for sandbox pods. Empty = Kubernetes default (Always for :latest, IfNotPresent otherwise). Set to "Always" for dev clusters so new images are picked up without manual eviction. |
| server.sandboxImagePullSecrets | list | `[]` | Image pull secrets attached to sandbox pods. Referenced Secrets must exist in the sandbox namespace. |
Expand All @@ -276,6 +277,7 @@ discovery endpoint or its TLS CA.
| server.sandboxJwt.signingSecretName | string | `""` | Name of the Opaque Secret holding the signing key material. Empty falls back to the chart fullname with "-jwt-keys" appended. |
| server.sandboxJwt.ttlSecs | int | `3600` | Token TTL in seconds. Defaults to 3600 (1h). |
| server.sandboxNamespace | string | `""` | Namespace where sandbox pods are created. Defaults to the Helm release namespace (.Release.Namespace) when left empty. |
| server.sandboxUid | string | `""` | Explicit UID for sandbox processes, the supervisor container securityContext, and the workspace PVC init container. Empty (default) = omit the field, letting the driver auto-detect from the OpenShift SCC annotation openshift.io/sa.scc.uid-range on the sandbox namespace and fall back to 1000 when that is absent. Set this on non-OpenShift clusters to pin a sandbox UID without the OpenShift-specific annotation. Any non-root UID is valid. |
| server.telemetryEnabled | bool | `true` | Enable anonymous OpenShell telemetry from the gateway and the sandbox supervisors it launches. |
| server.tls.certSecretName | string | `"openshell-server-tls"` | K8s secret (type kubernetes.io/tls) with tls.crt and tls.key for the server. |
| server.tls.clientCaSecretName | string | `"openshell-server-client-ca"` | K8s secret with ca.crt for client certificate verification (mTLS). Set to "" to disable mTLS and run HTTPS-only (use OIDC for auth instead). |
Expand Down
6 changes: 6 additions & 0 deletions deploy/helm/openshell/templates/gateway-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,12 @@ data:
{{- if .Values.server.appArmorProfile }}
app_armor_profile = {{ .Values.server.appArmorProfile | quote }}
{{- end }}
{{- if .Values.server.sandboxUid }}
sandbox_uid = {{ .Values.server.sandboxUid }}
{{- end }}
{{- if .Values.server.sandboxGid }}
sandbox_gid = {{ .Values.server.sandboxGid }}
{{- end }}
{{- if .Values.supervisor.image.pullPolicy }}
supervisor_image_pull_policy = {{ .Values.supervisor.image.pullPolicy | quote }}
{{- end }}
Expand Down
40 changes: 40 additions & 0 deletions deploy/helm/openshell/tests/gateway_config_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,46 @@ tests:
path: data["gateway.toml"]
pattern: 'app_armor_profile\s*='

- it: omits the sandbox UID and GID by default
template: templates/gateway-config.yaml
asserts:
- notMatchRegex:
path: data["gateway.toml"]
pattern: 'sandbox_uid\s*='
- notMatchRegex:
path: data["gateway.toml"]
pattern: 'sandbox_gid\s*='

# The driver parses both as TOML integers, so the trailing `$` anchors
# matter: a quoted scalar would be rejected at gateway startup rather
# than at render time.
- it: renders an explicit sandbox UID and GID under [openshell.drivers.kubernetes]
template: templates/gateway-config.yaml
set:
server.sandboxUid: 1500
server.sandboxGid: 1600
asserts:
- matchRegex:
path: data["gateway.toml"]
pattern: '(?ms)\[openshell\.drivers\.kubernetes\].*?sandbox_uid\s*=\s*1500$'
- matchRegex:
path: data["gateway.toml"]
pattern: '(?ms)\[openshell\.drivers\.kubernetes\].*?sandbox_gid\s*=\s*1600$'

# resolve_sandbox_gid() falls back to the configured UID, so a bare
# sandboxUid must not drag an empty sandbox_gid into the config.
- it: renders the sandbox UID without a GID when only sandboxUid is set
template: templates/gateway-config.yaml
set:
server.sandboxUid: 1500
asserts:
- matchRegex:
path: data["gateway.toml"]
pattern: '(?m)^\s*sandbox_uid\s*=\s*1500$'
- notMatchRegex:
path: data["gateway.toml"]
pattern: 'sandbox_gid\s*='

- it: does not reuse gateway image pull secrets for sandbox pods
template: templates/gateway-config.yaml
set:
Expand Down
13 changes: 13 additions & 0 deletions deploy/helm/openshell/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,19 @@ server:
# the field, "RuntimeDefault" to force the runtime default profile, or
# "Localhost/profile-name" for an operator-managed localhost profile.
appArmorProfile: "Unconfined"
# -- Explicit UID for sandbox processes, the supervisor container
# securityContext, and the workspace PVC init container. Empty (default)
# = omit the field, letting the driver auto-detect from the OpenShift SCC
# annotation openshift.io/sa.scc.uid-range on the sandbox namespace and
# fall back to 1000 when that is absent. Set this on non-OpenShift
# clusters to pin a sandbox UID without the OpenShift-specific
# annotation. Any non-root UID is valid.
sandboxUid: ""
# -- Explicit GID paired with sandboxUid. Empty (default) = omit the
# field; the driver then reuses the resolved UID as the GID. Setting this
# without sandboxUid has no effect on UID resolution. Any non-root GID is
# valid.
sandboxGid: ""
# Kubernetes compute driver settings.
drivers:
kubernetes:
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/sandbox-compute-drivers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,8 @@ The Kubernetes driver auto-detects the sandbox UID from OpenShift SCC namespace

You can override autodetection with explicit `sandbox_uid` / `sandbox_gid` config in `[openshell.drivers.kubernetes]`. When set, the driver skips namespace annotation lookup entirely.

On a Helm-installed gateway, set the `server.sandboxUid` / `server.sandboxGid` chart values; they render into those same config keys. This is the platform-agnostic way to pin a sandbox identity on non-OpenShift clusters, where the SCC annotation is not otherwise used.

The resolved UID/GID appear in:

- Supervisor container environment variables (`OPENSHELL_SANDBOX_UID`, `OPENSHELL_SANDBOX_GID`) for direct kernel-level privilege dropping without `/etc/passwd` lookups.
Expand Down
Loading