Add direct SigV4 transport to exec-server (#42781)

## Why

Allow remote exec servers to connect directly to AWS-hosted registries that
authenticate registry requests and WebSocket handshakes with AWS SigV4.

## What changed

- Add `--remote-transport direct` with SigV4 profile, region, and service
  options while keeping Noise as the default transport.
- Register the `direct_jsonrpc_v1` transport and carry plain exec-server
  JSON-RPC messages over the authenticated WebSocket.
- Reuse direct registrations across transient disconnects, refresh them after
  a `409 Conflict`, and require TLS for non-loopback endpoints.

## Testing

- Cover CLI validation and SigV4 request signing.
- Exercise direct registration, handshake retry behavior, JSON-RPC
  interoperability, and process recovery after reconnecting.

GitOrigin-RevId: 0755df330ba3abe5db0a516fdaa49338d9bbe2d2
This commit is contained in:
ostepanian
2026-09-04 14:49:46 +00:00
committed by copyberry
parent c9fac4dd5a
commit b3f5e45cc1
15 changed files with 1988 additions and 121 deletions
@@ -144,30 +144,7 @@ impl ExecServerHarness {
pub(crate) async fn disconnectable_websocket_proxy(
&self,
) -> anyhow::Result<DisconnectableWebSocketProxy> {
let upstream = self
.websocket_url
.strip_prefix("ws://")
.ok_or_else(|| anyhow!("exec-server websocket URL must use ws://"))?
.to_string();
let listener = TcpListener::bind("127.0.0.1:0").await?;
let websocket_url = format!("ws://{}", listener.local_addr()?);
let (pause_tx, pause_rx) = oneshot::channel();
let (blocked_connection_tx, blocked_connection_rx) = oneshot::channel();
let (resume_tx, resume_rx) = oneshot::channel();
let task = tokio::spawn(run_disconnectable_proxy(
listener,
upstream,
pause_rx,
blocked_connection_tx,
resume_rx,
));
Ok(DisconnectableWebSocketProxy {
websocket_url,
pause_tx: Some(pause_tx),
blocked_connection_rx: Some(blocked_connection_rx),
resume_tx: Some(resume_tx),
task,
})
DisconnectableWebSocketProxy::new(&self.websocket_url).await
}
pub(crate) async fn send_request(
@@ -278,6 +255,33 @@ impl ExecServerHarness {
}
impl DisconnectableWebSocketProxy {
pub(crate) async fn new(websocket_url: &str) -> anyhow::Result<Self> {
let upstream = websocket_url
.strip_prefix("ws://")
.ok_or_else(|| anyhow!("exec-server websocket URL must use ws://"))?
.trim_end_matches('/')
.to_string();
let listener = TcpListener::bind("127.0.0.1:0").await?;
let websocket_url = format!("ws://{}", listener.local_addr()?);
let (pause_tx, pause_rx) = oneshot::channel();
let (blocked_connection_tx, blocked_connection_rx) = oneshot::channel();
let (resume_tx, resume_rx) = oneshot::channel();
let task = tokio::spawn(run_disconnectable_proxy(
listener,
upstream,
pause_rx,
blocked_connection_tx,
resume_rx,
));
Ok(DisconnectableWebSocketProxy {
websocket_url,
pause_tx: Some(pause_tx),
blocked_connection_rx: Some(blocked_connection_rx),
resume_tx: Some(resume_tx),
task,
})
}
pub(crate) fn websocket_url(&self) -> &str {
&self.websocket_url
}