krabka_authz/source.rs
1//! Abstraction over "where ACL entries come from".
2//!
3//! One evaluator therefore serves both the broker and the gateway. The broker
4//! uses a `MetadataImage` snapshot. The gateway uses a `Vec<AclEntry>` cache
5//! that it fetched with `DescribeAcls`.
6
7use krabka_metadata::{AclEntry, ResourceType, metadata_version::CIDR_ACL_MIN_LEVEL};
8
9/// Borrowed ACL entries returned by a metadata image or gateway snapshot.
10pub type AclEntries<'a> = Box<dyn Iterator<Item = &'a AclEntry> + 'a>;
11
12/// A source of ACL entries the authorizer can match against.
13///
14/// `matching_acls` MUST return every entry whose resource pattern matches
15/// `(rt, name)`: LITERAL entries equal to `name`, the LITERAL `*` wildcard, and
16/// PREFIXED entries where `name.starts_with(entry.resource_name)`.
17///
18/// Mirror [`krabka_metadata::MetadataImage::matching_acls`] in
19/// `crates/metadata/src/image.rs`.
20pub trait AclSource {
21 fn matching_acls<'a>(&'a self, rt: ResourceType, name: &'a str) -> AclEntries<'a>;
22
23 /// Every stored entry of resource type `rt`, regardless of resource name.
24 ///
25 /// [`crate::SimpleAclAuthorizer`]'s `authorize_by_resource_type` scans
26 /// this set for an ALLOW grant that no DENY covers, so unlike
27 /// `matching_acls` it is not scoped to one candidate resource name.
28 fn acls_of_type(&self, rt: ResourceType) -> AclEntries<'_>;
29
30 /// Whether a stored host containing `/` is a CIDR range (KIP-1276) rather
31 /// than plain text. Kafka 4.3.1 compares every host as text, and trunk
32 /// reads a range only once the cluster's `metadata.version` reaches
33 /// 4.4-IV1, so a source says here whether the cluster it reads from has
34 /// reached it. There is no default: a source that holds only entries, such
35 /// as [`crate::AclCache`], must carry the answer of the broker it fetched
36 /// them from, or it would read a range where that broker compares text.
37 fn cidr_hosts_supported(&self) -> bool;
38}
39
40// The broker's MetadataImage already implements the exact matching semantics;
41// adapt its iterator. (Trait is local ⇒ orphan rule satisfied for the foreign
42// MetadataImage type.)
43impl AclSource for krabka_metadata::MetadataImage {
44 fn matching_acls<'a>(&'a self, rt: ResourceType, name: &'a str) -> AclEntries<'a> {
45 Box::new(Self::matching_acls(self, rt, name))
46 }
47
48 fn acls_of_type(&self, rt: ResourceType) -> AclEntries<'_> {
49 Box::new(Self::all_acls(self).filter(move |e| e.resource_type == rt))
50 }
51
52 /// An unfinalized `metadata.version` is the bootstrap level, `4.3-IV0`,
53 /// which is below the CIDR floor.
54 fn cidr_hosts_supported(&self) -> bool {
55 self.finalized_metadata_version()
56 .is_some_and(|level| level >= CIDR_ACL_MIN_LEVEL)
57 }
58}