pub struct WhoIs {
pub node: Node,
pub user_profile: Option<UserProfile>,
pub capabilities: Vec<(String, Vec<String>)>,
pub cap_map: BTreeMap<String, Vec<String>>,
}Expand description
The result of a Runtime::whois lookup: the node that owns a tailnet
source address, plus its user and capabilities.
Analogous to tsnet’s apitype.WhoIsResponse.
Fields§
§node: NodeThe node that owns the queried source IP.
user_profile: Option<UserProfile>The profile of the user that owns the node — Go apitype.WhoIsResponse.UserProfile.
Resolved by joining the node’s owning user id against the netmap’s UserProfiles table
(accumulated by the PeerTracker across delta updates).
None when control sent no profile for that user — a tagged node with no human owner, or a
profile not yet delivered. Carries the whole profile rather than one flattened label so an
embedder can authorise on UserProfile::groups, which is the one owner attribute a node
cannot re-derive locally; user is still there for the display case.
capabilities: Vec<(String, Vec<String>)>The node’s node-level capability map (Go Node.CapMap — node attributes like
can-funnel), as (capability, args) pairs, populated from the domain
Node’s cap_map, sorted by capability name. Distinct from
cap_map, which is the flow-scoped peer-capability grants.
cap_map: BTreeMap<String, Vec<String>>The flow-scoped peer-capability grants for the queried src -> dst flow — Go
apitype.WhoIsResponse.CapMap (tailcfg.PeerCapMap). The grants control’s packet-filter
application rules authorize for traffic from this node to the queried address, keyed by
capability name with raw-JSON values. Empty when no grant matches the flow (or no scoped
query was made). Distinct from the node-level capabilities.
Implementations§
Source§impl WhoIs
impl WhoIs
Sourcepub fn user(&self) -> Option<String>
pub fn user(&self) -> Option<String>
The best human-facing label for the owning user: the profile’s login name when present,
else its display name, else None (no profile, or a profile with neither).
This is the flattened view user_profile replaced; use the profile
itself for anything but display.
Sourcepub fn user_groups(&self) -> &[String]
pub fn user_groups(&self) -> &[String]
The groups control reported for the owning user — Go
apitype.WhoIsResponse.UserProfile.Groups. SCIM groups (e.g. engineering@example.com) or
tailnet-policy group names (e.g. group:eng).
The authorisation shortcut: whois.user_groups().iter().any(|g| g == "group:eng").
Empty both when there is no profile at all and when control reported no groups — which includes every control server that does not send the field. An empty list is therefore “control told this node nothing”, not a proof of non-membership: fail closed on it (deny), never treat it as a negative assertion.
Trait Implementations§
impl Eq for WhoIs
impl StructuralPartialEq for WhoIs
Auto Trait Implementations§
impl Freeze for WhoIs
impl RefUnwindSafe for WhoIs
impl Send for WhoIs
impl Sync for WhoIs
impl Unpin for WhoIs
impl UnsafeUnpin for WhoIs
impl UnwindSafe for WhoIs
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,
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>>
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.impl<T> ErasedDestructor for Twhere
T: 'static,
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