Package myproxy :: Package server :: Package wsgi :: Module middleware
[hide private]

Source Code for Module myproxy.server.wsgi.middleware

  1  """MyProxy WSGI middleware - places a MyProxy client instance in environ for 
  2  other downstream middleware or apps to access and use 
  3    
  4  NERC DataGrid Project 
  5  """ 
  6  __author__ = "P J Kershaw" 
  7  __date__ = "23/03/11" 
  8  __copyright__ = "(C) 2010 Science and Technology Facilities Council" 
  9  __license__ = "BSD - see LICENSE file in top-level directory" 
 10  __contact__ = "Philip.Kershaw@stfc.ac.uk" 
 11  __revision__ = "$Id: $" 
 12  import logging 
 13  log = logging.getLogger(__name__) 
 14  import httplib 
 15   
 16  from myproxy.client import MyProxyClient 
17 18 19 -class MyProxyClientMiddlewareError(Exception):
20 """Runtime error with MyProxyClientMiddleware"""
21
22 23 -class MyProxyClientMiddlewareConfigError(MyProxyClientMiddlewareError):
24 """Configuration error with MyProxyClientMiddleware"""
25
26 27 -class MyProxyClientMiddlewareBase(object):
28 """Base class for common functionality 29 30 @cvar CLIENT_ENV_KEYNAME_OPTNAME: ini file option which sets the key name 31 in the WSGI environ for referring to the MyProxy client instance shared 32 between MyProxy* middleware/apps 33 @type CLIENT_ENV_KEYNAME_OPTNAME: string 34 35 @cvar DEFAULT_CLIENT_ENV_KEYNAME: default value for key name set in the 36 WSGI environ dict which refers to the MyProxy client instance shared 37 between MyProxy* middleware/apps 38 @type DEFAULT_CLIENT_ENV_KEYNAME: string 39 40 @ivar __app: WSGI callable for next middleware or app in the WSGI stack 41 @type __app: function 42 43 @ivar __clientEnvironKeyName: key name set in the WSGI environ dict which 44 refers to the MyProxy client instance shared between MyProxy* middleware/ 45 apps 46 @type __clientEnvironKeyName: string 47 """ 48 __slots__ = ( 49 '__app', 50 '__clientEnvironKeyName', 51 ) 52 53 CLIENT_ENV_KEYNAME_OPTNAME = 'clientEnvKeyName' 54 DEFAULT_CLIENT_ENV_KEYNAME = ('myproxy.server.wsgi.middleware.' 55 'MyProxyClientMiddleware.myProxyClient') 56
57 - def __init__(self, app):
58 """Create WSGI app and MyProxy client attributes 59 @type app: function 60 @param app: WSGI callable for next middleware or app in the WSGI stack 61 """ 62 self.__app = app 63 self.__clientEnvironKeyName = None
64
65 - def _getClientEnvironKeyName(self):
66 """Get MyProxyClient environ key name 67 68 @rtype: basestring 69 @return: MyProxyClient environ key name 70 """ 71 return self.__clientEnvironKeyName
72
73 - def _setClientEnvironKeyName(self, value):
74 """Set MyProxyClient environ key name 75 76 @type value: basestring 77 @param value: MyProxyClient environ key name 78 """ 79 if not isinstance(value, basestring): 80 raise TypeError('Expecting string type for "clientEnvironKeyName"; ' 81 'got %r type' % type(value)) 82 self.__clientEnvironKeyName = value
83 84 clientEnvironKeyName = property(fget=_getClientEnvironKeyName, 85 fset=_setClientEnvironKeyName, 86 doc="key name in environ for the " 87 "MyProxyClient instance") 88 89 @property
90 - def app(self):
91 """Get Property method for reference to next WSGI application in call 92 stack 93 @rtype: function 94 @return: WSGI application 95 """ 96 return self.__app
97 98 @staticmethod
99 - def getStatusMessage(statusCode):
100 '''Make a standard status message for use with start_response 101 @type statusCode: int 102 @param statusCode: HTTP status code 103 @rtype: string 104 @return: status code with standard message 105 @raise KeyError: for invalid status code 106 ''' 107 return '%d %s' % (statusCode, httplib.responses[statusCode])
108
109 110 -class MyProxyClientMiddleware(MyProxyClientMiddlewareBase):
111 '''Create a MyProxy client and make it available to other middleware in the 112 WSGI stack 113 114 @cvar PARAM_PREFIX: prefix for ini file option names 115 @type PARAM_PREFIX: string 116 117 @cvar MYPROXY_CLIENT_PARAM_PREFIX: default value for ini file sub-prefix 118 used for MyProxyClient initialisation settings such as MyProxy server 119 hostname, CA cert directory etc. The prefix is such that option names 120 will look like this e.g. 121 <PARAM_PREFIX><MYPROXY_CLIENT_PARAM_PREFIX>hostname 122 ... 123 @type MYPROXY_CLIENT_PARAM_PREFIX: string 124 125 @ivar __myProxyClient: MyProxy client interface object to enable this 126 middleware to communicate with a backend MyProxy server using the MyProxy 127 protocol 128 @type __myProxyClient: myproxy.client.MyProxyClient 129 ''' 130 # Option prefixes 131 PARAM_PREFIX = 'myproxy.' 132 MYPROXY_CLIENT_PARAM_PREFIX = 'client.' 133 134 __slots__ = ( 135 '__myProxyClient', 136 ) 137
138 - def __init__(self, app):
139 '''Create attributes 140 141 @type app: function 142 @param app: WSGI callable for next application in stack 143 ''' 144 super(MyProxyClientMiddleware, self).__init__(app) 145 self.__myProxyClient = None
146 147 @classmethod
148 - def filter_app_factory(cls, app, global_conf, 149 prefix=PARAM_PREFIX, 150 myProxyClientPrefix=MYPROXY_CLIENT_PARAM_PREFIX, 151 **app_conf):
152 """Function following Paste filter app factory signature 153 154 @type app: callable following WSGI interface 155 @param app: next middleware/application in the chain 156 @type global_conf: dict 157 @param global_conf: PasteDeploy global configuration dictionary 158 @type prefix: basestring 159 @param prefix: prefix for configuration items 160 @type myProxyClientPrefix: ini file sub-prefix used for MyProxyClient 161 initialisation settings such as MyProxy server hostname, CA cert. 162 directory etc. 163 @param myProxyClientPrefix: basestring 164 @type app_conf: dict 165 @param app_conf: PasteDeploy application specific configuration 166 dictionary 167 168 @rtype: myproxy.server.wsgi.middleware.MyProxyClientMiddleware 169 @return: an instance of this application 170 """ 171 app = cls(app) 172 app.parseConfig(prefix=prefix, myProxyClientPrefix=myProxyClientPrefix, 173 **app_conf) 174 return app
175
176 - def parseConfig(self, 177 prefix=PARAM_PREFIX, 178 myProxyClientPrefix=MYPROXY_CLIENT_PARAM_PREFIX, 179 **app_conf):
180 """Parse dictionary of configuration items updating the relevant 181 attributes of this instance 182 183 @type prefix: basestring 184 @param prefix: prefix for configuration items 185 @type myProxyClientPrefix: basestring 186 @param myProxyClientPrefix: explicit prefix for MyProxyClient class 187 specific configuration items 188 @type app_conf: dict 189 @param app_conf: PasteDeploy application specific configuration 190 dictionary 191 """ 192 193 # Get MyProxyClient initialisation parameters 194 myProxyClientFullPrefix = prefix + myProxyClientPrefix 195 196 myProxyClientKw = dict([(k.replace(myProxyClientFullPrefix, ''), v) 197 for k,v in app_conf.items() 198 if k.startswith(myProxyClientFullPrefix)]) 199 200 self.myProxyClient = MyProxyClient(**myProxyClientKw) 201 clientEnvKeyOptName = prefix + \ 202 MyProxyClientMiddleware.CLIENT_ENV_KEYNAME_OPTNAME 203 204 self.clientEnvironKeyName = app_conf.get(clientEnvKeyOptName, 205 MyProxyClientMiddleware.DEFAULT_CLIENT_ENV_KEYNAME)
206
207 - def _getMyProxyClient(self):
208 """Get MyProxyClient instance 209 210 @rtype: myproxy.client.MyProxyClient 211 @return: MyProxyClient instance 212 """ 213 return self.__myProxyClient
214
215 - def _setMyProxyClient(self, value):
216 """Set MyProxyClient instance 217 218 @type value: myproxy.client.MyProxyClient 219 @param value: MyProxyClient instance 220 """ 221 if not isinstance(value, MyProxyClient): 222 raise TypeError('Expecting %r type for "myProxyClient" attribute ' 223 'got %r' % (MyProxyClient, type(value))) 224 self.__myProxyClient = value
225 226 myProxyClient = property(fget=_getMyProxyClient, 227 fset=_setMyProxyClient, 228 doc="MyProxyClient instance used to convert HTTPS" 229 " call into a call to a MyProxy server") 230
231 - def __call__(self, environ, start_response):
232 '''Set MyProxyClient instance and MyProxy logon method in environ 233 234 @type environ: dict 235 @param environ: WSGI environment variables dictionary 236 @type start_response: function 237 @param start_response: standard WSGI start response function 238 ''' 239 log.debug("MyProxyClientMiddleware.__call__ ...") 240 environ[self.clientEnvironKeyName] = self.myProxyClient 241 242 return self.app(environ, start_response)
243