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
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.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ terminal-colorsaurus = "1.0"
# Error handling
miette = { version = "7", features = ["fancy"] }
thiserror = "2"

# Windows platform APIs (ETW/TDH audit consumer in openshell-driver-mxc; Windows-only)
windows = { version = "0.62", features = ["Win32_Foundation", "Win32_System_Diagnostics_Etw", "Win32_System_Time"] }
anyhow = "1"

# Logging/Tracing
Expand Down
9 changes: 9 additions & 0 deletions crates/openshell-driver-mxc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ name = "openshell_driver_mxc"

[dependencies]
openshell-core = { path = "../openshell-core" }
# OCSF builders + emit target used by the Windows ETW audit consumer. OS-agnostic
# crate (no windows deps), so safe to depend on from all targets; only the
# windows-gated `etw_consumer` module actually uses it.
openshell-ocsf = { path = "../openshell-ocsf" }
tokio = { workspace = true }
tonic = { workspace = true }
futures = { workspace = true }
Expand All @@ -26,6 +30,11 @@ tracing = { workspace = true }
thiserror = { workspace = true }
uuid = { workspace = true }

# ETW/TDH real-time consumer (Plane A audit). Windows-only so the Linux/WSL
# build stays an empty stub.
[target.'cfg(target_os = "windows")'.dependencies]
windows = { workspace = true }

[dev-dependencies]
tokio = { workspace = true }
# tempfile is not a workspace dependency; 3.27 is already resolved in Cargo.lock.
Expand Down
77 changes: 77 additions & 0 deletions crates/openshell-driver-mxc/examples/README-ocsf-audit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
OpenShell MXC - ETW -> OCSF audit-trail example
===============================================

WHAT THIS PROVES / PRODUCES
The full Windows OCSF audit path on this box:
gateway -> MXC driver -> process_container sandbox
-> the OS "Sandboxing" ETW provider fires as the sandbox is created
-> the gateway's in-process consumer decodes each event, attributes it to
an OpenShell sandbox_id, and maps it to OCSF
-> events are written to a durable JSONL audit log AND printed as
human-readable shorthand.

The deliverable is the OCSF log: openshell-ocsf.<date>.log, one OCSF event
object per line - the same schema and medium the Linux OpenShell pipeline
produces (Windows is at functional parity).

OCSF classes you will see:
[6002] Application Lifecycle - sandbox created
[5019] Device Config State Change - OS policy / hardening / proxy / console
[1007] Process Activity - in-sandbox process launch (+ cmd line)
[2004] Detection Finding - MXC setup activity errors (informational)

PREREQUISITES (on this test box)
- wxc-exec.exe present (default expected: C:\mxc-kit\bin\wxc-exec.exe)
- process_container backend live (it was for our earlier runs)
- Run ELEVATED (Run as administrator) OR from an account in the
'Performance Log Users' group. Opening the real-time ETW session needs this;
without it the run fails fast with a clear message.

HOW TO RUN
1. Open an ELEVATED PowerShell in THIS folder.
2. Run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\run-ocsf-audit.ps1
If wxc-exec is somewhere else:
... -File .\run-ocsf-audit.ps1 -WxcExecPath "D:\path\to\wxc-exec.exe"

WHAT YOU GET BACK
The script prints PASS/FAIL + an event-type coverage count and class breakdown,
points you at the OCSF audit log, and creates:
results-<timestamp>.zip
It contains the OCSF audit log (openshell-ocsf.<date>.log), the full transcript,
the gateway logs (with the human-readable OCSF shorthand), a summary, and the
exact config + policy used. To auto-copy the bundle to a shared location, pass
-ShareOut '\\server\share' (off by default; results stay local otherwise).

FILES IN THIS PACKAGE
openshell-gateway.exe the gateway (self-contained; needs only VC++ runtime)
openshell.exe the CLI
mxc-ocsf-audit.toml gateway/driver config (process_container, etw_audit=true, egress proxy)
ocsf-audit.yaml sandbox policy (read-write grant to the share dir)
run-ocsf-audit.ps1 the orchestrator you run
README-ocsf-audit.txt this file
(wxc-exec.exe is used IN PLACE on the box; not shipped)

USEFUL OPTIONS
-SandboxCount <n> Create n sandboxes (default 2). More sandboxes = more events.
-NoProxy Skip the per-sandbox egress proxy. This omits ONLY the
SandboxProxyConfigured config event; everything else is
still produced. (Default is proxy ON for the full set.)
-WxcExecPath <path> Path to wxc-exec.exe on this box.
-ShareOut <path> Copy the results bundle to a shared location
(e.g. \\server\share). Off by default (results stay local).
-KeepRunning Leave the gateway running afterward for inspection.

NOTES
- The control plane between CLI and gateway runs with --disable-tls on loopback;
that is unrelated to the OCSF audit path this example exercises.
- A "supervisor session not connected" / ssh 255 message during sandbox create
is EXPECTED on MXC and harmless - the agent already ran in-driver.
- The proxy path requires the host-side CONNECT proxy and an absolute agent
binary (the packaged config uses C:\Windows\System32\cmd.exe); the run script
handles this for you.
- The Sandboxing provider reports the sandbox entry-point process, not the full
in-sandbox process tree. Deep process-tree auditing would need a second ETW
source (Microsoft-Windows-Kernel-Process) and is out of scope for this trail.
- cmd_line is captured verbatim into OCSF process.cmd_line with no redaction on
this path; treat the audit log as sensitive at rest and in transit.
54 changes: 54 additions & 0 deletions crates/openshell-driver-mxc/examples/mxc-ocsf-audit.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# MXC gateway config for the ETW -> OCSF audit-trail example.
#
# Goal: exercise the in-process ETW consumer (Plane A) end-to-end so that
# creating a sandbox produces a full OCSF audit trail — Application Lifecycle
# [6002], Device Config State Change [5019], Process Activity [1007] and
# Detection Finding [2004] — written to a durable JSONL log, just like the Linux
# OCSF pipeline.
#
# run-ocsf-audit.ps1 patches wxc_exec_path, backend, etw_audit, the egress-proxy
# switch and agent_command into a disposable copy of this file, so the values
# here are sane defaults; edit them if you run the gateway directly.

[openshell.drivers.mxc]
# Path to wxc-exec.exe on the box (patched by the run script; default is the
# location observed on the MXC test boxes).
wxc_exec_path = "C:\\mxc-kit\\bin\\wxc-exec.exe"

# One-shot AppContainer. This is the backend whose Sandboxing ETW the consumer
# captures. (isolation_session is "dark" — it emits no provider events.)
backend = "process_container"

default_configuration_id = "composable"

# Host folder mapped read-write into the sandbox.
share_dir = "C:/work/openshell-mxc-demo"
agent_cwd = "C:/work/openshell-mxc-demo"

# A simple in-policy write — enough to make wxc-exec provision an AppContainer and
# drive the Sandboxing provider. Absolute cmd.exe path is REQUIRED when the egress
# proxy is on (the host proxy hashes agent_command[0] as its static identity
# binary, so it must be an absolute, existing exe).
agent_command = [
"C:\\Windows\\System32\\cmd.exe",
"/c",
"echo hello from openshell ocsf audit 1>C:\\work\\openshell-mxc-demo\\hello.txt",
]

debug = false

# Turn ON the Plane-A ETW -> OCSF audit consumer. This is the core of the example.
etw_audit = true

# Per-sandbox governed egress. Enabling this makes the driver start a host CONNECT
# proxy and hand MXC a `network.proxy` redirect, which is what makes MXC emit the
# SandboxProxyConfigured event — the config event mapped to OCSF CONFIG [5019]
# that completes full event coverage. Requires backend = process_container and a
# loopback (127.0.0.1) seed address; the driver allocates a unique ephemeral port
# per sandbox from this seed. Run-ocsf-audit.ps1 disables this when passed
# -NoProxy.
egress_proxy = true
egress_proxy_addr = "127.0.0.1:18080"
19 changes: 19 additions & 0 deletions crates/openshell-driver-mxc/examples/ocsf-audit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# ocsf-audit.yaml — sandbox policy for the MXC ETW -> OCSF audit-trail example.
#
# Minimal filesystem policy granting the shared host folder read-write; everything
# else is default-deny. The granted path MUST match `share_dir` /
# OPENSHELL_MXC_SHARE_DIR in mxc-ocsf-audit.toml.
#
# No network_policies block is needed here: the per-sandbox egress proxy is driven
# by `egress_proxy = true` in mxc-ocsf-audit.toml (that is what makes MXC emit the
# SandboxProxyConfigured event we map to OCSF), not by a policy rule.
version: 1

filesystem_policy:
include_workdir: false
read_only: []
read_write:
- "C:/work/openshell-mxc-demo"
Loading
Loading