Files
OpenShell/crates/openshell-supervisor-process
Adel Zaalouk def7da876c fix(ocsf): emit schema-conformant OCSF 1.8 events (#4288)
Native events failed the official OCSF 1.8.0 validator: HTTP Activity
emitted is_src_dst_assignment_known, sandbox Process Activity events had
no actor, connection_info lacked direction_id, and SSH Activity events
named no endpoint. Schema tests missed these because they checked only
top-level, non-profile attributes.

Add a connection direction enum, require an actor on Process Activity
and an endpoint on SSH Activity at compile time, and name the
supervisor's SSH server with svc_name and its socket path.

Validate against OCSF 1.8.0 only. validate_required_fields and
validate_known_fields share one recursive walker that rejects undefined
attributes at every level and, for events, attributes from undeclared
profiles; objects are validated as objects. Records labelled with
another version fail. Vendor tactic and technique so ATT&CK-mapped
findings validate, drop the unused v1.7.0 schemas, and make the
embedded-schema drift test tolerate CRLF checkouts.

Keep it fixed with a per-builder conformance test and a Podman e2e test
that runs an L7 policy against a local server and validates the
supervisor's real Network, HTTP and SSH Activity JSONL. Top-level
container stays unchanged; #4915 tracks it. The schema
downgrade is unchanged.

Closes #4283

Signed-off-by: Adel Zaalouk <azaalouk@redhat.com>
2026-10-28 20:50:57 +00:00
..

OpenShell process supervisor

This crate manages workload processes and SSH sessions through the admitted isolation backend.

Bounded streaming uploads

The CLI's built-in uploads use the openshell-upload-v1 SSH subsystem. Russh returns SSH receive credit before the supervisor consumes channel data, so this subsystem returns its own credit and uses SSH for everything else. The gateway relays the channel without interpreting it.

The client sends one JSON plan line with the destination, then the raw tar stream, then SSH EOF. When the plan arrives, the supervisor starts the extractor through the ordinary BoundaryExec path, with the same workload identity, environment, working directory and filesystem policy as other SSH children. Startup runs inline, like an exec request.

Stdout carries only big-endian u64 totals of archive bytes that InputTask has written through BoundaryInput::write_all. The first total, zero, means extraction started. Extractor stdout and stderr are both sent as SSH stderr, so extractor output cannot forge credit. The client keeps at most 1 MiB beyond the last total outstanding; the supervisor rejects input beyond that window. The existing 4 MiB pending-input guard remains active.

After the extractor exits successfully and stdin has drained, the supervisor sends the final total, then the exit status. The client succeeds only when the status is zero and the final total equals the bytes it sent. A malformed plan, credit violation, extended data or EOF before the plan fails the upload with exit status 74. A rejection wins until the supervisor reports the exit result, even after the extractor exits. Rejection, channel close or disconnect terminates the extractor. Extraction writes directly to the destination, so failures can leave partially extracted files; there is no rollback or atomic replacement.

The CLI requires supervisor support for this subsystem before sending archive data. It does not fall back to the previous unpaced exec-stdin upload path. Ordinary exec stdin and SFTP retain their existing input-budget behavior.