Changeset 7661 for TI12-security


Ignore:
Timestamp:
27/10/10 16:05:18 (9 years ago)
Author:
pjkersha
Message:

ndg_xacml:

  • added support for custom AttributeValue? DataTypes? - this means that the ESGF GroupRole? attribute type can be added directly into XACML policies.
  • TODO: add support for adding custom functions so that a PDP can correctly apply rules based on custom types like the ESGF GroupRole?.
Location:
TI12-security/trunk/ndg_xacml/ndg/xacml
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/ndg_xacml/ndg/xacml/core/attributevalue.py

    r7652 r7661  
    241241 
    242242 
    243 # Dynamically Create classes based on AttributeValue for all the XACML primitive 
    244 # types 
    245 _IDENTIFIER2CLASS_MAP = AttributeValueClassMap() 
    246  
    247 for typeName, _type in AttributeValue.TYPE_MAP.items(): 
    248     identifier = AttributeValue.TYPE_URI_MAP[typeName] 
    249  
    250     className = typeName + AttributeValue.CLASS_NAME_SUFFIX                
    251     classVars = {'TYPE': _type, 'IDENTIFIER': identifier} 
    252      
    253     attributeValueClass = type(className, (AttributeValue, ), classVars) 
    254     AttributeValue.register(attributeValueClass) 
    255     _IDENTIFIER2CLASS_MAP[identifier] = attributeValueClass 
    256      
    257      
    258 def extendAttributeValueClassMap(classMap, overwrite=False): 
    259     """Extend Default AttributeValue Class Map with custom types.  This enables 
    260     the policy to support additional attribute types 
    261      
    262     @param classMap: input an alternative to the default class mapping  
    263     object _IDENTIFIER2CLASS_MAP, if None, it will default to this setting 
    264     @type classMap: ndg.xacml.core.attributevalue.AttributeValueClassMap   
    265     @param overwrite: set to True to allow overwriting of existing map entries, 
    266     defaults to disable overwrite 
    267     @type overwrite: bool 
    268     """ 
    269     if not isinstance(classMap, AttributeValueClassMap): 
    270         raise TypeError('Expecting %r derived type for "map" input; got %r' %  
    271                         (AttributeValueClassMap, type(map))) 
    272  
    273     if overwrite: 
    274         _IDENTIFIER2CLASS_MAP.update(classMap) 
    275     else: 
    276         for k, v in classMap.items(): 
    277             if k not in _IDENTIFIER2CLASS_MAP: 
    278                 _IDENTIFIER2CLASS_MAP[k] = v 
    279     
    280     
    281243class AttributeValueClassFactory(object): 
    282244    """Create AttributeValue types based on the XML namespace identifier 
    283245     
    284     Convenience wrapper for _IDENTIFIER2CLASS_MAP instance of  
     246    Convenience wrapper for IDENTIFIER2CLASS_MAP instance of  
    285247    AttributeValueClassMap 
    286248     
     
    291253    __slots__ = ('__classMap',) 
    292254     
     255    # Dynamically Create classes based on AttributeValue for all the XACML  
     256    # primitive types 
     257    IDENTIFIER2CLASS_MAP = AttributeValueClassMap() 
     258    _typeName, _type, _identifier, _className, _classVars, \ 
     259        _attributeValueClass = (None,)*6 
     260         
     261    for _typeName, _type in AttributeValue.TYPE_MAP.items(): 
     262        _identifier = AttributeValue.TYPE_URI_MAP[_typeName] 
     263     
     264        _className = _typeName + AttributeValue.CLASS_NAME_SUFFIX                
     265        _classVars = {'TYPE': _type, 'IDENTIFIER': _identifier} 
     266         
     267        _attributeValueClass = type(_className, (AttributeValue, ), _classVars) 
     268        AttributeValue.register(_attributeValueClass) 
     269        IDENTIFIER2CLASS_MAP[_identifier] = _attributeValueClass 
     270     
     271    del _typeName, _type, _identifier, _className, _classVars, \ 
     272        _attributeValueClass 
     273         
    293274    def __init__(self, classMap=None): 
    294275        """Set a mapping object to map attribute value URIs to their  
     
    296277         
    297278        @param classMap: input an alternative to the default class mapping  
    298         object _IDENTIFIER2CLASS_MAP, if None, it will default to this setting 
     279        object IDENTIFIER2CLASS_MAP, if None, it will default to this setting 
    299280        @type classMap: ndg.xacml.core.attributevalue.AttributeValueClassMap 
    300281        """ 
    301282        if classMap is None: 
    302             self.__classMap = _IDENTIFIER2CLASS_MAP 
     283            self.__classMap = self.__class__.IDENTIFIER2CLASS_MAP 
    303284        elif isinstance(classMap, AttributeValueClassMap): 
    304285            self.__classMap = classMap 
     
    316297        """ 
    317298        return self.__classMap.get(identifier) 
    318          
     299     
     300    @classmethod 
     301    def addClass(cls, identifier, attributeValueClass, overwrite=False): 
     302        """Extend Default AttributeValue Class Map with custom types.  This  
     303        enables the policy to support additional attribute types 
     304         
     305        @param identifier: ID for candidate Attribute Value class 
     306        @type identifier: ndg.xacml.core.attributevalue.AttributeValueClassMap  
     307        @param attributeValueClass: new Attribute Value class to be added 
     308        @type attributeValueClass: ndg.xacml.core.attributevalue.AttributeValue 
     309        @param overwrite: set to True to allow overwriting of existing map  
     310        entries, defaults to disable overwrite 
     311        @type overwrite: bool 
     312        """ 
     313        # Instantiate class map to validate input types. 
     314        classMap = AttributeValueClassMap() 
     315        classMap[identifier] = attributeValueClass 
     316         
     317        if overwrite: 
     318            cls.IDENTIFIER2CLASS_MAP.update(classMap) 
     319        else: 
     320            for k, v in classMap.items(): 
     321                if k not in cls.IDENTIFIER2CLASS_MAP: 
     322                    cls.IDENTIFIER2CLASS_MAP[k] = v         
     323                     
  • TI12-security/trunk/ndg_xacml/ndg/xacml/parsers/etree/applyreader.py

    r7109 r7661  
    2424from ndg.xacml.parsers.etree import QName 
    2525from ndg.xacml.parsers.etree.reader import ETreeAbstractReader 
    26 from ndg.xacml.parsers.etree.expressionreader import ExpressionReader 
    2726from ndg.xacml.parsers.etree.factory import ReaderFactory 
    2827 
  • TI12-security/trunk/ndg_xacml/ndg/xacml/parsers/etree/attributevaluereader.py

    r7109 r7661  
    1515from ndg.xacml.parsers.etree import QName 
    1616from ndg.xacml.parsers.etree.expressionreader import ExpressionReader 
     17from ndg.xacml.utils import VettedDict 
    1718 
    1819 
    1920class AttributeValueReader(ExpressionReader): 
    20     '''ElementTree based XACML Expression type parser 
     21    '''ElementTree based XACML AttributeValue type parser 
    2122     
    2223    @cvar TYPE: XACML class type that this reader will read values into 
     
    6162              
    6263        attributeValueClass = self.__class__.FACTORY(elemAttributeValues[0]) 
     64        if attributeValueClass is None: 
     65            raise XMLParseError("No Attribute Value class available for " 
     66                                "parsing %r type" % elemAttributeValues[0]) 
     67             
    6368        attributeValue = attributeValueClass() 
    6469        attributeValue.dataType = elemAttributeValues[0] 
     
    7984        @raise XMLParseError: error parsing attribute ID XML attribute 
    8085        """ 
     86        reader = DataTypeReaderClassFactory.getReader(attributeValue) 
     87        reader.parse(elem, attributeValue) 
     88         
     89 
     90class ETreeDataTypeReaderBase(object):   
     91    @classmethod 
     92    def parse(cls, elem, attributeValue): 
    8193        if elem.text is None: 
    8294            raise XMLParseError('No attribute value element found parsing %r' %  
     
    8496             
    8597        attributeValue.value = elem.text 
     98 
     99         
     100class ETreeDataTypeReaderClassMap(VettedDict): 
     101    """Specialised dictionary to hold mappings of XACML AttributeValue DataTypes 
     102    and their equivalent ElementTree reader classes 
     103    """ 
    86104     
     105    def __init__(self): 
     106        """Force entries to derive from AttributeValue and IDs to 
     107        be string type 
     108        """         
     109        # Filters are defined as staticmethods but reference via self here to  
     110        # enable derived class to override them as standard methods without 
     111        # needing to redefine this __init__ method             
     112        VettedDict.__init__(self, self.keyFilter, self.valueFilter) 
     113         
     114    @staticmethod 
     115    def keyFilter(key): 
     116        """Enforce string type keys for Attribute Value DataType URIs 
     117         
     118        @param key: URN for attribute 
     119        @type key: basestring 
     120        @return: boolean True indicating key is OK 
     121        @rtype: bool 
     122        @raise TypeError: incorrect input type 
     123        """ 
     124        if not isinstance(key, basestring): 
     125            raise TypeError('Expecting %r derived type for key; got %r' %  
     126                            (basestring, type(key)))  
     127        return True  
     128     
     129    @staticmethod 
     130    def valueFilter(value): 
     131        """Enforce ElementTree abstract reader derived types for values 
     132        @param value: attribute value 
     133        @type value:  
     134        ndg.xacml.parsers.etree.attributevaluereader.ETreeDataTypeReaderBase to  
     135        their derived type 
     136        @return: boolean True indicating attribute value is correct type 
     137        @rtype: bool 
     138        @raise TypeError: incorrect input type 
     139        """ 
     140        if not issubclass(value, ETreeDataTypeReaderBase): 
     141            raise TypeError('Expecting %r derived type for value; got %r' %  
     142                            (ETreeDataTypeReaderBase, type(value)))  
     143        return True  
     144     
     145               
     146class DataTypeReaderClassFactory(object): 
     147    """Return class to parse the content of the Attribute value based on the  
     148    DataType setting""" 
     149    MAP = ETreeDataTypeReaderClassMap() 
     150    _id = None 
     151    for _id in AttributeValue.TYPE_URIS: 
     152        MAP[_id] = ETreeDataTypeReaderBase 
     153         
     154    del _id 
     155     
     156    @classmethod 
     157    def addReader(cls, identifier, readerClass): 
     158        cls.MAP[identifier] = readerClass 
     159         
     160    @classmethod 
     161    def getReader(cls, attributeValue): 
     162        return cls.MAP[attributeValue.dataType] 
     163     
  • TI12-security/trunk/ndg_xacml/ndg/xacml/parsers/etree/factory.py

    r7087 r7661  
    1515from ndg.xacml.parsers import AbstractReaderFactory 
    1616from ndg.xacml.utils.factory import importModuleObject 
    17  
    18 from ndg.xacml.core.policy import Policy 
    19 from ndg.xacml.core.target import Target 
    20 from ndg.xacml.core.rule import Rule 
    21  
    22 # Target child elements 
    23 from ndg.xacml.core.subject import Subject 
    24 from ndg.xacml.core.action import Action 
    25 from ndg.xacml.core.resource import Resource 
    26 from ndg.xacml.core.environment import Environment 
     17from ndg.xacml.utils import VettedDict 
     18from ndg.xacml.core import XacmlCoreBase 
     19from ndg.xacml.parsers.etree.reader import ETreeAbstractReader 
    2720 
    2821 
     22class ETreeReaderClassMap(VettedDict): 
     23    """Specialised dictionary to hold mappings of XACML classes to their 
     24    equivalent ElementTree reader classes 
     25    """ 
     26     
     27    def __init__(self): 
     28        """Force entries to derive from AttributeValue and IDs to 
     29        be string type 
     30        """         
     31        # Filters are defined as staticmethods but reference via self here to  
     32        # enable derived class to override them as standard methods without 
     33        # needing to redefine this __init__ method             
     34        VettedDict.__init__(self, self.keyFilter, self.valueFilter) 
     35         
     36    @staticmethod 
     37    def keyFilter(key): 
     38        """Enforce XACML base class type keys 
     39         
     40        @param key: URN for attribute 
     41        @type key: basestring 
     42        @return: boolean True indicating key is OK 
     43        @rtype: bool 
     44        @raise TypeError: incorrect input type 
     45        """ 
     46        if not issubclass(key, XacmlCoreBase): 
     47            raise TypeError('Expecting %r derived type for key; got %r' %  
     48                            (XacmlCoreBase, type(key)))  
     49        return True  
     50     
     51    @staticmethod 
     52    def valueFilter(value): 
     53        """Enforce ElementTree abstract reader derived types for values 
     54        @param value: attribute value 
     55        @type value: ndg.xacml.core.attributevalue.AttributeValue derived type 
     56        @return: boolean True indicating attribute value is correct type 
     57        @rtype: bool 
     58        @raise TypeError: incorrect input type 
     59        """ 
     60        if not issubclass(value, ETreeAbstractReader): 
     61            raise TypeError('Expecting %r derived type for value; got %r' %  
     62                            (ETreeAbstractReader, type(value)))  
     63        return True  
     64     
     65     
    2966class ReaderFactory(AbstractReaderFactory): 
    3067    """Parser factory for ElementTree based parsers for XACML types""" 
     68    READER_CLASS_MAP = ETreeReaderClassMap() 
     69     
     70    @classmethod 
     71    def addReader(cls, xacmlType, readerClass): 
     72        """Add custom classes and readers 
     73         
     74        @param xacmlType: XACML type to return a parser class for 
     75        @type xacmlType: type 
     76        @param readerClass: ElementTree based reader for the input XACML type.   
     77        @type readerClass: ndg.xacml.parsers.etree.reader.ETreeAbstractReader  
     78        derived type 
     79        """ 
     80        cls.READER_CLASS_MAP[xacmlType] = readerClass 
    3181     
    3282    @classmethod 
     
    3787        @type xacmlType: type 
    3888        @return: ElementTree based reader for the input XACML type.  The class 
    39         and module containing the class are infered from the XACML class name 
     89        and module containing the class are inferred from the XACML class name 
    4090        input e.g.  
    4191         
     
    4696        @raise ImportError: if no reader class found for input type 
    4797        """ 
    48         xacmlTypeName = xacmlType.__name__ 
    49         readerClassName = 'ndg.xacml.parsers.etree.%sreader.%sReader' % ( 
     98        if xacmlType in cls.READER_CLASS_MAP: 
     99            # Retrieve from mapping 
     100            return cls.READER_CLASS_MAP[xacmlType] 
     101        else: 
     102            # Infer from the package structure 
     103            xacmlTypeName = xacmlType.__name__ 
     104            readerClassName = 'ndg.xacml.parsers.etree.%sreader.%sReader' % ( 
    50105                                                        xacmlTypeName.lower(), 
    51106                                                        xacmlTypeName) 
    52         readerClass = importModuleObject(readerClassName) 
    53         return readerClass 
     107            readerClass = importModuleObject(readerClassName) 
     108            return readerClass 
    54109             
  • TI12-security/trunk/ndg_xacml/ndg/xacml/test

    • Property svn:ignore set to
      esg-grouprole.xsd
  • TI12-security/trunk/ndg_xacml/ndg/xacml/test/test_policy.py

    r7087 r7661  
    1919from ndg.xacml.core.attributedesignator import SubjectAttributeDesignator 
    2020from ndg.xacml.core.attributeselector import AttributeSelector 
     21from ndg.xacml.core.attributevalue import (AttributeValueClassFactory,  
     22                                           AttributeValue) 
     23from ndg.xacml.parsers.etree import QName 
    2124from ndg.xacml.parsers.etree.factory import ReaderFactory 
     25from ndg.xacml.parsers.etree.attributevaluereader import ( 
     26                                                DataTypeReaderClassFactory, 
     27                                                ETreeDataTypeReaderBase) 
    2228 
    2329from ndg.xacml.test import XACML_NDGTEST1_FILEPATH, THIS_DIR 
    2430 
    2531 
     32class GroupRoleAttributeValue(AttributeValue): 
     33    IDENTIFIER = 'urn:esgf:pcmdi:grouprole' 
     34    TYPE = dict 
     35    GROUPROLE_ELEMENT_LOCAL_NAME = 'groupRole' 
     36    GROUP_ELEMENT_LOCAL_NAME = 'group' 
     37    ROLE_ELEMENT_LOCAL_NAME = 'role' 
     38    ROLE_DEFAULT_VALUE = 'default' 
     39     
     40    __slots__ = ('group', 'role') 
     41     
     42    def __init__(self): 
     43        super(GroupRoleAttributeValue, self).__init__() 
     44        self.group = None 
     45        self.role = self.__class__.ROLE_DEFAULT_VALUE 
     46     
     47     
     48class ETreeGroupRoleDataTypeReader(ETreeDataTypeReaderBase): 
     49         
     50    @classmethod 
     51    def parse(cls, elem, attributeValue): 
     52        """Parse ESG Group/Role type object 
     53 
     54        @param obj: input object to parse 
     55        @type obj: ElementTree Element, or stream object 
     56        @return: ElementTree element 
     57        @rtype: xml.etree.Element 
     58        """ 
     59        if len(elem) != 1: 
     60            raise XMLParseError("Expecting single groupRole child element but "  
     61                                "found only %d element(s)" % len(elem)) 
     62                      
     63        groupRoleElem = elem[0] 
     64         
     65        if (QName.getLocalPart(groupRoleElem.tag) !=  
     66            attributeValue.__class__.GROUPROLE_ELEMENT_LOCAL_NAME): 
     67            raise XMLParseError("%r element found, expecting \"%s\" element "   
     68                                "instead" %  
     69                                xacmlType.GROUPROLE_ELEMENT_LOCAL_NAME) 
     70         
     71        # Allow for any of the defined Expression sub-types in the child  
     72        # elements 
     73        for subElem in groupRoleElem: 
     74            localName = QName.getLocalPart(subElem.tag) 
     75            if localName == attributeValue.__class__.ROLE_ELEMENT_LOCAL_NAME: 
     76                attributeValue.role = subElem.text 
     77            elif localName == attributeValue.__class__.GROUP_ELEMENT_LOCAL_NAME: 
     78                attributeValue.group = subElem.text 
     79            else: 
     80                raise XMLParseError('%r ESG Group/Role sub-element not ' 
     81                                    'recognised' % localName)  
     82                                
     83     
    2684class XACMLPolicyTestCase(unittest.TestCase): 
    2785    XACML_TEST1_FILENAME = "rule1.xml" 
     
    3391    XACML_TEST4_FILENAME = "rule4.xml" 
    3492    XACML_TEST4_FILEPATH = path.join(THIS_DIR, XACML_TEST4_FILENAME) 
    35     
     93    XACML_ESGFTEST1_FILENAME = "esgf1.xml" 
     94    XACML_ESGFTEST1_FILEPATH = path.join(THIS_DIR, XACML_ESGFTEST1_FILENAME) 
     95     
    3696    def test01ETreeParseRule1Policy(self): 
    3797        PolicyReader = ReaderFactory.getReader(Policy) 
     
    239299         
    240300        try: 
    241             policy = PolicyReader.parse(XACMLPolicyTestCase.XACML_TEST3_FILEPATH) 
     301            policy = PolicyReader.parse( 
     302                                    XACMLPolicyTestCase.XACML_TEST3_FILEPATH) 
    242303            self.assert_(policy) 
    243304        except NotImplementedError, e: 
     
    255316        policy = PolicyReader.parse(XACML_NDGTEST1_FILEPATH) 
    256317        self.assert_(policy)     
    257  
     318                     
     319    def test05ETreeParseEsgf1Policy(self): 
     320        # Example policy with custom attribute value type used with ESGF 
     321         
     322        # Add new type 
     323        AttributeValueClassFactory.addClass('urn:esgf:pcmdi:grouprole',  
     324                                            GroupRoleAttributeValue) 
     325         
     326        # Add new parser for this type 
     327        DataTypeReaderClassFactory.addReader('urn:esgf:pcmdi:grouprole',  
     328                                ETreeGroupRoleDataTypeReader) 
     329         
     330        PolicyReader = ReaderFactory.getReader(Policy) 
     331        policy = PolicyReader.parse(self.__class__.XACML_ESGFTEST1_FILEPATH) 
     332        self.assert_(policy)   
     333         
    258334         
    259335if __name__ == "__main__": 
Note: See TracChangeset for help on using the changeset viewer.