Ignore:
Timestamp:
14/10/09 16:41:01 (10 years ago)
Author:
pjkersha
Message:

Completed unit tests for MyProxy? logon web service interface.

Location:
TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/myproxy
Files:
1 added
1 moved

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/myproxy/__init__.py

    r5839 r5843  
    1313import re 
    1414import httplib 
     15import socket 
    1516 
    16 from myproxy.client import MyProxyClient 
     17from myproxy.client import MyProxyClient, MyProxyClientError 
     18from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 
     19    NDGSecurityMiddlewareConfigError 
     20     
    1721from ndg.security.server.wsgi.authn import HTTPBasicAuthMiddleware 
     22         
     23         
     24class MyProxyClientMiddlewareConfigError(NDGSecurityMiddlewareConfigError): 
     25    """Configuration error with MyProxyClientMiddleware""" 
    1826 
    19 class MyProxyClientMiddleware(object): 
     27 
     28class MyProxyClientMiddleware(NDGSecurityMiddlewareBase): 
    2029    ''' 
    21     HTTPS proxy to a MyProxy server to enable HTTPS type calls to MyProxy 
     30    Create a MyProxy client and make it available to other middleware in the  
     31    WSGI stack 
    2232    ''' 
    2333    # Options for ini file 
    24     RE_PATH_MATCH_LIST_OPTNAME = 'rePathMatchList' 
     34    CLIENT_ENV_KEYNAME_OPTNAME = 'clientEnvKeyName' 
     35    LOGON_FUNC_ENV_KEYNAME_OPTNAME = 'logonFuncEnvKeyName'      
    2536     
     37    # Default environ key names 
     38    CLIENT_ENV_KEYNAME = ('ndg.security.server.wsgi.authn.' 
     39                          'MyProxyClientMiddleware') 
    2640    LOGON_FUNC_ENV_KEYNAME = ('ndg.security.server.wsgi.authn.' 
    2741                              'MyProxyClientMiddleware.logon') 
    28     LOGON_FUNC_ENV_KEYNAME_OPTNAME = 'logonFunc'      
     42     
     43    # Option prefixes 
    2944    PARAM_PREFIX = 'myproxy.' 
    3045    MYPROXY_CLIENT_PARAM_PREFIX = 'client.' 
    3146     
    32     def __init__(self, app, global_conf, prefix=PARAM_PREFIX, **app_conf): 
     47    def __init__(self, app, global_conf, prefix=PARAM_PREFIX,  
     48                 myProxyClientPrefix=MYPROXY_CLIENT_PARAM_PREFIX, **app_conf): 
    3349        '''''' 
    34         super(MyProxyClientMiddleware, self).__init__(app,  
    35                                                       global_conf,  
    36                                                       prefix=prefix, 
    37                                                       *app_conf) 
     50        super(MyProxyClientMiddleware, self).__init__(app, global_conf) 
    3851        self.__myProxyClient = None 
    3952 
    40         rePathMatchListParamName = prefix + \ 
    41                             MyProxyClientMiddleware.RE_PATH_MATCH_LIST_OPTNAME 
    42         rePathMatchListVal = app_conf.get(rePathMatchListParamName, '') 
    43          
    44         self.rePathMatchList = [re.compile(r)  
    45                                 for r in rePathMatchListVal.split()] 
    46  
    4753        # Get MyProxyClient initialisation parameters 
    48         myProxyClientPrefix = prefix + \ 
    49                             MyProxyClientMiddleware.MYPROXY_CLIENT_PARAM_PREFIX 
     54        myProxyClientFullPrefix = prefix + myProxyClientPrefix 
    5055                             
    51         myProxyClientKw = dict([(k.replace(myProxyClientPrefix, ''), v)  
     56        myProxyClientKw = dict([(k.replace(myProxyClientFullPrefix, ''), v)  
    5257                                 for k,v in app_conf.items()  
    53                                  if k.startswith(myProxyClientPrefix)]) 
     58                                 if k.startswith(myProxyClientFullPrefix)]) 
    5459         
    5560        self.myProxyClient = MyProxyClient(**myProxyClientKw) 
    56         paramName = prefix + \ 
     61        clientEnvKeyOptName = prefix + \ 
     62                            MyProxyClientMiddleware.CLIENT_ENV_KEYNAME_OPTNAME 
     63                     
     64        self.clientEnvironKeyName = app_conf.get(clientEnvKeyOptName, 
     65                                MyProxyClientMiddleware.CLIENT_ENV_KEYNAME) 
     66                     
     67        logonFuncEnvKeyOptName = prefix + \ 
    5768                    MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME_OPTNAME 
    58                      
    59         self.logonFuncEnvironKeyName = local_conf.get(paramName, 
     69 
     70        self.logonFuncEnvironKeyName = app_conf.get(logonFuncEnvKeyOptName, 
    6071                                MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME) 
     72 
     73    def _getClientEnvironKeyName(self): 
     74        return self.__clientEnvironKeyName 
     75 
     76    def _setClientEnvironKeyName(self, value): 
     77        if not isinstance(value, basestring): 
     78            raise TypeError('Expecting string type for "clientEnvironKeyName"; ' 
     79                            'got %r type' % type(value)) 
     80        self.__clientEnvironKeyName = value 
     81 
     82    clientEnvironKeyName = property(fget=_getClientEnvironKeyName,  
     83                                    fset=_setClientEnvironKeyName,  
     84                                    doc="key name in environ for the " 
     85                                        "MyProxyClient instance")     
    6186 
    6287    def _getLogonFuncEnvironKeyName(self): 
     
    7398                                       fset=_setLogonFuncEnvironKeyName,  
    7499                                       doc="key name in environ for the " 
    75                                            "custom authentication function " 
    76                                            "used by this class") 
     100                                           "MyProxy logon function") 
     101     
    77102    def _getMyProxyClient(self): 
    78103        return self.__myProxyClient 
     
    91116    @NDGSecurityMiddlewareBase.initCall 
    92117    def __call__(self, environ, start_response): 
    93         '''Intercept MyProxy call and relay to MyProxy server 
     118        '''Set MyProxyClient instance and MyProxy logon method in environ 
    94119         
    95120        @type environ: dict 
     
    99124        ''' 
    100125        log.debug("MyProxyClientMiddleware.__call__ ...") 
    101         environ[self.logonFuncEnvironKeyName] = self.myProxyLogonFunc 
     126        environ[self.clientEnvironKeyName] = self.myProxyClient 
     127        environ[self.logonFuncEnvironKeyName] = self.myProxyLogon 
    102128         
    103 #        if not self._pathMatch(): 
    104 #            return self._app(environ, start_response) 
    105 #        else: 
    106 #            try: 
    107 #                # TODO: get username/passphrase from upstream HTTP Basic Auth 
    108 #                # middleware 
    109 #                credentials = self.myProxyClient.logon(username, passphrase) 
    110 #            except Exception, e: 
    111 #                log.error(e) 
    112 #                 
    113 #                # TODO: fit to appropriate HTTP error code 
    114 #                raise 
    115 #             
    116 #            response = '\n'.join(credentials) 
    117 #            start_response(MyProxyClientMiddleware.getStatusMessage(httplib.OK), 
    118 #                           [('Content-length', str(len(response))), 
    119 #                            ('Content-type', 'plain/text')]) 
    120 #            return [response] 
    121          
    122     def _pathMatch(self): 
    123         """Apply a list of regular expression matching patterns to the contents 
    124         of environ['PATH_INFO'], if any match, return True.  This method is 
    125         used to determine whether to apply SSL client authentication 
    126         """ 
    127         path = self.pathInfo 
    128         for regEx in self.rePathMatchList: 
    129             if regEx.match(path): 
    130                 return True 
    131              
    132         return False    
     129        return self._app(environ, start_response) 
    133130     
    134131    @property 
    135     def myProxyLogonFunc(self): 
     132    def myProxyLogon(self): 
    136133        """Return the MyProxy logon method wrapped as a HTTP Basic Auth  
    137134        authenticate interface function 
    138135        """ 
    139         def HTTPBasicAuthFunc(environ, username, password): 
    140             """Wrap MyProxy logon method as HTTPBasicAuthMiddleware  
    141             authenticate function""" 
    142             return self.myProxyClient.logon(environ, username, password) 
     136        def _myProxylogon(environ, start_response, username, password): 
     137            """Wrap MyProxy logon method as a WSGI app 
     138            """ 
     139            try: 
     140                credentials = self.myProxyClient.logon(username, password) 
     141                status = self.getStatusMessage(httplib.OK) 
     142                response = '\n'.join(credentials) 
     143                 
     144            except MyProxyClientError, e: 
     145                status = self.getStatusMessage(httplib.UNAUTHORIZED) 
     146                response = str(e) 
     147             
     148            except socket.error, e: 
     149                raise MyProxyClientMiddlewareConfigError("Socket error " 
     150                                        "with MyProxy server %r: %s" %  
     151                                        (self.myProxyClient.hostname, e)) 
     152             
     153            start_response(status, 
     154                           [('Content-length', str(len(response))), 
     155                            ('Content-type', 'text/plain')]) 
     156            return [response] 
    143157         
    144         return HTTPBasicAuthFunc 
     158        return _myProxylogon 
    145159         
    146160         
     161class MyProxyLogonMiddlewareConfigError(NDGSecurityMiddlewareConfigError): 
     162    """Configuration error with MyProxyLogonMiddleware""" 
     163     
     164     
    147165class MyProxyLogonMiddleware(NDGSecurityMiddlewareBase): 
    148     """HTTP Basic Auth interface to MyProxy logon""" 
     166    """HTTP Basic Auth interface to MyProxy logon.  This interfaces creates a 
     167    MyProxy client instance and HTTP Basic Auth based web service interface 
     168    for MyProxy logon calls.  This WSGI must be run over HTTPS to ensure 
     169    confidentiality of username/passphrase credentials 
     170    """ 
    149171    PARAM_PREFIX = 'myproxy.logon.' 
    150172     
    151     def __init__(self, app, app_conf, prefix=PARAM_PREFIX, **local_conf): 
    152         app = HTTPBasicAuthMiddleware(app, app_conf, **local_conf) 
    153         app = MyProxyClientMiddleware(app, app_conf, **local_conf) 
     173    def __init__(self, app, global_conf, prefix=PARAM_PREFIX, **app_conf):         
     174         
     175        authnFuncEnvKeyNameOptName = HTTPBasicAuthMiddleware.PARAM_PREFIX + \ 
     176                        HTTPBasicAuthMiddleware.AUTHN_FUNC_ENV_KEYNAME_OPTNAME 
     177                         
     178        if authnFuncEnvKeyNameOptName in app_conf: 
     179            raise MyProxyLogonMiddlewareConfigError("Found %r option name in " 
     180                "application configuration settings.  Use %r instead" % 
     181                (authnFuncEnvKeyNameOptName,  
     182                 MyProxyClientMiddleware.PARAM_PREFIX + \ 
     183                 MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME_OPTNAME)) 
     184         
     185        httpBasicAuthApp = HTTPBasicAuthMiddleware(app, app_conf, **app_conf) 
     186        app = MyProxyClientMiddleware(httpBasicAuthApp, app_conf, **app_conf) 
     187         
     188        # Set HTTP Basic Auth to use the MyProxy client logon for its 
     189        # authentication method 
     190        httpBasicAuthApp.authnFuncEnvironKeyName = app.logonFuncEnvironKeyName 
     191         
     192        super(MyProxyLogonMiddleware, self).__init__(app, global_conf,  
     193                                                     prefix=prefix, **app_conf) 
Note: See TracChangeset for help on using the changeset viewer.