Changeset 5843 for TI12-security/trunk/python
- Timestamp:
- 14/10/09 16:41:01 (11 years ago)
- Location:
- TI12-security/trunk/python
- Files:
-
- 5 added
- 4 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/__init__.py
r5774 r5843 236 236 237 237 if propertyDefaults is not None and filtK not in propertyDefaults: 238 badOpt += [k] 238 badOpt += [k] 239 239 else: 240 240 opt[filtK] = v -
TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/authn.py
r5838 r5843 16 16 log = logging.getLogger(__name__) 17 17 18 import re 18 19 import base64 19 20 import httplib 20 21 import urllib 21 from urlparse import urlsplit 22 from paste.request import construct_url 23 from paste.request import parse_querystring 24 from beaker.middleware import SessionMiddleware 22 from paste.request import construct_url, parse_querystring 25 23 import authkit.authenticate 26 24 … … 52 50 AUTHN_FUNC_ENV_KEYNAME = ('ndg.security.server.wsgi.authn.' 53 51 'HTTPBasicAuthMiddleware.authenticate') 54 AUTHN_FUNC_ENV_KEYNAME_ PARAMNAME = 'authnFunc'55 PARAM_PREFIX = 'http.auth.basic '52 AUTHN_FUNC_ENV_KEYNAME_OPTNAME = 'authnFuncEnvKeyName' 53 PARAM_PREFIX = 'http.auth.basic.' 56 54 HTTP_HDR_FIELDNAME = 'basic' 57 55 FIELD_SEP = ':' 58 56 AUTHZ_ENV_KEYNAME = 'HTTP_AUTHORIZATION' 59 57 58 RE_PATH_MATCH_LIST_OPTNAME = 'rePathMatchList' 59 60 60 def __init__(self, app, app_conf, prefix=PARAM_PREFIX, **local_conf): 61 self.__rePathMatchList = None 61 62 self.__authnFuncEnvironKeyName = None 62 63 63 64 super(HTTPBasicAuthMiddleware, self).__init__(app, app_conf, 64 65 **local_conf) 66 67 rePathMatchListOptName = prefix + \ 68 HTTPBasicAuthMiddleware.RE_PATH_MATCH_LIST_OPTNAME 69 rePathMatchListVal = app_conf.pop(rePathMatchListOptName, '') 70 71 self.rePathMatchList = [re.compile(i) 72 for i in rePathMatchListVal.split()] 73 65 74 paramName = prefix + \ 66 HTTPBasicAuthMiddleware.AUTHN_FUNC_ENV_KEYNAME_ PARAMNAME75 HTTPBasicAuthMiddleware.AUTHN_FUNC_ENV_KEYNAME_OPTNAME 67 76 68 77 self.authnFuncEnvironKeyName = local_conf.get(paramName, … … 84 93 "custom authentication function " 85 94 "used by this class") 95 96 def _getRePathMatchList(self): 97 return self.__rePathMatchList 98 99 def _setRePathMatchList(self, value): 100 if not isinstance(value, (list, tuple)): 101 raise TypeError('Expecting list or tuple type for ' 102 '"rePathMatchList"; got %r' % type(value)) 103 104 self.__rePathMatchList = value 105 106 rePathMatchList = property(fget=_getRePathMatchList, 107 fset=_setRePathMatchList, 108 doc="List of regular expressions determine the " 109 "URI paths intercepted by this middleware") 110 111 def _pathMatch(self): 112 """Apply a list of regular expression matching patterns to the contents 113 of environ['PATH_INFO'], if any match, return True. This method is 114 used to determine whether to apply SSL client authentication 115 """ 116 path = self.pathInfo 117 for regEx in self.rePathMatchList: 118 if regEx.match(path): 119 return True 120 121 return False 86 122 87 123 def _parseCredentials(self): … … 116 152 log.debug("HTTPBasicAuthNMiddleware.__call__ ...") 117 153 154 if not self._pathMatch(): 155 return self._app(environ, start_response) 156 118 157 authenticate = environ.get(self.authnFuncEnvironKeyName) 119 158 if authenticate is None: … … 126 165 return self._setErrorResponse(code=httplib.UNAUTHORIZED) 127 166 167 # Call authentication application 128 168 try: 129 authenticate(environ, username, password)130 169 return authenticate(environ, start_response, username, password) 170 131 171 except HTTPBasicAuthUnauthorized, e: 132 172 log.error(e) -
TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/myproxy/__init__.py
r5839 r5843 13 13 import re 14 14 import httplib 15 import socket 15 16 16 from myproxy.client import MyProxyClient 17 from myproxy.client import MyProxyClient, MyProxyClientError 18 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 19 NDGSecurityMiddlewareConfigError 20 17 21 from ndg.security.server.wsgi.authn import HTTPBasicAuthMiddleware 22 23 24 class MyProxyClientMiddlewareConfigError(NDGSecurityMiddlewareConfigError): 25 """Configuration error with MyProxyClientMiddleware""" 18 26 19 class MyProxyClientMiddleware(object): 27 28 class MyProxyClientMiddleware(NDGSecurityMiddlewareBase): 20 29 ''' 21 HTTPS proxy to a MyProxy server to enable HTTPS type calls to MyProxy 30 Create a MyProxy client and make it available to other middleware in the 31 WSGI stack 22 32 ''' 23 33 # Options for ini file 24 RE_PATH_MATCH_LIST_OPTNAME = 'rePathMatchList' 34 CLIENT_ENV_KEYNAME_OPTNAME = 'clientEnvKeyName' 35 LOGON_FUNC_ENV_KEYNAME_OPTNAME = 'logonFuncEnvKeyName' 25 36 37 # Default environ key names 38 CLIENT_ENV_KEYNAME = ('ndg.security.server.wsgi.authn.' 39 'MyProxyClientMiddleware') 26 40 LOGON_FUNC_ENV_KEYNAME = ('ndg.security.server.wsgi.authn.' 27 41 'MyProxyClientMiddleware.logon') 28 LOGON_FUNC_ENV_KEYNAME_OPTNAME = 'logonFunc' 42 43 # Option prefixes 29 44 PARAM_PREFIX = 'myproxy.' 30 45 MYPROXY_CLIENT_PARAM_PREFIX = 'client.' 31 46 32 def __init__(self, app, global_conf, prefix=PARAM_PREFIX, **app_conf): 47 def __init__(self, app, global_conf, prefix=PARAM_PREFIX, 48 myProxyClientPrefix=MYPROXY_CLIENT_PARAM_PREFIX, **app_conf): 33 49 '''''' 34 super(MyProxyClientMiddleware, self).__init__(app, 35 global_conf, 36 prefix=prefix, 37 *app_conf) 50 super(MyProxyClientMiddleware, self).__init__(app, global_conf) 38 51 self.__myProxyClient = None 39 52 40 rePathMatchListParamName = prefix + \41 MyProxyClientMiddleware.RE_PATH_MATCH_LIST_OPTNAME42 rePathMatchListVal = app_conf.get(rePathMatchListParamName, '')43 44 self.rePathMatchList = [re.compile(r)45 for r in rePathMatchListVal.split()]46 47 53 # Get MyProxyClient initialisation parameters 48 myProxyClientPrefix = prefix + \ 49 MyProxyClientMiddleware.MYPROXY_CLIENT_PARAM_PREFIX 54 myProxyClientFullPrefix = prefix + myProxyClientPrefix 50 55 51 myProxyClientKw = dict([(k.replace(myProxyClient Prefix, ''), v)56 myProxyClientKw = dict([(k.replace(myProxyClientFullPrefix, ''), v) 52 57 for k,v in app_conf.items() 53 if k.startswith(myProxyClient Prefix)])58 if k.startswith(myProxyClientFullPrefix)]) 54 59 55 60 self.myProxyClient = MyProxyClient(**myProxyClientKw) 56 paramName = prefix + \ 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 + \ 57 68 MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME_OPTNAME 58 59 self.logonFuncEnvironKeyName = local_conf.get(paramName,69 70 self.logonFuncEnvironKeyName = app_conf.get(logonFuncEnvKeyOptName, 60 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") 61 86 62 87 def _getLogonFuncEnvironKeyName(self): … … 73 98 fset=_setLogonFuncEnvironKeyName, 74 99 doc="key name in environ for the " 75 " custom authentication function "76 "used by this class")100 "MyProxy logon function") 101 77 102 def _getMyProxyClient(self): 78 103 return self.__myProxyClient … … 91 116 @NDGSecurityMiddlewareBase.initCall 92 117 def __call__(self, environ, start_response): 93 ''' Intercept MyProxy call and relay to MyProxy server118 '''Set MyProxyClient instance and MyProxy logon method in environ 94 119 95 120 @type environ: dict … … 99 124 ''' 100 125 log.debug("MyProxyClientMiddleware.__call__ ...") 101 environ[self.logonFuncEnvironKeyName] = self.myProxyLogonFunc 126 environ[self.clientEnvironKeyName] = self.myProxyClient 127 environ[self.logonFuncEnvironKeyName] = self.myProxyLogon 102 128 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 129 return self._app(environ, start_response) 133 130 134 131 @property 135 def myProxyLogon Func(self):132 def myProxyLogon(self): 136 133 """Return the MyProxy logon method wrapped as a HTTP Basic Auth 137 134 authenticate interface function 138 135 """ 139 def HTTPBasicAuthFunc(environ, username, password): 140 """Wrap MyProxy logon method as HTTPBasicAuthMiddleware 141 authenticate function""" 142 return self.myProxyClient.logon(environ, username, password) 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] 143 157 144 return HTTPBasicAuthFunc158 return _myProxylogon 145 159 146 160 161 class MyProxyLogonMiddlewareConfigError(NDGSecurityMiddlewareConfigError): 162 """Configuration error with MyProxyLogonMiddleware""" 163 164 147 165 class MyProxyLogonMiddleware(NDGSecurityMiddlewareBase): 148 """HTTP Basic Auth interface to MyProxy logon""" 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 """ 149 171 PARAM_PREFIX = 'myproxy.logon.' 150 172 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) 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) -
TI12-security/trunk/python/ndg_security_server/setup.py
r5788 r5843 23 23 'ndg_security_common', 24 24 'Pylons <= 0.9.6.2', # TODO: drop Pylons dependency in future release 25 'AuthKit' 25 'AuthKit', 26 'MyProxyClient' 26 27 ] 27 28 -
TI12-security/trunk/python/ndg_security_test/ndg/security/test/unit/wsgi/authn/test_httpbasicauth.py
r5838 r5843 25 25 response = "Test HTTP Basic Authentication application" 26 26 27 loggedIn = lambda self, environ: 'username' in environ.get(28 self.beakerSessionKeyName, {})29 30 27 def __init__(self, app_conf, **local_conf): 31 self.beakerSessionKeyName = app_conf.get('beakerSessionKeyName')28 pass 32 29 33 30 def __call__(self, environ, start_response): 34 31 35 if environ['PATH_INFO'] == '/test_401WithNotLoggedIn': 36 status = "401 Unauthorized" 37 38 elif environ['PATH_INFO'] == '/test_401WithLoggedIn': 39 status = "401 Unauthorized" 40 41 elif environ['PATH_INFO'] == '/test_200WithNotLoggedIn': 32 if environ['PATH_INFO'] == '/test_200': 42 33 status = "200 OK" 43 44 elif environ['PATH_INFO'] == '/test_200':45 status = "200 OK"46 47 elif environ['PATH_INFO'] == '/test_sslClientAuthn':48 if self.loggedIn(environ):49 status = "200 OK"50 else:51 status = "401 Unauthorized"52 34 else: 53 35 status = "404 Not found" … … 124 106 authHeader = "Basic %s" % base64String 125 107 req.add_header("Authorization", authHeader) 126 try: 127 handle = urllib2.urlopen(req) 128 except IOError, e: 129 print("It looks like the username or password is wrong: %s" % e) 130 return 108 109 handle = urllib2.urlopen(req) 131 110 132 111 response = handle.read()
Note: See TracChangeset
for help on using the changeset viewer.