source: TI12-security/trunk/NDG_XACML/ndg/xacml/core/context/pdp.py @ 6806

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDG_XACML/ndg/xacml/core/context/pdp.py@6806
Revision 6806, 6.8 KB checked in by pjkersha, 10 years ago (diff)

Moving matching and rule evaluation code out of the PDP class and into the relevant classes they pertain to e.g. target matching moved to Target class match method and so on.

Line 
1"""NDG Security Policy Decision Point type definition
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "25/02/10"
7__copyright__ = "(C) 2010 Science and Technology Facilities Council"
8__contact__ = "Philip.Kershaw@stfc.ac.uk"
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = "$Id: $"
12import logging
13log = logging.getLogger(__name__)
14
15import traceback
16
17from ndg.xacml.core.context.exceptions import XacmlContextError
18from ndg.xacml.core.context.pdpinterface import PDPInterface
19from ndg.xacml.core.policy import Policy
20from ndg.xacml.core.apply import Apply
21from ndg.xacml.core.context.request import Request
22from ndg.xacml.core.context.response import Response
23from ndg.xacml.core.context.result import Result, Decision
24from ndg.xacml.core.context.result import StatusCode
25from ndg.xacml.core.exceptions import (UnsupportedStdFunctionError,
26                                       UnsupportedFunctionError)     
27       
28
29class PDPError(XacmlContextError):
30    """Base class for PDP class exceptions"""
31     
32   
33class UnsupportedElementError(PDPError):
34    """Element type is not supported in this implementation"""
35    def __init__(self, *arg, **kw):
36        super(UnsupportedElementError, self).__init__(*arg, **kw)
37        self.response.results[0
38                            ].status.statusCode.value = StatusCode.SYNTAX_ERROR
39
40
41class UnsupportedStdElementError(UnsupportedElementError):
42    """Element type is part of the XACML spec. but is not supported in this
43    implementation""" 
44   
45   
46class PDP(PDPInterface):
47    """A XACML Policy Decision Point implementation.  It supports the use of a
48    single policy but not policy sets
49    """
50    __slots__ = ('__policy', '__request')
51   
52    def __init__(self, policy=None):
53        """
54        @param policy: policy object for PDP to use to apply access control
55        decisions, may be omitted.
56        @type policy: ndg.xacml.core.policy.Policy / None
57        """
58        self.__policy = None
59        if policy is not None:
60            self.policy = policy
61           
62        self.__request = None
63
64    @classmethod
65    def fromPolicySource(cls, source, readerFactory):
66        """Create a new PDP instance with a given policy
67        @param source: source for policy
68        @type source: type (dependent on the reader set, it could be for example
69        a file path string, file object, XML element instance)
70        @param readerFactory: reader factory returns the reader to use to read
71        this policy
72        @type readerFactory: ndg.xacml.parsers.AbstractReader derived type
73        """           
74        pdp = cls()
75        pdp.policy = Policy.fromSource(source, readerFactory)
76        return pdp
77   
78    @property
79    def policy(self):
80        """policy object for PDP to use to apply access control decisions"""
81        return self.__policy
82   
83    @policy.setter
84    def policy(self, value):
85        '''policy object for PDP to use to apply access control decisions'''
86        if not isinstance(value, Policy):
87            raise TypeError('Expecting %r derived type for "policy" input; got '
88                            '%r instead' % (Policy, type(value)))
89        self.__policy = value
90
91    @property
92    def request(self):
93        """request context"""
94        return self.__request
95   
96    @request.setter
97    def request(self, value):
98        '''request context'''
99        if not isinstance(value, Request):
100            raise TypeError('Expecting %r derived type for "request" '
101                            'input; got %r instead' % (Request, 
102                                                       type(value)))
103        self.__request = value
104                                       
105    def evaluate(self, request):
106        """Make an access control decision for the given request based on the
107        policy set
108       
109        @param request: XACML request context
110        @type request: ndg.xacml.core.context.request.Request
111        @return: XACML response instance
112        @rtype: ndg.xacml.core.context.response.Response
113        """
114        response = Response()
115        result = Result.createInitialised(decision=Decision.NOT_APPLICABLE)
116        response.results.append(result)
117       
118        try:
119            self.request = request
120           
121        except AttributeError, e:
122            log.error(str(e))
123            result.decision = Decision.INDETERMINATE
124            return response
125           
126        # Exception block around all rule processing in order to set
127        # INDETERMINATE response from any exceptions raised
128        try:
129            log.debug('Checking policy target for match with request...')
130           
131            target = self.policy.target
132           
133            if target is None:
134                log.debug('No target set so no match with request context')
135                result.decision = Decision.NOT_APPLICABLE
136                return response
137           
138            if not target.match(request):
139                log.debug('No match for policy target setting %r decision',
140                          Decision.NOT_APPLICABLE_STR)
141               
142                result.decision = Decision.NOT_APPLICABLE
143                return response
144           
145            log.debug('Request matches the Policy target')
146           
147            # Check rules
148            ruleStatusValues = [False]*len(self.policy.rules)
149            for i, rule in enumerate(self.policy.rules):
150                ruleStatusValues[i] = rule.evaluate()
151#                log.debug('Checking policy rule %r for match...', rule.id)
152#                if not self.matchTarget(rule.target, request):
153#                    log.debug('No match to request context for target in rule '
154#                              '%r', rule.id)
155#                    ruleStatusValues[i] = True
156#                    continue   
157#               
158#                # Apply the condition
159#                ruleStatusValues[i] = self.evaluateCondition(rule.condition)
160                     
161        except PDPError, e:
162            log.error('Exception raised evaluating request context, returning '
163                      '%r decision:%s', 
164                      e.response.results[0].decision, 
165                      traceback.format_exc())
166           
167            result = e.response.results[0]
168           
169        except Exception:
170            # Catch all so that nothing is handled from within the scope of this
171            # method
172            log.error('No PDPError type exception raised evaluating request '
173                      'context, returning %r decision:%s', 
174                      Decision.INDETERMINATE_STR, 
175                      traceback.format_exc()) 
176                       
177            result.decision = Decision.INDETERMINATE
178            result.status.statusCode.value = StatusCode.PROCESSING_ERROR
179           
180        return response
181
182
183
Note: See TracBrowser for help on using the repository browser.