pub struct Acl { /* private fields */ }Expand description
A parsed ACL file: which users hold which grants, and until when.
Empty means nobody holds anything, which under a configured ACL denies every request. That is the intended failure mode, and the reason a malformed file is never partially applied.
This type answers no authorization question. It is what the file
says; Acl::at turns it into the Effective table that holds at
one instant, and that is the only type with allows on it. The split
is the whole D66 mechanism: a grant with a deadline is only safe if
forgetting the deadline is impossible, and here forgetting it does not
compile.
Implementations§
Source§impl Acl
impl Acl
Sourcepub fn parse(text: &str) -> Result<Self, String>
pub fn parse(text: &str) -> Result<Self, String>
Parses the ACL grammar described in the module documentation.
§Errors
Returns a message naming the offending line number. A file with one bad line does not parse at all: a partially applied ACL would silently revoke somebody’s access.
A deadline already in the past is not an error. It parses, and
then never matches: refusing the file would turn one stale line
into a node-wide lockout, which is a worse failure than the one it
would be reporting. Acl::expired is how the operator sees it.
Sourcepub fn grants_node(&self, user: &str) -> bool
pub fn grants_node(&self, user: &str) -> bool
Whether user is granted anything at Scope::Node here, at any
level and whatever its deadline says.
Deliberately not an Effective question. D36 forbids
self-service from issuing node-wide authority at all, and a
deadline must never be the thing that enforces that: a grant
dated into the past would answer “no” today and “yes” to anyone
who reads the same table with a different clock. The rule is
about what may be written, so it is asked of what is written.
Sourcepub fn at(&self, now: u64) -> Effective
pub fn at(&self, now: u64) -> Effective
The grants that hold at now, in unix seconds — the only table
that answers an authorization question.
Evaluated per request rather than cached across one, so a caller holding this decides every question at a single instant. A grant that lapses mid-request therefore lapses at the next request, not between two checks of the same one.
Sourcepub fn expired(&self, now: u64) -> usize
pub fn expired(&self, now: u64) -> usize
How many grants have a deadline that has already passed at now.
Reported at startup and on reload so a line that is dead on arrival — a typo in the deadline, or a file that outlived what it was granting — is visible without an operator diffing behaviour against intent.
Sourcepub fn load(path: &Path) -> Result<Self, String>
pub fn load(path: &Path) -> Result<Self, String>
Reads and parses the file at path.
§Errors
Returns a message when the file cannot be read, or when it does not parse.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether the table holds no grants at all, in which case a configured ACL denies everyone.
Sourcepub fn merged(&self, other: &Self) -> Self
pub fn merged(&self, other: &Self) -> Self
This table plus other’s grants, as one table.
The union, never an intersection: the operator’s file and the
self-service store (D36) each answer for the grants they issued,
and neither can withdraw the other’s. Written so that every
enforcement point keeps consulting exactly one Acl — the two
sources are a detail of where grants come from, not a second
decision anybody has to remember to make.