feat(runtime): encrypt TCP request dispatch (frontend → worker) - #12533
Merged
Merged
Conversation
walkoss
temporarily deployed
to
external_collaborator
August 1, 2026 16:09 — with
GitHub Actions
Inactive
walkoss
temporarily deployed
to
external_collaborator
August 1, 2026 16:09 — with
GitHub Actions
Inactive
Contributor
walkoss
force-pushed
the
walid/request-plane-tls
branch
from
August 1, 2026 16:14
bf9b03a to
bce0da3
Compare
walkoss
temporarily deployed
to
external_collaborator
August 1, 2026 16:14 — with
GitHub Actions
Inactive
walkoss
temporarily deployed
to
external_collaborator
August 3, 2026 21:22 — with
GitHub Actions
Inactive
This comment has been minimized.
This comment has been minimized.
Extend TLS support to the shared TCP request plane that carries inference requests from frontend to worker. This closes the security gap where user prompts were transmitted in plaintext. Server side (shared_tcp_endpoint.rs): - Build TlsAcceptor from DYN_TCP_TLS_CERT_PATH/KEY_PATH at startup - Per-connection TLS handshake with configurable timeout - BoxRead/BoxWrite unify TLS and plaintext through read/write loops Client side (egress/tcp_client.rs): - OnceLock-cached TlsConnector from DYN_TCP_TLS_CA_CERT_PATH/INSECURE - TLS handshake with timeout on each pooled connection - BoxRead/BoxWrite through writer_task and reader_task Reuses the same DYN_TCP_TLS_* env vars as the call-home transport. No new env vars needed. Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com>
…ane TLS config SharedTcpServer::new was the only TLS entry point that panicked on bad/partial cert config; every other path (tcp/server.rs build_tls_acceptor, tcp/client.rs, egress/tcp_client.rs, nats.rs) returns a fallible Result. Make new() return anyhow::Result<Arc<Self>> and propagate the error, matching the response-stream server, so misconfiguration fails startup cleanly instead of aborting the process. Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com> (cherry picked from commit ac3623b) Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com>
walkoss
force-pushed
the
walid/request-plane-tls
branch
from
August 4, 2026 09:12
0667773 to
09293f9
Compare
walkoss
temporarily deployed
to
external_collaborator
August 4, 2026 09:12 — with
GitHub Actions
Inactive
Mirror the response-stream `build_tls_acceptor` tests from tcp/server.rs for the request-plane ingress: - new_no_tls_env_is_plaintext: no TLS env vars -> plaintext (no acceptor) - new_partial_tls_config_errors: only cert or only key -> returns Err (covers the panic->error fix, ensuring startup fails cleanly) - new_both_paths_enables_tls: cert + key -> TLS acceptor built Uses rcgen self-signed certs and temp_env, matching the existing pattern. Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com>
walkoss
temporarily deployed
to
external_collaborator
August 4, 2026 15:12 — with
GitHub Actions
Inactive
walkoss
marked this pull request as ready for review
August 4, 2026 15:46
Contributor
WalkthroughChangesTCP transport TLS
Estimated code review effort: 4 (Complex) | ~45 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
Contributor
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/fern/pages/reference/components/tls-configuration.mdx`:
- Around line 153-158: Update the TLS lifecycle description to state that
REQUEST_PLANE_TLS_CONNECTOR is cached after the first client connection, while
SharedTcpServer::new creates the TlsAcceptor during server initialization; note
that the TLS server name and handshake timeout are read per connection, and
remove the conflicting claim that all TLS configuration is cached after the
first connection.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: c0733a02-ee7f-4aa5-adcb-509b47c546ac
📒 Files selected for processing (4)
docs/fern/pages/reference/components/tls-configuration.mdxlib/runtime/src/pipeline/network/egress/tcp_client.rslib/runtime/src/pipeline/network/ingress/shared_tcp_endpoint.rslib/runtime/src/pipeline/network/manager.rs
…ckpressure writer_task wrote each batch via poll_write_vectored but never flushed the write half. With a plaintext WriteHalf<TcpStream> that was fine, but the request plane now writes through a BoxWrite that may wrap a tokio-rustls TlsStream — whose poll_write can report Ready(Ok(n)) with encrypted records still buffered in the session when the socket would block. Without a flush, a batch could stall until the next write, hanging its callers until timeout. Flush after each batch write (no-op for plaintext), failing the batch on error like a write failure. Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com>
walkoss
force-pushed
the
walid/request-plane-tls
branch
from
August 5, 2026 11:37
dd0b186 to
e88abb1
Compare
walkoss
temporarily deployed
to
external_collaborator
August 5, 2026 11:37 — with
GitHub Actions
Inactive
sttts
reviewed
Aug 5, 2026
Per review feedback (sttts), the intro overstated coverage: TLS here encrypts only the frontend<->worker TCP request and response streams, not "all traffic between components". The KV event plane (ZMQ or NATS Core) is a separate transport and is not encrypted by this configuration. Also soften the cert- rotation note — restart is a consequence of caching, not a hard requirement; hot-reload via a rustls cert resolver is a possible future enhancement. Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com>
walkoss
force-pushed
the
walid/request-plane-tls
branch
from
August 5, 2026 16:02
e88abb1 to
d4786f4
Compare
walkoss
temporarily deployed
to
external_collaborator
August 5, 2026 16:02 — with
GitHub Actions
Inactive
jthomson04
approved these changes
Aug 6, 2026
jthomson04
left a comment
Contributor
There was a problem hiding this comment.
The transport implementation follows #10921 closely. I left targeted follow-ups on test coverage and small Rust/tracing cleanup.
Contributor
|
/ok to test d4786f4 |
Per PR review (jthomson04): - store Option<TlsAcceptor> instead of Option<Arc<TlsAcceptor>> — TlsAcceptor is cheaply Clone and already holds an Arc<ServerConfig>, so the outer Arc added a redundant pointer/refcount. - emit structured tracing fields (peer_addr, error) on the request-plane TLS handshake-failed and handshake-timeout warnings instead of formatting them into the message, keeping them queryable. Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com>
walkoss
temporarily deployed
to
external_collaborator
August 11, 2026 12:22 — with
GitHub Actions
Inactive
walkoss
force-pushed
the
walid/request-plane-tls
branch
from
August 11, 2026 12:53
3bf00aa to
c4a66a4
Compare
walkoss
temporarily deployed
to
external_collaborator
August 11, 2026 12:53 — with
GitHub Actions
Inactive
sttts
enabled auto-merge (squash)
August 11, 2026 17:29
Contributor
|
/ok to test c4a66a4 |
Serve the server leaf certificate through a ReloadingCertifiedKey that reloads the cert/key from disk when their contents change, so certificate rotation (an in-place rewrite or an atomic symlink swap) takes effect without a process restart — addressing the cert-expiry outage risk raised in review (sttts): - Change is detected by hashing the file contents (blake3), not mtime, so rotations done by an atomic symlink swap are handled reliably. - The current identity is held in an ArcSwap; a single caller performs the rate-limited reload (>=30s, 1s retry after a failure) under try_lock, so a reload never blocks a handshake and a bad/partial file keeps the last valid identity. - CertifiedKey.keys_match() validates the cert and key belong together. Applies to every server built via tls_utils::server_tls_config — both the request-plane ingress and the response-stream server. The same type also implements ResolvesClientCert, so mTLS client identities reload the same way once wired on the mTLS branch. Initial load is still validated eagerly. Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com>
Per PR review (jthomson04): the previous test built TlsAcceptor/TlsConnector directly, so it could not catch env parsing, connector wiring, SNI, boxed I/O, or reader/writer integration. - Split the env->connector logic into build_request_plane_tls_connector_from_env (behind the OnceCell) so it can be unit-tested directly. - Add TcpConnection::connect_with_connector so a test can drive the real connect/handshake/reader/writer path with an explicit connector, without initializing (and poisoning) the process-global REQUEST_PLANE_TLS_CONNECTOR. - request_plane_tls_end_to_end drives a real encrypted request (connect + TLS handshake with SNI from env + boxed I/O + send_request framing) against a TLS-wrapped echo server built from the production server_tls_config. - request_plane_tls_connector_from_env_parses covers the env parsing. Signed-off-by: Walid <walid.elbouchikhi@datadoghq.com>
auto-merge was automatically disabled
August 12, 2026 08:15
Head branch was pushed to by a user without write access
walkoss
force-pushed
the
walid/request-plane-tls
branch
from
August 12, 2026 08:15
c4a66a4 to
e94247a
Compare
walkoss
temporarily deployed
to
external_collaborator
August 12, 2026 08:15 — with
GitHub Actions
Inactive
Contributor
|
/ok to test e94247a |
This was referenced Aug 19, 2026
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.
Overview
Extends TLS encryption to the TCP request plane (
egress/tcp_client/ingress/shared_tcp_endpoint), which carries user prompts from frontend to worker. This closes the security gap where inference request payloads were transmitted in plaintext while only the response stream was encrypted (#10921).Details
Server side (
ingress/shared_tcp_endpoint.rs):TlsAcceptorfromDYN_TCP_TLS_CERT_PATH/KEY_PATHat startupBoxRead/BoxWriteunify TLS and plaintext throughread_loop/write_loopClient side (
egress/tcp_client.rs):OnceLock-cachedTlsConnectorfromDYN_TCP_TLS_CA_CERT_PATH/INSECUREDYN_TCP_TLS_SERVER_NAMEfor SNI overrideBoxRead/BoxWritethroughwriter_task/reader_taskReuses the same
DYN_TCP_TLS_*environment variables as the call-home transport (#10921). No new env vars needed.Where should the reviewer start?
lib/runtime/src/pipeline/network/ingress/shared_tcp_endpoint.rs- TLS acceptor innew()+accept_loop()lib/runtime/src/pipeline/network/egress/tcp_client.rs- TLS connector inconnect()+get_request_plane_tls_connector()Related Issues
Summary by CodeRabbit
New Features
Bug Fixes
Documentation