pub struct ProxyAuth { /* private fields */ }Expand description
Mints, caches, and refreshes the proxy token for one MicroVM and one port.
Shared behind an Arc and mutated through &self, because every request needs
the headers and a request path that needed &mut would serialize the whole
session behind one lock.
Implementations§
Source§impl ProxyAuth
impl ProxyAuth
Sourcepub fn with_clock(
minter: Arc<dyn TokenMinter>,
port: u16,
clock: Arc<dyn Clock>,
) -> ProxyAuth
pub fn with_clock( minter: Arc<dyn TokenMinter>, port: u16, clock: Arc<dyn Clock>, ) -> ProxyAuth
A ProxyAuth with the default refresh interval, on clock.
Infallible where Self::with_refresh_after isn’t: DEFAULT_REFRESH_AFTER is a
constant this module owns, and a test below asserts it satisfies that guard.
ProxyAuth::new(minter, port) is this on tokio’s clock, in microvms_core::prelude.
Sourcepub fn with_refresh_after(
minter: Arc<dyn TokenMinter>,
port: u16,
refresh_after: Duration,
clock: Arc<dyn Clock>,
) -> Result<ProxyAuth, Error>
pub fn with_refresh_after( minter: Arc<dyn TokenMinter>, port: u16, refresh_after: Duration, clock: Arc<dyn Clock>, ) -> Result<ProxyAuth, Error>
A ProxyAuth with an explicit refresh interval and clock.
Refuses an interval at or above MAX_TOKEN_LIFETIME (S2, TRAP-9). An
interval at the ceiling is the specific mistake: it looks like “refresh when
the token expires”, and it means every refresh races the expiry it exists to
avoid. Refused locally rather than documented, because the symptom is a 401
from the proxy that reads as a wrong agent token.
Sourcepub fn port(&self) -> u16
pub fn port(&self) -> u16
The port this token is scoped to, and the PROXY_PORT_HEADER value.
Sourcepub fn mint_count(&self) -> u64
pub fn mint_count(&self) -> u64
How many tokens have been minted over this instance’s life.
Public because it is the only externally visible evidence that minting happens in the request path at all: a token cached forever and a token refreshed on schedule produce identical successful requests, and the count is what distinguishes them. STATE-8’s resume test asserts on it.
Sourcepub fn invalidate(&self)
pub fn invalidate(&self)
Drops the cached token so the next request mints a fresh one (STATE-8).
Called after a resume. The measured behaviour is that a resumed VM keeps its endpoint URL and its bootstrap state, but a token minted against the pre-suspend instance is not guaranteed to survive — and a stale-token rejection there reads exactly like a daemon that died.
Synchronous, so a state machine can call it from a non-async transition.
Sourcepub fn is_cached(&self) -> bool
pub fn is_cached(&self) -> bool
Whether a token is cached and still inside the refresh window.
Exposed for the resume lane: after Self::invalidate this is false, which is
a fact a test can assert without issuing a request.
Asked about this session’s own port, which is the one every request on the hot path
targets. A token warmed only for some other port would read false here, and that is
the right answer to “is a request ready to go” — see Self::fresh_token_for.
Sourcepub async fn headers(&self) -> Result<Vec<(String, String)>, Error>
pub async fn headers(&self) -> Result<Vec<(String, String)>, Error>
Every header this request needs, minting first if the cache is stale.
Both headers, always. The auth value is read out of the token’s map by name; the rest of the map rides along in case the platform adds a third header; and the port header is filled from this instance’s port unless the token already named one.
Sourcepub async fn headers_for_port(
&self,
port: u16,
) -> Result<Vec<(String, String)>, Error>
pub async fn headers_for_port( &self, port: u16, ) -> Result<Vec<(String, String)>, Error>
Both required headers, for a port this instance was not built with.
What a caller opening its own connection to some other port on the same VM needs —
the harness contract’s getPortEndpoint() -> {url, headers} is exactly this shape,
and reimplementing it outside this module would mean a second mint path (see the
module docs on why there is one).
The requested port wins over one the token map carries, which is the opposite of
Self::headers. The reason is that a caller naming a port is answering the
question the header asks, and quietly substituting a different port would send a
request the caller can neither predict nor debug: the rejection names the token.
Self::headers defers to the map instead because nobody named a port there.
The auth value is a bearer credential. Nothing in this crate logs the returned pairs and no type here stores them; a caller that logs them is past what this module can prevent.
Sourcepub async fn subprotocols(&self, port: u16) -> Result<[String; 3], Error>
pub async fn subprotocols(&self, port: u16) -> Result<[String; 3], Error>
The three subprotocols a WebSocket handshake through the endpoint proxy offers.
In wire order: WS_SUBPROTOCOL, the JWE behind
WS_AUTH_SUBPROTOCOL_PREFIX, and port behind WS_PORT_SUBPROTOCOL_PREFIX.
See the module docs for why a handshake carries these instead of the two headers,
and note that the platform strips all three before forwarding — so a server inside
the VM never negotiates them.
Minted through the same cache and refresh schedule as Self::headers: a
long-lived connection opened at minute fifty gets a token minted at minute fifty,
not the one from construction, and nothing here can mint a token this instance’s
schedule does not know about.
The middle string contains the credential. Same rule as
Self::headers_for_port: this crate stores and logs none of it.
Trait Implementations§
Source§impl ProxyAuthExt for ProxyAuth
impl ProxyAuthExt for ProxyAuth
Source§fn new(minter: Arc<dyn TokenMinter>, port: u16) -> Self
fn new(minter: Arc<dyn TokenMinter>, port: u16) -> Self
ProxyAuth with the validated defaults: ProxyAuth::with_clock on tokio’s clock.Auto Trait Implementations§
impl !Freeze for ProxyAuth
impl !RefUnwindSafe for ProxyAuth
impl !UnwindSafe for ProxyAuth
impl Send for ProxyAuth
impl Sync for ProxyAuth
impl Unpin for ProxyAuth
impl UnsafeUnpin for ProxyAuth
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more