Changeset 7310


Ignore:
Timestamp:
10/08/10 16:40:37 (9 years ago)
Author:
pjkersha
Message:

Incomplete - task 2: XACML-Security Integration

  • progress with SAML attribute query interface to PIP.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/pip/saml_pip.py

    r7298 r7310  
    1818from ndg.xacml.core.context.request import Request 
    1919 
    20 from ndg.saml.saml2.core import AttributeQuery 
     20from ndg.saml.saml2.core import (AttributeQuery as SamlAttributeQuery,  
     21                                 Attribute as SamlAttribute) 
     22from ndg.saml.utils import TypedList as SamlTypedList 
    2123from ndg.saml.saml2.binding.soap.client.attributequery import \ 
    2224                                            AttributeQuerySslSOAPBinding 
     
    3335    DISALLOWED_ATTRIBUTE_QUERY_OPTNAMES = ( 
    3436        AttributeQuerySslSOAPBinding.SUBJECT_ID_OPTNAME, 
     37        AttributeQuerySslSOAPBinding.QUERY_ATTRIBUTES_ATTRNAME 
    3538    ) 
    3639    ATTRIBUTE_QUERY_ATTRNAME = 'attributeQuery' 
    3740    LEN_ATTRIBUTE_QUERY_ATTRNAME = len(ATTRIBUTE_QUERY_ATTRNAME) 
    3841     
    39     __slots__ = ('__attributeQueryBinding') 
     42    # +1 allows for '.' or other separator e.g.  
     43    # pip.attributeQuery.issuerName 
     44    #                   ^ 
     45    ATTRIBUTE_QUERY_ATTRNAME_OFFSET = LEN_ATTRIBUTE_QUERY_ATTRNAME + 1 
     46     
     47    __slots__ = ('__mappingFilePath',) 
    4048     
    4149    def __init__(self): 
    4250        '''Initialise settings for connection to an Attribute Authority''' 
    4351        self.__attributeQueryBinding = AttributeQuerySslSOAPBinding()     
     52        self.__mappingFilePath = None 
     53 
     54    def _getMappingFilePath(self): 
     55        return self.__mappingFilePath 
     56 
     57    def _setMappingFilePath(self, value): 
     58        if not isinstance(value, basestring): 
     59            raise TypeError('Expecting string type for "mappingFilePath"; got ' 
     60                            '%r' % type(value)) 
     61        self.__mappingFilePath = value 
     62 
     63    mappingFilePath = property(_getMappingFilePath,  
     64                               _setMappingFilePath,  
     65                               doc="Mapping File maps attribute IDs to the " 
     66                                   "Attribute Authorities from which they may " 
     67                                   "be queried for") 
    4468 
    4569    @classmethod 
     
    5579         
    5680        return obj 
     81     
     82    def __setAttr(self, optName, val):  
     83        """Helper method to differentiate attribute query binding option names 
     84        from other config options 
     85         
     86        @param optName: config file option name 
     87        @type optName: basestring 
     88        @param val: corresponding value 
     89        @type val: basestring 
     90        """ 
     91        if optName.startswith(self.__class__.ATTRIBUTE_QUERY_ATTRNAME): 
     92            setattr(self,  
     93                    optName[self.__class__.ATTRIBUTE_QUERY_ATTRNAME_OFFSET:], 
     94                    val) 
     95        else: 
     96            setattr(self, optName, val) 
    5797 
    5898    def parseConfig(self, cfg, prefix='', section='DEFAULT'): 
     
    84124         
    85125        prefixLen = len(prefix) 
     126         
    86127        for optName, val in items: 
    87128            if prefix: 
    88129                # Filter attributes based on prefix 
    89130                if optName.startswith(prefix): 
    90                     setattr(self, optName[prefixLen:], val) 
     131                    self.__setAttr(optName[prefixLen:], val) 
    91132            else: 
    92133                # No prefix set - attempt to set all attributes    
    93                 setattr(self, optName, val) 
    94                  
    95         if (not self.attributeQueryBinding.issuerName and  
    96             self.attributeQueryBinding.sslCtxProxy.sslCertFilePath is not None): 
    97             issuerX509Cert = X509Cert.Read( 
    98                         self.attributeQueryBinding.sslCtxProxy.sslCertFilePath) 
    99             self.attributeQueryBinding.issuerName = str(issuerX509Cert.dn) 
    100              
    101     def __setattr__(self, name, value): 
    102         """Enable setting of AttributeQuerySslSOAPBinding attributes from 
    103         names starting with attributeQuery.* / attributeQuery_*.  Addition for 
    104         setting these values from ini file 
    105         """ 
    106  
    107         # Coerce into setting AttributeQuerySslSOAPBinding attributes -  
    108         # names must start with 'attributeQuery\W' e.g. 
    109         # attributeQuery.clockSkew or attributeQuery_issuerDN 
    110         if name.startswith(self.__class__.ATTRIBUTE_QUERY_ATTRNAME): 
    111             queryAttrName = name[self.__class__.LEN_ATTRIBUTE_QUERY_ATTRNAME+1:] 
    112              
    113             # Skip subject related parameters to prevent settings from static 
    114             # configuration.  These are set at runtime 
    115             if queryAttrName in self.__class__.DISALLOWED_ATTRIBUTE_QUERY_OPTNAMES: 
    116                 super(PIP, self).__setattr__(name, value) 
    117                  
    118             setattr(self.__attributeQueryBinding, queryAttrName, value) 
    119         else: 
    120             super(PIP, self).__setattr__(name, value)     
    121  
    122     @property 
    123     def attributeQueryBinding(self): 
    124         """SAML SOAP Attribute Query client binding object""" 
    125         return self.__attributeQueryBinding 
     134                self.__setAttr(optName, val) 
     135                             
     136#    def __setattr__(self, name, value): 
     137#        """Enable setting of AttributeQuerySslSOAPBinding attributes from 
     138#        names starting with attributeQuery.* / attributeQuery_*.  Addition for 
     139#        setting these values from ini file 
     140#        """ 
     141# 
     142#        # Coerce into setting AttributeQuerySslSOAPBinding attributes -  
     143#        # names must start with 'attributeQuery\W' e.g. 
     144#        # attributeQuery.clockSkew or attributeQuery_issuerDN 
     145#        if name.startswith(self.__class__.ATTRIBUTE_QUERY_ATTRNAME): 
     146#            queryAttrName = name[ 
     147#                                self.__class__.ATTRIBUTE_QUERY_ATTRNAME_OFFSET:] 
     148#             
     149#            # Skip subject and attribute Id related parameters to prevent  
     150#            # settings from static configuration.  These are set from the  
     151#            # incoming XACML context 
     152#            if min([queryAttrName.startswith(i) for i in  
     153#                    self.__class__.DISALLOWED_ATTRIBUTE_QUERY_OPTNAMES]): 
     154#                super(PIP, self).__setattr__(name, value) 
     155#                 
     156#            setattr(self.__attributeQueryBinding, queryAttrName, value) 
     157#        else: 
     158#            super(PIP, self).__setattr__(name, value)     
     159 
    126160     
    127161    def readMappingFile(self): 
    128162        """Read the file which maps attribute names to Attribute Authorities 
    129163        """ 
     164        mappingFile = open(self.mappingFilePath) 
     165        self.__attribute2AttributeAuthorityMap = dict() 
     166        for line in mappingFile.readline(): 
     167            if not line.startswith('#'): 
     168                attributeId, attributeAuthorityURI = line.split() 
     169                self.__attribute2AttributeAuthorityMap[attributeId 
     170                                                       ] = attributeAuthorityURI 
    130171         
    131172    def attributeQuery(self, context, attributeDesignator): 
     
    141182                            (Request, type(context))) 
    142183         
    143         # Check for cached attributes for this subject (i.e. user) 
     184        # TODO: Check for cached attributes for this subject (i.e. user) 
    144185         
    145186        # If none found send a query to the attribute authority 
    146187         
    147         # Find out the attribute authority corresponding to the query 
    148         attributeName = attributes[0] 
    149         attributeAuthorityURI = self.__attribute2AttributeAuthorityMap.get(attributeName) 
    150          
    151                 
    152         log.debug("PIP: received attribute query: %r", attributeQuery) 
    153           
    154         try: 
    155             self.attributeQueryBinding.subjectID = None 
    156             response = self.attributeQueryBinding.send( 
    157                                                     uri=attributeAuthorityURI) 
    158         finally: 
    159             # Ensure subject ID is reset ready for any subsequent query 
    160             self.attributeQueryBinding.subjectID = '' 
    161          
    162         attributeResponse = PIPAttributeResponse() 
    163         attributeResponse[Subject.ROLES_NS] = [] 
    164          
    165         # Unpack assertion attribute values and add to the response object 
     188        # TODO: Look-up the attribute authority corresponding to the query 
     189 
     190#        attributeAuthorityURI = self.__attribute2AttributeAuthorityMap.get( 
     191#                                                                attributeName) 
     192        attributeAuthorityURI = 'https://localhost:7443/AttributeAuthority' 
     193                         
     194        # Get subject from the request context 
     195        # TODO: parameterise data type setting 
     196        subjectId = None 
     197        for subject in context.subjects: 
     198            for attribute in subject.attributes: 
     199                if attribute.dataType == 'urn:esg:openid': 
     200                    if len(attribute.attributeValues) != 1: 
     201                        raise Exception("Expecting a single attribute value " 
     202                                        "for query subject ID") 
     203                    subjectId = attribute.attributeValues[0].value 
     204                    break 
     205         
     206        if subjectId is None: 
     207            # TODO: parameterise data type setting 
     208            raise Exception('No subject found of type %r in request context' % 
     209                            'urn:esg:openid') 
     210        else: 
     211            # Keep a reference to the matching Subject instance 
     212            _subject = subject 
     213             
     214        # Get the id of the attribute to be queried for and add it to the SAML 
     215        # query 
     216        attributeFormat = attributeDesignator.dataType 
     217        samlAttribute = SamlAttribute() 
     218        samlAttribute.name = attributeDesignator.attributeId 
     219        samlAttribute.nameFormat = attributeFormat 
     220        attributeQueryBinding.query.attributes.append(samlAttribute) 
     221         
     222         
     223        attributeQueryBinding.subjectID = subjectId 
     224        response = attributeQueryBinding.send(uri=attributeAuthorityURI) 
     225         
     226        # Unpack SAML assertion attribute values corresponding to the name  
     227        # format specified 
     228        attributeValues = [] 
    166229        for assertion in response.assertions: 
    167230            for statement in assertion.attributeStatements: 
    168231                for attribute in statement.attributes: 
    169                     attributeResponse[Subject.ROLES_NS] += [ 
    170                         attributeValue.value  
    171                         for attributeValue in attribute.attributeValues 
    172                         if attributeValue.value not in attributeResponse[ 
    173                                                             Subject.ROLES_NS] 
    174                     ] 
    175          
    176         log.debug("PIP.attributeQuery response: %r", attributeResponse) 
    177          
    178         return attributeResponse 
     232                    if attribute.nameFormat == attributeFormat: 
     233                        attributeValues.append(attribute.attributeValues) 
     234         
     235        # Update the XACML request context subject with the new attributes 
     236        _subject.attributes.append(attributeValues) 
     237         
     238        # Return the attributes to the caller to comply with the interface 
     239        return attributeValues 
    179240        
Note: See TracChangeset for help on using the changeset viewer.