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
24 changes: 24 additions & 0 deletions .github/workflows/branch-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -278,12 +278,22 @@ jobs:
vm-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway, build-vm-driver]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
strategy:
fail-fast: false
matrix:
include:
- suite: managed
test_name: ""
- suite: additional-ca
test_name: additional_ca
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-vm-test.yml
with:
suite-name: ${{ matrix.suite }}
test-name: ${{ matrix.test_name }}
conformance-artifact-prefix: openshell-conformance

docker-external-driver-e2e:
Expand Down Expand Up @@ -356,14 +366,27 @@ jobs:
agent_sandbox_version: v0.5.0
topology: combined
extra_helm_values: ""
test_name: ""
- agent_sandbox_api: v1alpha1
agent_sandbox_version: v0.4.6
topology: combined
extra_helm_values: ""
test_name: ""
- agent_sandbox_api: v1beta1
agent_sandbox_version: v0.5.0
topology: sidecar
extra_helm_values: deploy/helm/openshell/ci/values-sidecar.yaml
test_name: ""
- agent_sandbox_api: v1beta1
agent_sandbox_version: v0.5.0
topology: combined-additional-ca
extra_helm_values: ""
test_name: additional_ca
- agent_sandbox_api: v1beta1
agent_sandbox_version: v0.5.0
topology: sidecar-additional-ca
extra_helm_values: deploy/helm/openshell/ci/values-sidecar.yaml
test_name: additional_ca
permissions:
actions: read
contents: read
Expand All @@ -374,6 +397,7 @@ jobs:
job-name: Kubernetes E2E (Rust smoke, ${{ matrix.topology }}, Agent Sandbox ${{ matrix.agent_sandbox_api }})
agent-sandbox-version: ${{ matrix.agent_sandbox_version }}
extra-helm-values: ${{ matrix.extra_helm_values }}
test-name: ${{ matrix.test_name }}
conformance-artifact-prefix: openshell-conformance

kubernetes-workspace-managed-e2e:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-docker-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ on:
required: false
type: string
default: >-
[{"suite":"python","cmd":"mise run --no-deps --skip-deps e2e:python","apt_packages":"","python_proto":true,"mcp":false},{"suite":"oidc-python","cmd":"mise run --no-deps --skip-deps e2e:oidc-python:docker","apt_packages":"","python_proto":true,"mcp":false},{"suite":"oidc-pkce-docker","cmd":"mise run --no-deps --skip-deps e2e:oidc-pkce:docker","apt_packages":"openssh-client","python_proto":false,"mcp":false},{"suite":"rust-docker","cmd":"mise run --no-deps --skip-deps e2e:rust","apt_packages":"openssh-client","python_proto":false,"mcp":false},{"suite":"mcp","cmd":"mise run --no-deps --skip-deps e2e:mcp","apt_packages":"","python_proto":false,"mcp":true}]
[{"suite":"python","cmd":"mise run --no-deps --skip-deps e2e:python","apt_packages":"","python_proto":true,"mcp":false},{"suite":"oidc-python","cmd":"mise run --no-deps --skip-deps e2e:oidc-python:docker","apt_packages":"","python_proto":true,"mcp":false},{"suite":"oidc-pkce-docker","cmd":"mise run --no-deps --skip-deps e2e:oidc-pkce:docker","apt_packages":"openssh-client","python_proto":false,"mcp":false},{"suite":"rust-docker","cmd":"mise run --no-deps --skip-deps e2e:rust","apt_packages":"openssh-client","python_proto":false,"mcp":false},{"suite":"additional-ca","cmd":"OPENSHELL_E2E_DOCKER_TEST=additional_ca mise run --no-deps --skip-deps e2e:docker","apt_packages":"openssh-client","python_proto":false,"mcp":false},{"suite":"mcp","cmd":"mise run --no-deps --skip-deps e2e:mcp","apt_packages":"","python_proto":false,"mcp":true}]

permissions:
actions: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-podman-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ on:
required: false
type: string
default: >-
[{"suite":"provider-refresh-keycloak","runner":"ubuntu-26.04","podman_major":"5","podman_package_version":"5.7.0+ds2-3build1","conmon_package_version":"2.1.13+ds1-2","cmd":"mise run --no-deps --skip-deps e2e:provider-refresh-keycloak"}]
[{"suite":"provider-refresh-keycloak","runner":"ubuntu-26.04","podman_major":"5","podman_package_version":"5.7.0+ds2-3build1","conmon_package_version":"2.1.13+ds1-2","cmd":"mise run --no-deps --skip-deps e2e:provider-refresh-keycloak"},{"suite":"additional-ca","runner":"ubuntu-26.04","podman_major":"5","podman_package_version":"5.7.0+ds2-3build1","conmon_package_version":"2.1.13+ds1-2","cmd":"OPENSHELL_E2E_PODMAN_TEST=additional_ca mise run --no-deps --skip-deps e2e:podman"}]

permissions:
actions: read
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/e2e-vm-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ on:
required: false
type: string
default: ""
test-name:
required: false
type: string
default: ""

permissions:
actions: read
Expand Down Expand Up @@ -61,4 +65,5 @@ jobs:
- name: Run tests
env:
E2E_TASK: ${{ inputs.e2e-task }}
OPENSHELL_E2E_VM_TEST: ${{ inputs.test-name }}
run: mise run --no-deps --skip-deps "$E2E_TASK"
11 changes: 11 additions & 0 deletions Cargo.lock

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

25 changes: 25 additions & 0 deletions architecture/sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,31 @@ maps an accepted proxy connection back to the workload socket by matching the
complete local-to-remote TCP tuple before resolving every process that owns the
socket inode.

### Additional Destination Trust

`[openshell.supervisor.network].additional_ca_cert_paths` adds operator-owned
certificate authorities to sandbox destination TLS trust. Gateway startup reads
and strictly normalizes the certificate-only PEM files into one bundle. An
invalid source or staging failure aborts startup or sandbox provisioning rather
than falling back to public roots. The bundle augments bundled, system, or
native roots and preserves normal hostname verification.

Drivers deliver the normalized material at their runtime boundary. Docker and
Podman bind-mount a gateway-owned artifact. Kubernetes creates immutable,
content-addressed ConfigMap generations in each target namespace and validates
an existing generation without mutation; combined topology mounts it only in
the agent container that runs the supervisor, while sidecar topology mounts it
only in `openshell-network`. VM writes it into the per-sandbox overlay. All paths
converge on `/etc/openshell-tls/network-additional-ca.crt` and protected
supervisor startup arguments. The supervisor verifies the expected generation
before including these roots in destination and child-process trust files.

Destination trust remains separate from corporate-proxy CA material, gateway
listener TLS, OIDC trust, and sandbox-to-gateway mTLS through
`OPENSHELL_TLS_CA`. Configuration is startup-only. Source changes require a
gateway restart, and running sandboxes retain their initialized trust until
recreated or restarted.

CONNECT and absolute-form forward HTTP are explicit-proxy adapters over the same
egress pipeline. Each adapter normalizes its request into an egress intent, and
the shared authorization result carries the process evidence and endpoint
Expand Down
5 changes: 4 additions & 1 deletion crates/openshell-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ tempfile = { version = "3", optional = true }
[target.'cfg(unix)'.dependencies]
nix = { workspace = true }
rustix = { workspace = true }
libc = "0.2"

[features]
default = ["telemetry"]
Expand All @@ -54,8 +55,10 @@ tonic-prost-build = { workspace = true }
protoc-bin-vendored = { workspace = true }

[dev-dependencies]
tempfile = "3"
h2 = "0.4"
rcgen = { workspace = true }
tempfile = "3"
tokio-rustls = { workspace = true }

[lints]
workspace = true
5 changes: 5 additions & 0 deletions crates/openshell-core/src/container_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ pub const CONTROL_ROOTS: &[&str] = &[
pub const SUPERVISOR_CONTAINER_DIR: &str = "/opt/openshell/bin";
pub const SUPERVISOR_CONTAINER_BINARY: &str = "/opt/openshell/bin/openshell-sandbox";
pub const TLS_CLIENT_DIR: &str = "/etc/openshell/tls/client";
/// Destination-only trust staged by compute drivers for the network
/// supervisor. This must remain separate from gateway client mTLS and the
/// corporate-proxy CA path.
pub const NETWORK_ADDITIONAL_CA_BUNDLE_PATH: &str = "/etc/openshell-tls/network-additional-ca.crt";
pub const TLS_CA_MOUNT_PATH: &str = "/etc/openshell/tls/client/ca.crt";
pub const TLS_CERT_MOUNT_PATH: &str = "/etc/openshell/tls/client/tls.crt";
pub const TLS_KEY_MOUNT_PATH: &str = "/etc/openshell/tls/client/tls.key";
Expand Down Expand Up @@ -108,6 +112,7 @@ mod tests {
SUPERVISOR_CONTAINER_DIR,
SUPERVISOR_CONTAINER_BINARY,
TLS_CLIENT_DIR,
NETWORK_ADDITIONAL_CA_BUNDLE_PATH,
TLS_CA_MOUNT_PATH,
TLS_CERT_MOUNT_PATH,
TLS_KEY_MOUNT_PATH,
Expand Down
2 changes: 1 addition & 1 deletion crates/openshell-core/src/driver_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ fn read_regular_file_bounded(path: &str, max_bytes: u64) -> Result<String, Bound
use std::os::unix::fs::OpenOptionsExt as _;
std::fs::OpenOptions::new()
.read(true)
.custom_flags(nix::libc::O_NONBLOCK)
.custom_flags(libc::O_NONBLOCK)
.open(path)
};
#[cfg(not(unix))]
Expand Down
Loading
Loading