"""
Policy targets class
"""
import fnmatch
from marshmallow import Schema, fields, post_load, validate
from ..context import EvaluationContext
[docs]class Targets(object):
"""
Policy targets
"""
def __init__(self, subject_id: list, resource_id: list, action_id: list):
self.subject_id = subject_id
self.resource_id = resource_id
self.action_id = action_id
[docs] def match(self, ctx: EvaluationContext):
"""
Check if request matches policy targets
:param ctx: policy evaluation context
:return: True if matches else False
"""
return self._is_in(self.subject_id, ctx.subject_id) and \
self._is_in(self.resource_id, ctx.resource_id) and \
self._is_in(self.action_id, ctx.action_id)
@staticmethod
def _is_in(ace_ids, ace_id: str):
"""
Returns True if `ace_id` is in `ace_ids`.
"""
_ace_ids = ace_ids if isinstance(ace_ids, list) else [ace_ids]
for _id in _ace_ids:
# Unix file name type string matching
if fnmatch.fnmatch(ace_id, _id):
return True
return False
[docs]class TargetField(fields.Field):
"""
Marshmallow field class for targets
"""
_single = fields.String(validate=validate.Length(min=1))
_many = fields.List(
fields.String(validate=validate.Length(min=1)),
validate=validate.Length(min=1)
)
def _serialize(self, value, attr, obj, **kwargs):
if isinstance(value, list):
return self._many._serialize(value, attr, obj, **kwargs) # pylint: disable=protected-access
return self._single._serialize(value, attr, obj, **kwargs) # pylint: disable=protected-access
def _deserialize(self, value, attr, data, **kwargs):
if isinstance(value, list):
return self._many.deserialize(value, attr, data, **kwargs) # pylint: disable=protected-access
return self._single.deserialize(value, attr, data, **kwargs) # pylint: disable=protected-access
[docs]class TargetsSchema(Schema):
"""
JSON schema for targets
"""
subject_id = TargetField(missing="*", default="*")
resource_id = TargetField(missing="*", default="*")
action_id = TargetField(missing="*", default="*")
[docs] @post_load
def post_load(self, data, **_): # pylint: disable=missing-docstring,no-self-use
return Targets(**data)