mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-15 05:09:44 +08:00
* feat(isolation): add RFC 0012 backend contract Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> * refactor(isolation): name the interface crate explicitly Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): expose trusted host gateway Signed-off-by: Drew Newberry <anewberry@nvidia.com> * docs(agents): inventory the MXC driver Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): add mediated DNS transport Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): tighten interface error and digest contracts Signed-off-by: Drew Newberry <anewberry@nvidia.com> * docs(isolation): remove unrelated driver inventory Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): define capability-free launch contract Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): seal confirmed boundary state Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): validate confirmation for external backend implementations Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): clarify mediated DNS identity Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(isolation): generalize loopback connector Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(isolation): unify typed network mediation Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): bind launches to sandbox sessions Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(mxc): initialize extended sandbox status Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): add boundary protocol and Linux primitives Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): harden signals and separate process status from transport Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): validate remote confirmation through public contract Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): validate wire state and propagate snapshot failures Signed-off-by: Drew Newberry <anewberry@nvidia.com> * test(isolation): import owned agent specification explicitly Signed-off-by: Drew Newberry <anewberry@nvidia.com> * docs(isolation): describe mediated DNS channel Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): bound mediation attach without nested retries Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(isolation): generalize loopback protocol Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): add transport-neutral session authentication Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(isolation): separate sandbox backend protocol Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): harden runtime boundary controls Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): add terminal boundary operation Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): split supervisor and sandbox runtimes Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): harden boundary isolation and lifecycle ownership Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): reject private root redirects and adopt typed errors Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): preserve accept thread ownership on musl Signed-off-by: Drew Newberry <anewberry@nvidia.com> * test(sandbox): isolate credential probes from filtered threads Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): return retained exec exit status to independent waiters Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): bound network mediation and preserve socket authorization Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): bound control admission and retire stale mediation Signed-off-by: Drew Newberry <anewberry@nvidia.com> * ci(e2e): select migrated drivers per stack layer Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(sandbox): implement loopback connector Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(isolation): authenticate the Sandbox Protocol Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(supervisor): rotate launch-scoped authentication Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(sandbox): consume dedicated backend crate Signed-off-by: Drew Newberry <anewberry@nvidia.com> * test(sandbox): align topology session fixture Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): align projected bootstrap bundle Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(auth): validate refreshed credentials before rotation Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): fail closed across supervisor disconnects Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): repair rebased sandbox CI Signed-off-by: Drew Newberry <anewberry@nvidia.com> * build(runtime): publish separate sandbox and supervisor images Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(config): configure the sandbox runtime image Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(ci): validate sandbox binary linkage Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(isolation): use backend and runtime terminology Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(sandbox): use a scratch runtime image Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(ci): refresh schema and dependency policy Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): bind reconnects to supervisor process Signed-off-by: Drew Newberry <anewberry@nvidia.com> * docs: align runtime split operational guidance Signed-off-by: Drew Newberry <anewberry@nvidia.com> * chore(security): document Kubernetes runtime RBAC Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): enforce runtime lifecycle invariants Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(compute): identify sandbox start generations Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(server): restore sandbox launch sessions Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): support authenticated runtime replacement Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(auth): bind sandbox session successors Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(auth): retry pending sandbox successors Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(vm): run the supervisor outside the guest workload Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(vm): use sandbox backend protocol Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): repair rebase integration Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): use unified build toolchain Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(vm): use sandbox runtime terminology Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(vm): own guest network bootstrap Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): expose guest init version Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): select native supervisor artifacts Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): guard guest init Linux symbols Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): scope Linux test imports Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): avoid guest interface casts Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): reconcile admitted sandbox identity Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): share resolved sandbox identity Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): surface host supervisor failures Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): include guest logs on supervisor exit Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): rotate and clean runtime generations Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): make sandbox starts generation-aware Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): rotate restored sandbox sessions Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(vm): keep shared paths in the base layer Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): bind sandbox session lineage Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(docker): isolate workloads behind the host supervisor Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(docker): rotate launch-scoped authentication Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(docker): use sandbox backend protocol Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(docker): use host networking for supervisor Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): preserve host gateway alias resolution Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(docker): use separate sandbox and supervisor images Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): restore startup validation after rebase Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(docker): name the sandbox runtime directly Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): narrow supervisor CA runtime storage Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): close companion isolation gaps Signed-off-by: Drew Newberry <anewberry@nvidia.com> * test(docker): align mediated network expectations Signed-off-by: Drew Newberry <anewberry@nvidia.com> * test(docker): exercise mediated network paths Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): attach supervisor to managed network Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): defer supervisor recovery until gateway is ready Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): make sandbox starts generation-aware Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): rotate restored sandbox sessions Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): preserve workloads during session rotation Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(docker): remove unrelated configuration RFC changes Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): bind sandbox session lineage Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(kubernetes): add proxy-pod isolation topology Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(kubernetes): use sandbox backend protocol Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): use stable sandbox service authority Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(kubernetes): split sandbox and supervisor images Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): adapt proxy pods to current runtime APIs Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(kubernetes): describe the single runtime placement Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(kubernetes): simplify sandbox orchestration Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): validate deployment prerequisites Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): update Trivy Helm profile inventory Signed-off-by: Drew Newberry <anewberry@nvidia.com> * test(kubernetes): update Trivy scan inventory count Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): reuse preloaded runtime images in e2e Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): type and clean runtime resources Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): make sandbox restarts recoverable Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): rotate restored sandbox sessions Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): preserve supervisor egress Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): bind sandbox session lineage Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(podman): adopt isolated sandbox and supervisor containers Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): stage bootstrap archives at named volume destinations Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(podman): rotate launch-scoped authentication Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(podman): use sandbox backend protocol Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(podman): use host networking for supervisor Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(podman): split sandbox and supervisor images Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): repair rebase integration Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(podman): name the sandbox runtime directly Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): provision supervisor CA runtime storage Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): address isolation review findings Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): inspect Debian supervisor provenance Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): use libpod-compatible tmpfs options Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): bind verified sandbox runtime binary Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): provide external driver data directory Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): start sandbox before joining user namespace Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): separate supervisor user namespace Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): make sandbox starts generation-aware Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): rotate restored sandbox sessions Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): bind sandbox session lineage Signed-off-by: Drew Newberry <anewberry@nvidia.com> * perf(isolation): add TCP and DNS benchmark harnesses Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(perf): align benchmark timing and supported protocols Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(perf): report TCP benchmark metrics accurately Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(perf): cancel failed worker startup Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(docker): build matching local supervisor image Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(podman): make local sandbox smoke test runnable Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): wire local sandbox runtime image Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(kubernetes): narrow sandbox service RBAC Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(ci): validate split runtime artifacts Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): harden runtime session handling Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(supervisor): add standalone network proxy role Signed-off-by: Drew Newberry <anewberry@nvidia.com> * docs(rfc): remove implementation companion notes Signed-off-by: Drew Newberry <anewberry@nvidia.com> * refactor(vm): standardize runtime release name Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(vm): pin renamed runtime artifacts Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(auth): persist sandbox runtime identity Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(runtime): restore branch validation Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(isolation): reconcile main after rebase Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(network): close unframed HTTP 1.0 responses Signed-off-by: Drew Newberry <anewberry@nvidia.com> * chore(isolation): preserve upstream OCSF updates Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(security): close credential and TLS replay paths Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(auth): make sandbox refresh retries idempotent Signed-off-by: Drew Newberry <anewberry@nvidia.com> --------- Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> Signed-off-by: Drew Newberry <anewberry@nvidia.com>
259 lines
8.0 KiB
Rust
259 lines
8.0 KiB
Rust
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#![cfg(feature = "e2e")]
|
|
|
|
//! E2E test: verify Kubernetes user namespace pod spec generation.
|
|
//!
|
|
//! Enables `OPENSHELL_ENABLE_USER_NAMESPACES` on the gateway, triggers sandbox
|
|
//! creation, and inspects the resulting pod spec to confirm:
|
|
//! 1. `spec.hostUsers` is `false`
|
|
//! 2. The container security context requests no added capabilities and
|
|
//! drops every capability
|
|
//!
|
|
//! The sandbox pod may fail to start in Docker-in-Docker dev clusters where the
|
|
//! filesystem does not support ID-mapped mounts. The test inspects the pod spec
|
|
//! regardless of runtime success.
|
|
|
|
use std::process::Stdio;
|
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
|
|
use openshell_e2e::harness::binary::openshell_cmd;
|
|
use tokio::process::Child;
|
|
|
|
async fn kubectl(args: &[&str]) -> Result<String, String> {
|
|
let output = tokio::process::Command::new("docker")
|
|
.args(["exec", "openshell-cluster-openshell", "kubectl"])
|
|
.args(args)
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped())
|
|
.output()
|
|
.await
|
|
.map_err(|e| format!("failed to run kubectl: {e}"))?;
|
|
|
|
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
|
|
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
|
|
|
|
if !output.status.success() {
|
|
return Err(format!("kubectl {args:?} failed: {stdout}{stderr}"));
|
|
}
|
|
Ok(stdout)
|
|
}
|
|
|
|
async fn set_user_namespaces(enable: bool) -> Result<(), String> {
|
|
let env_arg = if enable {
|
|
"OPENSHELL_ENABLE_USER_NAMESPACES=true"
|
|
} else {
|
|
"OPENSHELL_ENABLE_USER_NAMESPACES-"
|
|
};
|
|
|
|
kubectl(&[
|
|
"set",
|
|
"env",
|
|
"statefulset/openshell",
|
|
"-n",
|
|
"openshell",
|
|
env_arg,
|
|
])
|
|
.await?;
|
|
|
|
kubectl(&[
|
|
"rollout",
|
|
"status",
|
|
"statefulset/openshell",
|
|
"-n",
|
|
"openshell",
|
|
"--timeout=120s",
|
|
])
|
|
.await?;
|
|
|
|
// Give the gateway time to fully initialize after rollout.
|
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn delete_sandbox(name: &str) {
|
|
let _ = kubectl(&["delete", "sandbox", name, "-n", "openshell"]).await;
|
|
}
|
|
|
|
fn unique_sandbox_name() -> String {
|
|
let suffix = SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_millis();
|
|
format!("userns-e2e-{suffix}")
|
|
}
|
|
|
|
async fn stop_child(child: &mut Child) {
|
|
let _ = child.kill().await;
|
|
let _ = child.wait().await;
|
|
}
|
|
|
|
async fn wait_for_sandbox(name: &str, timeout_secs: u64) -> Result<(), String> {
|
|
let deadline = tokio::time::Instant::now() + Duration::from_secs(timeout_secs);
|
|
while tokio::time::Instant::now() < deadline {
|
|
if let Ok(n) = kubectl(&[
|
|
"get",
|
|
"sandbox",
|
|
name,
|
|
"-n",
|
|
"openshell",
|
|
"-o",
|
|
"jsonpath={.metadata.name}",
|
|
])
|
|
.await
|
|
{
|
|
if !n.trim().is_empty() {
|
|
return Ok(());
|
|
}
|
|
}
|
|
tokio::time::sleep(Duration::from_secs(2)).await;
|
|
}
|
|
Err(format!(
|
|
"sandbox {name} did not appear within {timeout_secs}s"
|
|
))
|
|
}
|
|
|
|
/// Find a sandbox pod by its sandbox CRD name. The CRD controller creates a
|
|
/// pod with the same name as the Sandbox resource.
|
|
async fn wait_for_sandbox_pod(name: &str, timeout_secs: u64) -> Result<(), String> {
|
|
let deadline = tokio::time::Instant::now() + Duration::from_secs(timeout_secs);
|
|
while tokio::time::Instant::now() < deadline {
|
|
if let Ok(n) = kubectl(&[
|
|
"get",
|
|
"pod",
|
|
name,
|
|
"-n",
|
|
"openshell",
|
|
"-o",
|
|
"jsonpath={.metadata.name}",
|
|
])
|
|
.await
|
|
{
|
|
if !n.trim().is_empty() {
|
|
return Ok(());
|
|
}
|
|
}
|
|
tokio::time::sleep(Duration::from_secs(2)).await;
|
|
}
|
|
Err(format!(
|
|
"sandbox pod {name} did not appear within {timeout_secs}s"
|
|
))
|
|
}
|
|
|
|
// Disabled by default — not reachable from any project-controlled cluster
|
|
// and brittle by design. See https://github.com/NVIDIA/OpenShell/issues/1597
|
|
// for the tracking issue context. Re-enable with `cargo test -- --ignored`
|
|
// after the issues below are addressed.
|
|
//
|
|
// Blocking issues:
|
|
// 1. `kubectl` is invoked as `docker exec openshell-cluster-openshell kubectl`.
|
|
// No setup in the repo (helm-k3s-local.sh, e2e/with-kube-gateway.sh, the
|
|
// CI kind workflow) creates a docker container with that name; only an
|
|
// external OpenShift/manual setup matches it.
|
|
// 2. The test mutates the gateway StatefulSet via `kubectl set env`, which
|
|
// triggers a pod rollout mid-test. The wrapper's `kubectl port-forward`
|
|
// to the old pod is disrupted during the rollout, and the test's
|
|
// `openshell sandbox create` is spawned without capturing stderr, so
|
|
// transient connection failures surface as a generic "sandbox did not
|
|
// appear within 60s" with no actionable signal.
|
|
#[ignore = "broken: hardcoded docker exec container name + brittle mid-test gateway rollout (see header)"]
|
|
#[tokio::test]
|
|
async fn sandbox_pod_spec_has_user_namespace_fields() {
|
|
// Enable user namespaces on the gateway.
|
|
set_user_namespaces(true)
|
|
.await
|
|
.expect("failed to enable user namespaces on gateway");
|
|
|
|
let sandbox_name = unique_sandbox_name();
|
|
|
|
// Start sandbox creation in the background. The pod may never become
|
|
// ready in DinD environments, so we spawn the CLI and inspect the pod
|
|
// spec independently.
|
|
let mut cmd = openshell_cmd();
|
|
cmd.arg("sandbox")
|
|
.arg("create")
|
|
.arg("--name")
|
|
.arg(&sandbox_name)
|
|
.arg("--")
|
|
.arg("sleep")
|
|
.arg("infinity");
|
|
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
|
|
|
|
let mut child = cmd.spawn().expect("failed to spawn openshell create");
|
|
|
|
if let Err(e) = wait_for_sandbox(&sandbox_name, 60).await {
|
|
stop_child(&mut child).await;
|
|
delete_sandbox(&sandbox_name).await;
|
|
set_user_namespaces(false).await.ok();
|
|
panic!("{e}");
|
|
}
|
|
|
|
// Wait for the pod to be created (the CRD controller creates it).
|
|
if let Err(e) = wait_for_sandbox_pod(&sandbox_name, 60).await {
|
|
stop_child(&mut child).await;
|
|
delete_sandbox(&sandbox_name).await;
|
|
set_user_namespaces(false).await.ok();
|
|
panic!("{e}");
|
|
}
|
|
|
|
// Inspect the pod spec for hostUsers.
|
|
let host_users = kubectl(&[
|
|
"get",
|
|
"pod",
|
|
&sandbox_name,
|
|
"-n",
|
|
"openshell",
|
|
"-o",
|
|
"jsonpath={.spec.hostUsers}",
|
|
])
|
|
.await;
|
|
|
|
// Inspect capabilities on the agent container.
|
|
let cap_add = kubectl(&[
|
|
"get",
|
|
"pod",
|
|
&sandbox_name,
|
|
"-n",
|
|
"openshell",
|
|
"-o",
|
|
"jsonpath={.spec.containers[?(@.name=='agent')].securityContext.capabilities.add}",
|
|
])
|
|
.await;
|
|
let cap_drop = kubectl(&[
|
|
"get",
|
|
"pod",
|
|
&sandbox_name,
|
|
"-n",
|
|
"openshell",
|
|
"-o",
|
|
"jsonpath={.spec.containers[?(@.name=='agent')].securityContext.capabilities.drop}",
|
|
])
|
|
.await;
|
|
|
|
// Clean up.
|
|
stop_child(&mut child).await;
|
|
delete_sandbox(&sandbox_name).await;
|
|
set_user_namespaces(false).await.ok();
|
|
|
|
// Assert hostUsers is false.
|
|
let host_users_val = host_users.expect("failed to get hostUsers from pod spec");
|
|
assert_eq!(
|
|
host_users_val.trim(),
|
|
"false",
|
|
"sandbox pod must have spec.hostUsers=false when user namespaces are enabled"
|
|
);
|
|
|
|
let cap_add = cap_add.expect("failed to get added capabilities from pod spec");
|
|
assert!(
|
|
cap_add.trim().is_empty(),
|
|
"sandbox pod must not request added capabilities, got: {cap_add}"
|
|
);
|
|
let cap_drop = cap_drop.expect("failed to get dropped capabilities from pod spec");
|
|
assert!(
|
|
cap_drop.contains("ALL"),
|
|
"sandbox pod must drop every capability, got: {cap_drop}"
|
|
);
|
|
}
|