source: TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/myproxy.py @ 5839

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/myproxy.py@5839
Revision 5839, 6.2 KB checked in by pjkersha, 10 years ago (diff)
Line 
1"""Functionality for WSGI HTTPS proxy to MyProxy server.
2 
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "13/01/09"
7__copyright__ = "(C) 2009 Science and Technology Facilities Council"
8__license__ = "BSD - see LICENSE file in top-level directory"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__revision__ = "$Id$"
11import logging
12log = logging.getLogger(__name__)
13import re
14import httplib
15
16from myproxy.client import MyProxyClient
17from ndg.security.server.wsgi.authn import HTTPBasicAuthMiddleware
18
19class MyProxyClientMiddleware(object):
20    '''
21    HTTPS proxy to a MyProxy server to enable HTTPS type calls to MyProxy
22    '''
23    # Options for ini file
24    RE_PATH_MATCH_LIST_OPTNAME = 'rePathMatchList'
25   
26    LOGON_FUNC_ENV_KEYNAME = ('ndg.security.server.wsgi.authn.'
27                              'MyProxyClientMiddleware.logon')
28    LOGON_FUNC_ENV_KEYNAME_OPTNAME = 'logonFunc'     
29    PARAM_PREFIX = 'myproxy.'
30    MYPROXY_CLIENT_PARAM_PREFIX = 'client.'
31   
32    def __init__(self, app, global_conf, prefix=PARAM_PREFIX, **app_conf):
33        ''''''
34        super(MyProxyClientMiddleware, self).__init__(app, 
35                                                      global_conf, 
36                                                      prefix=prefix,
37                                                      *app_conf)
38        self.__myProxyClient = None
39
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
47        # Get MyProxyClient initialisation parameters
48        myProxyClientPrefix = prefix + \
49                            MyProxyClientMiddleware.MYPROXY_CLIENT_PARAM_PREFIX
50                           
51        myProxyClientKw = dict([(k.replace(myProxyClientPrefix, ''), v) 
52                                 for k,v in app_conf.items() 
53                                 if k.startswith(myProxyClientPrefix)])
54       
55        self.myProxyClient = MyProxyClient(**myProxyClientKw)
56        paramName = prefix + \
57                    MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME_OPTNAME
58                   
59        self.logonFuncEnvironKeyName = local_conf.get(paramName,
60                                MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME)
61
62    def _getLogonFuncEnvironKeyName(self):
63        return self.__logonFuncEnvironKeyName
64
65    def _setLogonFuncEnvironKeyName(self, value):
66        if not isinstance(value, basestring):
67            raise TypeError('Expecting string type for '
68                            '"logonFuncEnvironKeyName"; got %r type' % 
69                            type(value))
70        self.__logonFuncEnvironKeyName = value
71
72    logonFuncEnvironKeyName = property(fget=_getLogonFuncEnvironKeyName, 
73                                       fset=_setLogonFuncEnvironKeyName, 
74                                       doc="key name in environ for the "
75                                           "custom authentication function "
76                                           "used by this class")
77    def _getMyProxyClient(self):
78        return self.__myProxyClient
79
80    def _setMyProxyClient(self, value):
81        if not isinstance(value, MyProxyClient):
82            raise TypeError('Expecting %r type for "myProxyClient" attribute '
83                            'got %r' % (MyProxyClient, type(value)))
84        self.__myProxyClient = value
85       
86    myProxyClient = property(fget=_getMyProxyClient,
87                             fset=_setMyProxyClient, 
88                             doc="MyProxyClient instance used to convert HTTPS"
89                                 " call into a call to a MyProxy server")
90
91    @NDGSecurityMiddlewareBase.initCall
92    def __call__(self, environ, start_response):
93        '''Intercept MyProxy call and relay to MyProxy server
94       
95        @type environ: dict
96        @param environ: WSGI environment variables dictionary
97        @type start_response: function
98        @param start_response: standard WSGI start response function
99        '''
100        log.debug("MyProxyClientMiddleware.__call__ ...")
101        environ[self.logonFuncEnvironKeyName] = self.myProxyLogonFunc
102       
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   
133   
134    @property
135    def myProxyLogonFunc(self):
136        """Return the MyProxy logon method wrapped as a HTTP Basic Auth
137        authenticate interface function
138        """
139        def HTTPBasicAuthFunc(environ, username, password):
140            """Wrap MyProxy logon method as HTTPBasicAuthMiddleware
141            authenticate function"""
142            return self.myProxyClient.logon(environ, username, password)
143       
144        return HTTPBasicAuthFunc
145       
146       
147class MyProxyLogonMiddleware(NDGSecurityMiddlewareBase):
148    """HTTP Basic Auth interface to MyProxy logon"""
149    PARAM_PREFIX = 'myproxy.logon.'
150   
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)
Note: See TracBrowser for help on using the repository browser.