Changeset 6938 for TI12-security/trunk/MyProxyLogonWebService
- Timestamp:
- 07/06/10 11:09:11 (11 years ago)
- Location:
- TI12-security/trunk/MyProxyLogonWebService
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/MyProxyLogonWebService/myproxy/server/test/myproxywsgi.ini
r6937 r6938 23 23 myproxy.logonFuncEnvKeyName = MYPROXY_LOGON_FUNC 24 24 myproxy.rePathMatchList = /logon 25 myproxy.getTrustRoots.path = /get-trustroots 25 26 #myproxy.client.hostname = localhost 26 27 myproxy.client.hostname = gabriel.badc.rl.ac.uk -
TI12-security/trunk/MyProxyLogonWebService/myproxy/server/test/test_myproxywsgi.py
r6897 r6938 55 55 self.assert_(response) 56 56 57 58 class MyProxyLogonAppTestCase(unittest.TestCase): 57 58 class MyProxyPasteDeployTestCaseBase(unittest.TestCase): 59 """Base class for common Paste Deploy related set-up""" 59 60 INI_FILENAME = 'myproxywsgi.ini' 60 61 THIS_DIR = os.path.dirname(__file__) … … 64 65 def __init__(self, *args, **kwargs): 65 66 here_dir = os.path.dirname(os.path.abspath(__file__)) 66 wsgiapp = loadapp('config:' + MyProxyLogonAppTestCase.INI_FILENAME,67 wsgiapp = loadapp('config:' + self.__class__.INI_FILENAME, 67 68 relative_to=here_dir) 68 69 self.app = paste.fixture.TestApp(wsgiapp) 69 70 70 self.cfg = SafeConfigParser({'here': MyProxyLogonAppTestCase.THIS_DIR})71 self.cfg = SafeConfigParser({'here': self.__class__.THIS_DIR}) 71 72 self.cfg.optionxform = str 72 self.cfg.read( MyProxyLogonAppTestCase.CONFIG_FILEPATH)73 self.cfg.read(self.__class__.CONFIG_FILEPATH) 73 74 74 unittest.TestCase.__init__(self, *args, **kwargs) 75 unittest.TestCase.__init__(self, *args, **kwargs) 76 77 78 class MyProxyLogonAppTestCase(MyProxyPasteDeployTestCaseBase): 79 """Test HTTP MyProxy logon interface""" 75 80 76 81 def _createRequestCreds(self): … … 153 158 self.assert_(response) 154 159 160 161 class MyProxyGetTrustRootsMiddlewareTestCase(MyProxyPasteDeployTestCaseBase): 162 """Test HTTP MyProxy get trust roots interface""" 163 164 def test01(self): 165 response = self.app.get('/get-trustroots', status=200) 166 self.assert_(response) 167 print response 168 155 169 if __name__ == "__main__": 156 170 unittest.main() -
TI12-security/trunk/MyProxyLogonWebService/myproxy/server/wsgi/app.py
r6897 r6938 10 10 __revision__ = "$Id: $" 11 11 from myproxy.server.wsgi.httpbasicauth import HttpBasicAuthMiddleware 12 from myproxy.server.wsgi.middleware import MyProxyClientMiddleware 12 from myproxy.server.wsgi.middleware import (MyProxyClientMiddleware, 13 MyProxyGetTrustRootsMiddleware) 13 14 14 15 15 class MyProxyLogonMiddlewareConfigError(Exception): 16 """Configuration error with MyProxyLogonMiddleware""" 17 18 19 class MyProxyLogonApp(object): 20 """HTTP interface to MyProxy logon. This interfaces creates a MyProxy 21 client instance with a HTTP Basic Auth based web service interface 22 to pass username/passphrase for MyProxy logon calls. 16 class MyProxyApp(object): 17 """HTTP interface to MyProxy logon and get trsut roots. This interfaces 18 creates a MyProxy client instance with a HTTP Basic Auth based web service 19 interface to pass username/passphrase for MyProxy logon calls. 23 20 24 21 This WSGI must be run over HTTPS to ensure confidentiality of … … 27 24 Apache SSL configuration. 28 25 """ 29 PARAM_PREFIX = 'myproxy.logon.' 26 PARAM_PREFIX = 'myproxy.' 27 GET_TRUSTROOTS_PARAM_PREFIX = 'getTrustRoots.' 30 28 HTTPBASICAUTH_REALM_OPTNAME = 'httpbasicauth.realm' 31 29 … … 42 40 dictionary 43 41 """ 44 logonFuncEnvKeyNameOptName = prefix + \45 MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME_OPTNAME42 # This app 43 app = cls() 46 44 47 logonFuncEnvironKeyName = app_conf.get(logonFuncEnvKeyNameOptName, 48 MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME) 49 50 app = MyProxyLogonApp() 45 # HTTP Basic auth middleware - a container for MyProxy logon 51 46 httpBasicAuthMWare = HttpBasicAuthMiddleware.filter_app_factory(app, 52 47 global_conf, … … 54 49 **app_conf) 55 50 56 app = MyProxyClientMiddleware.filter_app_factory(httpBasicAuthMWare, 51 # MyProxy get trust roots middleware 52 getTrustRootsPrefix = prefix + cls.GET_TRUSTROOTS_PARAM_PREFIX 53 getTrustRootsMWare = MyProxyGetTrustRootsMiddleware.filter_app_factory( 54 httpBasicAuthMWare, 55 global_conf, 56 prefix=getTrustRootsPrefix) 57 58 # Middleware to hold a MyProxy client and expose interface in environ 59 app = MyProxyClientMiddleware.filter_app_factory(getTrustRootsMWare, 57 60 global_conf, 58 61 prefix=prefix, -
TI12-security/trunk/MyProxyLogonWebService/myproxy/server/wsgi/middleware.py
r6937 r6938 32 32 33 33 34 class MyProxyClientMiddleware(object): 34 class MyProxyClientMiddlewareBase(object): 35 """Base class for common functionality""" 36 __slots__ = ('__app', '__clientEnvironKeyName',) 37 38 CLIENT_ENV_KEYNAME_OPTNAME = 'clientEnvKeyName' 39 DEFAULT_CLIENT_ENV_KEYNAME = ('myproxy.server.wsgi.middleware.' 40 'MyProxyClientMiddleware.myProxyClient') 41 42 def __init__(self, app): 43 self.__app = app 44 self.__clientEnvironKeyName = None 45 46 def _getClientEnvironKeyName(self): 47 """Get MyProxyClient environ key name 48 49 @rtype: basestring 50 @return: MyProxyClient environ key name 51 """ 52 return self.__clientEnvironKeyName 53 54 def _setClientEnvironKeyName(self, value): 55 """Set MyProxyClient environ key name 56 57 @type value: basestring 58 @param value: MyProxyClient environ key name 59 """ 60 if not isinstance(value, basestring): 61 raise TypeError('Expecting string type for "clientEnvironKeyName"; ' 62 'got %r type' % type(value)) 63 self.__clientEnvironKeyName = value 64 65 clientEnvironKeyName = property(fget=_getClientEnvironKeyName, 66 fset=_setClientEnvironKeyName, 67 doc="key name in environ for the " 68 "MyProxyClient instance") 69 70 @property 71 def app(self): 72 """Get Property method for reference to next WSGI application in call 73 stack 74 @rtype: function 75 @return: WSGI application 76 """ 77 return self.__app 78 79 @staticmethod 80 def getStatusMessage(statusCode): 81 '''Make a standard status message for use with start_response 82 @type statusCode: int 83 @param statusCode: HTTP status code 84 @rtype: str 85 @return: status code with standard message 86 @raise KeyError: for invalid status code 87 ''' 88 return '%d %s' % (statusCode, httplib.responses[statusCode]) 89 90 91 class MyProxyClientMiddleware(MyProxyClientMiddlewareBase): 35 92 ''' 36 93 Create a MyProxy client and make it available to other middleware in the … … 38 95 ''' 39 96 # Options for ini file 40 CLIENT_ENV_KEYNAME_OPTNAME = 'clientEnvKeyName'41 97 LOGON_FUNC_ENV_KEYNAME_OPTNAME = 'logonFuncEnvKeyName' 42 98 43 99 # Default environ key names 44 CLIENT_ENV_KEYNAME = ('myproxy.server.wsgi.middleware.'45 'MyProxyClientMiddleware.myProxyClient')46 100 LOGON_FUNC_ENV_KEYNAME = ('myproxy.server.wsgi.middleware.' 47 101 'MyProxyClientMiddleware.logon') 48 102 49 CERTIFICATE_REQUST_POST_PARAM_KEYNAME = 'certificate_request' 50 GET_TRUSTROOTS_PARAM_KEYNAME = 'get_trustroots' 51 GET_TRUSTROOTS_TRUE_STR = '1' 103 CERT_REQ_POST_PARAM_KEYNAME = 'certificate_request' 52 104 53 105 # Option prefixes … … 59 111 '__myProxyClient', 60 112 '__logonFuncEnvironKeyName', 61 '__clientEnvironKeyName'62 113 ) 63 114 64 115 def __init__(self, app): 65 '''''' 66 self.__app = app 116 '''Create attributes 117 118 @type app: function 119 @param app: WSGI callable for next application in stack 120 ''' 121 super(MyProxyClientMiddleware, self).__init__(app) 67 122 self.__myProxyClient = None 68 123 self.__logonFuncEnvironKeyName = None 69 self.__clientEnvironKeyName = None70 124 71 125 @classmethod … … 118 172 119 173 self.clientEnvironKeyName = app_conf.get(clientEnvKeyOptName, 120 MyProxyClientMiddleware.CLIENT_ENV_KEYNAME)174 MyProxyClientMiddleware.DEFAULT_CLIENT_ENV_KEYNAME) 121 175 122 176 logonFuncEnvKeyOptName = prefix + \ … … 124 178 125 179 self.logonFuncEnvironKeyName = app_conf.get(logonFuncEnvKeyOptName, 126 MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME) 127 128 def _getClientEnvironKeyName(self): 129 return self.__clientEnvironKeyName 130 131 def _setClientEnvironKeyName(self, value): 132 if not isinstance(value, basestring): 133 raise TypeError('Expecting string type for "clientEnvironKeyName"; ' 134 'got %r type' % type(value)) 135 self.__clientEnvironKeyName = value 136 137 clientEnvironKeyName = property(fget=_getClientEnvironKeyName, 138 fset=_setClientEnvironKeyName, 139 doc="key name in environ for the " 140 "MyProxyClient instance") 180 MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME) 141 181 142 182 def _getLogonFuncEnvironKeyName(self): 183 """Get MyProxyClient logon function environ key name 184 185 @rtype: basestring 186 @return: MyProxyClient logon function environ key name 187 """ 143 188 return self.__logonFuncEnvironKeyName 144 189 145 190 def _setLogonFuncEnvironKeyName(self, value): 191 """Set MyProxyClient environ key name 192 193 @type value: basestring 194 @param value: MyProxyClient logon function environ key name 195 """ 146 196 if not isinstance(value, basestring): 147 197 raise TypeError('Expecting string type for ' … … 156 206 157 207 def _getMyProxyClient(self): 208 """Get MyProxyClient instance 209 210 @rtype: myproxy.client.MyProxyClient 211 @return: MyProxyClient instance 212 """ 158 213 return self.__myProxyClient 159 214 160 215 def _setMyProxyClient(self, value): 216 """Set MyProxyClient instance 217 218 @type value: myproxy.client.MyProxyClient 219 @param value: MyProxyClient instance 220 """ 161 221 if not isinstance(value, MyProxyClient): 162 222 raise TypeError('Expecting %r type for "myProxyClient" attribute ' … … 181 241 environ[self.logonFuncEnvironKeyName] = self.myProxyLogon 182 242 183 return self. __app(environ, start_response)243 return self.app(environ, start_response) 184 244 185 245 @property … … 200 260 201 261 request = Request(environ) 202 certReqKey = self.__class__.CERT IFICATE_REQUST_POST_PARAM_KEYNAME262 certReqKey = self.__class__.CERT_REQ_POST_PARAM_KEYNAME 203 263 pemCertReq = request.POST.get(certReqKey) 204 264 if pemCertReq is None: … … 208 268 httplib.BAD_REQUEST) 209 269 log.debug("cert req = %r", pemCertReq) 210 getTrustRootsKey = self.__class__.GET_TRUSTROOTS_PARAM_KEYNAME211 getTrustRoots = (request.postvars.get(getTrustRootsKey) ==212 self.__class__.GET_TRUSTROOTS_TRUE_STR)213 270 214 271 # Expecting PEM encoded request … … 228 285 229 286 try: 230 if getTrustRoots:231 trustRootsDict = self.myProxyClient.getTrustRoots()232 233 trustRoots = '\n'.join([234 "FILEDATA_%s=%s" % (fileName, fileContents)235 for fileName, fileContents in trustRootsDict.items()236 ])237 else:238 trustRoots = ''239 240 287 credentials = self.myProxyClient.logon(username, 241 288 password, … … 243 290 status = self.getStatusMessage(httplib.OK) 244 291 response = '\n'.join(credentials) 245 response += '\n'+trustRoots246 292 247 293 start_response(status, … … 264 310 raise # Trigger 500 Internal Server Error 265 311 266 267 268 312 return _myProxylogon 269 270 @staticmethod 271 def getStatusMessage(statusCode): 272 '''Make a standard status message for use with start_response 273 @type statusCode: int 274 @param statusCode: HTTP status code 275 @rtype: str 276 @return: status code with standard message 277 @raise KeyError: for invalid status code 313 314 315 class MyProxyGetTrustRootsMiddlewareError(Exception): 316 """MyProxyGetTrustRootsMiddleware exception class""" 317 318 319 class MyProxyGetTrustRootsMiddleware(MyProxyClientMiddlewareBase): 320 """HTTP client interface for MyProxy server Get Trust Roots method 321 322 It relies on a myproxy.server.wsgi.MyProxyClientMiddleware instance called 323 upstream in the WSGI stack to set up a MyProxyClient instance and make it 324 available in the environ to call its getTrustRoots method. 325 """ 326 327 # Options for ini file 328 CLIENT_ENV_KEYNAME_OPTNAME = \ 329 MyProxyClientMiddleware.CLIENT_ENV_KEYNAME_OPTNAME 330 331 PATH_OPTNAME = 'path' 332 333 DEFAULT_CLIENT_ENV_KEYNAME = \ 334 MyProxyClientMiddleware.DEFAULT_CLIENT_ENV_KEYNAME 335 336 DEFAULT_PATH = '/myproxy/get-trustroots' 337 338 # Option prefixes 339 PARAM_PREFIX = 'myproxy.getTrustRoots.' 340 341 __slots__ = ( 342 '__path', 343 ) 344 345 def __init__(self, app): 346 '''Create attributes 347 348 @type app: function 349 @param app: WSGI callable for next application in stack 278 350 ''' 279 return '%d %s' % (statusCode, httplib.responses[statusCode]) 280 351 super(MyProxyGetTrustRootsMiddleware, self).__init__(app) 352 self.__path = None 353 354 @classmethod 355 def filter_app_factory(cls, app, global_conf, prefix=PARAM_PREFIX, 356 **app_conf): 357 """Function following Paste filter app factory signature 358 359 @type app: callable following WSGI interface 360 @param app: next middleware/application in the chain 361 @type global_conf: dict 362 @param global_conf: PasteDeploy global configuration dictionary 363 @type prefix: basestring 364 @param prefix: prefix for configuration items 365 @type app_conf: dict 366 @param app_conf: PasteDeploy application specific configuration 367 dictionary 368 """ 369 app = cls(app) 370 app.parseConfig(prefix=prefix, **app_conf) 371 return app 372 373 def parseConfig(self, prefix=PARAM_PREFIX, **app_conf): 374 """Parse dictionary of configuration items updating the relevant 375 attributes of this instance 376 377 @type prefix: basestring 378 @param prefix: prefix for configuration items 379 @type app_conf: dict 380 @param app_conf: PasteDeploy application specific configuration 381 dictionary 382 """ 383 clientEnvKeyOptName = prefix + self.__class__.CLIENT_ENV_KEYNAME_OPTNAME 384 385 self.clientEnvironKeyName = app_conf.get(clientEnvKeyOptName, 386 self.__class__.DEFAULT_CLIENT_ENV_KEYNAME) 387 388 pathOptName = prefix + self.__class__.PATH_OPTNAME 389 self.path = app_conf.get(pathOptName, self.__class__.DEFAULT_PATH) 390 391 def _getPath(self): 392 """Get URI path for get trust roots method 393 @rtype: basestring 394 @return: path for get trust roots method 395 """ 396 return self.__path 397 398 def _setPath(self, value): 399 """Set URI path for get trust roots method 400 @type value: basestring 401 @param value: path for get trust roots method 402 """ 403 if not isinstance(value, basestring): 404 raise TypeError('Expecting string type for "path"; got %r' % 405 type(value)) 406 407 self.__path = value 408 409 path = property(fget=_getPath, fset=_setPath, 410 doc="environ SCRIPT_NAME path which invokes the " 411 "getTrustRoots method on this middleware") 412 413 def __call__(self, environ, start_response): 414 '''Get MyProxyClient instance from environ and call MyProxy 415 getTrustRoots method returning the response. 416 417 MyProxyClientMiddleware must be in place upstream in the WSGI stack 418 419 @type environ: dict 420 @param environ: WSGI environment variables dictionary 421 @type start_response: function 422 @param start_response: standard WSGI start response function 423 ''' 424 # Skip if path doesn't match 425 if environ['PATH_INFO'] != self.path: 426 return self.app(environ, start_response) 427 428 log.debug("MyProxyGetTrustRootsMiddleware.__call__ ...") 429 430 # Check method 431 requestMethod = environ.get('REQUEST_METHOD') 432 if requestMethod != 'GET': 433 response = "HTTP Request method not recognised" 434 log.error("HTTP Request method %r not recognised", requestMethod) 435 status = self.__class__.getStatusMessage(httplib.BAD_REQUEST) 436 start_response(status, 437 [('Content-type', 'text/plain'), 438 ('Content-length', str(len(response)))]) 439 return [response] 440 441 myProxyClient = environ[self.clientEnvironKeyName] 442 if not isinstance(myProxyClient, MyProxyClient): 443 raise TypeError('Expecting %r type for "myProxyClient" environ[%r] ' 444 'attribute got %r' % (MyProxyClient, 445 self.clientEnvironKeyName, 446 type(myProxyClient))) 447 448 response = self._getTrustRoots(myProxyClient) 449 start_response(self.getStatusMessage(httplib.OK), 450 [('Content-length', str(len(response))), 451 ('Content-type', 'text/plain')]) 452 453 return [response] 454 455 @classmethod 456 def _getTrustRoots(cls, myProxyClient): 457 """Call getTrustRoots method on MyProxyClient instance retrieved from 458 environ and format and return a HTTP response 459 460 @type myProxyClient: myproxy.client.MyProxyClient 461 @param myProxyClient: MyProxyClient instance on which to call 462 getTrustRoots method 463 464 @rtype: basestring 465 @return: trust roots formatted as a HTTP response 466 """ 467 try: 468 trustRoots = myProxyClient.getTrustRoots() 469 470 # Serialise dict response 471 response = "\n".join(["%s=%s" % i for i in trustRoots.items()]) 472 473 return response 474 475 except MyProxyClientError, e: 476 log.error("MyProxyClient.getTrustRoots raised an " 477 "MyProxyClientError exception calling %r: %s", 478 myProxyClient.hostname, 479 traceback.format_exc()) 480 481 except socket.error, e: 482 raise MyProxyGetTrustRootsMiddlewareError("Socket error with " 483 "MyProxy server %r: %s" % 484 (myProxyClient.hostname, 485 e)) 486 except Exception, e: 487 log.error("MyProxyClient.getTrustRoots raised an unknown exception " 488 "calling %r: %s", 489 myProxyClient.hostname, 490 traceback.format_exc()) 491 raise # Trigger 500 Internal Server Error 492 -
TI12-security/trunk/MyProxyLogonWebService/setup.py
r6886 r6938 35 35 url = 'http://proj.badc.rl.ac.uk/ndg/wiki/Security/MyProxyClient', 36 36 platforms = ['POSIX', 'Linux', 'Windows'], 37 install_requires = ['MyProxyClient'], 37 install_requires = ['PasteDeploy', 38 'PasteSecript', 39 'WebOb', 40 'MyProxyClient'], 38 41 license = __license__, 39 42 test_suite = 'myproxy.server.test',
Note: See TracChangeset
for help on using the changeset viewer.