Repository navigation
feat(supervisor): pass caller identity to middleware - #5134
Open
vineethsai7 wants to merge 2 commits into
Open
vineethsai7 wants to merge 2 commits into
vineethsai7 wants to merge 2 commits into
Conversation
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Author
|
I have read the DCO document and I hereby sign the DCO. |
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
10 of 11 tasks
vineethsai7
marked this pull request as ready for review
November 3, 2026 04:23
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Populate the existing
RequestContext.originating_processfield from the caller identity resolved when the supervisor admits an egress connection. Middleware attached to a credential-bound endpoint can now decide on request content and caller before OpenShell injects provider credentials.#5135 builds on this PR and adds upstream socket audit correlation.
This is a draft design proposal. Issue #4269 is still
state:triage-needed; maintainer feedback on the identity and truncation semantics is welcome.Related Issue
Closes #4269.
Design
The L7 relay already carries the binary path and nearest-first ancestor paths used by network policy. This change also retains the resolved PID and passes that connection identity through the existing middleware request context for HTTP requests, HTTP response preflight, and WebSocket preflight. All requests on a persistent connection use the identity captured at admission. No protobuf field or configuration key is added.
The encoded request context remains limited to 4 KiB. OpenShell preserves the leaf binary and as many nearest ancestors as fit, dropping distant ancestors first. If the leaf binary itself cannot fit,
originating_processis absent. A missing identity also leaves the field absent; a backend-supplied identity without a PID usespid: 0. When a socket has multiple owners with the same policy identity, the resolver reportspid: 0because it cannot identify the sender; it denies owners with different identities before middleware runs.This uses the supervisor middleware hook because it is already on the HTTP data path before credential injection and already has the optional
originating_processcontract. Binary-scoped network policy can gate destinations and methods but cannot decide on request content. Gateway interceptors run on control-plane RPCs, while an upstream proxy sees the request after credential injection and lacks the sandbox caller identity.Changes
An existing registered middleware can use a policy attachment such as:
Apply a reviewed complete policy with
openshell policy set my-sandbox --policy policy.yaml --wait. For acurlprocess started by a coding agent, the service receives a context with this shape:{ "originating_process": { "binary": "/usr/bin/curl", "pid": 42, "ancestors": ["/usr/bin/claude"] } }The same identity reaches the response and WebSocket preflight for that connection. This is an additive value in an existing optional field, so the wire contract and existing policy files remain valid. The field is absent in endpoint-only proxy mode or when the supervisor cannot attribute a process. Existing middleware that assumed the field was always absent should handle the populated value.
Release Notes
Supervisor middleware can use the admitted process binary and ancestry when evaluating HTTP requests before credentials are injected, HTTP responses, and WebSocket preflight.
Testing
cargo fmt --check -p openshell-supervisor-middleware -p openshell-supervisor-networkthroughdcb.cargo clippy --locked -p openshell-supervisor-middleware -p openshell-supervisor-network --all-targets -- -D warningsthroughdcb.cargo test --locked -p openshell-supervisor-middleware -p openshell-supervisor-networkthroughdcb: 129 middleware unit tests, 1,584 network unit tests, and local integration tests passed. LocalStack tests remain ignored by their own fixture requirement.uv run tasks/scripts/check_docs_nav.py,fern-api@5.112.0 check, andmarkdownlint-cli2@0.22.0throughdcb: zero errors. Fern reported three warnings outside the changed page.Follow-ups
Checklist
Review follow-up
e1a3fc756. The resolver now leaves the PID unavailable when multiple processes with the same policy identity hold the socket. Middleware receivespid: 0.e1a3fc756. Middleware identity now uses exact UTF-8 paths. The process field is absent when a leaf or ancestor path cannot be represented exactly.AGENTS.md:184requires an accepted issue for an author without upstream write access. GitHub reports no upstream push access forvineethsai7, while issue feat(supervisor): populateRequestContext.originating_processfor supervisor middleware #4269 remainsstate:triage-needed. A maintainer must address the issue state or access; this task prohibits issue and PR edits.The GitHub review APIs had no actionable reviewer comments. The only conversation comments were the automated workflow vetting notice and the DCO acknowledgement. Formatting, Clippy with
-D warnings, full crate tests (129 middleware and 1,584 network unit tests plus local integration tests), docs navigation, Fern, and Markdown lint passed throughdcb; the final test run passed after one transientETXTBSYfailure in an existing hot-swap fixture on an intermediate run. No test host was used.Manual verification
PR: NVIDIA/OpenShell #5134 (feat/4269-v1), head
e1a3fc7561ce27c55dcf6ba3b839f5db081a1bc3.Before: upstream main
be5e49499(openshell 0.1.7-dev.40+gbe5e49499). After: the PR head.Environment
cargo build --release); supervisor and sandbox runtime packaged as local images and set assupervisor_image/sandbox_runtime_image. Gateway and CLI ran on RHEL 9 through an Ubuntu 24.04 glibc loader.examples/supervisor-middleware-content-guardservice, built from the PR tree with one extra line (eprintln!("MW-REQ-CONTEXT {:?}", request.context)at the top ofevaluate_http_request) so each request'sRequestContextis printed. Registered in the gateway TOML as[[openshell.supervisor.middleware]] name = "content-guard-example",grpc_endpoint = "http://127.0.0.1:28110",allow_insecure_transport = true. The same service process served both the main and the PR gateway.ubuntu:24.04pluscurl. Upstream: a small Python HTTP server on the host (port 28120) reached ashost.openshell.internal.Steps
Before (main supervisor)
The middleware sees no caller:
originating_processis absent.After (PR supervisor)
Three sandboxes on the PR gateway, each running
curlthrough different shells (requests allowed by policy, responseok, HTTP 200):The caller binary and its ancestry (nearest parent first) reach the middleware before credential injection, for both the forwarded-HTTP and the CONNECT-tunnel request styles. Each request on the connection carries the identity captured at admission.
Observation (not a failure of the documented contract)
pidwas0on every request in this Docker deployment, although each connection was held by a singlecurlprocess. The PR documentspid: 0when the owner is ambiguous (several processes holding the socket), so this is within the documented contract, but the PID was never populated in a real run; PID attribution is covered only by the unit tests (which setbinary_pid = Some(42)). The main supervisor's own network events showpid0 for the same traffic in this deployment, so this is not introduced by the PR. I did not find out why the PID is not resolved here.Result
PASS for the stated purpose:
originating_processwith the caller binary and ancestor paths is populated in a real middleware request on a real sandbox, and absent on main. The PID part was not demonstrated (pid: 0in all runs).