feat(mxc): add Windows ETW-to-OCSF audit trail - #3015
Conversation
|
I have read the DCO document and I hereby sign the DCO. |
|
/ok to test 3e46489 |
Follow-Up NeededI cannot validate this submission yet because it is a large, cross-cutting Windows audit feature (17 files across the MXC driver, OCSF, and server configuration) without a linked validated issue, roadmap item, reviewed RFC, or maintainer confirmation of the scope. I checked PR #2959 as well; it was closed because it targeted the wrong branch, so this PR appears to be the intended continuation rather than a competing duplicate. @araza008, please link the issue, roadmap item, or RFC that authorizes this work, or ask a maintainer to confirm in this thread that this scope should proceed. If the original submitter or a maintainer does not respond within 48 business hours, this may be closed as not planned. Weekend hours do not count toward the TTL. Gator metadata
|
|
Maintainer confirmation: this scope should proceed. Please continue the Gator code review on the current head SHA. This is an explicit same-SHA review request; post the resulting review disposition if warranted. |
drew
left a comment
There was a problem hiding this comment.
gator-agent
PR Review Status
Thanks @drew, I verified your maintainer confirmation that this cross-cutting Windows audit scope should proceed and completed the requested initial review of the current head. The review found five blocking correctness, security, and audit-integrity issues.
Action required: @araza008, address the five inline findings and push an updated head for a focused follow-up review.
Blocking findings:
GATOR-3e464893-01: the shipped example uses unsupported MXC configuration and cannot complete its advertised workflow.GATOR-3e464893-02: raw command arguments are copied into durable and routed audit logs.GATOR-3e464893-03: a second gateway stops the first gateway's shared ETW session.GATOR-3e464893-04: system-wide ETW input feeds an unbounded in-memory queue.GATOR-3e464893-05: weak and stale correlation keys can misattribute host ETW activity to a sandbox.
Carried findings:
- None.
Non-blocking suggestions:
GATOR-3e464893-06: documentetw_audit,OPENSHELL_OCSF_JSON, andOPENSHELL_OCSF_LOG_DIRin the canonical gateway and observability docs.
Gator metadata
- Validation: Project-valid because verified maintainer @drew explicitly confirmed this cross-cutting scope should proceed.
- Docs: Missing canonical Fern coverage for the new gateway configuration and audit-output controls.
- Checks: Current-head
OpenShell / Branch Checksis failing in Rust lint jobs; Helm Lint and existing E2E gate statuses are green. - E2E:
test:e2ewill be required for MXC lifecycle and gateway audit behavior after review feedback is resolved; it has not been dispatched by Gator yet. - Head SHA:
3e4648932dbe1e823ac190560a3e507c7dd97ad2 - Base SHA:
74654ac30dfe7115b6b9dfdf9480342b34290607 - Merge base SHA:
65745a06ef7b4aafc00600fd7f2d16ef7da49c26 - Patch ID:
776036d10cddf58d3776c3d2c356ba322336966b - Gator payload:
7 - Review mode:
initial - Previous reviewed SHA: none
- Review budget exhausted: no
- Maintainer decision required: no
- Next state:
gator:in-review
03a78b2 to
b13cf5a
Compare
Add a Windows MXC ETW->OCSF audit trail in openshell-driver-mxc: a real-time Sandboxing-provider ETW consumer that decodes events (TDH), attributes each to an OpenShell sandbox_id, and maps them to OCSF (lifecycle 6002, config 5019, process 1007, finding 2004). cp6 Phase 1 - durable OCSF JSONL audit-file parity with Linux: - openshell-ocsf: add emit_ocsf_event_routed (populates the event-bridge thread-local AND stamps sandbox_id+message in one dispatch) plus public set/clear_current_event; OS-aware device (Device::windows/for_current_os) so device.os.name reflects the host instead of a hardcoded Linux stub. - etw_consumer: emit via the routed emit (previously fired a bare info! that never populated the bridge, so the structured event was dropped). - openshell-server: install OcsfJsonlLayer over a synchronous daily-rotated appender (durable under force-kill), gated by OPENSHELL_OCSF_JSON, path via %PROGRAMDATA%\OpenShell\logs (override OPENSHELL_OCSF_LOG_DIR). - device.hostname now resolves to the real gateway machine name. Box-proven on 7F203-MXC-001: JSONL lines == shorthand OCSF rows, all valid OCSF JSON, per-sandbox attribution intact, disabled state writes nothing. Signed-off-by: Akber Raza <akberr@nvidia.com>
Close the last three ETW->OCSF gaps so the audit trail covers the full set of events the Sandboxing provider emits (12/12): - ProcessLaunched -> Process Activity [1007] "Launch" (confirmed start; carries the real processId/threadId, the twin of CreateProcessInSandbox which only has the request + command line). - SandboxProxyConfigured -> Device Config State Change [5019] (the one network-plane setup event; surfaces proxyPort, "no proxy" when 0). - SandboxConsoleReferencePlumbed -> Device Config State Change [5019] (console-handle plumbing). map_config_state now handles the full config/hardening/setup family and carries proxyPort/hasConsoleReference/creationFlags as unmapped fields. Verified on 7F203-MXC-001: 11/12 event types emit OCSF without a proxy (SandboxProxyConfigured requires proxy config to fire). Signed-off-by: Akber Raza <akberr@nvidia.com>
Address CodeRabbit review on !31: - Prevent stale ETW attribution on a delete/launch race: register the wxc-exec pid while holding the registry lock, and bail if the sandbox entry is already gone. Previously the attribution key could be seeded after `delete` had removed the sandbox, leaving a stale key that could misroute later Sandboxing ETW events to a dead sandbox_id. Lock order (registry -> attribution) matches the delete path, so no deadlock. - Add unit tests for the new Device::windows and Device::for_current_os constructors to harden Windows/Linux OCSF device parity. Signed-off-by: Akber Raza <akberr@nvidia.com>
Addresses two ETW->OCSF attribution review items (Shailendra NVIDIA#1, NVIDIA#2). NVIDIA#2 early-event loss: ETW delivers the sandbox create/config burst the instant wxc-exec starts, which can beat the driver's register_launch (now under the registry lock post-Ready). process_event previously dropped anything unresolved, losing the racing burst. Add a bounded, time-bounded pending buffer (PENDING_MAX=4096, PENDING_TTL=5s): unresolved events are held and replayed once attribution lands, aged-out ones dropped. Consumer switched to a timed recv_timeout(200ms) so the buffer is re-driven after each event and on a tick. Emit path factored into shared emit_resolved(). NVIDIA#1 attribution collisions: a Windows PID is recycled after exit and a command line is commonly identical across sandboxes. register_launch now rebinds by_pid on reuse and clears the stale last_pid_sid hint (warns if the PID still pointed at a different, leaked sandbox); command line is held in by_cmd only while unique and demoted to a new ambiguous_cmds set on a second owner, so a duplicate command refuses to resolve rather than misroute. Unit tests: buffer replay (direct + cross-link), buffer bound, PID-reuse rebind, duplicate-cmd non-resolution. Box-verified on 7F203-MXC-001 (5 sandboxes, identical cmd -> 5 isolated sandbox_ids, 50/50 OCSF/JSONL, BuffersLost=0). Signed-off-by: Akber Raza <akberr@nvidia.com>
Review item NVIDIA#3 (Shailendra): add a PRIVACY NOTE on map_process_launch stating cmd_line is copied verbatim into OCSF process.cmd_line with no redaction, so secrets/PII on a command line land unredacted in the durable audit trail (deliberate audit-fidelity trade-off; treat the log as sensitive). Redaction is owned by an upstream privacy layer, not this path; no general audit-output PII scrubber exists today (openshell_core::secrets [CREDENTIAL] redaction is scoped to the proxy HTTP-target logging, a separate egress path). Signed-off-by: Akber Raza <akberr@nvidia.com>
…s real status Review item NVIDIA#4 (Shailendra): start_session previously returned Ok(EtwSession) as soon as the pump thread was spawned, but OpenTraceW ran later inside that thread; if it failed we still handed back a live-looking session and logged 'consumer started' (silent failure = false audit coverage). Split the two Win32 calls instead of adding a channel handshake (avoids any lost-wakeup/hang risk): the quick, synchronous OpenTraceW now runs on the caller thread (open_trace), and only the blocking ProcessTrace runs on the pump thread (run_trace). start_session returns Err if OpenTraceW fails (reclaiming the boxed Sender so the consumer disconnects, stopping the session, joining the consumer) and returns Ok/logs 'started' only once capture is genuinely open. Opened handle + LoggerName buffer + boxed Sender are carried to the pump via a Send OpenedTrace so they outlive ProcessTrace. Box-verified on 7F203-MXC-001: consumer started=True, failed-to-start=False, 50 OCSF rows / 50 JSONL, BuffersLost=0 (no regression to capture/emit). Signed-off-by: Akber Raza <akberr@nvidia.com>
CodeRabbit flagged that drain_resolved() re-resolved buffered events against the live by_pid map, so if Windows recycled a wxc-exec PID within PENDING_TTL a stale event from the dead sandbox could be emitted under the new owner. Stamp each by_pid registration with its Instant and add resolve_replay(), used only on the buffered/replay path. It (a) never falls back to the recycle-/ambiguity-prone by_cmd or last_pid_sid keys, and (b) trusts a PID match only when the registration is not newer than the buffered event by more than REPLAY_PID_GRACE (2s) - a recycled PID's registration lands well outside that window, so the stale event ages out instead of misattributing. The legitimate NVIDIA#2 seed race (registration lands ~immediately) still replays. Adds unit tests for the recycle-refusal, in-grace acceptance, and weak-fallback exclusion. Signed-off-by: Akber Raza <akberr@nvidia.com>
…DIA#4) start_session already returns Err on OpenTraceW failure (runs on the caller thread since e41a770), closing the first half of Shailendra's NVIDIA#4. This closes the second half: ProcessTrace's result was discarded, so if capture died mid-run the backend had no way to know. Add a shared CaptureHealth (stopped/stopping/exit_code) between the pump thread and EtwSession. run_trace now records ProcessTrace's WIN32_ERROR and, when the pump returns without a deliberate stop, logs at ERROR that MXC OCSF capture is no longer running. EtwSession::stop() sets `stopping` before teardown so a normal shutdown isn't misreported, and EtwSession::is_capture_alive() exposes the state for status/diagnostics. Box-verified on 7F203-MXC-001: 5 sandboxes, 50 attributed OCSF rows, JSONL parity 50/50, BuffersLost=0, clean start/stop (no false failure). Signed-off-by: Akber Raza <akberr@nvidia.com>
…figured message Add a runnable OCSF audit-trail example under examples/ (run-ocsf-audit.ps1, mxc-ocsf-audit.toml, ocsf-audit.yaml, README) that spins up sandboxes with the in-process ETW consumer and egress proxy on, emitting a full OCSF JSONL audit trail across all four classes (6002/5019/1007/2004). Fix SandboxProxyConfigured mapping to log "MXC sandbox proxy configured" instead of a misleading "(no proxy)" when the provider reports proxyPort=0; the event's presence already indicates proxy configuration. Verified on-box: 26 events, all mapped ETW event types present. Signed-off-by: Akber Raza <akberr@nvidia.com>
Improve the ETW to OCSF audit-trail example output and make it safe to ship.
Report:
- Add an event-type coverage count ("N of M expected event types fired");
the denominator auto-adjusts (8 with proxy on, 7 with -NoProxy).
- Split the checklist into expected event types vs anomaly findings
(ActivityError/FallbackError), which are reported separately and not
counted toward coverage (a clean run may emit none).
- Verdict is now coverage-based (all expected types must fire) instead of
the looser "at least 3 OCSF classes".
- Call out the absolute path to the durable OCSF JSONL log prominently.
Client-safety:
- Default -ShareOut to empty (no auto-copy); pass -ShareOut a UNC path to
opt in. Removes a hardcoded internal share path from a published example.
- Drop internal-team wording ("Hand that zip back for evaluation", "BUNDLE:")
in favor of neutral "Results bundle:".
- Update README-ocsf-audit.txt to match the opt-in -ShareOut behavior.
Verified on both MXC boxes: 7F203-MXC-001 (base-container) -> PASS, 8 of 8
event types, 26 OCSF events across 4 classes; 7F203-MXC-003 (AppContainer
fallback) -> reduced set as expected, clean output.
Signed-off-by: Akber Raza <akberr@nvidia.com>
- remove unsupported gateway-scoped workload fields from the shipped MXC audit example. - build the command, working directory, and filesystem grant from each run's ShareDir - pass the workload through --driver-config-json. - preserve the host CONNECT proxy configuration and conditional audit coverage for the future host_connect_proxy merge - require the workload output when determining the audit verdict. Signed-off-by: Akber Raza <akberr@nvidia.com>
- record only the executable basename for MXC CreateProcessInSandbox audit events - leave process.cmd_line unset so workload arguments cannot reach shorthand or JSONL logs - cover tokens, passwords, signed URLs, and PII with a secret-leak regression test - update the audit example, architecture guidance, and published logging documentation - preserve ETW attribution and future host_connect_proxy enforcement behavior Signed-off-by: Akber Raza <akberr@nvidia.com>
…ncurrent gateways
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
|
/ok to test f6c029f |
Maintainer Convergence DecisionThe third finding-bearing review round is complete. The merge-main update integrates the OCSF Root-cause findings:
Scope growth:
Reviewer-quality signals:
Action required: @NVIDIA/openshell-maintainers, decide specifically whether Gator metadata
|
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
johntmyers
left a comment
There was a problem hiding this comment.
gator-agent
PR Review Status
Thanks @drew, I checked the PID-reuse remediation you added at the latest head. It removes the synthetic old lifetime and adds both displacement-direction tests, but the fixed grace period still allows a new process event to resolve through the stale old PID registration after two seconds. The carried audit-integrity finding therefore remains open, and this is the third finding-bearing round.
Action required: @NVIDIA/openshell-maintainers, decide whether GATOR-3e464893-05 must be completed with generation-backed PID evidence before test dispatch or is explicitly waived. If it remains required, @araza008 or @drew should address the carried finding below and push a new head.
Blocking findings:
- No new findings.
Carried findings:
GATOR-3e464893-05: elapsed time is still treated as proof that a stale PID registration owns an event.
Gator metadata
- Validation: Project-valid because verified maintainer @drew confirmed this cross-cutting Windows audit scope.
- Docs: Fern gateway configuration and OCSF export documentation are updated.
- Checks: Current-head Branch Checks and Helm Lint are pending; DCO and Trivy Changes are green.
- E2E:
test:e2eis required but not dispatched while the carried review obligation remains unresolved. - Head SHA:
333c114d45ce89525536fd0387946603acd21485 - Base SHA:
38f2aef930140a74ecc573811ab7f3ac15d14b8a - Merge base SHA:
38f2aef930140a74ecc573811ab7f3ac15d14b8a - Patch ID:
259293644227b575a718ed3e131944efa2a0718d - Gator payload:
8 - Review mode:
follow_up - Previous reviewed SHA:
f443a0a46135f2710ccfb8166656e861a04655f6 - Review budget exhausted:
yes - Maintainer decision required:
yes — disposition of GATOR-3e464893-05 after the third finding-bearing round - Next state:
gator:blocked - Blocked reason:
review_convergence_decision_required
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
|
Label |
|
/ok to test ac559fe |
PR Review StatusThanks @drew. I checked your process-generation remediation on the latest head and your maintainer approval. PID attribution now requires the ETW process start key to match the key queried from the driver-owned child handle, retired PID evidence is discarded, and the added regressions cover both directions of PID reuse. This resolves Blocking findings:
Carried findings:
Gator metadata
|
Monitoring CompleteMonitoring is complete because this PR has merged. Final status: The current head I removed the active |
Summary
Adds a Windows MXC audit trail that consumes Sandboxing ETW events, attributes them to OpenShell sandboxes, and emits structured OCSF events to a durable JSONL log. This provides Windows audit coverage and output parity with the Linux OCSF path.
Changes
ProcessTracefailures accurately.Testing
mise run --skip-tools windows:cisuccessfully on an x64 Windows host.openshell-gateway.exeandopenshell.exe.Checklist