1 """NDG Security Rule type definition
2
3 NERC DataGrid
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: rule.py 7955 2011-12-21 18:29:45Z rwilkinson $"
12 import traceback
13 import logging
14 log = logging.getLogger(__name__)
15
16 from ndg.xacml.core import XacmlCoreBase
17 from ndg.xacml.core.target import Target
18 from ndg.xacml.core.condition import Condition
19 from ndg.xacml.core.context.result import Decision
23 """Rule Effect
24
25 @cvar PERMIT_STR: permit decision string
26 @type PERMIT_STR: string
27
28 @cvar DENY_STR: deny decision string
29 @type DENY_STR: string
30
31 @cvar TYPES: list of valid effect strings
32 @type TYPES: tuple
33
34 @ivar value: effect value
35 @type value: string
36 """
37 DENY_STR = 'Deny'
38 PERMIT_STR = 'Permit'
39 TYPES = (DENY_STR, PERMIT_STR)
40 __slots__ = ('__value',)
41
43 """@param effect: initialise effect value, defaults to deny
44 @type effect: basestring / ndg.xacml.core.rule.Effect
45 """
46 self.__value = None
47 self.value = effect
48
50 '''Enable pickling
51
52 @return: class instance attributes dictionary
53 @rtype: dict
54 '''
55 _dict = {}
56 for attrName in Effect.__slots__:
57
58
59 if attrName.startswith('__'):
60 attrName = "_Effect" + attrName
61
62 _dict[attrName] = getattr(self, attrName)
63
64 return _dict
65
67 '''Enable pickling
68
69 @param attrDict: class instance attributes dictionary
70 @type attrDict: dict
71 '''
72 for attrName, val in attrDict.items():
73 setattr(self, attrName, val)
74
76 """Set effect value
77
78 @param value: effect value - constrained vocabulary to Effect.TYPES
79 @type value: string or ndg.xacml.core.rule.Effect
80 @raise AttributeError: invalid decision string value input
81 @raise TypeError: invalid type for input decision value
82 """
83 if isinstance(value, Effect):
84
85 value = str(value)
86
87 elif not isinstance(value, basestring):
88 raise TypeError('Expecting string or Effect instance for '
89 '"value" attribute; got %r instead' % type(value))
90
91 if value not in self.__class__.TYPES:
92 raise AttributeError('Permissable effect types are %r; got '
93 '%r instead' % (Effect.TYPES, value))
94 self.__value = value
95
97 """Get effect value
98
99 @return: effect value
100 @rtype: string
101 """
102 return self.__value
103
104 value = property(fget=_getValue, fset=_setValue, doc="Effect value")
105
107 """represent decision as a string
108
109 @return: decision value
110 @rtype: string
111 """
112 return self.__value
113
115 """
116 @param effect: effect value to compare with self's
117 @type effect: string or ndg.xacml.core.rule.Effect
118 @return: True if the decision values match, False otherwise
119 @rtype: bool
120 @raise AttributeError: invalid decision string value input
121 @raise TypeError: invalid type for input decision value
122 """
123 if isinstance(effect, Effect):
124
125 value = effect.value
126
127 elif isinstance(effect, basestring):
128 value = effect
129
130 else:
131 raise TypeError('Expecting string or Effect instance for '
132 'input effect value; got %r instead' % type(value))
133
134 if value not in self.__class__.TYPES:
135 raise AttributeError('Permissable effect types are %r; got '
136 '%r instead' % (Effect.TYPES, value))
137
138 return self.__value == value
139
141 """Boolean evaluation of a rule effect - True = Allow; False = Deny
142
143 @return: True if the effect value is permit, False otherwise
144 @rtype: bool
145 """
146 return self.__value == Effect.PERMIT_STR
147
150 """Permit authorisation Effect"""
151 __slots__ = ()
152
156
158 """Make value read-only
159 @raise AttributeError: value can't be set
160 """
161 raise AttributeError("can't set attribute")
162
165 """Deny authorisation Effect"""
166 __slots__ = ()
167
171
173 """Make value read-only
174 @raise AttributeError: value can't be set
175 """
176 raise AttributeError("can't set attribute")
177
178
179 Effect.PERMIT = PermitEffect()
180 Effect.DENY = DenyEffect()
181
182
183 -class Rule(XacmlCoreBase):
184 """XACML Policy Rule
185
186 @cvar ELEMENT_LOCAL_NAME: XML local name for this element
187 @type ELEMENT_LOCAL_NAME: string
188 @cvar DESCRIPTION_LOCAL_NAME: XML local name for the description element
189 @type DESCRIPTION_LOCAL_NAME: string
190 @cvar RULE_ID_ATTRIB_NAME: rule id XML attribute name
191 @type RULE_ID_ATTRIB_NAME: string
192 @cvar EFFECT_ATTRIB_NAME: effect XML attribute name
193 @type EFFECT_ATTRIB_NAME: string
194
195 @ivar __target: rule target
196 @type __target: ndg.xacml.core.target.Target / NoneType
197 @ivar __condition: rule condition
198 @type __condition: ndg.xacml.core.condition.Condition / NoneType
199 @ivar __description: rule description text
200 @type __description: basestring / NoneType
201 @ivar __id: rule ID
202 @type __id: basestring / NoneType
203 @ivar __effect: rule effect
204 @type __effect: ndg.xacml.core.rule.Effect / NoneType
205 """
206 ELEMENT_LOCAL_NAME = 'Rule'
207 RULE_ID_ATTRIB_NAME = 'RuleId'
208 EFFECT_ATTRIB_NAME = 'Effect'
209
210 DESCRIPTION_LOCAL_NAME = 'Description'
211
212 __slots__ = (
213 '__target',
214 '__condition',
215 '__description',
216 '__id',
217 '__effect'
218 )
219
228
229 @property
231 """Get Rule target
232 @return: rule target
233 @rtype: ndg.xacml.core.target import Target / NoneType
234 """
235 return self.__target
236
237 @target.setter
239 """Set rule target
240 @param value: rule target
241 @type value: ndg.xacml.core.target import Target
242 @raise TypeError: incorrect type set
243 """
244 if not isinstance(value, Target):
245 raise TypeError('Expecting %r type for "id" '
246 'attribute; got %r' % (Target, type(value)))
247 self.__target = value
248
249 @property
251 """Get rule condition
252
253 @return: rule condition
254 @rtype: ndg.xacml.core.condition.Condition / NoneType
255 """
256 return self.__condition
257
258 @condition.setter
260 """Set rule condition
261
262 @param value: rule condition
263 @type value: ndg.xacml.core.condition.Condition
264 @raise TypeError: incorrect type set
265 """
266 if not isinstance(value, Condition):
267 raise TypeError('Expecting %r type for "id" attribute; got %r' %
268 (Condition, type(value)))
269
270 self.__condition = value
271
273 """Get rule ID
274
275 @return: rule ID
276 @rtype: ndg.xacml.core.condition.Condition / NoneType
277 """
278 return self.__id
279
281 """Set rule ID
282
283 @param value: rule ID
284 @type value: basestring
285 @raise TypeError: incorrect type set
286 """
287 if not isinstance(value, basestring):
288 raise TypeError('Expecting %r type for "id" attribute; got %r' %
289 (basestring, type(value)))
290
291 self.__id = value
292
293 id = property(_get_id, _set_id, None, "Rule identifier attribute")
294
296 """Get rule effect
297
298 @return: rule effect
299 @rtype: ndg.xacml.core.rule.Effect / NoneType
300 """
301 return self.__effect
302
304 """Set rule effect
305
306 @param value: rule effect
307 @type value: ndg.xacml.core.rule.Effect
308 @raise TypeError: incorrect type set
309 """
310 if not isinstance(value, Effect):
311 raise TypeError('Expecting %r type for "effect" '
312 'attribute; got %r' % (Effect, type(value)))
313
314 self.__effect = value
315
316 effect = property(_get_effect, _set_effect, None,
317 "Rule effect attribute")
318
320 """Get rule description
321
322 @return: rule description
323 @rtype: basestring / NoneType
324 """
325 return self.__description
326
328 """Set rule description
329
330 @param value: rule description
331 @type value: basestring
332 @raise TypeError: incorrect type set
333 """
334 if not isinstance(value, basestring):
335 raise TypeError('Expecting string type for "description" '
336 'attribute; got %r' % type(value))
337 self.__description = value
338
339 description = property(_getDescription, _setDescription,
340 doc="Rule Description text")
341
343 """Evaluate a rule
344 @param context: the request context
345 @type context: ndg.xacml.core.request.Request
346 @return: result of the evaluation - the decision for this rule
347 @rtype: ndg.xacml.core.context.result.Decision
348 """
349
350
351
352 try:
353 log.debug('Evaluating rule %r ...', self.id)
354
355
356 decision = Decision()
357
358
359 if self.target is not None:
360 targetMatch = self.target.match(context)
361 if targetMatch:
362 log.debug('Match to request context for target in rule '
363 '%r', self.id)
364 else:
365 log.debug('No target set in rule %r', self.id)
366 targetMatch = True
367
368 if not targetMatch:
369 log.debug('No match to request context for target in rule '
370 '%r returning NotApplicable status', self.id)
371 decision = Decision.NOT_APPLICABLE
372 return decision
373
374
375 if self.condition is not None:
376 conditionStatus = self.condition.evaluate(context)
377 else:
378
379
380
381
382 log.debug('No condition set for rule %r: setting condition '
383 'status True', self.id)
384 conditionStatus = True
385
386
387
388 if conditionStatus:
389 decision = Decision(decision=self.effect.value)
390 else:
391 decision = Decision.NOT_APPLICABLE
392
393 log.debug('Rule %r evaluates to %s', self.id, decision)
394 return decision
395
396 except Exception:
397 _traceback = traceback.format_exc()
398 log.error('Error occurred evaluating rule %r, returning '
399 'Indeterminate result to caller: %s',
400 self.id, _traceback)
401 return Decision.INDETERMINATE
402