source: TI12-security/trunk/ndg_xacml/ndg/xacml/core/context/result.py @ 7087

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

Incomplete - task 2: XACML-Security Integration

  • updating epydoc ready for release.
  • Property svn:keywords set to Id
Line 
1"""NDG XACML module for Result type
2
3NERC DataGrid
4"""
5__author__ = "P J Kershaw"
6__date__ = "23/03/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
15from ndg.xacml.core.context import XacmlContextBase
16from ndg.xacml.core.obligation import Obligation
17
18
19class StatusCode(XacmlContextBase):
20    '''XACML Response Result StatusCode.
21   
22    @cvar ELEMENT_LOCAL_NAME: XML Local Name of StatusCode element
23    @type ELEMENT_LOCAL_NAME: string
24   
25    @cvar IDENTIFIER_PREFIX: namespace prefix for status codes
26    @type IDENTIFIER_PREFIX: string
27   
28    @cvar OK: OK response status
29    @type OK: string
30   
31    @cvar MISSING_ATTRIBUTE: missing attribute response status
32    @type MISSING_ATTRIBUTE: string
33   
34    @cvar PROCESSING_ERROR: response status indicating a processing error
35    @type PROCESSING_ERROR: string
36   
37    @cvar SYNTAX_ERROR: response status for a syntax error
38    @type SYNTAX_ERROR: string
39   
40    @cvar CODES: list of recognised codes
41    @type CODES: tuple
42   
43    @ivar __value: status code value
44    @type __value: basestring
45   
46    @ivar __childStatusCode: child status code
47    @type __childStatusCode: ndg.xacml.core.result.StatusCode
48    '''
49   
50    ELEMENT_LOCAL_NAME = "StatusCode"
51
52    IDENTIFIER_PREFIX = XacmlContextBase.XACML_1_0_NS_PREFIX + ':status'
53   
54    OK = IDENTIFIER_PREFIX + ":ok"
55    MISSING_ATTRIBUTE = IDENTIFIER_PREFIX + ":missing-attribute"
56    PROCESSING_ERROR = IDENTIFIER_PREFIX + ":processing-error"
57    SYNTAX_ERROR = IDENTIFIER_PREFIX + ":syntax-error"
58   
59    CODES = (OK, MISSING_ATTRIBUTE, PROCESSING_ERROR, SYNTAX_ERROR)
60   
61    __slots__ = ('__value', '__childStatusCode',)
62   
63    def __init__(self, **kw):
64        super(StatusCode, self).__init__(**kw)
65       
66        # Value attribute URI.
67        self.__value = None
68   
69        # Nested secondary StatusCode child element.
70        self.__childStatusCode = None
71
72    def _getStatusCode(self): 
73        '''@return: child status code
74        @rtype: ndg.xacml.core.result.StatusCode
75        '''
76        return self.__childStatusCode
77   
78    def _setStatusCode(self, value):
79        '''@param value: child status code
80        @type value: ndg.xacml.core.result.StatusCode
81        '''
82        if not isinstance(value, StatusCode):
83            raise TypeError('Child "statusCode" must be a %r derived type, '
84                            "got %r" % (StatusCode, type(value)))
85           
86        self.__childStatusCode = value
87
88    value = property(fget=_getStatusCode, 
89                     fset=_setStatusCode, 
90                     doc="Child Status code")
91             
92    def _getValue(self):
93        '''@return: status code value
94        @rtype: basestring
95        '''
96        return self.__value
97       
98    def _setValue(self, value):
99        '''@param value: status code value
100        @type value: basestring
101        '''
102        if not isinstance(value, basestring):
103            raise TypeError("\"value\" must be a basestring derived type, "
104                            "got %r" % value.__class__)
105       
106        if value not in self.__class__.CODES:
107            raise AttributeError('Status code expected values are %r; got %r' %
108                                 (self.__class__.CODES, value))
109               
110        self.__value = value
111
112    value = property(fget=_getValue, fset=_setValue, doc="Status code value")
113   
114
115class Status(XacmlContextBase): 
116    '''XACML Response Result Status
117
118    @cvar ELEMENT_LOCAL_NAME: XML Local Name of Status element
119    @type ELEMENT_LOCAL_NAME: string
120   
121    @ivar __statusCode: Status code element
122    @type __statusCode: None / ndg.xacml.core.context.result.StatusCode
123    @ivar __statusMessage: Status message element
124    @type __statusMessage: None / basestring
125    @ivar __statusDetail: Status detail element
126    @type __statusDetail: None / any type
127    '''
128   
129    # Local Name of Status.
130    ELEMENT_LOCAL_NAME = "Status"
131
132    __slots__ = ('__statusCode', '__statusMessage', '__statusDetail', )
133   
134    def __init__(self, **kw):
135        super(Status, self).__init__(**kw)
136       
137        # StatusCode element.
138        self.__statusCode = None
139   
140        # StatusMessage element.
141        self.__statusMessage = None
142   
143        # StatusDetail element.
144        self.__statusDetail = None
145   
146    @classmethod
147    def createInitialised(cls, code=StatusCode.OK, message='', detail=''):
148        """Create with an empty StatusCode object set
149
150        @param code: Status code - defaults to OK code
151        @type code: basestring
152        @param message: Status Message
153        @type message: basestring
154        @param detail: Status detail
155        @type detail: string / any
156        @return: Status instance
157        @rtype: ndg.xacml.core.context.Status
158        """
159        status = cls()
160        status.statusCode = StatusCode()
161        status.statusCode.value = code
162        status.statusMessage = message
163        status.statusDetail = detail
164       
165        return status
166       
167    def _getStatusCode(self):
168        '''
169        Gets the Code of this Status.
170       
171        @return: Status StatusCode
172        @rtype: ndg.xacml.core.context.StatusCode
173        '''
174        return self.__statusCode
175
176    def _setStatusCode(self, value):
177        '''
178        Sets the Code of this Status.
179       
180        @param value: the Code of this Status
181        @type value: ndg.xacml.core.context.StatusCode
182        '''
183        if not isinstance(value, StatusCode):
184            raise TypeError('"statusCode" must be a %r derived type, '
185                            "got %r" % (StatusCode, type(value)))
186           
187        self.__statusCode = value
188       
189    statusCode = property(fget=_getStatusCode,
190                          fset=_setStatusCode,
191                          doc="status code object")
192   
193    def _getStatusMessage(self):
194        '''
195        Gets the Message of this Status.
196       
197        @return: Status StatusMessage
198        @rtype: basestring
199        '''
200        return self.__statusMessage
201
202    def _setStatusMessage(self, value):
203        '''
204        Sets the Message of this Status.
205       
206        @param value: the Message of this Status
207        @type value: basestring
208        '''
209        if not isinstance(value, basestring):
210            raise TypeError('"statusMessage" must be a %r derived type, '
211                            "got %r" % (basestring, type(value)))
212           
213        self.__statusMessage = value
214       
215    statusMessage = property(fget=_getStatusMessage,
216                             fset=_setStatusMessage,
217                             doc="status message")
218
219    def _getStatusDetail(self):
220        '''
221        Gets the Detail of this Status.
222       
223        @return: Status detail
224        @rtype: any
225        '''
226        return self.__statusDetail
227   
228    def _setStatusDetail(self, value):
229        '''
230        Sets the Detail of this Status.
231       
232        @param value: the Detail of this Status
233        @type value: any type
234        '''
235        self.__statusDetail = value
236       
237    statusDetail = property(fget=_getStatusDetail,
238                            fset=_setStatusDetail,
239                            doc="status message")
240           
241
242class Decision(object):
243    """Define decision types for Response Result
244   
245    @cvar PERMIT_STR: permit decision string
246    @type PERMIT_STR: string
247   
248    @cvar DENY_STR: deny decision string
249    @type DENY_STR: string
250   
251    @cvar INDETERMINATE_STR: indeterminate decision string
252    @type INDETERMINATE_STR: string
253   
254    @cvar NOT_APPLICABLE_STR: not applicable decision string
255    @type NOT_APPLICABLE_STR: string
256   
257    @cvar TYPES: list of valid decision strings
258    @type TYPES: tuple
259   
260    @ivar value: decision value
261    @type value: string
262    """
263   
264    # "Permit" decision type
265    PERMIT_STR = "Permit"
266   
267    # "Deny" decision type
268    DENY_STR = "Deny"
269   
270    # "Indeterminate" decision type
271    INDETERMINATE_STR = "Indeterminate"
272   
273    NOT_APPLICABLE_STR = "NotApplicable"
274       
275    TYPES = (PERMIT_STR, DENY_STR, INDETERMINATE_STR, NOT_APPLICABLE_STR)
276   
277    __slots__ = ('__value',)
278   
279    def __init__(self, decision=INDETERMINATE_STR):
280        self.__value = None
281        self.value = decision
282
283    def __getstate__(self):
284        '''Enable pickling
285       
286        @return: class instance attributes dictionary
287        @rtype: dict
288        '''
289        _dict = {}
290        for attrName in Decision.__slots__:
291            # Ugly hack to allow for derived classes setting private member
292            # variables
293            if attrName.startswith('__'):
294                attrName = "_Decision" + attrName
295               
296            _dict[attrName] = getattr(self, attrName)
297           
298        return _dict
299 
300    def __setstate__(self, attrDict):
301        '''Enable pickling
302       
303        @param attrDict: class instance attributes dictionary
304        @type attrDict: dict
305        '''
306        for attrName, val in attrDict.items():
307            setattr(self, attrName, val)
308           
309    def _setValue(self, value):
310        """Set decision value
311       
312        @param value: decision value - constrained vocabulary to Decision.TYPES
313        @type value: string or ndg.xacml.core.context.result.Decision
314        @raise AttributeError: invalid decision string value input
315        @raise TypeError: invalid type for input decision value
316        """
317        if isinstance(value, Decision):
318            # Cast to string
319            value = str(value)
320           
321        elif not isinstance(value, basestring):
322            raise TypeError('Expecting string or Decision instance for '
323                            '"value" attribute; got %r instead' % type(value))
324           
325        if value not in self.__class__.TYPES:
326            raise AttributeError('Permissable decision types are %r; got '
327                                 '%r instead' % (Decision.TYPES, value))
328        self.__value = value
329       
330    def _getValue(self):
331        """Get decision value
332       
333        @return: decision value
334        @rtype: string
335        """
336        return self.__value
337   
338    value = property(fget=_getValue, fset=_setValue, doc="Decision value")
339   
340    def __str__(self):
341        """represent decision as a string
342       
343        @return: decision value
344        @rtype: string
345        """
346        return self.__value
347
348    def __repr__(self):
349        """Overridden to show the decision value
350       
351        @return: decision representation
352        @rtype: string
353        """
354        return "%s = %r" % (super(Decision, self).__repr__(), self.__value)
355   
356    def __eq__(self, decision):
357        """
358        @param decision: decision value to compare with self's
359        @type param: string or ndg.xacml.core.context.result.Decision
360        @return: True if the decision values match, False otherwise
361        @rtype: bool
362        @raise AttributeError: invalid decision string value input
363        @raise TypeError: invalid type for input decision value
364        """
365        if isinstance(decision, Decision):
366            # Cast to string
367            value = decision.value
368           
369        elif isinstance(decision, basestring):
370            value = decision
371           
372        else:
373            raise TypeError('Expecting string or Decision instance for '
374                            'input decision value; got %r instead' % type(value))
375           
376        if value not in self.__class__.TYPES:
377            raise AttributeError('Permissable decision types are %r; got '
378                                 '%r instead' % (Decision.TYPES, value))
379           
380        return self.__value == value       
381
382
383class PermitDecision(Decision):
384    """Permit authorisation Decision"""
385    __slots__ = ()
386
387    def __init__(self):
388        """Initialise set with Permit value"""
389        super(PermitDecision, self).__init__(Decision.PERMIT_STR)
390       
391    def _setValue(self): 
392        """Make value read-only
393        @raise AttributeError: value can't be set
394        """
395        raise AttributeError("can't set attribute")
396
397
398class DenyDecision(Decision):
399    """Deny authorisation Decision"""
400    __slots__ = ()
401   
402    def __init__(self):
403        """Initialise set with deny value"""
404        super(DenyDecision, self).__init__(Decision.DENY_STR)
405       
406    def _setValue(self, value): 
407        """Make value read-only
408        @raise AttributeError: value can't be set
409        """
410        raise AttributeError("can't set attribute")
411
412
413class IndeterminateDecision(Decision):
414    """Indeterminate authorisation Decision"""
415    __slots__ = ()
416   
417    def __init__(self):
418        """Initialise set with indeterminate value"""
419        super(IndeterminateDecision, self).__init__(Decision.INDETERMINATE_STR)
420       
421    def _setValue(self, value): 
422        """Make value read-only
423        @raise AttributeError: value can't be set
424        """
425        raise AttributeError("can't set attribute")
426
427
428class NotApplicableDecision(Decision):
429    """NotApplicable authorisation Decision"""
430    __slots__ = ()
431   
432    def __init__(self):
433        """Initialise set with not applicable value"""
434        super(NotApplicableDecision, self).__init__(Decision.NOT_APPLICABLE_STR)
435       
436    def _setValue(self, value): 
437        """Make value read-only
438        @raise AttributeError: value can't be set
439        """
440        raise AttributeError("can't set attribute")
441   
442   
443# Add instances of each for convenience
444Decision.PERMIT = PermitDecision()
445Decision.DENY = DenyDecision()
446Decision.INDETERMINATE = IndeterminateDecision()
447Decision.NOT_APPLICABLE = NotApplicableDecision()
448
449
450class Result(XacmlContextBase):
451    """XACML Result type - element in a Response
452   
453    @cvar ELEMENT_LOCAL_NAME: XML element local name
454    @type ELEMENT_LOCAL_NAME: string
455   
456    @cvar OBLIGATIONS_ELEMENT_LOCAL_NAME: obligations XML element local name
457    @type OBLIGATIONS_ELEMENT_LOCAL_NAME: string
458   
459    @cvar RESOURCE_ID_ATTRIB_NAME: resource ID XML attribute name
460    @type RESOURCE_ID_ATTRIB_NAME: string
461   
462    @ivar __resourceId: resource id
463    @type __resourceId: None/basestring
464   
465    @ivar __decision: decision for this result
466    @type __decision: ndg.xacml.core.context.result.Decision
467   
468    @ivar __status: result status
469    @type __status: ndg.xacml.core.context.result.Status
470       
471    @ivar __obligations: obligations associated with this result
472    @type __obligations: ndg.xacml.core.obligation.Obligation
473    """
474    __slots__ = ('__resourceId', '__decision', '__status', '__obligations')
475   
476    ELEMENT_LOCAL_NAME  = 'Result'
477    OBLIGATIONS_ELEMENT_LOCAL_NAME = 'Obligations'
478    RESOURCE_ID_ATTRIB_NAME = 'ResourceId'
479   
480    def __init__(self):
481        super(Result, self).__init__()
482        self.__decision = None
483        self.__status = None
484        self.__resourceId = None
485        self.__obligations = None
486       
487    @classmethod
488    def createInitialised(cls, 
489                          decision=Decision.NOT_APPLICABLE,
490                          resourceId='', 
491                          obligations=None,
492                          **kw):
493        """Create a result object populated with all it's child elements
494        rather than set to None as is the default from __init__
495       
496        @param decision: decision for this result
497        @type decision: ndg.xacml.core.context.result.Decision
498       
499        @param resourceId: resource id for associated resource
500        @type resourceId: basestring
501       
502        @param obligations: obligations associated with this result
503        @type obligations: None/ndg.xacml.core.obligation.Obligation
504       
505        @param kw: keywords for status attribute initialisation
506        @type kw: dict
507       
508        @return: new result object with all its child attributes created
509        @rtype: ndg.xacml.core.context.result.Result
510        """
511        result = cls()
512        result.decision = Decision()
513        result.decision.value = decision
514        result.status = Status.createInitialised(**kw)
515       
516        if obligations is not None:
517            result.obligations = obligations
518           
519        return result
520       
521    @property
522    def resourceId(self):
523        """Get Result resource Id
524       
525        @return: resource Id
526        @rtype: basestring
527        """
528        return self.__resourceId
529
530    @resourceId.setter
531    def resourceId(self, value):
532        """Set Result resource Id
533       
534        @param value: resource Id
535        @type value: basestring
536        @raise TypeError: incorrect type for input
537        """
538        if not isinstance(value, basestring):
539            raise TypeError('Expecting %r type for "resourceId" '
540                            'result; got %r' % (basestring, type(value)))
541           
542        self.__resourceId = value
543                       
544    @property
545    def decision(self):
546        """Get Result decision
547       
548        @return: decision for this result
549        @rtype: ndg.xacml.core.context.result.Decision
550        """
551        return self.__decision
552   
553    @decision.setter
554    def decision(self, value):
555        """Set Request decision
556       
557        @param value: decision for this result
558        @type value: ndg.xacml.core.context.result.Decision
559        @raise TypeError: incorrect type for input
560        """
561        if not isinstance(value, Decision):
562            raise TypeError('Expecting %r type for result "decision" '
563                            'attribute; got %r' % (Decision, type(value)))
564        self.__decision = value
565       
566    @property
567    def status(self):
568        """Get Result status
569       
570        @return: status for this result
571        @rtype: ndg.xacml.core.context.result.Status
572        """
573        return self.__status
574   
575    @status.setter
576    def status(self, value):
577        """Set Result status
578       
579        @param value: status for this result
580        @type value: ndg.xacml.core.context.result.Status
581        @raise TypeError: incorrect type for input
582        """
583        if not isinstance(value, Status):
584            raise TypeError('Expecting %r type for result "status" '
585                            'attribute; got %r' % (Status, type(value)))
586           
587        self.__status = value
588                                   
589    @property
590    def obligations(self):
591        """Get Result obligations
592       
593        @return: obligations associated with this result
594        @rtype: ndg.xacml.core.obligations.Obligations       
595        """
596        return self.__obligations
597   
598    @obligations.setter
599    def obligations(self, value):
600        """Set Result obligations
601       
602        @param value: obligations associated with this result
603        @type value: ndg.xacml.core.obligations.Obligations       
604       
605        @raise TypeError: incorrect type for input
606        """
607        if not isinstance(value, Obligation):
608            raise TypeError('Expecting %r type for result "obligations" '
609                            'attribute; got %r' % (Obligation, type(value)))
610           
611        self.__obligations = value
Note: See TracBrowser for help on using the repository browser.