Skip to main content

Module proxy

Module proxy 

Source
Expand description

The endpoint proxy’s authentication: two headers, and a token minted inside the request path.

§Two headers, not one (TRAP-7)

X-aws-proxy-auth carries a JWE scoped to one MicroVM and a set of ports. X-aws-proxy-port names which of that token’s allowed ports this request targets. Omitting the second is a rejection that reads like a bad token, which is the worst available diagnostic: the header that is wrong is not the header the error mentions. Both measured 2026-08-05; see docs/PLATFORM.md, “Endpoint authentication”.

The other half of the same finding is the shape of the token. CreateMicrovmAuthToken answers with authToken as a map of header name to value, not a bare string, because the API is shaped for schemes needing more than one header. Reading that map as a string is the trap, and ProxyToken closes it by construction: it holds a map, exposes no as_str, has no Display, and the only way to reach the auth value is ProxyToken::auth_value, which names the header it reads.

§Minting inside the request path (TRAP-9)

The service caps a proxy token at sixty minutes. That is not a choice, and it is shorter than a long agent run — so a token minted once at construction expires mid-trial, and the resulting rejection is indistinguishable from a daemon that died. Minting therefore happens in ProxyAuth::headers, which every request calls, and a stale cache re-mints there.

DEFAULT_REFRESH_AFTER is half the ceiling rather than just under it. Refreshing at fifty-nine minutes puts the expiry inside the window between building the headers and the proxy validating them: the token is live when the request is written and dead when it is read. Half the ceiling means a request in flight across the rollover is still holding a token with about thirty minutes left.

A mint failure is WireKind::AuthTokenMint, which is retryable, and that is load-bearing rather than optimistic: a control-plane throttle at minute thirty must not kill a trial that is otherwise healthy.

§A WebSocket carries the same two facts as subprotocols, not as headers

The browser WebSocket constructor cannot set a request header, so the platform moves both facts into the one field a handshake does let a client choose: Sec-WebSocket-Protocol. Three values, in this order — WS_SUBPROTOCOL, then the token under WS_AUTH_SUBPROTOCOL_PREFIX, then the target port under WS_PORT_SUBPROTOCOL_PREFIX — and “Lambda removes MicroVM-specific subprotocols from the request before forwarding it to your application”, so an in-VM server never sees them and must not be written to expect them.

ProxyAuth::subprotocols mints through the same cache and the same refresh schedule as ProxyAuth::headers. That is the whole point of it living here rather than in a caller: a second token path would be a second place TRAP-9 has to be got right, and the one that is not on the hot path is the one that is wrong.

§Nothing here logs the token, and that is by construction rather than by care

ProxyToken’s Debug names keys only, and ProxyAuth’s prints a mint count and a cached flag. The values that do carry the credential — the header pairs and the subprotocol strings — are returned to a caller and stored on nothing, so there is no type whose Debug could leak one. A caller that logs what it was handed is outside what this module can prevent, which is why both accessors say so in their own docs.

Structs§

ProxyAuth
Mints, caches, and refreshes the proxy token for one MicroVM and one port.
ProxyToken
The minted token, as the control plane returns it: a map of header name to value.
TokioClock
The production clock. Virtual under turmoil, real otherwise.

Constants§

DEFAULT_AGENT_PORT
The port the daemon listens on in the images this repo builds (AGENTD_PORT).
DEFAULT_REFRESH_AFTER
When to re-mint: half MAX_TOKEN_LIFETIME. See the module docs for why not fifty-nine minutes.
MAX_TOKEN_LIFETIME
The ceiling the service enforces on a proxy token’s life. Not a choice.
PROXY_AUTH_HEADER
The header carrying the minted JWE. One of the two keys read out of the authToken map.
PROXY_PORT_HEADER
The header naming which of the token’s allowed ports this request targets.
WS_AUTH_SUBPROTOCOL_PREFIX
The prefix the JWE rides behind in a WebSocket handshake.
WS_PORT_SUBPROTOCOL_PREFIX
The prefix the target port rides behind in a WebSocket handshake.
WS_SUBPROTOCOL
The base subprotocol every MicroVM WebSocket handshake offers first.

Traits§

Clock
A monotonic clock, injectable so a refresh boundary is a test rather than a wait.
TokenMinter
Mints a proxy token. One method, so a test needs no AWS.