Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
3ae3108
feat(testkit): create a sandbox with a policy, an image, and providers
matthewgrossman Nov 5, 2026
7d8a7e7
test(conformance): port the credential gating e2e tests
matthewgrossman Nov 5, 2026
15fd553
test(e2e): provide the Python test image to host-lane conformance
matthewgrossman Nov 5, 2026
38842bb
test(e2e): remove the credential gating tests ported to conformance
matthewgrossman Nov 5, 2026
7a70c12
test(testkit): add policy helpers, provider install, and YAML files
matthewgrossman Nov 6, 2026
f0d5287
test(support): add host servers that record what sandboxes send
matthewgrossman Nov 6, 2026
566b39d
test(conformance): build credential gating on shared test support
matthewgrossman Nov 6, 2026
99bbed4
fix(e2e): pass the host gateway IP to the external Kubernetes driver
matthewgrossman Nov 6, 2026
61504a3
test(testkit): default python_image() to a public pinned image
matthewgrossman Nov 6, 2026
3a31220
test(conformance): tighten credential gating checks from review
matthewgrossman Nov 7, 2026
9ab1be1
test(testkit): restore openshell/e2e-python:dev as the default test i…
matthewgrossman Nov 9, 2026
4ff621b
test(conformance): add a positive control to the WebSocket denial test
matthewgrossman Nov 9, 2026
e5e72bf
docs(testing): link the remote-cluster follow-up for credential gating
matthewgrossman Nov 9, 2026
eb3561b
refactor(test-support): derive the WebSocket accept key with tungstenite
matthewgrossman Nov 9, 2026
d246355
fix(e2e): fail the external-driver render when the host gateway alias…
matthewgrossman Nov 9, 2026
e22087f
test(testkit): split provider install into profile import and provide…
matthewgrossman Nov 9, 2026
aeec397
Merge remote-tracking branch 'origin/main' into test/5296-credential-…
matthewgrossman Nov 9, 2026
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
17 changes: 12 additions & 5 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,11 +424,14 @@ Suites:

- Common suite (`--features e2e`) - driver-neutral CLI behavior, sandbox lifecycle, sync, port forwarding, policy, and provider tests.
- Conformance (`tests/suites/conformance`) - the testkit `conformance` crate:
lifecycle, the CLI, persistent workspaces, file transfer, and the policy
advisor. Driver E2E runs it with `openshell-conformance` against the lane's
gateway and writes a JUnit report under `results/`; set
`OPENSHELL_CONFORMANCE_BIN` to use a prebuilt program, as Branch E2E does
with the static build it makes once per architecture. The
lifecycle, the CLI, persistent workspaces, file transfer, the policy
advisor, and credential gating. Driver E2E runs it with
`openshell-conformance` against the lane's gateway and writes a JUnit report
under `results/`; set `OPENSHELL_CONFORMANCE_BIN` to use a prebuilt program,
as Branch E2E does with the static build it makes once per architecture.
The Docker and Podman runners build `openshell/e2e-python:dev` for it; the
Kubernetes and VM runners set `OPENSHELL_TEST_PYTHON_IMAGE` to a pullable
Python image unless it is already set. The
installed-artifact conformance lanes run the same crate through
`openshell-test-runner` (see above).
- Driver suites (`--features e2e-docker`, `e2e-podman`, `e2e-kubernetes`, or
Expand Down Expand Up @@ -656,6 +659,10 @@ explains the isolation backend separation behind the capability-free runtime.
On a **remote** cluster, drop the `e2e-host-gateway` feature. Those tests rely

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking, fine as a follow-up

Before this PR, e2e:kubernetes with e2e,e2e-kubernetes excluded the host-dependent credential tests. With this PR, openshell-conformance runs them unconditionally, so a remote Kubernetes or OpenShift gateway fails with connection errors even when it meets the contract. The compatibility bot flagged the same thing.

This is acceptable for the pilot if it is tracked. Please link a follow-up issue and say here that these tests need the gateway to reach host.openshell.internal. The options for the follow-up are to preserve the host-gateway opt-in, move these tests to a feature suite, or add an up-front reachability probe that skips with a clear message instead of a 10s poll timeout.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracked in #5409, under #5281, with the three options you listed (keep an opt-in, move the tests to a feature suite, or check reachability up front and skip with a clear message). TESTING.md and the conformance README now say these tests need sandboxes to reach the test machine as host.openshell.internal and link the issue.

on the sandbox-side `host.openshell.internal` alias reaching the machine running
the tests, which is unreachable from pods on a remote cluster, so they fail.
The conformance suite's `credential_gating` tests need the alias to reach that
machine too, and the feature selection doesn't skip them, so they fail on a
remote cluster. [#5409](https://github.com/NVIDIA/OpenShell/issues/5409)
tracks handling that.
Left enabled, the `host_gateway_alias` suite fails because
`host.openshell.internal` does not resolve inside the pod, so the gateway
SSRF-denies the request (`DNS resolution failed` / `ssrf_denied`) — a networking
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: openshell
spec:
template:
spec:
containers:
- name: kubernetes-compute-driver
env:
- name: OPENSHELL_HOST_GATEWAY_IP
value: replaced-by-kustomize
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# The in-process driver reads server.hostGatewayIP from the rendered gateway
# TOML. The external driver reads it from its own environment, so copy the
# chart's rendered value into that container.
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
patches:
- path: driver-env-patch.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: openshell
replacements:
- source:
group: apps
version: v1
kind: StatefulSet
name: openshell
fieldPath: spec.template.spec.hostAliases.0.ip
targets:
- select:
group: apps
version: v1
kind: StatefulSet
name: openshell
fieldPaths:
- spec.template.spec.containers.[name=kubernetes-compute-driver].env.[name=OPENSHELL_HOST_GATEWAY_IP].value
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,18 @@ cp "${plugin_dir}/kustomization.yaml" "${work_dir}/kustomization.yaml"
cp "${plugin_dir}/workload-patch.yaml" "${work_dir}/workload-patch.yaml"
tee "${work_dir}/rendered.yaml" >/dev/null

# server.hostGatewayIP renders the gateway pod's only hostAliases entry
# (deploy/helm/openshell/templates/_gateway-workload.tpl), which the
# host-gateway component copies from hostAliases.0.ip. The lane exports
# OPENSHELL_E2E_EXPECTED_HOST_GATEWAY_IP when it sets server.hostGatewayIP, so
# a chart change that moves the alias fails here instead of leaving the
# external driver without the IP.
if grep -q '^ *- host\.openshell\.internal$' "${work_dir}/rendered.yaml"; then
cp -R "${plugin_dir}/host-gateway" "${work_dir}/host-gateway"
printf 'components:\n - host-gateway\n' >>"${work_dir}/kustomization.yaml"
elif [ -n "${OPENSHELL_E2E_EXPECTED_HOST_GATEWAY_IP:-}" ]; then
echo "ERROR: server.hostGatewayIP is set, but the rendered chart has no host.openshell.internal hostAliases entry." >&2
exit 1
fi

kubectl kustomize "${work_dir}"
5 changes: 0 additions & 5 deletions e2e/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,6 @@ name = "websocket_conformance"
path = "tests/websocket_conformance.rs"
required-features = ["e2e-host-gateway"]

[[test]]
name = "credential_gating"
path = "tests/credential_gating.rs"
required-features = ["e2e-host-gateway"]

[[test]]
name = "user_namespaces"
path = "tests/user_namespaces.rs"
Expand Down
6 changes: 3 additions & 3 deletions e2e/rust/e2e-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ if [ "${1:-}" = "${RUN_WITH_GATEWAY_COMMAND}" ]; then
exit 0
fi

if [ "${E2E_FEATURES}" != "e2e-conformance-only" ]; then
CONTAINER_ENGINE=docker bash "${ROOT}/tasks/scripts/e2e-build-workload.sh"
fi
# The conformance suite runs on every lane, including e2e-conformance-only,
# and creates sandboxes from this image (testkit::python_image()).
CONTAINER_ENGINE=docker bash "${ROOT}/tasks/scripts/e2e-build-workload.sh"

exec "${ROOT}/e2e/with-docker-gateway.sh" \
bash "${BASH_SOURCE[0]}" "${RUN_WITH_GATEWAY_COMMAND}"
1 change: 1 addition & 0 deletions e2e/rust/e2e-kubernetes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ run_conformance() {
fi

OPENSHELL_CONFORMANCE_JUNIT="${OPENSHELL_CONFORMANCE_JUNIT:-${ROOT}/results/${OPENSHELL_E2E_REPORT_NAME:-e2e-kubernetes}-conformance.xml}" \
OPENSHELL_TEST_PYTHON_IMAGE="${OPENSHELL_TEST_PYTHON_IMAGE:-${E2E_PULLABLE_PYTHON_IMAGE}}" \
e2e_run_openshell_conformance "Kubernetes"
}

Expand Down
7 changes: 3 additions & 4 deletions e2e/rust/e2e-podman.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ PODMAN_CI_TESTS=(
bypass_detection
ephemeral_cleanup
core_dump_hardening
credential_gating
default_image
driver_config_volume
edge_tunnel_e2e
Expand Down Expand Up @@ -117,9 +116,9 @@ if [ -n "${OPENSHELL_GATEWAY_ENDPOINT:-}" ] && [ -z "${OPENSHELL_BIN:-}" ]; then
export OPENSHELL_BIN="${ROOT}/target/debug/openshell"
fi

if [ "${E2E_FEATURES}" != "e2e-conformance-only" ]; then
CONTAINER_ENGINE=podman bash "${ROOT}/tasks/scripts/e2e-build-workload.sh"
fi
# The conformance suite runs on every lane, including e2e-conformance-only,
# and creates sandboxes from this image (testkit::python_image()).
CONTAINER_ENGINE=podman bash "${ROOT}/tasks/scripts/e2e-build-workload.sh"

exec "${ROOT}/e2e/with-podman-gateway.sh" \
bash "${BASH_SOURCE[0]}" "${RUN_WITH_GATEWAY_COMMAND}"
3 changes: 2 additions & 1 deletion e2e/rust/e2e-vm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,8 @@ e2e_export_gateway_restart_metadata \
# preparation; allow 180s for slower CI runners.
export OPENSHELL_PROVISION_TIMEOUT="${SANDBOX_PROVISION_TIMEOUT}"

e2e_run_openshell_conformance "VM"
OPENSHELL_TEST_PYTHON_IMAGE="${OPENSHELL_TEST_PYTHON_IMAGE:-${E2E_PULLABLE_PYTHON_IMAGE}}" \
e2e_run_openshell_conformance "VM"
if [ "${E2E_FEATURES}" = "e2e-conformance-only" ]; then
echo "::notice::Skipping Rust e2e tests (e2e-conformance-only)"
exit 0
Expand Down
Loading
Loading