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
4 changes: 2 additions & 2 deletions .github/workflows/release-vm-kernel.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Release VM Kernel

# Build custom libkrunfw (kernel firmware) + libkrun (VMM) + gvproxy for all
# Build custom libkrunfw (kernel firmware) + libkrun (VMM) for all
# supported openshell-driver-vm platforms. Artifacts are uploaded to the
# rolling "vm-runtime" GitHub Release and consumed by normal dev/tag release
# workflows when building the openshell-driver-vm binary.
Expand Down Expand Up @@ -237,7 +237,7 @@ jobs:

### Kernel Runtime Artifacts

Pre-built kernel runtime (libkrunfw + libkrun + gvproxy + umoci) for embedding
Pre-built kernel runtime (libkrunfw + libkrun + umoci) for embedding
into the `openshell-driver-vm` binary. These are rebuilt on demand when the
kernel config or pinned dependency versions change.

Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions architecture/sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,11 +320,12 @@ file and builds the `Proxy-Authorization: Basic` header; a credential that is
empty, contains control characters, or is not in `user:pass` form is fatal on
both sides.

The VM driver runs `openshell-supervisor` on the host. Corporate-proxy
credentials, private CA keys, policy, and gateway credentials never enter the
guest. The NIC-less guest reaches the host supervisor only through the
authenticated vsock channel; the host supervisor performs DNS and upstream
connections.
The VM driver starts `openshell-supervisor` on the host and
`openshell-sandbox` as capability-free guest PID 1. Corporate proxy arguments,
credentials, private CA keys, policy, and gateway credentials stay host-side.
Both libkrun and QEMU guests are NIC-less; intercepted workload connections
cross the authenticated vsock channel. A gateway-host proxy is addressed as
`host.openshell.internal`, which the host supervisor normalizes to `127.0.0.1`.

The Docker driver runs `openshell-supervisor` in a separate companion container.
Its private named volume contains supervisor bootstrap and channel material.
Expand Down
28 changes: 0 additions & 28 deletions crates/openshell-core/src/container_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,31 +66,6 @@ pub const VM_GUEST_SANDBOX_TOKEN_PATH: &str = "/opt/openshell/auth/sandbox.jwt";
pub const VM_GUEST_INIT_DROPIN_DIR: &str = "/opt/openshell/init.d";
pub const VM_GUEST_INIT_DROPIN_MANIFEST: &str = "/opt/openshell/init.d.manifest";

/// Guest path for the corporate upstream-proxy credential in VM sandboxes.
///
/// The VM driver stages the `user:pass` credential here (mode `0600`,
/// root-only) inside the per-sandbox overlay upperdir, and passes only this
/// path on the supervisor's argv. A microVM has no bind mounts or container
/// secrets, so this is the same delivery the per-sandbox JWT already uses.
pub const VM_GUEST_UPSTREAM_PROXY_AUTH_PATH: &str = "/opt/openshell/auth/upstream-proxy";

/// Guest path for the corporate proxy CA bundle in VM sandboxes.
///
/// A CA certificate is not secret, so unlike the credential this is staged
/// world-readable. The supervisor trusts it for the handshake with an
/// `https://` proxy and for server certificates re-signed by a
/// TLS-intercepting proxy.
pub const VM_GUEST_PROXY_CA_PATH: &str = "/opt/openshell/tls/proxy-ca.pem";

/// Guest path for the driver-authored supervisor argument list in VM sandboxes.
///
/// Podman and Kubernetes build the supervisor's command line directly; the VM
/// guest init script execs a fixed argv, so driver-owned arguments travel
/// through this file instead. The driver writes it into the overlay upperdir
/// on every launch — empty when it has no arguments to pass — so a sandbox
/// image can neither forge entries nor shadow the driver's copy, and the
/// guest appends exactly what it finds there and nothing else.
pub const VM_GUEST_SUPERVISOR_ARGS_PATH: &str = "/opt/openshell/supervisor-args";
pub const VM_UMOCI_PATH: &str = "/opt/openshell/bin/umoci";
pub const VM_SANDBOX_OWNER_NORMALIZED_MARKER: &str = "/opt/openshell/.sandbox-owner-normalized";

Expand Down Expand Up @@ -129,9 +104,6 @@ mod tests {
VM_GUEST_SANDBOX_TOKEN_PATH,
VM_GUEST_INIT_DROPIN_DIR,
VM_GUEST_INIT_DROPIN_MANIFEST,
VM_GUEST_UPSTREAM_PROXY_AUTH_PATH,
VM_GUEST_PROXY_CA_PATH,
VM_GUEST_SUPERVISOR_ARGS_PATH,
VM_UMOCI_PATH,
VM_SANDBOX_OWNER_NORMALIZED_MARKER,
];
Expand Down
100 changes: 69 additions & 31 deletions crates/openshell-driver-vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,83 @@ path = "src/lib.rs"
[[bin]]
name = "openshell-driver-vm"
path = "src/main.rs"
required-features = ["compute-driver"]

[dependencies]
openshell-core = { path = "../openshell-core", default-features = false }
openshell-otel = { path = "../openshell-otel" }
openshell-policy = { path = "../openshell-policy" }
openshell-driver-podman = { path = "../openshell-driver-podman" }
openshell-vfio = { path = "../openshell-vfio" }
openshell-isolation-interface = { path = "../openshell-isolation-interface" }
openshell-otel = { path = "../openshell-otel", optional = true }
openshell-policy = { path = "../openshell-policy", optional = true }
openshell-driver-podman = { path = "../openshell-driver-podman", optional = true }
openshell-vfio = { path = "../openshell-vfio", optional = true }

bollard = { version = "0.20", features = ["ssh"] }
base64 = { workspace = true, optional = true }
bollard = { version = "0.20", features = ["ssh"], optional = true }
tokio = { workspace = true }
tonic = { workspace = true, features = ["transport"] }
tower-http = { workspace = true }
http = { workspace = true }
prost = { workspace = true }
prost-types = { workspace = true }
futures = { workspace = true }
tokio-stream = { workspace = true, features = ["net"] }
nix = { workspace = true }
clap = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
opentelemetry = { workspace = true }
opentelemetry_sdk = { workspace = true }
tracing-opentelemetry = { workspace = true }
miette = { workspace = true }
url = { workspace = true }
tonic = { workspace = true, features = ["transport"], optional = true }
tower-http = { workspace = true, optional = true }
http = { workspace = true, optional = true }
prost = { workspace = true, optional = true }
prost-types = { workspace = true, optional = true }
futures = { workspace = true, optional = true }
tokio-stream = { workspace = true, features = ["net"], optional = true }
nix = { workspace = true, optional = true }
clap = { workspace = true, optional = true }
tracing = { workspace = true, optional = true }
tracing-subscriber = { workspace = true, optional = true }
opentelemetry = { workspace = true, optional = true }
opentelemetry_sdk = { workspace = true, optional = true }
tracing-opentelemetry = { workspace = true, optional = true }
miette = { workspace = true, optional = true }
rand = { workspace = true, optional = true }
url = { workspace = true, optional = true }
serde = { workspace = true }
serde_json = { workspace = true }
oci-client = "0.16"
oci-client = { version = "0.16", optional = true }
libc = "0.2"
rustix = { workspace = true }
libloading = "0.8"
tar = "0.4"
flate2 = "1"
sha2 = "0.10"
zstd = "0.13"
rustix = { workspace = true, optional = true }
libloading = { version = "0.8", optional = true }
tar = { version = "0.4", optional = true }
flate2 = { version = "1", optional = true }
sha2 = { version = "0.10", optional = true }
zstd = { version = "0.13", optional = true }

[features]
default = ["telemetry"]
default = ["compute-driver", "telemetry"]
## Build the standalone compute driver and its host runtime implementation.
compute-driver = [
"dep:base64",
"dep:bollard",
"dep:clap",
"dep:flate2",
"dep:futures",
"dep:http",
"dep:libloading",
"dep:miette",
"dep:nix",
"dep:oci-client",
"dep:openshell-otel",
"dep:openshell-policy",
"dep:openshell-driver-podman",
"dep:openshell-vfio",
"dep:opentelemetry",
"dep:opentelemetry_sdk",
"dep:polling",
"dep:prost",
"dep:prost-types",
"dep:rand",
"dep:rustix",
"dep:sha2",
"dep:tar",
"dep:tokio-stream",
"dep:tonic",
"dep:tower-http",
"dep:tracing",
"dep:tracing-opentelemetry",
"dep:tracing-subscriber",
"dep:url",
"dep:zstd",
]
## Compile in telemetry support (forwards to openshell-core/telemetry). On by
## default; build with `--no-default-features` for a telemetry-free VM driver
## that reports telemetry disabled to the sandboxes it launches.
Expand All @@ -68,7 +106,7 @@ telemetry = ["openshell-core/telemetry"]
## enabling it alongside `telemetry` is a compile error rather than a silent
## telemetry-on build. Kept in sync with `default` by
## `rust:verify:defaults-without-telemetry`.
defaults-without-telemetry = []
defaults-without-telemetry = ["compute-driver"]

[dev-dependencies]
openshell-otel-test-support = { path = "../openshell-otel-test-support" }
Expand All @@ -82,7 +120,7 @@ opentelemetry_sdk = { workspace = true, features = ["testing"] }
# nix::sys::prctl::set_pdeathsig there keeps the Linux path a single
# syscall with no helper thread.
[target.'cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly"))'.dependencies]
polling = "3.11"
polling = { version = "3.11", optional = true }

[lints]
workspace = true
Loading
Loading