pub struct Authz {
pub allowed_consumers: Vec<String>,
pub denied_consumers: Vec<String>,
pub allowed_groups: Vec<String>,
pub denied_groups: Vec<String>,
pub required_scopes: Vec<String>,
pub required_claims: BTreeMap<String, String>,
pub ip_acl: Option<IpAcl>,
pub geoip: Option<GeoipRules>,
pub dry_run: bool,
}Expand description
Route-level authorization rules (DW-020, feature analysis 4.7).
Rule semantics (frozen here; evaluation lives in the authz module):
denied_consumers/denied_groupsbeatallowed_*at the SAME level: within oneAuthz, a deny always wins a tie.allowed_consumers, when non-empty, is a closed set: the authenticated consumer must be listed. Empty = any authenticated consumer passes the consumer rule.allowed_groups, when non-empty, requires the consumer to be a member of at least one listed group. Group membership comes from the CONFIG consumer’sgroupsfield; store-only consumers (DWARA_STATE_DB deployments whose consumer has no config entry) have no groups and therefore never satisfy anallowed_groupsrule (documented limitation until the state store carries groups).required_scopes: every listed scope must appear in the JWTscopeclaim. The claim may be a space-separated string ("read write", the OAuth convention) or a JSON array of strings (["read", "write"], joined to its space-separated form when the identity’s claims are captured inauthn); non-JWT identities (API key / Basic) carry no claims and never satisfy scope rules.required_claims: exact string equality on the stringified claim value; a claim absent from the token fails the match. Only string- and number-valued claims are captured on the identity (seeauthn), so a claim that is a JSONtrue/false,null, object, or nested structure can NEVER satisfy arequired_claimsentry — there is no stringified form to compare. Comparisons are CASE-SENSITIVE throughout: consumer names, groups, scopes, and claim values must match byte-for-byte.ip_acl: evaluated against the EFFECTIVE client IP — theX-Forwarded-For-resolved client when the direct peer is insidegateway.trusted_proxies(DW-009 chain), otherwise the direct peer. SeeIpAcl.
Authentication implication: an Authz carrying ANY identity rule
(consumer/group/scope/claim) rejects anonymous requests with 401; an
ip_acl-only Authz is the one authorization shape that can
ADMIT anonymous traffic (from an IP the ACL allows). A denial of an
AUTHENTICATED request is 403 (forbidden), never 401.
Fields§
§allowed_consumers: Vec<String>Consumers allowed to call the route (empty = any authenticated).
denied_consumers: Vec<String>Consumers explicitly rejected, even when otherwise allowed.
allowed_groups: Vec<String>Groups allowed to call the route (empty = no group constraint).
denied_groups: Vec<String>Groups explicitly rejected, even when otherwise allowed.
required_scopes: Vec<String>JWT scopes (from the scope claim) every request must carry.
required_claims: BTreeMap<String, String>Claims (name -> exact stringified value) every request must carry. A listed claim absent from the token’s claims fails.
ip_acl: Option<IpAcl>IP allow/deny gate on the effective client IP.
geoip: Option<GeoipRules>GeoIP gate on the effective client IP (DW-050): country/ASN
allow and deny lists resolved through gateway.geoip’s
database. An address the database does not resolve (private
ranges, not-in-DB, no database loaded) is UNKNOWN and matches
NEITHER list: deny-lists keep passing unknowns, allow-lists
keep rejecting them. Requires a gateway.geoip block —
validation rejects the predicate without one. See
GeoipRules.
dry_run: boolMonitor mode (DW-041): evaluate this block’s rules, LOG and count
every would-be denial (the dwara_policy_dry_run_total{phase= "authz"} counter plus a dwara::policy warn event), but let the
request PROCEED as if allowed. The flag is per ATTACHMENT and
mutes only this block’s OWN denials: a LIVE deny at any other
level of the chain still enforces (dry run never makes
enforcement more permissive — the resolver walks past a dry deny
and stops only at a live one). Route auth_required is an
authentication-phase check, not an authorization rule, and is
never muted by this flag.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Authz
impl<'de> Deserialize<'de> for Authz
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl JsonSchema for Authz
impl JsonSchema for Authz
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreimpl StructuralPartialEq for Authz
Auto Trait Implementations§
impl Freeze for Authz
impl RefUnwindSafe for Authz
impl Send for Authz
impl Sync for Authz
impl Unpin for Authz
impl UnwindSafe for Authz
Blanket Implementations§
§impl<T> AnyExt for T
impl<T> AnyExt for T
§fn downcast_ref<T>(this: &Self) -> Option<&T>where
T: Any,
fn downcast_ref<T>(this: &Self) -> Option<&T>where
T: Any,
T behind reference§fn downcast_mut<T>(this: &mut Self) -> Option<&mut T>where
T: Any,
fn downcast_mut<T>(this: &mut Self) -> Option<&mut T>where
T: Any,
T behind mutable reference§fn downcast_rc<T>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>>where
T: Any,
fn downcast_rc<T>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>>where
T: Any,
T behind Rc pointer§fn downcast_arc<T>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>>where
T: Any,
fn downcast_arc<T>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>>where
T: Any,
T behind Arc pointer§fn downcast_box<T>(this: Box<Self>) -> Result<Box<T>, Box<Self>>where
T: Any,
fn downcast_box<T>(this: Box<Self>) -> Result<Box<T>, Box<Self>>where
T: Any,
T behind Box pointer§fn downcast_move<T>(this: Self) -> Option<T>
fn downcast_move<T>(this: Self) -> Option<T>
Self to T,
useful only in generic context as a workaround for specializationSource§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,
§impl<T, X> CoerceTo<T> for Xwhere
T: CoerceFrom<X> + ?Sized,
impl<T, X> CoerceTo<T> for Xwhere
T: CoerceFrom<X> + ?Sized,
fn coerce_rc_to(self: Rc<X>) -> Rc<T>
fn coerce_box_to(self: Box<X>) -> Box<T>
fn coerce_ref_to(&self) -> &T
fn coerce_mut_to(&mut self) -> &mut T
§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