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

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

Incomplete - task 2: XACML-Security Integration

  • added deny overrides rule implementation
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 isinstance(ruleCombiningAlgClass, type) or 
186            not issubclass(ruleCombiningAlgClass, RuleCombiningAlgInterface)):
187            raise TypeError('Expecting %r derived type for rule combining '
188                            'algorithm class; got %r type' %
189                            (RuleCombiningAlgInterface, ruleCombiningAlgClass))
190           
191        self.__ruleCombiningAlg = ruleCombiningAlgClass()
192        if self.__ruleCombiningAlg is NotImplemented:
193            raise UnsupportedStdFunctionError('The rule combining algorithm %r '
194                                              'is not currently implemented' % 
195                                              self.__ruleCombiningAlgId)
196           
197        elif self.__ruleCombiningAlg is None:
198            raise UnsupportedFunctionError('%r is not recognised as a valid '
199                                           'XACML rule combining algorithm' % 
200                                           self.__ruleCombiningAlgId) 
201
202    ruleCombiningAlgId = property(_getRuleCombiningAlgId, 
203                                  _setRuleCombiningAlgId, None, 
204                                  doc="Rule Combining Algorithm Id")
205
206    @property
207    def combinerParameters(self):
208        raise NotImplementedError()
209   
210    @property
211    def ruleCombinerParameters(self):
212        raise NotImplementedError()
213   
214    @property
215    def variableDefinitions(self):
216        raise NotImplementedError()
217   
218    @property
219    def rules(self):
220        return self.__attr
221   
222    @property
223    def obligations(self):
224        return self.__obligations
225
226    def _getTarget(self):
227        return self.__target
228
229    def _setTarget(self, value):
230        if not isinstance(value, Target):
231            raise TypeError('Expecting Target for "target" '
232                            'attribute; got %r' % type(value))
233        self.__target = value
234
235    target = property(_getTarget, _setTarget, doc="list of Policy targets")
236
237    def _getDescription(self):
238        return self.__description
239
240    def _setDescription(self, value):
241        if not isinstance(value, basestring):
242            raise TypeError('Expecting string type for "description" '
243                            'attribute; got %r' % type(value))
244        self.__description = value
245
246    description = property(_getDescription, _setDescription, 
247                           doc="Policy Description text")
248
249    def _getPolicyDefaults(self):
250        return self.__policyDefaults
251
252    def _setPolicyDefaults(self, value):
253        if not isinstance(value, PolicyDefaults):
254            raise TypeError('Expecting string type for "policyDefaults" '
255                            'attribute; got %r' % type(value))
256           
257        self.__policyDefaults = value
258
259    policyDefaults = property(_getPolicyDefaults, 
260                              _setPolicyDefaults, 
261                              None, 
262                              "Policy PolicyDefaults element")   
263
264    def evaluate(self, request):
265        """Make an access control decision for the given request based on this
266        policy
267       
268        @param request: XACML request context
269        @type request: ndg.xacml.core.context.request.Request
270        @return: XACML response instance
271        @rtype: ndg.xacml.core.context.response.Response
272        """
273        response = Response()
274        result = Result.createInitialised(decision=Decision.NOT_APPLICABLE)
275        response.results.append(result)
276           
277        # Exception block around all rule processing in order to set
278        # INDETERMINATE response from any exceptions raised
279        try:
280            log.debug('Checking policy %r target for match with request...',
281                      self.policyId)
282           
283            target = self.target
284           
285            # If no target is set, ALL requests are counted as matches
286            if target is not None:
287                if not target.match(request):
288                    # The target didn't match so the whole policy does not apply
289                    # to this request
290                    log.debug('No match for policy target setting %r decision',
291                              Decision.NOT_APPLICABLE_STR)
292                   
293                    result.decision = Decision.NOT_APPLICABLE
294                    return response
295           
296            log.debug('Request matches the Policy %r target', self.policyId)
297           
298            # Apply the rule combining algorithm here combining the
299            # effects from the rules evaluated into an overall decision
300            result.decision = self.ruleCombiningAlg.evaluate(self.rules,
301                                                             request)
302        except XacmlContextError, e:
303            log.error('Exception raised evaluating request context, returning '
304                      '%r decision:%s', 
305                      e.response.results[0].decision, 
306                      traceback.format_exc())
307           
308            result = e.response.results[0]
309           
310        except Exception:
311            # Catch all so that nothing is handled from within the scope of this
312            # method
313            log.error('No PDPError type exception raised evaluating request '
314                      'context, returning %r decision:%s', 
315                      Decision.INDETERMINATE_STR, 
316                      traceback.format_exc()) 
317                       
318            result.decision = Decision.INDETERMINATE
319            result.status.statusCode.value = StatusCode.PROCESSING_ERROR
320           
321        return response
322
Note: See TracBrowser for help on using the repository browser.