source: TI12-security/trunk/ndg_xacml/ndg/xacml/core/attributevalue.py @ 7351

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/ndg_xacml/ndg/xacml/core/attributevalue.py@7351
Revision 7351, 9.7 KB checked in by pjkersha, 9 years ago (diff)

Incomplete - task 2: XACML-Security Integration

  • important fix to ndg.xacml.core.rule.Rule.evaluate: return NotApplicable? where Target matches but Condition does not match
  • optimised ndg.xacml.core.functions.v1.at_least_one_member_of.AtLeastOneMemberOfBase? to use set and '&' operator for this function.
  • fix to ndg.xacml.core.functions.FunctionMap?.loadFunction to catch function namespace not recognised.
  • Property svn:keywords set to Id
Line 
1"""NDG XACML attribute type definition
2
3NERC 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$"
12from datetime import datetime, timedelta
13
14from ndg.xacml.utils import VettedDict
15from ndg.xacml.core.expression import Expression
16   
17
18class AttributeValue(Expression):
19    """XACML Attribute Value type
20   
21    @cvar ELEMENT_LOCAL_NAME: XML local name for this element
22    @type ELEMENT_LOCAL_NAME: string 
23    @cvar CLASS_NAME_SUFFIX: all attribute value classes end with this suffix
24    @type CLASS_NAME_SUFFIX: string
25    @cvar IDENTIFIER_PREFIX: geberic prefix for attribute value URNs
26    @type IDENTIFIER_PREFIX: string
27    @cvar IDENTIFIER: URN for attribute value in derived class
28    @type IDENTIFIER: NoneType - derived classes should set to appropriate
29    string
30    @cvar TYPE_URIS: URIs for all the different supported types
31    @type TYPE_URIS: tuple
32    @cvar TYPE_NAMES: corresponding short names for all the types
33    @type TYPE_NAMES: tuple
34    @cvar NATIVE_TYPES: equivalent python types as implemented
35    @cvar TYPE_MAP: mapping from type names to python types
36    @type TYPE_MAP: dict
37    @cvar TYPE_URI_MAP: mapping from type names to type URIs
38    @type TYPE_URI_MAP: dict
39    @cvar TYPE: type name for derived type - set to None in this parent class
40    @type TYPE: NoneType / string in derived type
41   
42    @ivar __value: setting for this attribute value
43    @type __value: any - constrained in derived classes
44    """
45    ELEMENT_LOCAL_NAME = 'AttributeValue'
46    CLASS_NAME_SUFFIX = 'AttributeValue'
47    IDENTIFIER_PREFIX = 'http://www.w3.org/2001/XMLSchema#'
48 
49    IDENTIFIER = None
50    TYPE_URIS = (
51    'http://www.w3.org/2001/XMLSchema#string',
52    'http://www.w3.org/2001/XMLSchema#anyURI',
53    'http://www.w3.org/2001/XMLSchema#integer',
54    'http://www.w3.org/2001/XMLSchema#boolean',
55    'http://www.w3.org/2001/XMLSchema#double',
56    'http://www.w3.org/2001/XMLSchema#date',
57    'http://www.w3.org/2001/XMLSchema#dateTime',
58    'http://www.w3.org/2001/XMLSchema#time',
59    'http://www.w3.org/TR/2002/WD-xquery-operators-20020816#dayTimeDuration',
60    'http://www.w3.org/TR/2002/WD-xquery-operators-20020816#yearMonthDuration',
61    'urn:oasis:names:tc:xacml:1.0:data-type:x500Name',
62    'urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name',
63    'http://www.w3.org/2001/XMLSchema#hexBinary',
64    'http://www.w3.org/2001/XMLSchema#base64Binary',
65    'urn:oasis:names:tc:xacml:2.0:data-type:ipAddress',
66    'urn:oasis:names:tc:xacml:2.0:data-type:dnsName'
67    )
68    TYPE_NAMES = (
69        'String',
70        'AnyURI',
71        'Integer',
72        'Boolean',
73        'Double',
74        'Date',
75        'DateTime',
76        'Time',
77        'DayTimeDuration',
78        'YearMonthDuration',
79        'X500Name',
80        'Rfc822Name',
81        'HexBinary',
82        'Base64Binary',
83        'IpAddress',
84        'DnsName',
85    )
86    NATIVE_TYPES = (
87        basestring,
88        basestring,
89        int,
90        bool,
91        float,
92        datetime,
93        datetime,
94        datetime,
95        timedelta,
96        timedelta,
97        basestring,
98        basestring,
99        int,
100        NotImplemented,
101        basestring,
102        basestring
103    )
104    TYPE_MAP = dict(zip(TYPE_NAMES, NATIVE_TYPES))
105    TYPE_URI_MAP = dict(zip(TYPE_NAMES, TYPE_URIS))
106    TYPE = None
107   
108    __slots__ = ('__value',) 
109   
110    def __init__(self, value=None):
111        """Derived classes must override setting TYPE class variable
112       
113        @param value: initialise the attribute value by setting this keyword
114        @type value: (set by self.__class__.TYPE)
115        """
116       
117        super(AttributeValue, self).__init__()
118        if self.__class__.TYPE is None:
119            raise NotImplementedError('TYPE class variable must be set to a '
120                                      'valid type in a derived class')
121           
122        self.__value = None
123       
124        # Allow derived classes to make an implicit data type setting
125        self.dataType = self.__class__.IDENTIFIER
126       
127        if value is not None:
128            self.value = value
129
130    def __repr__(self):
131        return "%s = %r " % (super(AttributeValue, self).__repr__(),
132                             self.__value)
133
134    def __eq__(self, attrVal):
135        """Check for equality by comparing the value attributes"""
136        if not isinstance(attrVal, self.__class__):
137            raise TypeError('Expecting %r type for "value" '
138                            'attribute; got %r' % (self.__class__.TYPE, 
139                                                   type(attrVal)))
140           
141        return self.__value == attrVal.value
142   
143    def _get_value(self):
144        """Get value
145        @return: setting for this attribute value
146        @rtype: any - constrained in derived classes
147        """
148        return self.__value
149
150    def _set_value(self, value):
151        """Set value
152       
153        @param value: setting for this attribute value
154        @type value: any - constrained in derived classes
155        @raise TypeError: if type doesn't match TYPE class variable.  Derived
156        classes should set this
157        """
158        if not isinstance(value, self.__class__.TYPE):
159            raise TypeError('Expecting %r type for "value" '
160                            'attribute; got %r' % (self.__class__.TYPE, 
161                                                   type(value)))
162           
163        self.__value = value 
164
165    value = property(_get_value, _set_value, None, "expression value") 
166   
167    def evaluate(self, context):
168        """Evaluate the result of the expression in a condition.  In the case of
169        an attribute value it's simply itself
170       
171        @param context: the request context
172        @type context: ndg.xacml.core.context.request.Request
173        @return: this attribute value
174        @rtype: AttributeValue 
175        """ 
176        return self
177
178
179class AttributeValueClassMap(VettedDict):
180    """Specialised dictionary to hold mappings of XML attribute type URIs to
181    their equivalent classes
182    """
183   
184    def __init__(self):
185        """Force entries to derive from AttributeValue and IDs to
186        be string type
187        """       
188        # Filters are defined as staticmethods but reference via self here to
189        # enable derived class to override them as standard methods without
190        # needing to redefine this __init__ method           
191        VettedDict.__init__(self, self.keyFilter, self.valueFilter)
192       
193    @staticmethod
194    def keyFilter(key):
195        """Enforce string type keys
196       
197        @param key: URN for attribute
198        @type key: basestring
199        @return: boolean True indicating key is OK
200        @rtype: bool
201        @raise TypeError: incorrect input type
202        """
203        if not isinstance(key, basestring):
204            raise TypeError('Expecting %r type for key; got %r' % 
205                            (basestring, type(key))) 
206        return True 
207   
208    @staticmethod
209    def valueFilter(value):
210        """Enforce AttributeValue derived types for values
211        @param value: attribute value
212        @type value: ndg.xacml.core.attributevalue.AttributeValue derived type
213        @return: boolean True indicating attribute value is correct type
214        @rtype: bool
215        @raise TypeError: incorrect input type
216        """
217        if not issubclass(value, AttributeValue):
218            raise TypeError('Expecting %r derived type for value; got %r' % 
219                            (AttributeValue, type(value))) 
220        return True 
221
222
223# Dynamically Create classes based on AttributeValue for all the XACML primitive
224# types
225_IDENTIFIER2CLASS_MAP = AttributeValueClassMap()
226
227for typeName, _type in AttributeValue.TYPE_MAP.items():
228    identifier = AttributeValue.TYPE_URI_MAP[typeName]
229
230    className = typeName + AttributeValue.CLASS_NAME_SUFFIX               
231    classVars = {'TYPE': _type, 'IDENTIFIER': identifier}
232   
233    attributeValueClass = type(className, (AttributeValue, ), classVars)
234    AttributeValue.register(attributeValueClass)
235    _IDENTIFIER2CLASS_MAP[identifier] = attributeValueClass
236   
237   
238class AttributeValueClassFactory(object):
239    """Create AttributeValue types based on the XML namespace identifier
240   
241    Convenience wrapper for _IDENTIFIER2CLASS_MAP instance of
242    AttributeValueClassMap
243   
244    @ivar __classMap: mapping object to map attribute value URIs to their
245    implementations as classes
246    @type __classMap: ndg.xacml.core.attributevalue.AttributeValueClassMap
247    """
248    __slots__ = ('__classMap',)
249   
250    def __init__(self, classMap=None):
251        """Set a mapping object to map attribute value URIs to their
252        implementations as classes
253       
254        @param classMap: input an alternative to the default class mapping
255        object _IDENTIFIER2CLASS_MAP, if None, it will default to this setting
256        @type classMap: ndg.xacml.core.attributevalue.AttributeValueClassMap
257        """
258        if classMap is None:
259            self.__classMap = _IDENTIFIER2CLASS_MAP
260        elif isinstance(classMap, AttributeValueClassMap):
261            self.__classMap = classMap
262        else:
263            raise TypeError('Expecting %r derived type for "map" input; got %r'
264                            % (AttributeValueClassMap, type(map)))
265           
266    def __call__(self, identifier):
267        """Return <type>AttributeValue class for given identifier URI or None
268        if no match is found
269       
270        @return: attribute value class
271        @rtype: NoneType / ndg.xacml.core.attributevalue.AttributeValue derived
272        type
273        """
274        return self.__classMap.get(identifier)
275       
Note: See TracBrowser for help on using the repository browser.