Package myproxy :: Package ws :: Package test :: Module test_httpbasicauth
[hide private]

Source Code for Module myproxy.ws.test.test_httpbasicauth

  1  #!/usr/bin/env python 
  2  """Unit tests for MyProxy WSGI Middleware classes and Application 
  3  """ 
  4  __author__ = "P J Kershaw" 
  5  __date__ = "21/05/10" 
  6  __copyright__ = "(C) 2010 Science and Technology Facilities Council" 
  7  __license__ = "BSD - see LICENSE file in top-level directory" 
  8  __contact__ = "Philip.Kershaw@stfc.ac.uk" 
  9  __revision__ = '$Id: $' 
 10  import unittest 
 11  import os 
 12  import base64 
 13   
 14  import paste.fixture 
 15  from paste.deploy import loadapp 
 16   
 17  from myproxy.ws.server.wsgi.httpbasicauth import (HttpBasicAuthMiddleware, 
 18                                                 HttpBasicAuthResponseException) 
 19   
 20   
21 -class TestApp(object):
22 """Test WSGI Application for use with the unit tests for the HTTP Basic 23 Auth middleware developed for the myproxy.server.app.MyProxyApp application 24 """
25 - def __init__(self, global_conf, **app_conf):
26 """Follow standard Paste Deploy app factory function signature"""
27
28 - def __call__(self, environ, start_response):
29 """Make a simple response for unit test code to trap and validate 30 against. If this method is executed then the HTTP Basic Auth step in 31 the upstream middleware has succeeded. 32 """ 33 contentType = 'text/plain' 34 response = 'Authenticated!' 35 status = 200 36 start_response(status, 37 [('Content-type', contentType), 38 ('Content-Length', str(len(response)))]) 39 return [response]
40 41
42 -class TestHttpBasicAuthCallBackAppMiddleware(object):
43 """Add an authentication function to the environ for HttpBasicAuthMiddleware 44 to pick up and use. It behaves as an application returning a response 45 """ 46 USERNAME = 'myusername' 47 PASSWORD = 'mypassword' 48 SUCCESS_RESPONSE = 'AUTHENTICATED' 49 FAILURE_RESPONSE = 'FAILED' 50
51 - def __init__(self, app, global_conf, **app_conf):
52 """Follow standard Paste Deploy app factory function signature""" 53 self.app = app
54
55 - def __call__(self, environ, start_response):
56 def authenticationApp(environ, start_response, username, password): 57 """Authentication callback application - its responsible for the 58 response message and response code 59 """ 60 if (username == self.__class__.USERNAME and 61 password == self.__class__.PASSWORD): 62 response = self.__class__.SUCCESS_RESPONSE 63 status = '200 OK' 64 else: 65 response = self.__class__.FAILURE_RESPONSE 66 status = '401 Unauthorized' 67 68 start_response(status, 69 [('Content-type', 'text/plain'), 70 ('Content-Length', str(len(response)))]) 71 return [response]
72 73 environ['HTTPBASICAUTH_FUNC'] = authenticationApp 74 75 return self.app(environ, start_response)
76 77
78 -class TestHttpBasicAuthCallBackMiddleware(object):
79 """Add an authentication function to the environ for HttpBasicAuthMiddleware 80 to pick up and use. The callback does not return a response leaving control 81 with the HttpBasicAuthMiddleware 82 """ 83 USERNAME = 'myusername' 84 PASSWORD = 'mypassword' 85
86 - def __init__(self, app, global_conf, **app_conf):
87 """Follow standard Paste Deploy app factory function signature""" 88 self.app = app
89
90 - def __call__(self, environ, start_response):
91 """Create HTTP Basic Auth callback""" 92 def authenticate(environ, start_response, username, password): 93 """HTTP Basic Auth callback function""" 94 if (username != self.__class__.USERNAME or 95 password != self.__class__.PASSWORD): 96 raise HttpBasicAuthResponseException("Invalid credentials")
97 98 environ['HTTPBASICAUTH_FUNC'] = authenticate 99 100 return self.app(environ, start_response)
101 102
103 -class HttpBasicAuthMiddlewareTestCase(unittest.TestCase):
104 """Unit tests for HTTP Basic Auth middleware used with the MyProxyWebService 105 package 106 """ 107 CONFIG_FILE = 'httpbasicauth.ini' 108
109 - def __init__(self, *args, **kwargs):
110 """Set-up Paste fixture from ini file settings""" 111 here_dir = os.path.dirname(os.path.abspath(__file__)) 112 configFilePath = ('config:%s' % 113 HttpBasicAuthMiddlewareTestCase.CONFIG_FILE) 114 wsgiapp = loadapp(configFilePath, relative_to=here_dir) 115 self.app = paste.fixture.TestApp(wsgiapp) 116 117 unittest.TestCase.__init__(self, *args, **kwargs)
118
120 # Try with no HTTP Basic Auth HTTP header 121 response = self.app.get('/auth', status=401)
122
123 - def test02ValidCredentials(self):
124 # Try with no HTTP Basic Auth HTTP header 125 username = TestHttpBasicAuthCallBackAppMiddleware.USERNAME 126 password = TestHttpBasicAuthCallBackAppMiddleware.PASSWORD 127 128 base64String = base64.encodestring('%s:%s' % (username, password))[:-1] 129 authHeader = "Basic %s" % base64String 130 headers = {'Authorization': authHeader} 131 132 response = self.app.get('/auth', headers=headers, status=200) 133 self.assert_((TestHttpBasicAuthCallBackAppMiddleware.SUCCESS_RESPONSE in 134 response))
135
136 - def test03InvalidCredentials(self):
137 # Try with no HTTP Basic Auth HTTP header 138 username = 'x' 139 password = 'y' 140 141 base64String = base64.encodestring('%s:%s' % (username, password))[:-1] 142 authHeader = "Basic %s" % base64String 143 headers = {'Authorization': authHeader} 144 145 response = self.app.get('/auth', headers=headers, status=401) 146 self.assert_((TestHttpBasicAuthCallBackAppMiddleware.FAILURE_RESPONSE in 147 response))
148
150 # Test creating app independently of PasteScript and using an 151 # alternate middleware which doesn't return a response but simply 152 # raises a 401 exception type if input credentials don't match 153 app = TestApp({}) 154 app = HttpBasicAuthMiddleware.filter_app_factory(app, {}, 155 prefix='', 156 authnFuncEnvironKeyName='HTTPBASICAUTH_FUNC') 157 app = TestHttpBasicAuthCallBackMiddleware(app, {}) 158 159 self.app2 = paste.fixture.TestApp(app)
160
162 self._createCallbackMiddleware() 163 username = TestHttpBasicAuthCallBackAppMiddleware.USERNAME 164 password = TestHttpBasicAuthCallBackAppMiddleware.PASSWORD 165 166 base64String = base64.encodestring('%s:%s' % (username, password))[:-1] 167 authHeader = "Basic %s" % base64String 168 headers = {'Authorization': authHeader} 169 170 response = self.app.get('/auth', headers=headers, status=200)
171
173 self._createCallbackMiddleware() 174 username = 'a' 175 password = 'b' 176 177 base64String = base64.encodestring('%s:%s' % (username, password))[:-1] 178 authHeader = "Basic %s" % base64String 179 headers = {'Authorization': authHeader} 180 181 response = self.app.get('/auth', headers=headers, status=401)
182