pyutils.security package

Submodules

pyutils.security.acl module

Right now this package only contains an implementation that allows you to define and evaluate Access Control Lists (ACLs) easily. For example:

even = acl.SetBasedACL(
    allow_set=set([2, 4, 6, 8, 10]),
    deny_set=set([1, 3, 5, 7, 9]),
    order_to_check_allow_deny=acl.Order.ALLOW_DENY,
    default_answer=False,
)
self.assertTrue(even(2))
self.assertFalse(even(3))
self.assertFalse(even(-4))

ACLs can also be defined based on other criteria, for example:

a_or_b = acl.StringWildcardBasedACL(
    allowed_patterns=['a*', 'b*'],
    order_to_check_allow_deny=acl.Order.ALLOW_DENY,
    default_answer=False,
)
self.assertTrue(a_or_b('aardvark'))
self.assertTrue(a_or_b('baboon'))
self.assertFalse(a_or_b('cheetah'))

Or:

weird = acl.StringREBasedACL(
    denied_regexs=[re.compile('^a.*a$'), re.compile('^b.*b$')],
    order_to_check_allow_deny=acl.Order.DENY_ALLOW,
    default_answer=True,
)
self.assertTrue(weird('aardvark'))
self.assertFalse(weird('anaconda'))
self.assertFalse(weird('blackneb'))
self.assertTrue(weird('crow'))

There are implementations for wildcards, sets, regular expressions, allow lists, deny lists, sequences of user defined predicates, etc… You can also just subclass the base SimpleACL interface to define your own ACLs easily. Its __call__() simply needs to decide whether an item is allowed or denied.

Once a SimpleACL is defined, it can be used within a CompoundACL:

a_b_c = acl.StringWildcardBasedACL(
    allowed_patterns=['a*', 'b*', 'c*'],
    order_to_check_allow_deny=acl.Order.ALLOW_DENY,
    default_answer=False,
)
c_d_e = acl.StringWildcardBasedACL(
    allowed_patterns=['c*', 'd*', 'e*'],
    order_to_check_allow_deny=acl.Order.ALLOW_DENY,
    default_answer=False,
)
conjunction = acl.AllCompoundACL(
    subacls=[a_b_c, c_d_e],
    order_to_check_allow_deny=acl.Order.ALLOW_DENY,
    default_answer=False,
)
self.assertFalse(conjunction('aardvark'))
self.assertTrue(conjunction('caribou'))
self.assertTrue(conjunction('condor'))
self.assertFalse(conjunction('eagle'))
self.assertFalse(conjunction('newt'))

A CompoundACL can also be used inside another CompoundACL so this should be a flexible framework when defining complex access control requirements:

There are two flavors of CompoundACL: AllCompoundACL and AnyCompoundAcl. The former only admits an item if all of its sub-acls admit it and the latter will admit an item if any of its sub-acls admit it.:

class pyutils.security.acl.AllCompoundACL(*, subacls: List[SimpleACL] | None = None, order_to_check_allow_deny: Order, default_answer: bool)[source]

Bases: SimpleACL

An ACL that allows if all of its subacls allow.

Parameters:
  • subacls (List[SimpleACL] | None) – a list of sub-ACLs that we will consult for each item. All sub-ACLs must allow an item for us to also allow that item.

  • order_to_check_allow_deny (Order) – set this argument to indicate what order to check items for allow and deny. Pass either Order.ALLOW_DENY to check allow first or Order.DENY_ALLOW to check deny first.

  • default_answer (bool) – pass this argument to provide the ACL with a default answer.

Note

By using order_to_check_allow_deny and default_answer you can create both allow lists and deny lists. The former uses Order.ALLOW_DENY with a default anwser of False whereas the latter uses Order.DENY_ALLOW with a default answer of True.

check_allowed(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly allowed, False otherwise.

Return type:

bool

check_denied(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly denied, False otherwise.

Return type:

bool

class pyutils.security.acl.AllowListACL(*, allow_set: Set[Any] | None)[source]

Bases: SetBasedACL

Convenience subclass for a list that only allows known items. i.e. an ‘allowlist’

Parameters:

allow_set (Set[Any] | None) – a set containing the items that are allowed.

class pyutils.security.acl.AnyCompoundACL(*, subacls: List[SimpleACL] | None = None, order_to_check_allow_deny: Order, default_answer: bool)[source]

Bases: SimpleACL

An ACL that allows if any of its subacls allow.

Parameters:
  • subacls (List[SimpleACL] | None) – a list of sub-ACLs we will consult for each item. If any of these sub-ACLs allow the item we will also allow it.

  • order_to_check_allow_deny (Order) – set this argument to indicate what order to check items for allow and deny. Pass either Order.ALLOW_DENY to check allow first or Order.DENY_ALLOW to check deny first.

  • default_answer (bool) – pass this argument to provide the ACL with a default answer.

Note

By using order_to_check_allow_deny and default_answer you can create both allow lists and deny lists. The former uses Order.ALLOW_DENY with a default anwser of False whereas the latter uses Order.DENY_ALLOW with a default answer of True.

check_allowed(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly allowed, False otherwise.

Return type:

bool

check_denied(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly denied, False otherwise.

Return type:

bool

class pyutils.security.acl.BlockListACL(*, deny_set: Set[Any] | None)[source]

Bases: SetBasedACL

Convenience subclass for a list that only disallows known items. i.e. a ‘blocklist’

Parameters:

deny_set (Set[Any] | None) – a set containing the items that are denied.

class pyutils.security.acl.DenyListACL(*, deny_set: Set[Any] | None)[source]

Bases: SetBasedACL

Convenience subclass for a list that only disallows known items. i.e. a ‘blocklist’

Parameters:

deny_set (Set[Any] | None) – a set containing the items that are denied.

class pyutils.security.acl.Order(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

A helper to express the order of evaluation for allows/denies in an Access Control List.

ALLOW_DENY = 1
DENY_ALLOW = 2
UNDEFINED = 0
class pyutils.security.acl.PredicateListBasedACL(*, allow_predicate_list: Sequence[Callable[[Any], bool]] = None, deny_predicate_list: Sequence[Callable[[Any], bool]] = None, order_to_check_allow_deny: Order, default_answer: bool)[source]

Bases: SimpleACL

An ACL that allows or denies by applying predicates.

Parameters:
  • allow_predicate_list (Sequence[Callable[[Any], bool]]) – a list of callables that indicate that an item should be allowed if they return True.

  • deny_predicate_list (Sequence[Callable[[Any], bool]]) – a list of callables that indicate that an item should be denied if they return True.

  • order_to_check_allow_deny (Order) – set this argument to indicate what order to check items for allow and deny. Pass either Order.ALLOW_DENY to check allow first or Order.DENY_ALLOW to check deny first.

  • default_answer (bool) – pass this argument to provide the ACL with a default answer.

Note

By using order_to_check_allow_deny and default_answer you can create both allow lists and deny lists. The former uses Order.ALLOW_DENY with a default anwser of False whereas the latter uses Order.DENY_ALLOW with a default answer of True.

check_allowed(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly allowed, False otherwise.

Return type:

bool

check_denied(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly denied, False otherwise.

Return type:

bool

class pyutils.security.acl.SetBasedACL(*, allow_set: Set[Any] | None = None, deny_set: Set[Any] | None = None, order_to_check_allow_deny: Order, default_answer: bool)[source]

Bases: SimpleACL

An ACL that allows or denies based on membership in a set.

Parameters:
  • allow_set (Set[Any] | None) – the set of items that are allowed.

  • deny_set (Set[Any] | None) – the set of items that are denied.

  • order_to_check_allow_deny (Order) – set this argument to indicate what order to check items for allow and deny. Pass either Order.ALLOW_DENY to check allow first or Order.DENY_ALLOW to check deny first.

  • default_answer (bool) – pass this argument to provide the ACL with a default answer.

Note

By using order_to_check_allow_deny and default_answer you can create both allow lists and deny lists. The former uses Order.ALLOW_DENY with a default anwser of False whereas the latter uses Order.DENY_ALLOW with a default answer of True.

check_allowed(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly allowed, False otherwise.

Return type:

bool

check_denied(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly denied, False otherwise.

Return type:

bool

class pyutils.security.acl.SimpleACL(*, order_to_check_allow_deny: Order, default_answer: bool)[source]

Bases: ABC

A simple Access Control List interface.

Parameters:
  • order_to_check_allow_deny (Order) – set this argument to indicate what order to check items for allow and deny. Pass either Order.ALLOW_DENY to check allow first or Order.DENY_ALLOW to check deny first.

  • default_answer (bool) – pass this argument to provide the ACL with a default answer.

Raises:

ValueError – Invalid Order argument

Note

By using order_to_check_allow_deny and default_answer you can create both allow lists and deny lists. The former uses Order.ALLOW_DENY with a default anwser of False whereas the latter uses Order.DENY_ALLOW with a default answer of True.

abstract check_allowed(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly allowed, False otherwise.

Return type:

bool

abstract check_denied(x: Any) bool[source]
Parameters:

x (Any) – the object being tested.

Returns:

True if x is explicitly denied, False otherwise.

Return type:

bool

class pyutils.security.acl.StringREBasedACL(*, allowed_regexs: List[Pattern] | None = None, denied_regexs: List[Pattern] | None = None, order_to_check_allow_deny: Order, default_answer: bool)[source]

Bases: PredicateListBasedACL

An ACL that allows or denies by applying regexps.

Parameters:
  • allowed_regexs (List[Pattern] | None) – a list of regular expressions that, if they match an item, indicate that the item should be allowed.

  • denied_regexs (List[Pattern] | None) – a list of regular expressions that, if they match an item, indicate that the item should be denied.

  • order_to_check_allow_deny (Order) – set this argument to indicate what order to check items for allow and deny. Pass either Order.ALLOW_DENY to check allow first or Order.DENY_ALLOW to check deny first.

  • default_answer (bool) – pass this argument to provide the ACL with a default answer.

Note

By using order_to_check_allow_deny and default_answer you can create both allow lists and deny lists. The former uses Order.ALLOW_DENY with a default anwser of False whereas the latter uses Order.DENY_ALLOW with a default answer of True.

class pyutils.security.acl.StringWildcardBasedACL(*, allowed_patterns: List[str] | None = None, denied_patterns: List[str] | None = None, order_to_check_allow_deny: Order, default_answer: bool)[source]

Bases: PredicateListBasedACL

An ACL that allows or denies based on string glob (*, ?) patterns.

Parameters:
  • allowed_patterns (List[str] | None) – a list of string, optionally containing glob-style wildcards, that, if they match an item, indicate it should be allowed.

  • denied_patterns (List[str] | None) – a list of string, optionally containing glob-style wildcards, that, if they match an item, indicate it should be denied.

  • order_to_check_allow_deny (Order) – set this argument to indicate what order to check items for allow and deny. Pass either Order.ALLOW_DENY to check allow first or Order.DENY_ALLOW to check deny first.

  • default_answer (bool) – pass this argument to provide the ACL with a default answer.

Note

By using order_to_check_allow_deny and default_answer you can create both allow lists and deny lists. The former uses Order.ALLOW_DENY with a default anwser of False whereas the latter uses Order.DENY_ALLOW with a default answer of True.

Module contents