1 """NDG Security Policy and PolicySet base class
2
3 NERC DataGrid
4 """
5 __author__ = "P J Kershaw"
6 __date__ = "01/11/11"
7 __copyright__ = "(C) 2011 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$"
12
13 from abc import ABCMeta, abstractmethod, abstractproperty
14 import traceback
15 import logging
16 log = logging.getLogger(__name__)
17
18 from ndg.xacml.finder.policyfinderbase import PolicyFinderBase
19 from ndg.xacml.parsers import AbstractReaderFactory, AbstractReader
20 from ndg.xacml.parsers.common import Common
21 from ndg.xacml.core import XacmlCoreBase
22
23
24 from ndg.xacml.core.context.response import Response
25 from ndg.xacml.core.context.result import Result, Decision
26 from ndg.xacml.core.context.exceptions import XacmlContextError
30 __metaclass__ = ABCMeta
31 '''
32 Base class for Policy and PolicySet, each of which can be nested within
33 PolicySets and evaluated with policy combining algorithms.
34 '''
35
36 __slots__ = ()
37
40
41 @abstractproperty
43 """Subclasses return the identifier appropriate to the class.
44 """
45 return None
46
47 @classmethod
48 - def fromSource(cls, source, readerFactory, finder):
49 """Create a new policy or policy set from the input source parsing it
50 using a reader from the required reader factory e.g. ETreeReaderFactory
51 to use ElementTree based parsing.
52
53 @param source: source from which to read the policy - file path,
54 file object, XML node or other dependent on the reader factory selected
55 @type source: string, file, XML node type
56 @param readerFactory: factory class returns reader class used to parse
57 the policy
58 @type readerFactory: ndg.xacml.parsers.AbstractReaderFactory
59 @param finder: policy finder
60 @type finder: ndg.xacml.finder.PolicyFinderBase subclass
61 @return: new policy instance
62 @rtype: ndg.xacml.core.policy.Policy
63 """
64 if not issubclass(readerFactory, AbstractReaderFactory):
65 raise TypeError('Expecting %r derived class for reader factory '
66 'method; got %r' % (AbstractReaderFactory,
67 readerFactory))
68
69 reader = readerFactory.getReader(cls)
70 if not issubclass(reader, AbstractReader):
71 raise TypeError('Expecting %r derived class for reader class; '
72 'got %r' % (AbstractReader, reader))
73
74 if not isinstance(finder, PolicyFinderBase):
75 raise TypeError('Expecting %r derived object for policy finder; '
76 'got %r' % (PolicyFinderBase, type(finder)))
77 finder.setReader(reader)
78
79 common = Common(finder)
80 return reader.parse(source, common)
81
82 @classmethod
84 """Create a new policy or policy set from the input source parsing it
85 using a reader from the required reader factory e.g. ETreeReaderFactory
86 to use ElementTree based parsing.
87
88 @param source: source from which to read the policy - file path,
89 file object, XML node or other dependent on the reader factory selected
90 @type source: string, file, XML node type
91 @param readerFactory: factory class returns reader class used to parse
92 the policy
93 @type readerFactory: ndg.xacml.parsers.AbstractReaderFactory
94 @return: new policy instance
95 @rtype: ndg.xacml.core.policy.Policy
96 """
97 reader = common.policyFinder.reader
98 return reader.parse(source, common)
99
124
126 """Evaluate the decision for this policy or policy set and context.
127
128 @param context: XACML request context
129 @type context: ndg.xacml.core.context.request.Request
130 @return: XACML response instance
131 @rtype: ndg.xacml.core.context.result.Decision
132 @raise XacmlContextError: error evaluating input request context
133 """
134
135
136 try:
137 log.debug('Evaluating %s %r ...', self.ELEMENT_LOCAL_NAME,
138 self.ident)
139
140
141 decision = Decision()
142
143
144 if self.target is not None:
145 targetMatch = self.target.match(context)
146 if targetMatch:
147 log.debug('Match to request context for target in %s '
148 '%r', self.ELEMENT_LOCAL_NAME, self.ident)
149 else:
150 log.debug('No target set in %s %r', self.ELEMENT_LOCAL_NAME,
151 self.ident)
152 targetMatch = True
153
154 if not targetMatch:
155 log.debug('No match to request context for target in %s '
156 '%r returning NotApplicable status',
157 self.ELEMENT_LOCAL_NAME, self.ident)
158 decision = Decision.NOT_APPLICABLE
159 return decision
160
161
162
163 decision = self.evaluateCombiningAlgorithm(context)
164
165 except Exception:
166
167
168 log.error('No PDPError type exception raised evaluating request '
169 'context, returning %r decision:%s',
170 Decision.INDETERMINATE_STR,
171 traceback.format_exc())
172
173 decision = Decision.INDETERMINATE
174
175 return decision
176
177 @abstractmethod
179 """Evaluates the appropriate combining algorithm for this policy or
180 policy set.
181 @param context: the request context
182 @type context: ndg.xacml.core.request.Request
183 @return: result of the evaluation - the decision for this rule
184 @rtype: ndg.xacml.core.context.result.Decision
185 """
186 return Decision.INDETERMINATE
187