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

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

Re-release as rc1

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.