Source code for py_abac.context

"""
    PDP policy evaluation context
"""

import logging
from typing import List, Any

from .provider.base import AttributeProvider
from .provider.request import RequestAttributeProvider
from .request import AccessRequest

LOG = logging.getLogger(__name__)


[docs]class EvaluationContext(object): """ Evaluation context class """ def __init__(self, request: AccessRequest, providers: List[AttributeProvider] = None): """ Initialize evaluation context object :param request: request object """ self._subject_id = request.subject_id self._resource_id = request.resource_id self._action_id = request.action_id self._request_provider = RequestAttributeProvider(request) self._other_providers = providers or [] # Access control element being evaluated self._ace = None # Path of attribute being evaluated self._attribute_path = None # Call stack of attribute providers as called by context. The stack # is used to prevent infinite recursive loops. self._provider_call_stack = [None] @property def subject_id(self) -> str: """ Subject identifier being evaluated """ return self._subject_id @property def resource_id(self) -> str: """ Resource identifier being evaluated """ return self._resource_id @property def action_id(self): """ Action identifier being evaluated """ return self._action_id @property def ace(self) -> str: """ Access control element being evaluated """ return self._ace @ace.setter def ace(self, value: str): """ Set access control element to evaluate """ self._ace = value @property def attribute_path(self) -> str: """ Attribute path being evaluated in ObjectPath notation """ return self._attribute_path @attribute_path.setter def attribute_path(self, path: str): """ Set attribute path to evaluate """ self._attribute_path = path @property def attribute_value(self) -> Any: """ Attribute value to evaluate """ return self.get_attribute_value(self.ace, self.attribute_path)
[docs] def get_attribute_value(self, ace: str, attribute_path: str): """ Get attribute value for given access control element and attribute path :param ace: access control element :param attribute_path: attribute path in ObjectPath format :return: attribute value """ rvalue = self._request_provider.get_attribute_value(ace, attribute_path, self) # If attribute value not found then check other attribute providers if rvalue is None: # Providers are checked in order for provider in self._other_providers: # To prevent infinite recursion skip provider if already in call stack. if provider not in self._provider_call_stack: # Append provider to call-stack self._provider_call_stack.append(provider) # Call attribute provider rvalue = provider.get_attribute_value(ace, attribute_path, self) # Pop provider from call-stack self._provider_call_stack.pop() if rvalue is not None: # Return attribute value for the very first provider which has the value. # Other providers are not checked. return rvalue return rvalue