source: TI12-security/trunk/NDG_XACML/ndg/xacml/core/policy.py @ 6825

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

Moved PDP evaluate content into Policy.evaluate

Line 
1"""NDG Security Policy type definition
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "24/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 traceback
13import logging
14log = logging.getLogger(__name__)
15
16from ndg.xacml.utils import TypedList
17from ndg.xacml.parsers import AbstractReaderFactory, AbstractReader
18from ndg.xacml.core import XacmlCoreBase
19from ndg.xacml.core.policydefaults import PolicyDefaults
20from ndg.xacml.core.target import Target
21from ndg.xacml.core.rule import Rule
22from ndg.xacml.core.obligation import Obligation
23from ndg.xacml.core.rule_combining_alg import (RuleCombiningAlgClassFactory,
24                                               RuleCombiningAlgInterface)
25from ndg.xacml.core.exceptions import (UnsupportedStdFunctionError,
26                                       UnsupportedFunctionError)
27
28# Evaluation of a request context
29from ndg.xacml.core.context.response import Response
30from ndg.xacml.core.context.result import Result, Decision, StatusCode
31from ndg.xacml.core.context.exceptions import XacmlContextError
32
33
34class PolicyParseError(Exception):
35    """Error reading policy attributes from file"""
36
37
38class InvalidPolicyXmlNsError(PolicyParseError):
39    """Invalid XML namespace for policy document"""
40
41
42class Policy(XacmlCoreBase):
43    """NDG MSI Policy.""" 
44    DEFAULT_XACML_VERSION = "1.0"
45    ELEMENT_LOCAL_NAME = "Policy"
46    POLICY_ID_ATTRIB_NAME = "PolicyId"
47    RULE_COMBINING_ALG_ID_ATTRIB_NAME = "RuleCombiningAlgId"
48    VERSION_ATTRIB_NAME = "Version"
49
50    DESCRIPTION_LOCAL_NAME = "Description"
51    POLICY_DEFAULTS_LOCAL_NAME = "PolicyDefaults"
52    COMBINER_PARAMETERS_LOCAL_NAME = "CombinerParameters"
53    RULE_COMBINER_PARAMETERS_LOCAL_NAME = "RuleCombinerParameters"
54    OBLIGATIONS_LOCAL_NAME = "Obligations"
55   
56    __slots__ = (
57        '__policyId',
58        '__version',
59        '__ruleCombiningAlgId',
60        '__description',
61        '__policyDefaults',
62        '__target',
63        '__attr',
64        '__obligations',
65        '__ruleCombiningAlgFactory',
66        '__ruleCombiningAlg'
67    )
68   
69    def __init__(self, ruleCombiningAlgFactory=None):
70        """Customise rule combining behaviour by passing in a custom combining
71        algorithm factory.  This is invoked when the combining algorithm Id
72        property is set in order to create the corresponding combining algorithm
73        object
74        """
75        super(Policy, self).__init__()
76        self.__policyId = None
77        self.__version = None
78        self.__ruleCombiningAlgId = None
79        self.__description = None
80        self.__target = None
81       
82        # Attr should eventually allow a choice of Rule, CombinerParameter,
83        # RuleCombinerParameter and VariableDefinition but only Rule type is
84        # currently supported
85        self.__attr = TypedList(Rule)
86       
87        self.__obligations = TypedList(Obligation)
88       
89        self.__ruleCombiningAlgFactory = None
90        if ruleCombiningAlgFactory is None:
91            self.ruleCombiningAlgFactory = RuleCombiningAlgClassFactory()
92        else:
93            self.ruleCombiningAlgFactory = ruleCombiningAlgFactory
94
95        self.__ruleCombiningAlg = None
96
97    def _getRuleCombiningAlgFactory(self):
98        return self.__ruleCombiningAlgFactory
99
100    def _setRuleCombiningAlgFactory(self, value):
101        if not isinstance(value, RuleCombiningAlgClassFactory):
102            raise TypeError('Expecting %r derived type for '
103                            '"ruleCombiningAlgFactory" attibute; got %r' % 
104                            (RuleCombiningAlgClassFactory, type(value)))
105           
106        self.__ruleCombiningAlgFactory = value
107
108    ruleCombiningAlgFactory = property(_getRuleCombiningAlgFactory, 
109                                       _setRuleCombiningAlgFactory, 
110                                       doc="Rule Combining Algorithm Factory")
111   
112    @property
113    def ruleCombiningAlg(self):
114        "Rule Combining algorithm"
115        return self.__ruleCombiningAlg
116   
117    @classmethod
118    def fromSource(cls, source, readerFactory):
119        """Create a new policy from the input source parsing it using a
120        reader from the required reader factory e.g. ETreeReaderFactory to use
121        ElementTree based parsing
122       
123        @param source: source from which to read the policy - file path,
124        file object, XML node or other dependent on the reader factory selected
125        @type source: string, file, XML node type
126        @param readerFactory: factory class returns reader class used to parse
127        the policy
128        @type readerFactory: ndg.xacml.parsers.AbstractReaderFactory
129        @return: new policy instance
130        @rtype: ndg.xacml.core.policy.Policy
131        """
132        if not issubclass(readerFactory, AbstractReaderFactory):
133            raise TypeError('Expecting %r derived class for reader factory '
134                            'method; got %r' % (AbstractReaderFactory, 
135                                                readerFactory))
136           
137        reader = readerFactory.getReader(cls)
138        if not issubclass(reader, AbstractReader):
139            raise TypeError('Expecting %r derived class for reader class; '
140                            'got %r' % (AbstractReader, reader))
141           
142        return reader.parse(source)
143       
144    def _getPolicyId(self):
145        return self.__policyId
146
147    def _setPolicyId(self, value):
148        if not isinstance(value, basestring):
149            raise TypeError('Expecting string type for "policyId" '
150                            'attribute; got %r' % type(value))
151           
152        self.__policyId = value
153
154    policyId = property(_getPolicyId, _setPolicyId, None, "Policy Id")
155
156    def _getVersion(self):
157        return self.__version
158
159    def _setVersion(self, value):
160        if not isinstance(value, basestring):
161            raise TypeError('Expecting string type for "version" '
162                            'attribute; got %r' % type(value))
163           
164        self.__version = value
165
166    version = property(_getVersion, _setVersion, None, "Policy Version")
167
168    def _getRuleCombiningAlgId(self):
169        return self.__ruleCombiningAlgId
170
171    def _setRuleCombiningAlgId(self, value):
172        if not isinstance(value, basestring):
173            raise TypeError('Expecting string type for "ruleCombiningAlgId" '
174                            'attribute; got %r' % type(value))
175           
176        self.__ruleCombiningAlgId = value
177        self._setRuleCombiningAlgFromId()
178       
179    def _setRuleCombiningAlgFromId(self):
180        """Set the rule combining algorithm implementation from the Id set
181        """
182        # Look-up rule combining algorithm
183        ruleCombiningAlgClass = self.__ruleCombiningAlgFactory(
184                                                    self.__ruleCombiningAlgId)
185        if not issubclass(ruleCombiningAlgClass, RuleCombiningAlgInterface):
186            raise TypeError('Expecting %r derived type for rule combining '
187                            'algorithm class; got %r' %
188                            (RuleCombiningAlgInterface, ruleCombiningAlgClass))
189           
190        self.__ruleCombiningAlg = ruleCombiningAlgClass()
191        if self.__ruleCombiningAlg is NotImplemented:
192            raise UnsupportedStdFunctionError('The rule combining algorithm %r '
193                                              'is not currently implemented' % 
194                                              self.__ruleCombiningAlgId)
195           
196        elif self.__ruleCombiningAlg is None:
197            raise UnsupportedFunctionError('%r is not recognised as a valid '
198                                           'XACML rule combining algorithm' % 
199                                           self.__ruleCombiningAlgId) 
200
201    ruleCombiningAlgId = property(_getRuleCombiningAlgId, 
202                                  _setRuleCombiningAlgId, None, 
203                                  doc="Rule Combining Algorithm Id")
204
205    @property
206    def combinerParameters(self):
207        raise NotImplementedError()
208   
209    @property
210    def ruleCombinerParameters(self):
211        raise NotImplementedError()
212   
213    @property
214    def variableDefinitions(self):
215        raise NotImplementedError()
216   
217    @property
218    def rules(self):
219        return self.__attr
220   
221    @property
222    def obligations(self):
223        return self.__obligations
224
225    def _getTarget(self):
226        return self.__target
227
228    def _setTarget(self, value):
229        if not isinstance(value, Target):
230            raise TypeError('Expecting Target for "target" '
231                            'attribute; got %r' % type(value))
232        self.__target = value
233
234    target = property(_getTarget, _setTarget, doc="list of Policy targets")
235
236    def _getDescription(self):
237        return self.__description
238
239    def _setDescription(self, value):
240        if not isinstance(value, basestring):
241            raise TypeError('Expecting string type for "description" '
242                            'attribute; got %r' % type(value))
243        self.__description = value
244
245    description = property(_getDescription, _setDescription, 
246                           doc="Policy Description text")
247
248    def _getPolicyDefaults(self):
249        return self.__policyDefaults
250
251    def _setPolicyDefaults(self, value):
252        if not isinstance(value, PolicyDefaults):
253            raise TypeError('Expecting string type for "policyDefaults" '
254                            'attribute; got %r' % type(value))
255           
256        self.__policyDefaults = value
257
258    policyDefaults = property(_getPolicyDefaults, 
259                              _setPolicyDefaults, 
260                              None, 
261                              "Policy PolicyDefaults element")   
262
263    def evaluate(self, request):
264        """Make an access control decision for the given request based on this
265        policy
266       
267        @param request: XACML request context
268        @type request: ndg.xacml.core.context.request.Request
269        @return: XACML response instance
270        @rtype: ndg.xacml.core.context.response.Response
271        """
272        response = Response()
273        result = Result.createInitialised(decision=Decision.NOT_APPLICABLE)
274        response.results.append(result)
275           
276        # Exception block around all rule processing in order to set
277        # INDETERMINATE response from any exceptions raised
278        try:
279            log.debug('Checking policy %r target for match with request...',
280                      self.policyId)
281           
282            target = self.target
283           
284            # If no target is set, ALL requests are counted as matches
285            if target is not None:
286                if not target.match(request):
287                    # The target didn't match so the whole policy does not apply
288                    # to this request
289                    log.debug('No match for policy target setting %r decision',
290                              Decision.NOT_APPLICABLE_STR)
291                   
292                    result.decision = Decision.NOT_APPLICABLE
293                    return response
294           
295            log.debug('Request matches the Policy %r target', self.policyId)
296           
297            # Apply the rule combining algorithm here combining the
298            # effects from the rules evaluated into an overall decision
299            result.decision = self.ruleCombiningAlg.evaluate(self.rules,
300                                                             request)
301        except XacmlContextError, e:
302            log.error('Exception raised evaluating request context, returning '
303                      '%r decision:%s', 
304                      e.response.results[0].decision, 
305                      traceback.format_exc())
306           
307            result = e.response.results[0]
308           
309        except Exception:
310            # Catch all so that nothing is handled from within the scope of this
311            # method
312            log.error('No PDPError type exception raised evaluating request '
313                      'context, returning %r decision:%s', 
314                      Decision.INDETERMINATE_STR, 
315                      traceback.format_exc()) 
316                       
317            result.decision = Decision.INDETERMINATE
318            result.status.statusCode.value = StatusCode.PROCESSING_ERROR
319           
320        return response
321
Note: See TracBrowser for help on using the repository browser.