Repository navigation
feat(observability): send configured headers to every OTLP collector - #5083
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
🌿 Preview your docs: https://nvidia-preview-pr-5083.docs.buildwithfern.com/openshell |
Compatibility review (advisory)New or updated breaking changes; see the full report for all findings. 1. api-behavior — No explicit risk acceptance foundWith trace export enabled, existing OTEL_EXPORTER_OTLP_TRACES_HEADERS or OTEL_EXPORTER_OTLP_HEADERS settings now add traces_otlp_headers to launch_authentication instead of preserving the baseline JSON payload.
Review details
Advisory review; publication gates are unchanged. |
c9ae50e to
dc42f93
Compare
rhuss
left a comment
There was a problem hiding this comment.
cc-review Summary
This is an agent-assisted review: cc-review ran several reviewer agents plus Codex and CodeRabbit over the diff. The redaction design holds up well, but three items should be fixed first: two error paths that can echo a credential into the gateway startup log, and an upgrade compatibility question that needs a maintainer decision. The failure scenarios come from reading the code, not from running a gateway. The one exception is the toml error message quoted in the parse_error_detail comment, which a reviewer agent reproduced in a scratch program against toml 0.8.23. The Minor findings are non-blocking, and once the three Important items are addressed (or a maintainer settles the compatibility question) this should be ready for a maintainer.
What Went Well
- Credential values stay out of logs. The hand-written
Debugimpls forOtlpTargetandOtlpHeadersprint header names only,SupervisorAuthBundleredacts the new header fields, andConfigFileError::Parsereports line and column instead of quoting the source. append_otlp_argshands the VM driver its trace headers throughOTEL_EXPORTER_OTLP_TRACES_HEADERSrather than argv, andvm_driver_receives_trace_headers_in_its_environment_onlychecks that no argument contains the secret.read_headers_filecaps the read withtake(MAX_HEADERS_FILE_BYTES + 1)and rejects non-UTF-8, malformed and duplicate lines before validation.- Header parsing now lives in the shared
headers.rs, used by the gateway, supervisor and relay alike, with a round-trip test for values containing,,=,%and spaces.configure_httpremoves the duplicated HTTP exporter setup between traces and logs. RawCollector::resolveapplies one rule to every lane (own endpoint, or inherit the whole shared collector), so one collector's credentials can't leak to another.
Findings
| Severity | File | Description | Source |
|---|---|---|---|
| Important | crates/openshell-server/src/config_file.rs:485 |
Invalid header name error echoes the headers_file line, so a padded token reaches the startup log |
security |
| Important | crates/openshell-server/src/config_file.rs:1232 |
parse_error_detail forwards serde messages that quote a string-typed headers value |
security |
| Important | crates/openshell-server/src/otel_tracing.rs:325 |
Env-only header setups now add traces_otlp_headers, which older supervisors and drivers reject |
production |
| Minor | crates/openshell-gateway/src/vm.rs:730 |
VM driver trace headers come from the supervisor helper, a second derivation of the same value | architecture |
| Minor | crates/openshell-otel/src/lib.rs:318 |
configure_http decodes header values twice on OTLP/HTTP, changing literal %XX sequences |
correctness |
| Minor | crates/openshell-otel/src/lib.rs:681 |
Header tests don't clear OTEL_EXPORTER_OTLP_*HEADERS and fail when a developer has them set |
test-quality |
| Minor | crates/openshell-server/src/config_file.rs:460 |
An unreadable headers_file stops the gateway from starting; the docs should say so |
production |
| Minor | crates/openshell-server/src/config_file.rs:795 |
Endpoint-required check duplicates RawCollector::resolve, and shared skips raw_collector! |
architecture |
| Minor | crates/openshell-server/src/config_file.rs:2111 |
No-echo assertions cover two of about fifteen header validation error cases | test-quality |
| Minor | crates/openshell-server/src/otel_tracing.rs:899 |
No test for env headers overriding configured headers on the gateway's own exporters | test-quality |
| Minor | crates/openshell-server/src/tracing_setup.rs:77 |
No test that in-process compute drivers receive the trace collector's configured headers | test-quality |
Review Details
- Findings posted: 11 (11 inline)
- Findings reviewed and not posted: 2 (documented behavior: header rotation needs restarts; external drivers must use the gateway's endpoints)
- Gate outcome: FAIL (3 Important)
- Participating reviewers: architecture, correctness, goal-alignment, production, security, test-quality, gator, codex, coderabbit
dc42f93 to
a69ff8e
Compare
rhuss
left a comment
There was a problem hiding this comment.
cc-review found no issues at a69ff8e.
Collectors that require authentication or a routing header could only get one through OTEL_EXPORTER_OTLP_*HEADERS in the gateway's environment, which reached the gateway's own exporters and supervisors' OCSF records but not supervisor spans or the agent relay, so a backend such as MLflow needed a sidecar collector to add its experiment header. Each [openshell.gateway.otlp] table now takes a headers table, or a headers_file of name=value lines that keeps credentials out of the config file, inherited with the rest of the collector by tables without their own endpoint. Exporters send them as gRPC metadata or HTTP headers, with environment headers replacing configured ones of the same name. Supervisors receive each lane's headers in their launch bundle and the VM driver in its environment; the agent relay uses only its table's headers. Config parse errors give a line and column instead of quoting the file, so a malformed header table cannot echo a token. Closes #5067 Signed-off-by: Kris Hicks <khicks@nvidia.com>
a69ff8e to
73c5c33
Compare
Summary
Collectors that need an authorization token or a routing header could get one only through
OTEL_EXPORTER_OTLP_*HEADERSin the gateway's environment, which never reached supervisor spans or the agent trace relay. Each[openshell.gateway.otlp]table now takesheaders, or aheaders_filethat keeps credentials out of the configuration file, and every exporter sends them.Related Issue
Closes #5067
Changes
headers(an inline table) andheaders_file(onename=valueheader per line, at most 64 KiB) on every OTLP table, mutually exclusive and inherited with the rest of the collector. Setting either in a table without its ownendpointis a configuration error.content-type,host,grpc-*, and others), no binary-binnames, and non-empty printable-ASCII values. Errors never include a value or a name that failed validation, andheaders_fileerrors cite the line number instead.Debugoutput redacts values, and values read fromheaders_fileare never serialized back out. Config parse errors now give the line, column (in characters), and parser message without quoting the file or any string in it, so a malformed header table cannot echo a token.OTEL_EXPORTER_OTLP_*HEADERS.Release Notes
OTLP collectors can require authentication or routing headers: set
headersorheaders_fileon[openshell.gateway.otlp]or a signal table. Supervisors and the agent trace relay send them too, so MLflow can ingest relayed agent traces directly withx-mlflow-experiment-id.Testing
cargo fmt --check, and everymise run rust:lintclippy invocation with--lockedopenshell-serverconfig tests pass on this commit; its tracing and compute tests andopenshell-gatewaylib tests pass at the top of the stackheaders_fileparsing and line-numbered errors, redaction, parse errors that do not quote the file, environment headers winning on the gateway's exporters, which headers each driver and supervisor lane receives, and headers arriving at loopback gRPC and HTTP collectors from the gateway, supervisor, and relayManually verified before the latest rebase: a dev Docker gateway relayed Pi agent traces directly to MLflow over OTLP/HTTP with
x-mlflow-experiment-id, and each trace carriedopenshell.sandbox.id.Checklist