Changeset 5491


Ignore:
Timestamp:
16/07/09 16:42:46 (10 years ago)
Author:
pjkersha
Message:

Nearing completion of IdP Validator implementation. This enables OpenID Relying Parties to whitelist OpenID Providers. Code based on ESG equivalent

Location:
TI12-security/trunk/python
Files:
7 added
2 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/utils/classfactory.py

    r5372 r5491  
    6262    which case, the class name is parsed from the moduleName last element 
    6363    @type className: str 
    64     @keyword moduleFilePath: Path to the module - if unset, assume module on  
     64    @param moduleFilePath: Path to the module - if unset, assume module on  
    6565    system path already 
    6666    @type moduleFilePath: str 
    67     @keyword classProperties: dict of properties to use when instantiating the  
     67    @param classProperties: dict of properties to use when instantiating the  
    6868    class 
    6969    @type classProperties: dict 
    70     @keyword objectType: expected type for the object to instantiate - to  
     70    @param objectType: expected type for the object to instantiate - to  
    7171    enforce use of specific interfaces  
    7272    @type objectType: object 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/relyingparty/validation.py

    r5372 r5491  
    1 """NDG Security OpenID Relying Party Provider Validator module 
     1"""NDG Security OpenID Relying Party Provider Validation module 
    22 
    33Based on the Earth System Grid IdPValidator interface for restricting 
     
    1818import os 
    1919 
     20from elementtree import ElementTree 
     21from ndg.security.common.utils import getLocalName 
     22from ndg.security.common.utils.classfactory import instantiateClass 
     23     
     24class _ConfigBase(object): 
     25    """Base class for IdP Validator and Attribute Provider configuration 
     26    """ 
     27     
     28    def __init__(self): 
     29        self._className = None 
     30        self._configFile = None 
     31        self._parameters = {} 
     32     
     33    def _set_className(self, className): 
     34        self._className = className 
     35     
     36    def _get_className(self): 
     37        return self._className 
     38     
     39    className = property(fget=_get_className, 
     40                         fset=_set_className) 
     41 
     42    def _get_configFile(self): 
     43        return self._configFile 
     44     
     45    def _set_configFile(self, configFile): 
     46        self._configFile = configFile 
     47 
     48    configFile = property(fget=_get_configFile, 
     49                          fset=_set_configFile) 
     50     
     51    def _get_parameters(self): 
     52        return self._parameters 
     53     
     54    def _set_parameters(self, parameters):     
     55        self._parameters = parameters 
     56     
     57    parameters = property(fget=_get_parameters, 
     58                          fset=_set_parameters) 
     59 
     60class IdPValidatorConfig(_ConfigBase): 
     61    """Container for IdP validator configuration""" 
     62     
     63class AttributeProviderConfig(_ConfigBase): 
     64    """Container for Attribute Provider configuration""" 
     65     
     66class XmlConfigReaderError(Exception): 
     67    """Raise from XmlConfigReader""" 
     68       
     69class XmlConfigReader(object): 
     70 
     71    def getValidators(self, filePath):   
     72        validators = None 
     73 
     74        doc = self.__parseConfigFile(filePath) 
     75        if doc is not None: 
     76            validators = extractValidatorConfigs(doc) 
     77         
     78        return validators 
     79     
     80    def getAttrProviders(self, filePath): 
     81     
     82        attrProviders = None 
     83 
     84        doc = self.__parseConfigFile(filePath) 
     85        if doc is not None: 
     86            attrProviders = self.extractAttrProviderConfigs(doc) 
     87         
     88        return attrProviders 
     89     
     90    def __parseConfigFile(self, filePath): 
     91        """Read in the XML configuration file 
     92        @type filePath: basestring 
     93        @param filePath: XML file to read 
     94        """ 
     95        elem = ElementTree.parse(source) 
     96        root = elem.getroot() 
     97         
     98        return root 
     99 
     100    def __extractValidatorConfigs(self, root): 
     101        """Parse Validator configuration from the XML config file 
     102        @type root: ElementTree.Element 
     103        @param root: root element of parsed XML config file 
     104        """ 
     105        validators = [] 
     106        validatorConfig = None 
     107        parameters = {} 
     108         
     109        for elem in root: 
     110            if getLocalName(elem).lower() == "validator":     
     111                if validatorConfig is not None: 
     112                    validatorConfig.setParameters(parameters) 
     113                    validators.append(validatorConfig) 
     114                 
     115                validatorConfig = IdPValidatorConfig() 
     116                validatorConfig.className = elem.attrib["name"] 
     117                validatorConfig.setClassName(className) 
     118             
     119            elif getLocalName(elem).lower() == "parameter": 
     120                if elem.attrib["name"] in parameters: 
     121                    raise XmlConfigReaderError('Duplicate parameter name "%s" ' 
     122                                               'found' % elem.attrib["name"]) 
     123                     
     124                parameters[elem.attrib["name"]] = elem.attrib["value"] 
     125             
     126        if validatorConfig is not None: 
     127            validatorConfig.parameters = parameters 
     128            validators.append(validatorConfig) 
     129         
     130        return validators 
     131     
     132    def __extractAttrProviderConfigs(self, root): 
     133        attrProviders = [] 
     134        validatorConfig = None 
     135        parameters = {} 
     136 
     137        for elem in root: 
     138            if getLocalName(elem).lower() == "attributeprovider": 
     139                if validatorConfig is not None: 
     140                    validatorConfig.parameters = parameters 
     141                    attrProviders.append(validatorConfig) 
     142                 
     143                validatorConfig = AttributeProviderConfig() 
     144                validatorConfig.className(elem.attrib("name")) 
     145             
     146            elif getLocalName(elem).lower() == "parameter": 
     147                if elem.attrib["name"] in parameters: 
     148                    raise XmlConfigReaderError('Duplicate parameter name "%s" ' 
     149                                               'found' % elem.attrib["name"]) 
     150             
     151                parameters[elem.attrib["name"]] = elem.attrib["value"] 
     152             
     153        if validatorConfig != None: 
     154            validatorConfig.parameters = parameters 
     155            attrProviders.append(validatorConfig) 
     156         
     157        return attrProviders 
     158 
     159 
    20160class IdPValidatorException(Exception): 
    21161    """Base class for IdPValidator exceptions""" 
    22162     
    23 class IdPInvalidException(): 
     163class IdPInvalidException(IdPValidatorException): 
    24164    """Raise from IdPValidator.validate if the IdP is not acceptable""" 
    25165 
    26 class ConfigException(): 
    27     """Problem with configuration for the validator""" 
     166class ConfigException(IdPValidatorException): 
     167    """Problem with configuration for the IdP Validator class""" 
     168  
    28169 
    29170class IdPValidator(object): 
     
    42183        @raise ConfigException:'''  
    43184        raise NotImplementedError() 
    44   
     185     
     186 
    45187class IdPValidationDriver(object): 
    46188    """Parse an XML Validation configuration containing XML Validators and  
    47189    execute these against the Provider (IdP) input"""    
    48190     
    49     @classmethod 
    50     def performIdPValidation(cls, identifier, discoveries): 
     191    def __init__(self): 
     192        self._idpValidators = None 
     193         
     194    def _get_idpValidators(self): 
     195        return self._idpValidators 
     196     
     197    def _set_idpValidators(self, idpValidators): 
     198        self._idpValidators = idpValidators 
     199         
     200    idpValidators = property(fget=_get_idpValidators, 
     201                             fset=_set_idpValidators, 
     202                             doc="list of IdP Validators") 
     203     
     204    def performIdPValidation(self, identifier, discoveries): 
     205        validators = [] 
     206         
    51207        idpConfigFilePath = os.environ("IDP_CONFIG_FILE") 
    52208        if idpConfigFilePath is None: 
     209            log.warning("IdPValidationDriver.performIdPValidation: No IdP " 
     210                        "Configuration file was set") 
    53211            return discoveries 
    54212         
    55         # TODO: refactor code copied direct from Java implementation 
    56         XmlConfigReader configReader = new XmlConfigReader() 
    57         Vector validatorConfigs = configReader.getValidators(idpConfigFile) 
    58         Vector validators = new Vector() 
    59         IdPValidator validator = None 
    60  
    61         for(int i = 0 i < validatorConfigs.size() i++) 
    62          
    63             IdPValidatorConfig idpConfig = (IdPValidatorConfig)validatorConfigs.get(i) 
    64             String className = idpConfig.getClassName() 
    65             NameValuePair[] parameters = idpConfig.getParameters() 
    66  
    67             try 
    68              
    69                 validator = (IdPValidator)Class.forName(className).newInstance() 
     213        configReader = XmlConfigReader() 
     214        validatorConfigs = configReader.getValidators(idpConfigFilePath) 
     215 
     216        for idpConfig in validatorConfigs: 
     217         
     218            className = idpConfig.className 
     219            parameters = idpConfig.parameters 
     220 
     221            try: 
     222                validator = instantiateClass(className, 
     223                                             None,  
     224                                             objectType=IdPValidator) 
    70225                validator.initialize(parameters) 
    71                 validators.add(validator) 
    72              
    73             catch(Exception e) 
    74              
    75                 log.error("Failed to initialize validator: " + e) 
    76              
    77          
    78  
    79         log.info(validators.size() + " IdPValidators initialized!") 
    80  
    81         // validate the discovered endpoints 
    82         if validators.size() > 0: 
    83          
    84             List newDiscoveries = new ArrayList() 
    85             Iterator validatorIter = validators.iterator() 
    86             while(validatorIter.hasNext()) 
    87              
    88                 validator = (IdPValidator)validatorIter.next() 
    89  
    90                 Iterator iter = discoveries.iterator() 
    91                 while(iter.hasNext()) 
    92                  
    93                     DiscoveryInformation dInfo = (DiscoveryInformation)iter.next() 
    94                     try 
     226                validators.append(validator) 
     227             
     228            except Exception, e:   
     229                log.error("Failed to initialise validator: " + e) 
     230             
     231        if self.idPValidators is not None: 
     232            validators += self.idPValidators 
     233 
     234        log.info(len(validators) + " IdPValidators initialised") 
     235 
     236        # validate the discovered endpoints 
     237        if len(validators) > 0: 
     238         
     239            newDiscoveries = [] 
     240            for validator in validators:    
     241                for discoveryInfo in discoveries: 
     242                    try:                     
     243                        validator.validate(discoveryInfo.getOPEndpoint(),  
     244                                           identifier.getIdentifier()) 
     245 
     246                        log.info("Whitelist Validator Accepting endpoint: " +  
     247                                 discoveryInfo.getOPEndpoint()) 
     248 
     249                        newDiscoveries.append(discoveryInfo) 
    95250                     
    96                         validator.validate( 
    97                             dInfo.getOPEndpoint(), identifier.getIdentifier()) 
    98  
    99                         log.info( 
    100                             "Whitelist Validator Accepting " + 
    101                             "endpoint: " + dInfo.getOPEndpoint()) 
    102  
    103                         newDiscoveries.add((Object)dInfo) 
    104                      
    105                     catch(Exception e) 
    106                      
    107                         log.info( 
    108                             "Whitelist Validator rejecting " + 
    109                             "endpoint: " + dInfo.getOPEndpoint() + 
    110                             ": " + e) 
    111                      
    112                  
    113              
    114  
    115             if newDiscoveries.size() > 0) 
    116              
     251                    except Exception, e:         
     252                        log.info("Whitelist Validator rejecting endpoint: %s: " 
     253                                 "%s", discoveryInfo.getOPEndpoint(), e) 
     254                         
     255            if len(newDiscoveries) > 0: 
    117256                discoveries = newDiscoveries 
    118                 log.info("Found " + discoveries.size() + 
    119                           " valid endpoints.") 
    120              
    121             else 
    122              
     257                log.info("Found %d valid endpoints." % len(discoveries)) 
     258            else:       
    123259                discoveries = None 
    124                 log.info("No valid endpoints were found " + 
    125                           "after validation.") 
    126                 throw new IdPInvalidException( 
    127                     "No valid endpoints were found after validation") 
    128              
    129          
    130      
    131     return discoveries 
     260                raise IdPInvalidException("No valid endpoints were found " 
     261                                          "after validation.") 
     262  
     263        return discoveries 
Note: See TracChangeset for help on using the changeset viewer.