From c086317533f8fdc53cd9b77863e7061b4b765f92 Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Thu, 8 Jul 2021 20:05:29 -0700 Subject: [PATCH] Clean up ACLs --- simple_acl.py | 60 +++++++++++++++++++++++----------------- tests/simple_acl_test.py | 2 ++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/simple_acl.py b/simple_acl.py index 39129ce..5040304 100644 --- a/simple_acl.py +++ b/simple_acl.py @@ -34,32 +34,44 @@ class SimpleACL(ABC): def __call__(self, x: Any) -> bool: """Returns True if x is allowed, False otherwise.""" + logger.debug(f'SimpleACL checking {x}') if self.order_to_check_allow_deny == ACL_ORDER_ALLOW_DENY: + logger.debug('Checking allowed first...') if self.check_allowed(x): + logger.debug(f'{x} was allowed explicitly.') return True + logger.debug('Checking denied next...') if self.check_denied(x): + logger.debug(f'{x} was denied explicitly.') return False - return self.default_answer elif self.order_to_check_allow_deny == ACL_ORDER_DENY_ALLOW: + logger.debug('Checking denied first...') if self.check_denied(x): + logger.debug(f'{x} was denied explicitly.') return False if self.check_allowed(x): + logger.debug(f'{x} was allowed explicitly.') return True - return self.default_answer - raise Exception('Should never get here.') + + logger.debug( + f'{x} was not explicitly allowed or denied; ' + + f'using default answer ({self.default_answer})' + ) + return self.default_answer @abstractmethod def check_allowed(self, x: Any) -> bool: - """Return True if x is allowed, False otherwise.""" + """Return True if x is explicitly allowed, False otherwise.""" pass @abstractmethod def check_denied(self, x: Any) -> bool: - """Return True if x is denied, False otherwise.""" + """Return True if x is explicitly denied, False otherwise.""" pass class SetBasedACL(SimpleACL): + """An ACL that allows or denies based on membership in a set.""" def __init__(self, *, allow_set: Optional[Set[Any]] = None, @@ -85,6 +97,7 @@ class SetBasedACL(SimpleACL): class PredicateListBasedACL(SimpleACL): + """An ACL that allows or denies by applying predicates.""" def __init__(self, *, allow_predicate_list: List[Callable[[Any], bool]] = None, @@ -110,6 +123,7 @@ class PredicateListBasedACL(SimpleACL): class StringWildcardBasedACL(PredicateListBasedACL): + """An ACL that allows or denies based on string glob (*, ?) patterns.""" def __init__(self, *, allowed_patterns: Optional[List[str]] = None, @@ -139,6 +153,7 @@ class StringWildcardBasedACL(PredicateListBasedACL): class StringREBasedACL(PredicateListBasedACL): + """An ACL that allows or denies by applying regexps.""" def __init__(self, *, allowed_regexs: Optional[List[re.Pattern]] = None, @@ -167,26 +182,21 @@ class StringREBasedACL(PredicateListBasedACL): ) -class CompoundACL(object): - ANY = 1 - ALL = 2 +class AnyCompoundACL(object): + """An ACL that allows if any of its subacls allow.""" + def __init__(self, subacls: List[SimpleACL]): + assert subacls is not None + self.subacls = subacls - def __init__( - self, - *, - subacls: Optional[List[SimpleACL]], - match_requirement: int = ALL - ) -> None: + def __call__(self, x: Any): + return any(acl(x) for acl in self.subacls) + + +class AllCompoundACL(object): + """An ACL that allows if all of its subacls allow.""" + def __init__(self, subacls: List[SimpleACL]): + assert subacls is not None self.subacls = subacls - if match_requirement not in (CompoundACL.ANY, CompoundACL.ALL): - raise Exception( - 'match_requirement must be CompoundACL.ANY or CompoundACL.ALL' - ) - self.match_requirement = match_requirement - def __call__(self, x: Any) -> bool: - if self.match_requirement == CompoundACL.ANY: - return any(acl(x) for acl in self.subacls) - elif self.match_requirement == CompoundACL.ALL: - return all(acl(x) for acl in self.subacls) - raise Exception('Should never get here.') + def __call__(self, x: Any): + return all(acl(x) for acl in self.subacls) diff --git a/tests/simple_acl_test.py b/tests/simple_acl_test.py index 7c17415..6c9b24c 100755 --- a/tests/simple_acl_test.py +++ b/tests/simple_acl_test.py @@ -3,6 +3,7 @@ import re import unittest +import bootstrap import simple_acl as acl @@ -44,4 +45,5 @@ class TestSimpleACL(unittest.TestCase): if __name__ == '__main__': + unittest.main = bootstrap.initialize(unittest.main) unittest.main() -- 2.45.2