Skip to main content

AuthGuard

Struct AuthGuard 

Source
pub struct AuthGuard { /* private fields */ }
Expand description

Wire-speed authorization guard.

Contains a bloom filter for O(1) per-packet checks and a verified-positive cache to avoid repeated full token verification on bloom hits.

§Performance

check_fast() does:

  • 2 hash computations (xxh3, ~1ns each)
  • 2 array lookups (bloom filter bits)
  • 1 DashMap probe (verified cache, ~5ns)

Total: <10ns for the Allowed/Denied paths.

Implementations§

Source§

impl AuthGuard

Source

pub fn new() -> Self

Create a new authorization guard.

Source

pub fn check_fast( &self, origin_hash: u64, channel_hash: ChannelHash, ) -> AuthVerdict

Fast-path authorization check.

Called on every packet by forwarding nodes. Must complete in <10ns.

§Ordering

The inner bloom.probe uses Relaxed loads. Cross- structure synchronization between a just-completed Self::authorize and this call is provided by DashMap’s per-shard parking_lot::Mutex on the verified.contains_key path (Acquire on shard-lock), not by bloom ordering. See the module-internal BloomCache struct docstring for the full rationale and the loom models at tests/loom_models.rs for the pinned invariants (auth_bloom_post_authorize_check_never_denies in particular pins the “subscribe-completes-before-first- packet-arrives” no-false-deny property).

Source

pub fn authorize(&self, origin_hash: u64, channel_hash: ChannelHash)

Authorize an (origin_hash, channel_hash) pair.

Called at subscription time (slow path). Inserts into both the bloom filter and the verified cache.

§Ordering

bloom.mark uses Relaxed fetch_or; verified.insert carries a Release via DashMap’s per-shard Mutex unlock. A subsequent check_fast that observes verified populated is guaranteed — via DashMap’s Acquire on shard-lock — to also observe the bloom bits, regardless of the bloom’s own ordering. See the module-internal BloomCache docstring for the full analysis of why Relaxed on the bloom is sufficient, and tests/loom_models.rs for the pinned invariants.

Source

pub fn revoke(&self, origin_hash: u64, channel_hash: ChannelHash)

Revoke authorization for an (origin_hash, channel_hash) pair.

Removes from verified cache. The bloom filter is not cleared (bloom filters don’t support deletion), but the verified cache miss will cause NeedsFullCheck which will then fail.

Bumps Self::revocations_since_rebuild so operators can schedule a rebuild_bloom when the dirty count crosses a deployment threshold and the false-positive rate makes the NeedsFullCheck fallback dominate the hot path.

Source

pub fn revocations_since_rebuild(&self) -> u64

Number of revoke calls since the last successful rebuild_bloom. Operators / monitoring hooks read this to decide when to schedule a rebuild — bloom filters can’t delete bits, so each revoke leaves a dirty bit that inflates the false-positive rate. A rule of thumb: rebuild when the count crosses ~1k or ~1% of the bloom capacity, whichever fires first.

Source

pub fn is_authorized(&self, origin_hash: u64, channel_hash: ChannelHash) -> bool

Check if a pair is authorized (verified cache only, no bloom).

This is the fast-path check used by the packet data plane. For control-plane / storage decisions, use Self::is_authorized_full — even the canonical 32-bit channel_hash could theoretically alias under adversarial name selection, so non-data-plane decisions must key on the canonical name string.

Source

pub fn allow_channel(&self, origin_hash: u64, name: &ChannelName)

Grant origin_hash full (control-plane) access to name.

Populates both ACL tiers:

Source

pub fn revoke_channel(&self, origin_hash: u64, name: &ChannelName)

Revoke origin_hash’s full access to name.

Removes from both the exact ACL and the fast-path verified cache. Bloom bits are not cleared (bloom filters don’t support deletion), so the fast path may transition to AuthVerdict::NeedsFullCheck for this pair — the exact-map miss then fails the full check.

Source

pub fn is_authorized_full(&self, origin_hash: u64, name: &ChannelName) -> bool

Exact authorization check keyed on the canonical ChannelName string. Used by control-plane / storage decisions (e.g. Redex::open_file). Unlike Self::is_authorized, this cannot be bypassed by a hash collision between two different channel names — two distinct canonical names can never alias.

Source

pub fn authorized_count(&self) -> usize

Number of authorized pairs in the verified cache.

Source

pub fn exact_authorized_count(&self) -> usize

Number of (origin, channel) pairs with exact (control-plane) authorization.

Source

pub fn rebuild_bloom(&mut self)

Rebuild the bloom filter from the verified cache.

Call this after many revocations to clear stale bloom bits. Requires &mut self to prevent concurrent reads during the clear-then-reinsert window, which would incorrectly deny authorized traffic.

Trait Implementations§

Source§

impl Debug for AuthGuard

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for AuthGuard

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more