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. The one exception is a credential failure,
which keeps ErrorKind::Credentials: an identity the control plane refuses is refused
again on the identical request.
§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.
Re-exports§
pub use crate::clock::Clock;
Structs§
- Proxy
Auth - Mints, caches, and refreshes the proxy token for one MicroVM and one port.
- Proxy
Token - The minted token, as the control plane returns it: a map of header name to value.
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
authTokenmap. - 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§
- Token
Minter - Mints a proxy token. One method, so a test needs no AWS.