pub struct AuthNonceStore { /* private fields */ }Expand description
cratestack_auth’s nonce store (in-memory, or Redis across replicas),
as the cratestack_core::NonceStore a server CoseEnvelope records
(kid, cti) in (§5, nonce mode).
Expiry. An entry must outlive expires_at, the instant after which
the opener would refuse the request as stale anyway (iat + 2·skew + 1,
see replay.rs). Auth’s Redis store turns timestamp + replay_window
into a whole-second TTL against its own clock and rounds down, so
the bridge claims with timestamp = now and replay_window = (expires_at + 1 s) - now: the key then lives at least until
expires_at and at most one second longer. The deadline is computed
with checked arithmetic: an expires_at too close to
DateTime::<Utc>::MAX_UTC for + 1 s is Internal (a 500) and no
claim is made, because auth’s in-memory store adds timestamp + replay_window unchecked and would panic. An expires_at already in
the past is reported new, the same answer core’s InMemoryNonceStore
gives; what is kept depends on the store: Redis floors the TTL at one
second, so the key exists for a second, while auth’s in-memory store
inserts an entry that is already expired and ignores it on the next
claim. The opener never asks, since it checks freshness first.
Errors. NonceReused is “seen” (Ok(false), the opener’s 401).
Every other error means the store could not answer, so it is
CratestackError::Internal (a 500, detail kept server-side), never
“new”. Answering “new” there would make a Redis outage switch replay
protection off.
Deploying the Redis store. Replay protection is only as durable as
the key. Run the nonce Redis with maxmemory-policy noeviction: an
evicting policy can drop a live nonce under memory pressure and let its
message be replayed. Redis replication is asynchronous, so a failover
can lose a SET the old primary acknowledged but had not yet
replicated, reopening the window for that nonce until it would have
expired. Known limitation: auth’s Redis store opens a new connection
for every claim (cratestack#1070).
Implementations§
Source§impl AuthNonceStore
impl AuthNonceStore
Sourcepub fn new(inner: Arc<dyn NonceStore>) -> AuthNonceStore
pub fn new(inner: Arc<dyn NonceStore>) -> AuthNonceStore
Bridge any cratestack_auth::NonceStore.
Sourcepub fn redis(redis_url: &str) -> Result<AuthNonceStore, CratestackError>
pub fn redis(redis_url: &str) -> Result<AuthNonceStore, CratestackError>
The Redis-backed store at redis_url, via
cratestack_auth::nonce_store_from_redis_url.
Unlike that function, an empty URL is an error, not a silent
in-memory fallback: a multi-replica deployment that lost its Redis
URL would otherwise get one nonce store per replica, and a request
replayed to another replica would be accepted. A deployment that
wants the in-memory store asks for it with new.
The URL is only parsed here; the first connection is made on the
first request, and a failure then is a 500.
Trait Implementations§
Source§impl Clone for AuthNonceStore
impl Clone for AuthNonceStore
Source§fn clone(&self) -> AuthNonceStore
fn clone(&self) -> AuthNonceStore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for AuthNonceStore
impl Debug for AuthNonceStore
Source§impl NonceStore for AuthNonceStore
impl NonceStore for AuthNonceStore
Source§fn record_if_unseen<'life0, 'life1, 'async_trait>(
&'life0 self,
nonce: &'life1 str,
expires_at: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<bool, CratestackError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
AuthNonceStore: 'async_trait,
fn record_if_unseen<'life0, 'life1, 'async_trait>(
&'life0 self,
nonce: &'life1 str,
expires_at: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<bool, CratestackError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
AuthNonceStore: 'async_trait,
nonce as seen. Returns Ok(true) if it
is the first time we see it (caller may proceed); Ok(false)
if it was already recorded (caller should reject). Implementations
must drop entries past expires_at to keep the working set bounded.Auto Trait Implementations§
impl !RefUnwindSafe for AuthNonceStore
impl !UnwindSafe for AuthNonceStore
impl Freeze for AuthNonceStore
impl Send for AuthNonceStore
impl Sync for AuthNonceStore
impl Unpin for AuthNonceStore
impl UnsafeUnpin for AuthNonceStore
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§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§impl<'src, T> IntoMaybe<'src, T> for Twhere
T: 'src,
impl<'src, T> IntoMaybe<'src, T> for Twhere
T: 'src,
impl<T> MaybeSend for T
impl<T> MaybeSendSync for T
impl<T> OrderedSeq<'_, T> for Twhere
T: Clone,
§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling [Attribute] value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi [Quirk] value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the [Condition] value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
§impl<'p, T> Seq<'p, T> for Twhere
T: Clone,
impl<'p, T> Seq<'p, T> for Twhere
T: Clone,
§type Iter<'a> = Once<&'a T>
where
T: 'a
type Iter<'a> = Once<&'a T> where T: 'a
§fn contains(&self, val: &T) -> boolwhere
T: PartialEq,
fn contains(&self, val: &T) -> boolwhere
T: PartialEq,
§fn to_maybe_ref<'b>(item: <T as Seq<'p, T>>::Item<'b>) -> Maybe<T, &'p T>where
'p: 'b,
fn to_maybe_ref<'b>(item: <T as Seq<'p, T>>::Item<'b>) -> Maybe<T, &'p T>where
'p: 'b,
MaybeRef].