source: TI12-security/trunk/ndg_xacml/ndg/xacml/core/attributedesignator.py @ 7365

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

Incomplete - task 2: XACML-Security Integration

  • added identifier URN constants
  • Property svn:keywords set to Id
Line 
1"""NDG XACML AttributeDesignator type
2
3NERC DataGrid
4"""
5__author__ = "P J Kershaw"
6__date__ = "16/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.utils import TypedList
16from ndg.xacml.core.expression import Expression
17from ndg.xacml.core.attributevalue import (AttributeValue, 
18                                           AttributeValueClassFactory)
19from ndg.xacml.core.context.request import Request
20from ndg.xacml.core.context.handler import CtxHandlerInterface
21from ndg.xacml.core.context.exceptions import MissingAttributeError
22
23
24class AttributeDesignator(Expression):
25    '''Base class for XACML Attribute Designator types
26   
27    @cvar ATTRIBUTE_ID_ATTRIB_NAME: attribute ID XML attribute name
28    @type ATTRIBUTE_ID_ATTRIB_NAME: string
29    @cvar ISSUER_ATTRIB_NAME: issuer XML attribute name
30    @type ISSUER_ATTRIB_NAME: string
31    @cvar MUST_BE_PRESENT_ATTRIB_NAME: must be present XML attribute name
32    @type MUST_BE_PRESENT_ATTRIB_NAME: string
33   
34    @ivar __attributeId: attribute ID for this designator
35    @type __attributeId: basestring / NoneType
36    @ivar __issuer: issuer if the designator
37    @type __issuer: basestring / NoneType
38    @ivar __mustBePresent: XML must be present flag
39    @type __mustBePresent: bool
40    @ivar __attributeValueFactory: When evaluating matches, use an attribute
41    value class factory to create attribute values for match bag of the correct
42    DataType to respect type based rule functions
43    @type __attributeValueFactory: ndg.xacml.core.attributevalue.AttributeValueClassFactory
44    '''
45    ATTRIBUTE_ID_ATTRIB_NAME = 'AttributeId'
46    ISSUER_ATTRIB_NAME = 'Issuer'
47    MUST_BE_PRESENT_ATTRIB_NAME = 'MustBePresent'
48   
49    __slots__ = (
50        '__attributeId', 
51        '__issuer', 
52        '__mustBePresent',
53        '__attributeValueFactory'
54    )
55   
56    def __init__(self):
57        """Initialise attributes"""
58        super(AttributeDesignator, self).__init__()
59        self.__attributeId = None
60        self.__issuer = None
61        self.__mustBePresent = False
62       
63        # When evaluating matches, use an attribute value class factory to
64        # create attribute values for match bag of the correct DataType to
65        # respect type based rule functions
66        self.__attributeValueFactory = AttributeValueClassFactory()
67
68    @property
69    def attributeId(self):
70        """Get Attribute Id
71        @return: attribute ID
72        @rtype: basestring / NoneType
73        """
74        return self.__attributeId
75
76    @attributeId.setter
77    def attributeId(self, value):
78        """Set Attribute Id
79        @param value: attribute ID
80        @type value: basestring
81        @raise TypeError: incorrect input type
82        """
83        if not isinstance(value, basestring):
84            raise TypeError('Expecting %r type for "attributeId" '
85                            'attribute; got %r' % (basestring, type(value)))
86           
87        self.__attributeId = value 
88       
89    @property
90    def issuer(self):
91        """Get Issuer
92        @return: issuer
93        @rtype: basestring / NoneType
94        """
95        return self.__issuer
96
97    @issuer.setter
98    def issuer(self, value):
99        """Set Issuer
100        @param value: issuer
101        @type value: basestring
102        @raise TypeError: incorrect input type
103        """
104        if not isinstance(value, basestring):
105            raise TypeError('Expecting %r type for "issuer" '
106                            'attribute; got %r' % (basestring, type(value)))
107           
108        self.__issuer = value   
109
110    @property
111    def mustBePresent(self):
112        """Get Must Be Present flag
113        @return: must be present flag
114        @rtype: bool
115        """
116        return self.__mustBePresent
117
118    @mustBePresent.setter
119    def mustBePresent(self, value):
120        """Set Must Be Present flag
121        @param value: must be present flag
122        @type value: bool
123        @raise TypeError: incorrect input type
124        """
125        if not isinstance(value, bool):
126            raise TypeError('Expecting %r type for "mustBePresent" '
127                            'attribute; got %r' % (bool, type(value)))
128           
129        self.__mustBePresent = value   
130             
131    @property
132    def attributeValueFactory(self):
133        """Get Attribute Value factory function
134       
135        @return: attribute value factory instance
136        @rtype: ndg.xacml.core.attributevalue.AttributeValueClassFactory
137        """
138        return self.__attributeValueFactory
139                           
140       
141class SubjectAttributeDesignator(AttributeDesignator):
142    """XACML Subject Attribute Designator type
143    @cvar ELEMENT_LOCAL_NAME: XML local name for this element
144    @type ELEMENT_LOCAL_NAME: string
145    """
146    ELEMENT_LOCAL_NAME = 'SubjectAttributeDesignator'
147    __slots__ = ()
148   
149    def evaluate(self, context):
150        """Evaluate the result of the SubjectAttributeDesignator in a condition
151       
152        @param context: the request context
153        @type context: ndg.xacml.core.context.request.Request
154        @return: attribute value(s) resulting from execution of this expression
155        in a condition
156        @rtype: AttributeValue/NoneType 
157        """ 
158        if not isinstance(context, Request):
159            raise TypeError('Expecting %r type for context input; got %r' %
160                            (Request, type(context)))
161       
162        dataType = self.dataType
163        attributeValueBag = TypedList(self.attributeValueFactory(dataType))
164        attributeId = self.attributeId
165        issuer = self.issuer
166       
167        log.debug("In SubjectAttributeDesignator for attribute %r", attributeId)
168       
169        if issuer is not None:
170            _issuerMatch = lambda _issuer: issuer == _issuer
171        else:
172            _issuerMatch = lambda _issuer: True
173       
174        _attributeMatch = lambda attr: (attr.attributeId == attributeId and 
175                                        attr.dataType == dataType and
176                                        _issuerMatch(attr.issuer))
177                                       
178        for subject in context.subjects: 
179            for attr in subject.attributes:
180                if _attributeMatch(attr):
181                    attributeValueBag.extend([i for i in attr.attributeValues
182                                              if i.dataType == dataType])
183                   
184            if context.ctxHandler is not None:
185                # Try querying the Policy Information Point via the Context
186                # Handler to see if values for the attribute specified in this
187                # designator can be retrieved externally. If retrieved, they're
188                # added to the bag.
189                log.debug("Making query to PIP for additional subject "
190                          "attributes to satify match")
191               
192                attributeValues = context.ctxHandler.pipQuery(context, self)
193                if attributeValues is not None:
194                    log.debug("PIP retrieved additional subject attributes: %r",
195                              attributeValues)
196                   
197                    # Weed out any duplicates
198                    if len(attributeValueBag) > 0:
199                        filtAttributeValues = [attrVal
200                                           for attrVal in attributeValues
201                                           if attrVal not in attributeValueBag]
202                    else:
203                        filtAttributeValues = attributeValues
204                       
205                    attributeValueBag.extend(filtAttributeValues)
206                   
207        if len(attributeValueBag) == 0 and self.mustBePresent:
208            raise MissingAttributeError('"MustBePresent" is set for %r but no '
209                                        'match for attributeId=%r, dataType=%r '
210                                        'and issuer=%r' % 
211                                        (self.__class__.__name__,
212                                         self.attributeId,
213                                         self.dataType,
214                                         self.issuer)) 
215                       
216        return attributeValueBag
217       
218       
219class ResourceAttributeDesignator(AttributeDesignator):
220    """XACML Resource Attribute Designator type
221    @cvar ELEMENT_LOCAL_NAME: XML local name for this element
222    @type ELEMENT_LOCAL_NAME: string
223    """
224    ELEMENT_LOCAL_NAME = 'ResourceAttributeDesignator'
225    __slots__ = ()
226   
227    def evaluate(self, context):
228        """Evaluate the result of the ResourceAttributeDesignator in a condition
229       
230        @param context: the request context
231        @type context: ndg.xacml.core.context.request.Request
232        @return: attribute value(s) resulting from execution of this expression
233        in a condition
234        @rtype: AttributeValue/NoneType 
235        """ 
236        if not isinstance(context, Request):
237            raise TypeError('Expecting %r type for context input; got %r' %
238                            (Request, type(context)))
239       
240        dataType = self.dataType
241        attributeValueBag = TypedList(self.attributeValueFactory(dataType))
242        attributeId = self.attributeId
243        issuer = self.issuer
244       
245        if issuer is not None:
246            _issuerMatch = lambda _issuer: issuer == _issuer
247        else:
248            _issuerMatch = lambda _issuer: True
249       
250        _attributeMatch = lambda attr: (attr.attributeId == attributeId and 
251                                        attr.dataType == dataType and
252                                        _issuerMatch(attr.issuer))
253                   
254        for resource in context.resources:
255            for attr in resource.attributes:
256                if _attributeMatch(attr):
257                    attributeValueBag.extend([i for i in attr.attributeValues
258                                              if i.dataType == dataType])
259                   
260        if len(attributeValueBag) == 0 and self.mustBePresent:
261            raise MissingAttributeError('"MustBePresent" is set for %r but no '
262                                        'match for attributeId=%r, dataType=%r '
263                                        'and issuer=%r' % 
264                                        (self.__class__.__name__,
265                                         self.attributeId,
266                                         self.dataType,
267                                         self.issuer)) 
268                       
269        return attributeValueBag
270   
271       
272class ActionAttributeDesignator(AttributeDesignator):
273    """XACML Action Attribute Designator type
274    @cvar ELEMENT_LOCAL_NAME: XML local name for this element
275    @type ELEMENT_LOCAL_NAME: string
276    """
277    ELEMENT_LOCAL_NAME = 'ActionAttributeDesignator'
278    __slots__ = ()
279   
280    def evaluate(self, context):
281        """Evaluate the result of the ActionAttributeDesignator in a condition
282       
283        @param context: the request context
284        @type context: ndg.xacml.core.context.request.Request
285        @return: attribute value(s) resulting from execution of this expression
286        in a condition
287        @rtype: AttributeValue/NoneType 
288        """ 
289        if not isinstance(context, Request):
290            raise TypeError('Expecting %r type for context input; got %r' %
291                            (Request, type(context)))
292       
293        dataType = self.dataType
294        attributeValueBag = TypedList(self.attributeValueFactory(dataType))
295        attributeId = self.attributeId
296        issuer = self.issuer
297        action = context.action
298       
299        if issuer is not None:
300            _issuerMatch = lambda _issuer: issuer == _issuer
301        else:
302            _issuerMatch = lambda _issuer: True
303       
304        _attributeMatch = lambda attr: (attr.attributeId == attributeId and 
305                                        attr.dataType == dataType and
306                                        _issuerMatch(attr.issuer))
307                   
308        for attr in action.attributes:
309            if _attributeMatch(attr):
310                attributeValueBag.extend([i for i in attr.attributeValues
311                                          if i.dataType == dataType])
312                   
313        if len(attributeValueBag) == 0 and self.mustBePresent:
314            raise MissingAttributeError('"MustBePresent" is set for %r but no '
315                                        'match for attributeId=%r, dataType=%r '
316                                        'and issuer=%r' % 
317                                        (self.__class__.__name__,
318                                         self.attributeId,
319                                         self.dataType,
320                                         self.issuer)) 
321                       
322        return attributeValueBag   
323   
324   
325class EnvironmentAttributeDesignator(AttributeDesignator):
326    """XACML Environment Attribute Designator type
327    @cvar ELEMENT_LOCAL_NAME: XML local name for this element
328    @type ELEMENT_LOCAL_NAME: string
329    """
330    ELEMENT_LOCAL_NAME = 'EnvironmentAttributeDesignator'
331    __slots__ = ()
332   
333    def evaluate(self, context):
334        """Evaluate the result of the EnvironmentAttributeDesignator in a
335        condition
336       
337        @param context: the request context
338        @type context: ndg.xacml.core.context.request.Request
339        @return: attribute value(s) resulting from execution of this expression
340        in a condition
341        @rtype: AttributeValue/NoneType 
342        """ 
343        if not isinstance(context, Request):
344            raise TypeError('Expecting %r type for context input; got %r' %
345                            (Request, type(context)))
346       
347        dataType = self.dataType
348        attributeValueBag = TypedList(self.attributeValueFactory(dataType))
349        attributeId = self.attributeId
350        issuer = self.issuer
351        environment = context.environment
352       
353        if issuer is not None:
354            _issuerMatch = lambda _issuer: issuer == _issuer
355        else:
356            _issuerMatch = lambda _issuer: True   
357       
358        _attributeMatch = lambda attr: (attr.attributeId == attributeId and 
359                                        attr.dataType == dataType and
360                                        _issuerMatch(attr.issuer))
361                 
362        for attr in environment.attributes:
363            if _attributeMatch(attr):
364                attributeValueBag.extend([i for i in attr.attributeValues
365                                          if i.dataType == dataType])
366                   
367        if len(attributeValueBag) == 0 and self.mustBePresent:
368            raise MissingAttributeError('"MustBePresent" is set for %r but no '
369                                        'match for attributeId=%r, dataType=%r '
370                                        'and issuer=%r' % 
371                                        (self.__class__.__name__,
372                                         self.attributeId,
373                                         self.dataType,
374                                         self.issuer)) 
375                       
376        return attributeValueBag
Note: See TracBrowser for help on using the repository browser.