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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/myproxy/__init__.py@5843
Revision 5843, 8.1 KB checked in by pjkersha, 10 years ago (diff)

Completed unit tests for MyProxy? logon web service interface.

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
15import socket
16
17from myproxy.client import MyProxyClient, MyProxyClientError
18from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \
19    NDGSecurityMiddlewareConfigError
20   
21from ndg.security.server.wsgi.authn import HTTPBasicAuthMiddleware
22       
23       
24class MyProxyClientMiddlewareConfigError(NDGSecurityMiddlewareConfigError):
25    """Configuration error with MyProxyClientMiddleware"""
26
27
28class MyProxyClientMiddleware(NDGSecurityMiddlewareBase):
29    '''
30    Create a MyProxy client and make it available to other middleware in the
31    WSGI stack
32    '''
33    # Options for ini file
34    CLIENT_ENV_KEYNAME_OPTNAME = 'clientEnvKeyName'
35    LOGON_FUNC_ENV_KEYNAME_OPTNAME = 'logonFuncEnvKeyName'     
36   
37    # Default environ key names
38    CLIENT_ENV_KEYNAME = ('ndg.security.server.wsgi.authn.'
39                          'MyProxyClientMiddleware')
40    LOGON_FUNC_ENV_KEYNAME = ('ndg.security.server.wsgi.authn.'
41                              'MyProxyClientMiddleware.logon')
42   
43    # Option prefixes
44    PARAM_PREFIX = 'myproxy.'
45    MYPROXY_CLIENT_PARAM_PREFIX = 'client.'
46   
47    def __init__(self, app, global_conf, prefix=PARAM_PREFIX, 
48                 myProxyClientPrefix=MYPROXY_CLIENT_PARAM_PREFIX, **app_conf):
49        ''''''
50        super(MyProxyClientMiddleware, self).__init__(app, global_conf)
51        self.__myProxyClient = None
52
53        # Get MyProxyClient initialisation parameters
54        myProxyClientFullPrefix = prefix + myProxyClientPrefix
55                           
56        myProxyClientKw = dict([(k.replace(myProxyClientFullPrefix, ''), v) 
57                                 for k,v in app_conf.items() 
58                                 if k.startswith(myProxyClientFullPrefix)])
59       
60        self.myProxyClient = MyProxyClient(**myProxyClientKw)
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 + \
68                    MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME_OPTNAME
69
70        self.logonFuncEnvironKeyName = app_conf.get(logonFuncEnvKeyOptName,
71                                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")   
86
87    def _getLogonFuncEnvironKeyName(self):
88        return self.__logonFuncEnvironKeyName
89
90    def _setLogonFuncEnvironKeyName(self, value):
91        if not isinstance(value, basestring):
92            raise TypeError('Expecting string type for '
93                            '"logonFuncEnvironKeyName"; got %r type' % 
94                            type(value))
95        self.__logonFuncEnvironKeyName = value
96
97    logonFuncEnvironKeyName = property(fget=_getLogonFuncEnvironKeyName, 
98                                       fset=_setLogonFuncEnvironKeyName, 
99                                       doc="key name in environ for the "
100                                           "MyProxy logon function")
101   
102    def _getMyProxyClient(self):
103        return self.__myProxyClient
104
105    def _setMyProxyClient(self, value):
106        if not isinstance(value, MyProxyClient):
107            raise TypeError('Expecting %r type for "myProxyClient" attribute '
108                            'got %r' % (MyProxyClient, type(value)))
109        self.__myProxyClient = value
110       
111    myProxyClient = property(fget=_getMyProxyClient,
112                             fset=_setMyProxyClient, 
113                             doc="MyProxyClient instance used to convert HTTPS"
114                                 " call into a call to a MyProxy server")
115
116    @NDGSecurityMiddlewareBase.initCall
117    def __call__(self, environ, start_response):
118        '''Set MyProxyClient instance and MyProxy logon method in environ
119       
120        @type environ: dict
121        @param environ: WSGI environment variables dictionary
122        @type start_response: function
123        @param start_response: standard WSGI start response function
124        '''
125        log.debug("MyProxyClientMiddleware.__call__ ...")
126        environ[self.clientEnvironKeyName] = self.myProxyClient
127        environ[self.logonFuncEnvironKeyName] = self.myProxyLogon
128       
129        return self._app(environ, start_response)
130   
131    @property
132    def myProxyLogon(self):
133        """Return the MyProxy logon method wrapped as a HTTP Basic Auth
134        authenticate interface function
135        """
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]
157       
158        return _myProxylogon
159       
160       
161class MyProxyLogonMiddlewareConfigError(NDGSecurityMiddlewareConfigError):
162    """Configuration error with MyProxyLogonMiddleware"""
163   
164   
165class MyProxyLogonMiddleware(NDGSecurityMiddlewareBase):
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    """
171    PARAM_PREFIX = 'myproxy.logon.'
172   
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 TracBrowser for help on using the repository browser.