Skip to content

Commit 2fc442b

Browse files
committed
feat(kubernetes): launch isolated sandbox and supervisor pods
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
1 parent c3a22d3 commit 2fc442b

45 files changed

Lines changed: 5171 additions & 3801 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/helm-dev-environment/SKILL.md

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -69,28 +69,12 @@ mise run helm:skaffold:dev
6969
mise run helm:skaffold:run
7070
```
7171

72-
**Supervisor sidecar topology** (build once and leave running):
73-
```bash
74-
mise run helm:skaffold:run:sidecar
75-
```
76-
77-
**Supervisor sidecar topology with TLS/mTLS enabled** (build once and leave running):
78-
```bash
79-
mise run helm:skaffold:run:sidecar-mtls
80-
```
81-
82-
Both commands build the `gateway` and `supervisor` images and deploy the OpenShell Helm
83-
chart. The sidecar profile renders an `openshell-network-init` init container for
84-
nftables setup and an `openshell-supervisor-network` runtime sidecar for proxying.
85-
Binary-aware policy mode runs that sidecar as UID 0 with `SYS_PTRACE` and
86-
`DAC_READ_SEARCH`; relaxed mode can run it as the configured proxy UID, which
87-
must be at least `1000` and distinct from the workload UID. The
88-
sidecar-mTLS profile reuses `ci/values-sidecar.yaml` and restores
89-
`server.disableTls=false` inline for Skaffold. The `pkiInitJob` hook (a pre-install
90-
Job that runs `openshell-gateway generate-certs`) generates mTLS secrets on first
91-
install. The default Skaffold values export gateway and Kubernetes-driver traces to
92-
the collector service installed by `helm:k3s:create`. Envoy Gateway opt-in; see the
93-
Optional Add-ons section below.
72+
Both commands build the gateway and trusted runtime image and deploy the
73+
OpenShell Helm chart. Kubernetes sandboxes always use the proxy-pod topology:
74+
a capability-free sandbox Pod behind an empty-egress NetworkPolicy and a
75+
separate capability-free supervisor Deployment. The default Skaffold values
76+
export gateway and Kubernetes-driver traces to the collector service installed
77+
by `helm:k3s:create`. Envoy Gateway is opt-in; see the Optional Add-ons section.
9478

9579
The gateway Service uses ClusterIP. Access is via Envoy Gateway (port `8080`) or
9680
the unified local forwarding task:
@@ -102,8 +86,8 @@ mise run helm:k3s:forward
10286
The task forwards OTLP/gRPC to `http://127.0.0.1:4317` and the trace UI to
10387
`http://127.0.0.1:18888`. When Skaffold has deployed a Kubernetes gateway, it
10488
also forwards the gateway to `http://127.0.0.1:8090`; otherwise it continues
105-
with the collector ports only. A successful plaintext `helm:skaffold:run` or
106-
`helm:skaffold:run:sidecar` registers the gateway under the worktree-specific
89+
with the collector ports only. A successful plaintext `helm:skaffold:run`
90+
registers the gateway under the worktree-specific
10791
k3d cluster name and selects it as the active gateway. Keep the forwarding
10892
task running while using those endpoints.
10993

@@ -134,8 +118,7 @@ create the Secret named `openshell-ha-pg` with a `uri` key, then run
134118
### TLS behaviour
135119

136120
`ci/values-skaffold.yaml` sets `server.disableTls: true`, so Skaffold-based deploys run
137-
plaintext by default. To test sidecar topology with TLS enabled, use
138-
`mise run helm:skaffold:run:sidecar-mtls`.
121+
plaintext by default. Remove that override to test gateway TLS/mTLS locally.
139122

140123
| Mode | `server.disableTls` | Gateway scheme |
141124
|------|---------------------|----------------|
@@ -188,12 +171,6 @@ openshell sandbox list --gateway-endpoint https://localhost:8090
188171
mise run helm:skaffold:delete
189172
```
190173

191-
For a sidecar-profile deployment:
192-
193-
```bash
194-
mise run helm:skaffold:delete:sidecar
195-
```
196-
197174
### Delete the cluster entirely
198175

199176
```bash
@@ -259,7 +236,7 @@ SPIFFE JWT-SVIDs for dynamic provider token grants:
259236
`openshell.local` and adds a `ClusterSPIFFEID` that maps sandbox pod
260237
annotations to `spiffe://openshell.local/openshell/sandbox/<sandbox-id>`.
261238
OpenShell mounts the SPIFFE CSI Workload API socket at
262-
`/spiffe-workload-api/spire-agent.sock` into sandbox pods for provider token
239+
`/spiffe-workload-api/spire-agent.sock` only into supervisor Pods for provider token
263240
grants. Supervisor-to-gateway authentication remains on the Kubernetes
264241
ServiceAccount bootstrap and gateway-minted sandbox JWT path; the selected
265242
Kubernetes compute driver validates the projected token before the gateway
@@ -320,7 +297,6 @@ for dependencies still declared in `Chart.yaml`.
320297
| `deploy/helm/openshell/ci/values-gateway.yaml` | Envoy Gateway GRPCRoute + Gateway overlay |
321298
| `deploy/helm/openshell/ci/values-high-availability.yaml` | HA test overlay (`replicaCount: 2` with external PostgreSQL Secret) |
322299
| `deploy/helm/openshell/ci/values-keycloak.yaml` | Keycloak OIDC overlay |
323-
| `deploy/helm/openshell/ci/values-sidecar.yaml` | Supervisor sidecar topology overlay for Kubernetes e2e/dev |
324300
| `deploy/helm/openshell/ci/values-spire.yaml` | SPIFFE/SPIRE provider token grant overlay |
325301
| `deploy/helm/openshell/ci/values-spire-stack.yaml` | SPIRE hardened chart values for local dev |
326302
| `deploy/helm/openshell/ci/values-tls-disabled.yaml` | Lint-only: TLS + auth disabled (reverse-proxy edge termination) |

.github/workflows/branch-e2e.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ jobs:
377377
extra_helm_values: ""
378378
- agent_sandbox_api: v1beta1
379379
agent_sandbox_version: v0.5.0
380-
topology: sidecar
381-
extra_helm_values: deploy/helm/openshell/ci/values-sidecar.yaml
380+
topology: proxy-pod
381+
extra_helm_values: deploy/helm/openshell/ci/values-proxy-pod.yaml
382382
permissions:
383383
actions: read
384384
contents: read

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ These pipelines connect skills into end-to-end workflows. Individual skill files
3838
| `crates/openshell-conformance/` | CLI conformance library | Reusable driver-agnostic scenarios and command runner |
3939
| `crates/openshell-conformance-cli/` | Conformance CLI | Distributable `list` and `run` entrypoint for gateway conformance |
4040
| `crates/openshell-server/` | Gateway server | Control-plane API, sandbox lifecycle, auth boundary |
41-
| `crates/openshell-sandbox/` | Sandbox runtime | Container supervision, policy-enforced egress routing |
41+
| `crates/openshell-sandbox/` | Sandbox runtime | Capability-free workload launcher, process identity, and seccomp-mediated I/O |
42+
| `crates/openshell-supervisor/` | Supervisor runtime | Gateway session, policy evaluation, credentials, and upstream networking |
4243
| `crates/openshell-binary-identity/` | Binary identity | Shared trusted procfs executable identity resolution for isolation backends |
4344
| `crates/openshell-isolation-interface/` | Isolation backend interface | RFC 0012 `IsolationBackend` trait + types; the supervisor-facing runtime contract for the boundary |
4445
| `crates/openshell-policy/` | Policy engine | Filesystem, network, process, and inference constraints |
@@ -59,7 +60,6 @@ These pipelines connect skills into end-to-end workflows. Individual skill files
5960
| `crates/openshell-driver-db-credstore/` | Database credential driver | In-process `CredentialDriver` backend for gateway database credential storage |
6061
| `crates/openshell-driver-kubernetes/` | Kubernetes compute driver | In-process `ComputeDriver` backend for K8s sandbox pods |
6162
| `crates/openshell-driver-docker/` | Docker compute driver | In-process `ComputeDriver` backend for local Docker sandbox containers |
62-
| `crates/openshell-driver-mxc/` | MXC compute driver | Windows in-process `ComputeDriver` backend for MXC sandbox execution |
6363
| `crates/openshell-driver-podman/` | Podman compute driver | In-process `ComputeDriver` backend for local Podman sandbox containers |
6464
| `crates/openshell-driver-vm/` | VM compute driver | Standalone libkrun-backed `ComputeDriver` subprocess (embeds its own rootfs + runtime) |
6565
| `crates/openshell-driver-mxc/` | Microsoft MXC compute driver | In-process Windows AppContainer and isolation-session compute backend |

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/openshell-core/src/container_paths.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ pub const OPT_ROOT: &str = "/opt/openshell";
1212
pub const ETC_ROOT: &str = "/etc/openshell";
1313
pub const TLS_ROOT: &str = "/etc/openshell-tls";
1414
pub const RUN_ROOT: &str = "/run/openshell";
15-
pub const SIDECAR_RUN_ROOT: &str = "/run/openshell-sidecar";
1615
pub const NETNS_MOUNT_ROOT: &str = "/run/netns";
1716
pub const NETNS_IPROUTE2_ROOT: &str = "/var/run/netns";
1817

@@ -34,7 +33,6 @@ pub const CONTROL_ROOTS: &[&str] = &[
3433
ETC_ROOT,
3534
TLS_ROOT,
3635
RUN_ROOT,
37-
SIDECAR_RUN_ROOT,
3836
NETNS_MOUNT_ROOT,
3937
// The supervisor currently uses the conventional iproute2 spelling.
4038
NETNS_IPROUTE2_ROOT,
@@ -52,9 +50,6 @@ pub const CONTAINER_POLICY_PATH: &str = "/etc/openshell/policy.yaml";
5250
pub const POLICY_ADVISOR_SKILL_PATH: &str = "/etc/openshell/skills/policy_advisor.md";
5351

5452
pub const SSH_SOCKET_PATH: &str = "/run/openshell/ssh.sock";
55-
pub const SIDECAR_CONTROL_SOCKET: &str = "/run/openshell-sidecar/control.sock";
56-
pub const SIDECAR_TLS_DIR: &str = "/etc/openshell-tls/proxy";
57-
pub const SIDECAR_CLIENT_TLS_DIR: &str = "/etc/openshell-tls/proxy/client";
5853
pub const CLIENT_TLS_DIR: &str = "/etc/openshell-tls/client";
5954
pub const SUPERVISOR_CA_CERT_PATH: &str = "/etc/openshell-tls/openshell-ca.pem";
6055
pub const SUPERVISOR_CA_BUNDLE_PATH: &str = "/etc/openshell-tls/ca-bundle.pem";
@@ -92,9 +87,6 @@ mod tests {
9287
CONTAINER_POLICY_PATH,
9388
POLICY_ADVISOR_SKILL_PATH,
9489
SSH_SOCKET_PATH,
95-
SIDECAR_CONTROL_SOCKET,
96-
SIDECAR_TLS_DIR,
97-
SIDECAR_CLIENT_TLS_DIR,
9890
CLIENT_TLS_DIR,
9991
SUPERVISOR_CA_CERT_PATH,
10092
SUPERVISOR_CA_BUNDLE_PATH,

crates/openshell-core/src/driver_mounts.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,6 @@ mod tests {
296296
"/etc/openshell-tls",
297297
"/run",
298298
"/run/openshell/cache",
299-
"/run/openshell-sidecar/control.sock",
300299
"/run/netns/project",
301300
"/var/run/netns/project",
302301
] {

crates/openshell-core/src/proposals.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! Shared state controlling agent-driven policy proposals.
55
//!
66
//! Initialised once during sandbox start from the `agent_policy_proposals_enabled`
7-
//! setting and updated by the policy poll loop or authoritative sidecar control
7+
//! setting and updated by the policy poll loop or authoritative supervisor
88
//! when the setting changes. Read by the `policy.local` route handler and by
99
//! the skills installer to gate the agent-controlled mutation surface.
1010
@@ -15,7 +15,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
1515
///
1616
/// Clones point at the same atomic value, so the sandbox orchestrator can pass
1717
/// this into the process and network supervisors and then update it from the
18-
/// settings poll loop or sidecar control.
18+
/// settings poll loop or supervisor control.
1919
#[derive(Clone, Debug)]
2020
pub struct AgentProposals {
2121
enabled: Arc<AtomicBool>,

crates/openshell-core/src/provider_credentials.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ impl ProviderCredentialState {
165165
/// Build a static provider state from an already-prepared child
166166
/// environment snapshot.
167167
///
168-
/// Kubernetes sidecar topology uses this in the process-only supervisor:
169-
/// the network sidecar owns provider credential resolvers and sends the
168+
/// The Kubernetes proxy-pod topology uses this in the sandbox process:
169+
/// the supervisor owns provider credential resolvers and sends the
170170
/// workload-facing env map over a local control channel. The process leaf
171171
/// must inject that map into child processes without re-placeholderizing it
172172
/// or holding the gateway-side resolver material.

crates/openshell-core/src/sandbox_env.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -130,20 +130,13 @@ impl MainProcessConfig {
130130
/// Deployment-controlled telemetry toggle propagated to the sandbox supervisor.
131131
pub const TELEMETRY_ENABLED: &str = "OPENSHELL_TELEMETRY_ENABLED";
132132

133-
/// Supervisor pod/runtime topology. Kubernetes sidecar mode sets this to
134-
/// `"sidecar"`; the default combined supervisor path omits it.
135-
pub const SUPERVISOR_TOPOLOGY: &str = "OPENSHELL_SUPERVISOR_TOPOLOGY";
136-
137133
/// The isolation backend admitted by the deployment configuration (RFC 0012).
138134
///
139135
/// Delivered on a channel separate from the topology descriptor so descriptor
140136
/// verification against the admitted backend is not self-referential. Required
141137
/// whenever a topology descriptor is supplied.
142138
pub const ADMITTED_ISOLATION_BACKEND: &str = "OPENSHELL_ADMITTED_ISOLATION_BACKEND";
143139

144-
/// Network enforcement backend selected by the compute driver.
145-
pub const NETWORK_ENFORCEMENT_MODE: &str = "OPENSHELL_NETWORK_ENFORCEMENT_MODE";
146-
147140
/// Comma-separated runtime networking capabilities supplied by the compute
148141
/// driver. Capabilities describe substrate the shared supervisor may activate;
149142
/// they never move policy evaluation into the driver.
@@ -152,20 +145,6 @@ pub const NETWORK_RUNTIME_CAPABILITIES: &str = "OPENSHELL_NETWORK_RUNTIME_CAPABI
152145
/// Driver capability for policy-gated DNS and transparent TCP interception.
153146
pub const POLICY_DNS_TRANSPARENT_TCP_CAPABILITY: &str = "policy-dns-transparent-tcp";
154147

155-
/// Whether network policy evaluation must bind requests to the peer binary.
156-
///
157-
/// The default when unset is `"required"`. Kubernetes sidecar experiments may
158-
/// set this to `"relaxed"` to enforce endpoint and L7 policy without per-binary
159-
/// `/proc` identity binding.
160-
pub const NETWORK_BINARY_IDENTITY: &str = "OPENSHELL_NETWORK_BINARY_IDENTITY";
161-
162-
/// Unix socket used by Kubernetes sidecar topology for local coordination.
163-
///
164-
/// The network sidecar owns gateway credentials and serves policy/provider
165-
/// state over this socket instead of exposing gateway credentials to the agent
166-
/// container.
167-
pub const SIDECAR_CONTROL_SOCKET: &str = "OPENSHELL_SIDECAR_CONTROL_SOCKET";
168-
169148
/// Optional TLS server name override used when connecting to the gateway.
170149
pub const GATEWAY_TLS_SERVER_NAME: &str = "OPENSHELL_GATEWAY_TLS_SERVER_NAME";
171150

crates/openshell-driver-kubernetes/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ path = "src/main.rs"
1616

1717
[dependencies]
1818
openshell-core = { path = "../openshell-core", default-features = false }
19+
openshell-isolation-interface = { path = "../openshell-isolation-interface" }
1920
openshell-otel = { path = "../openshell-otel" }
2021
openshell-policy = { path = "../openshell-policy" }
2122

@@ -37,6 +38,8 @@ tracing-subscriber = { workspace = true }
3738
thiserror = { workspace = true }
3839
miette = { workspace = true }
3940
notify = "8"
41+
rand = { workspace = true }
42+
rcgen = { workspace = true }
4043

4144
[dev-dependencies]
4245
openshell-otel-test-support = { path = "../openshell-otel-test-support" }

0 commit comments

Comments
 (0)