pub struct Authority { /* private fields */ }Expand description
A tailnet-lock authority as a client tracks it: the current trusted-key State and the chain
head. Built by replaying the AUM chain (or from a control-provided checkpoint); the client
then uses Authority::node_key_authorized to decide whether a peer is trusted.
Implementations§
Source§impl Authority
impl Authority
Sourcepub fn from_state(head: AumHash, state: State) -> Authority
pub fn from_state(head: AumHash, state: State) -> Authority
Construct an authority directly from a known head and trusted-key state (e.g. a
control-provided checkpoint the client already trusts).
Sourcepub fn head_matches(&self, head: &AumHash) -> bool
pub fn head_matches(&self, head: &AumHash) -> bool
Whether head (e.g. decoded from TkaInfo.head) matches this authority’s head. A client
that finds a mismatch must resync before trusting verifications.
Verify that node_key is authorized under the current authority state by the given
node-key-signature CBOR blob (Go Authority.NodeKeyAuthorized).
Fail-closed: a credential-only signature, an untrusted authorizing key, a malformed blob, or
a bad signature all return Err.
§Errors
Returns TkaError::Decode if signature_cbor is malformed,
TkaError::CredentialCannotAuthorize for a credential-only signature,
TkaError::UntrustedKey if the authorizing key is not in the current state,
TkaError::NodeKeyMismatch if the signature does not cover node_key, or
TkaError::BadSignature if cryptographic verification fails.
Source§impl Authority
impl Authority
Sourcepub fn from_verified_chain(chain: VerifiedAumChain) -> Authority
pub fn from_verified_chain(chain: VerifiedAumChain) -> Authority
Build an Authority from a VerifiedAumChain — the trust-boundary constructor.
Because a VerifiedAumChain can only be produced by VerifiedAumChain::verify (which runs
Go’s aumVerify on every link), this is the constructor a live client must use when the chain
originates from an untrusted source (the control plane / /machine/tka/* sync RPC). The type
system makes the signature check un-skippable: there is no way to reach this function with an
unverified chain. Mirrors Go tka.Open, which folds only AUMs already verified by Inform.
Sourcepub fn from_chain(aums: &[Aum]) -> Result<Authority, TkaError>
pub fn from_chain(aums: &[Aum]) -> Result<Authority, TkaError>
Build an Authority by replaying a linear chain of AUMs from genesis to head (Go
tka.Authority.Head after computeActiveChain on a single confirmed branch), checking only
the chain’s structure (genesis kind, parent links, key-state transitions, checkpoint
StateID) — NOT AUM signatures.
§This is NOT a trust boundary
from_chain does not verify that each AUM is signed by keys trusted at its parent. It is safe
only for chains whose authenticity is already established by other means — the existing unit
tests, and a chain the caller has itself fed through VerifiedAumChain::verify. For any
chain that comes from an untrusted source (the control plane), use
VerifiedAumChain::verify + Authority::from_verified_chain, which the type system makes
impossible to bypass. (A malicious control plane could otherwise forge an AddKey/RemoveKey
here and silently defeat tailnet lock — the exact threat TKA exists to stop.)
aums must be ordered parent→child: the first is the genesis — a NoOp, AddKey, or
Checkpoint with no parent (Go computeStateAt rejects any other kind as an invalid
genesis) — and each subsequent AUM’s prev_aum_hash must equal the prior AUM’s Aum::hash.
A slice that is actually a suffix of a chain (its first AUM names a parent not in the slice)
is rejected rather than mis-rooted.
For the forked case (competing children of one parent), use Authority::from_forked_chain.
§Errors
TkaError::BadChain if aums is empty or its genesis is an invalid kind;
TkaError::BadParent if a link doesn’t chain (incl. a genesis that carries a parent);
TkaError::BadKeyState for an invalid add/remove/update or a mismatched checkpoint StateID;
TkaError::Decode for a malformed checkpoint/add.
Sourcepub fn from_forked_chain(
prefix: &[Aum],
branches: &[&[Aum]],
) -> Result<Authority, TkaError>
pub fn from_forked_chain( prefix: &[Aum], branches: &[&[Aum]], ) -> Result<Authority, TkaError>
Resolve a single fork point: a shared linear prefix (genesis→fork point, parent-ordered)
followed by branches, the competing children of the fork point. The active child is chosen by
[pick_next_aum]’s deterministic rules (weight → RemoveKey preference → lowest hash),
evaluated against the state at the fork point, and applied. This is the consensus-critical
selection every node must make identically; the linear Authority::from_chain is the common
(no-fork) case.
Each branch must be exactly one AUM. In this single-AUM-per-branch shape the choice is
provably identical to Go’s pickNextAUM over the fork point’s children. A multi-step branch
is rejected (TkaError::BadChain) rather than mis-resolved: Go re-runs pickNextAUM at
every link (advanceByPrimary), re-evaluating weight against the evolving state, so judging a
whole multi-AUM branch by its first AUM alone could pick a different active head than Go and
silently fork the trusted-key set. Implementing the per-step loop (and a general multi-fork DAG
walk) is deferred to when the sync layer can actually surface such a chain; until then this
guard keeps the model honest. (The common re-bootstrap case — competing single-AUM heads — is
fully covered.)
§Errors
As Authority::from_chain, plus TkaError::BadChain if branches is empty, or any branch
is not exactly one AUM.
Source§impl Authority
impl Authority
Sourcepub fn sync_offer(
&self,
storage: &dyn AumStore,
oldest: AumHash,
) -> Result<SyncOffer, TkaError>
pub fn sync_offer( &self, storage: &dyn AumStore, oldest: AumHash, ) -> Result<SyncOffer, TkaError>
Build the SyncOffer this authority would send a peer (Go Authority.SyncOffer): its
head plus an exponentially-spaced sample of ancestors back to oldest, ending with
oldest. oldest is the oldest AUM the caller holds (Go a.oldestAncestor.Hash()); our
verify-only Authority does not track it, so it is passed in — typically the genesis hash
of the chain the caller staged in storage.
storage must contain the chain from head back to oldest; a gap simply truncates the
ancestor list early (the walk breaks on the first missing parent, exactly like Go).
Sourcepub fn missing_aums(
&self,
storage: &dyn AumStore,
remote_offer: &SyncOffer,
oldest: AumHash,
) -> Result<Vec<Aum>, TkaError>
pub fn missing_aums( &self, storage: &dyn AumStore, remote_offer: &SyncOffer, oldest: AumHash, ) -> Result<Vec<Aum>, TkaError>
Given a peer’s SyncOffer, compute the AUMs they are missing — the ones to send them so
their chain catches up to ours (Go Authority.MissingAUMs). storage must hold our chain.
Returns an empty Vec when the peer is already up to date.
Mirrors Go: compute our own offer, find the intersection of the two chains, then gather every AUM from the intersection forward to our head (excluding the intersection AUM itself).
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Authority
impl RefUnwindSafe for Authority
impl Send for Authority
impl Sync for Authority
impl Unpin for Authority
impl UnsafeUnpin for Authority
impl UnwindSafe for Authority
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<A, T> DynMessage<A> for T
impl<A, T> DynMessage<A> for T
Source§fn handle_dyn<'a>(
self: Box<T>,
state: &'a mut A,
actor_ref: ActorRef<A>,
tx: Option<Sender<Result<Box<dyn Any + Send>, SendError<Box<dyn Any + Send>, Box<dyn Any + Send>>>>>,
stop: &'a mut bool,
) -> Pin<Box<dyn Future<Output = Result<(), Box<dyn ReplyError>>> + Send + 'a>>
fn handle_dyn<'a>( self: Box<T>, state: &'a mut A, actor_ref: ActorRef<A>, tx: Option<Sender<Result<Box<dyn Any + Send>, SendError<Box<dyn Any + Send>, Box<dyn Any + Send>>>>>, stop: &'a mut bool, ) -> Pin<Box<dyn Future<Output = Result<(), Box<dyn ReplyError>>> + Send + 'a>>
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
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