Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: third_party/google-endpoints/test/test_wsgi.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from __future__ import absolute_import
16
17 from apitools.base.py import encoding
18 import mock
19 import os
20 import tempfile
21 import unittest2
22 from expects import be_false, be_none, be_true, expect, equal, raise_error
23
24 from google.api.auth import suppliers
25 from google.api.auth import tokens
26 from google.api.control import client, messages, report_request, service, wsgi
27
28
29 def _dummy_start_response(content, dummy_response_headers):
30 pass
31
32
33 _DUMMY_RESPONSE = ('All must answer "here!"',)
34
35
36 class _DummyWsgiApp(object):
37
38 def __call__(self, environ, dummy_start_response):
39 return _DUMMY_RESPONSE
40
41
42 class TestEnvironmentMiddleware(unittest2.TestCase):
43
44 def test_should_add_service_et_al_to_environment(self):
45 cls = wsgi.EnvironmentMiddleware
46 wrappee = _DummyWsgiApp()
47 wanted_service = service.Loaders.SIMPLE.load()
48 wrapped = cls(wrappee, wanted_service)
49
50 given = {
51 'wsgi.url_scheme': 'http',
52 'HTTP_HOST': 'localhost',
53 'REQUEST_METHOD': 'GET'
54 }
55 wrapped(given, _dummy_start_response)
56 expect(given.get(cls.SERVICE)).to(equal(wanted_service))
57 expect(given.get(cls.SERVICE_NAME)).to(equal(wanted_service.name))
58 expect(given.get(cls.METHOD_REGISTRY)).not_to(be_none)
59 expect(given.get(cls.REPORTING_RULES)).not_to(be_none)
60 expect(given.get(cls.METHOD_INFO)).not_to(be_none)
61
62
63 class TestMiddleware(unittest2.TestCase):
64 PROJECT_ID = 'middleware'
65
66 def test_should_not_send_requests_if_there_is_no_service(self):
67 wrappee = _DummyWsgiApp()
68 control_client = mock.MagicMock(spec=client.Client)
69
70 given = {
71 'wsgi.url_scheme': 'http',
72 'PATH_INFO': '/any/method',
73 'REMOTE_ADDR': '192.168.0.3',
74 'HTTP_HOST': 'localhost',
75 'HTTP_REFERER': 'example.myreferer.com',
76 'REQUEST_METHOD': 'GET'
77 }
78 dummy_response = messages.CheckResponse(operationId='fake_operation_id')
79 wrapped = wsgi.Middleware(wrappee, self.PROJECT_ID, control_client)
80 wrapped(given, _dummy_start_response)
81 expect(control_client.check.called).to(be_false)
82 expect(control_client.report.called).to(be_false)
83
84 def test_should_send_requests_using_the_client(self):
85 wrappee = _DummyWsgiApp()
86 control_client = mock.MagicMock(spec=client.Client)
87
88 given = {
89 'wsgi.url_scheme': 'http',
90 'PATH_INFO': '/any/method',
91 'REMOTE_ADDR': '192.168.0.3',
92 'HTTP_HOST': 'localhost',
93 'HTTP_REFERER': 'example.myreferer.com',
94 'REQUEST_METHOD': 'GET'
95 }
96 dummy_response = messages.CheckResponse(operationId='fake_operation_id')
97 with_control = wsgi.Middleware(wrappee, self.PROJECT_ID, control_client)
98 wrapped = wsgi.EnvironmentMiddleware(with_control,
99 service.Loaders.SIMPLE.load())
100 control_client.check.return_value = dummy_response
101 wrapped(given, _dummy_start_response)
102 expect(control_client.check.called).to(be_true)
103 expect(control_client.report.called).to(be_true)
104
105 def test_should_send_report_request_if_check_fails(self):
106 wrappee = _DummyWsgiApp()
107 control_client = mock.MagicMock(spec=client.Client)
108 given = {
109 'wsgi.url_scheme': 'http',
110 'PATH_INFO': '/any/method',
111 'REMOTE_ADDR': '192.168.0.3',
112 'HTTP_HOST': 'localhost',
113 'HTTP_REFERER': 'example.myreferer.com',
114 'REQUEST_METHOD': 'GET'
115 }
116 dummy_response = messages.CheckResponse(
117 operationId = 'fake_operation_id',
118 checkErrors = [
119 messages.CheckError(
120 code=messages.CheckError.CodeValueValuesEnum.PROJECT_DELETED )
121 ]
122 )
123 wrapped = wsgi.add_all(wrappee,
124 self.PROJECT_ID,
125 control_client,
126 loader=service.Loaders.SIMPLE)
127 control_client.check.return_value = dummy_response
128 wrapped(given, _dummy_start_response)
129 expect(control_client.check.called).to(be_true)
130 expect(control_client.report.called).to(be_true)
131
132 def test_load_service_failed(self):
133 loader = mock.MagicMock(load=lambda: None)
134 with self.assertRaisesRegex(ValueError, "Failed to load service config") :
135 wsgi.add_all(_DummyWsgiApp(),
136 self.PROJECT_ID,
137 mock.MagicMock(spec=client.Client),
138 loader=loader)
139
140
141 _SYSTEM_PARAMETER_CONFIG_TEST = """
142 {
143 "name": "system-parameter-config",
144 "systemParameters": {
145 "rules": [{
146 "selector": "Uvw.Method1",
147 "parameters": [{
148 "name": "name1",
149 "httpHeader": "Header-Key1",
150 "urlQueryParameter": "param_key1"
151 }, {
152 "name": "name2",
153 "httpHeader": "Header-Key2",
154 "urlQueryParameter": "param_key2"
155 }, {
156 "name": "api_key",
157 "httpHeader": "ApiKeyHeader",
158 "urlQueryParameter": "ApiKeyParam"
159 }, {
160 "httpHeader": "Ignored-NoName-Key3",
161 "urlQueryParameter": "Ignored-NoName-key3"
162 }]
163 }, {
164 "selector": "Bad.NotConfigured",
165 "parameters": [{
166 "name": "neverUsed",
167 "httpHeader": "NeverUsed-Key1",
168 "urlQueryParameter": "NeverUsed_key1"
169 }]
170 }]
171 },
172 "http": {
173 "rules": [{
174 "selector": "Uvw.Method1",
175 "get": "/uvw/method1/*"
176 }, {
177 "selector": "Uvw.MethodNeedsApiKey",
178 "get": "/uvw/method_needs_api_key/*"
179 }, {
180 "selector": "Uvw.DefaultParameters",
181 "get": "/uvw/default_parameters"
182 }]
183 },
184 "usage": {
185 "rules": [{
186 "selector" : "Uvw.Method1",
187 "allowUnregisteredCalls" : true
188 }, {
189 "selector": "Uvw.MethodNeedsApiKey",
190 "allowUnregisteredCalls" : false
191 }, {
192 "selector" : "Uvw.DefaultParameters",
193 "allowUnregisteredCalls" : true
194 }]
195 }
196 }
197 """
198
199 class TestMiddlewareWithParams(unittest2.TestCase):
200 PROJECT_ID = 'middleware-with-params'
201
202 def setUp(self):
203 _config_fd = tempfile.NamedTemporaryFile(delete=False)
204 with _config_fd as f:
205 f.write(_SYSTEM_PARAMETER_CONFIG_TEST)
206 self._config_file = _config_fd.name
207 os.environ[service.CONFIG_VAR] = self._config_file
208
209 def tearDown(self):
210 if os.path.exists(self._config_file):
211 os.remove(self._config_file)
212
213 def test_should_send_requests_with_no_param(self):
214 wrappee = _DummyWsgiApp()
215 control_client = mock.MagicMock(spec=client.Client)
216 given = {
217 'wsgi.url_scheme': 'http',
218 'PATH_INFO': '/uvw/method1/with_no_param',
219 'REMOTE_ADDR': '192.168.0.3',
220 'HTTP_HOST': 'localhost',
221 'HTTP_REFERER': 'example.myreferer.com',
222 'REQUEST_METHOD': 'GET'
223 }
224 dummy_response = messages.CheckResponse(operationId='fake_operation_id')
225 wrapped = wsgi.add_all(wrappee,
226 self.PROJECT_ID,
227 control_client,
228 loader=service.Loaders.ENVIRONMENT)
229 control_client.check.return_value = dummy_response
230 wrapped(given, _dummy_start_response)
231 expect(control_client.check.called).to(be_true)
232 req = control_client.check.call_args[0][0]
233 expect(req.checkRequest.operation.consumerId).to(
234 equal('project:middleware-with-params'))
235 expect(control_client.report.called).to(be_true)
236
237 def test_should_send_requests_with_configured_query_param_api_key(self):
238 wrappee = _DummyWsgiApp()
239 control_client = mock.MagicMock(spec=client.Client)
240 given = {
241 'wsgi.url_scheme': 'http',
242 'QUERY_STRING': 'ApiKeyParam=my-query-value',
243 'PATH_INFO': '/uvw/method1/with_query_param',
244 'REMOTE_ADDR': '192.168.0.3',
245 'HTTP_HOST': 'localhost',
246 'HTTP_REFERER': 'example.myreferer.com',
247 'REQUEST_METHOD': 'GET'
248 }
249 dummy_response = messages.CheckResponse(operationId='fake_operation_id')
250 wrapped = wsgi.add_all(wrappee,
251 self.PROJECT_ID,
252 control_client,
253 loader=service.Loaders.ENVIRONMENT)
254 control_client.check.return_value = dummy_response
255 wrapped(given, _dummy_start_response)
256 expect(control_client.check.called).to(be_true)
257 check_req = control_client.check.call_args[0][0]
258 expect(check_req.checkRequest.operation.consumerId).to(
259 equal('api_key:my-query-value'))
260 expect(control_client.report.called).to(be_true)
261 report_req = control_client.report.call_args[0][0]
262 expect(report_req.reportRequest.operations[0].consumerId).to(
263 equal('api_key:my-query-value'))
264
265 def test_should_send_requests_with_configured_header_api_key(self):
266 wrappee = _DummyWsgiApp()
267 control_client = mock.MagicMock(spec=client.Client)
268 given = {
269 'wsgi.url_scheme': 'http',
270 'PATH_INFO': '/uvw/method1/with_query_param',
271 'REMOTE_ADDR': '192.168.0.3',
272 'HTTP_HOST': 'localhost',
273 'HTTP_APIKEYHEADER': 'my-header-value',
274 'HTTP_REFERER': 'example.myreferer.com',
275 'REQUEST_METHOD': 'GET'
276 }
277 dummy_response = messages.CheckResponse(operationId='fake_operation_id')
278 wrapped = wsgi.add_all(wrappee,
279 self.PROJECT_ID,
280 control_client,
281 loader=service.Loaders.ENVIRONMENT)
282 control_client.check.return_value = dummy_response
283 wrapped(given, _dummy_start_response)
284 expect(control_client.check.called).to(be_true)
285 check_request = control_client.check.call_args_list[0].checkRequest
286 check_req = control_client.check.call_args[0][0]
287 expect(check_req.checkRequest.operation.consumerId).to(
288 equal('api_key:my-header-value'))
289 expect(control_client.report.called).to(be_true)
290 report_req = control_client.report.call_args[0][0]
291 expect(report_req.reportRequest.operations[0].consumerId).to(
292 equal('api_key:my-header-value'))
293
294 def test_should_send_requests_with_default_query_param_api_key(self):
295 for default_key in ('key', 'api_key'):
296 wrappee = _DummyWsgiApp()
297 control_client = mock.MagicMock(spec=client.Client)
298 given = {
299 'wsgi.url_scheme': 'http',
300 'QUERY_STRING': '%s=my-default-api-key-value' % (default_key,),
301 'PATH_INFO': '/uvw/method_needs_api_key/with_query_param',
302 'REMOTE_ADDR': '192.168.0.3',
303 'HTTP_HOST': 'localhost',
304 'HTTP_REFERER': 'example.myreferer.com',
305 'REQUEST_METHOD': 'GET'
306 }
307 dummy_response = messages.CheckResponse(operationId='fake_operation_ id')
308 wrapped = wsgi.add_all(wrappee,
309 self.PROJECT_ID,
310 control_client,
311 loader=service.Loaders.ENVIRONMENT)
312 control_client.check.return_value = dummy_response
313 wrapped(given, _dummy_start_response)
314 expect(control_client.check.called).to(be_true)
315 check_request = control_client.check.call_args_list[0].checkRequest
316 check_req = control_client.check.call_args[0][0]
317 expect(check_req.checkRequest.operation.consumerId).to(
318 equal('api_key:my-default-api-key-value'))
319 expect(control_client.report.called).to(be_true)
320 report_req = control_client.report.call_args[0][0]
321 expect(report_req.reportRequest.operations[0].consumerId).to(
322 equal('api_key:my-default-api-key-value'))
323
324 def test_should_not_perform_check_if_needed_api_key_is_missing(self):
325 wrappee = _DummyWsgiApp()
326 control_client = mock.MagicMock(spec=client.Client)
327 given = {
328 'wsgi.url_scheme': 'http',
329 'PATH_INFO': '/uvw/method_needs_api_key/more_stuff',
330 'REMOTE_ADDR': '192.168.0.3',
331 'HTTP_HOST': 'localhost',
332 'HTTP_REFERER': 'example.myreferer.com',
333 'REQUEST_METHOD': 'GET'
334 }
335 dummy_response = messages.CheckResponse(operationId='fake_operation_id')
336 wrapped = wsgi.add_all(wrappee,
337 self.PROJECT_ID,
338 control_client,
339 loader=service.Loaders.ENVIRONMENT)
340 control_client.check.return_value = dummy_response
341 wrapped(given, _dummy_start_response)
342 expect(control_client.check.called).to(be_false)
343 expect(control_client.report.called).to(be_true)
344 report_req = control_client.report.call_args[0][0]
345 expect(report_req.reportRequest.operations[0].consumerId).to(
346 equal('project:middleware-with-params'))
347
348 AuthMiddleware = wsgi.AuthenticationMiddleware
349
350
351 class TestAuthenticationMiddleware(unittest2.TestCase):
352
353 def setUp(self):
354 self._mock_application = _DummyWsgiApp()
355 self._mock_authenticator = mock.MagicMock(spec=tokens.Authenticator)
356 self._middleware = AuthMiddleware(self._mock_application,
357 self._mock_authenticator)
358
359 def test_no_authentication(self):
360 with self.assertRaisesRegex(ValueError, "Invalid authenticator"):
361 AuthMiddleware(self._mock_application, None)
362
363 def test_no_method_info(self):
364 environ = {}
365 self.assertEqual(_DUMMY_RESPONSE,
366 self._middleware(environ, _dummy_start_response))
367
368 def test_no_auth_token(self):
369 auth_app = AuthMiddleware(self.UserInfoWsgiApp(), self._mock_authenticator )
370 method_info = mock.MagicMock()
371 method_info.auth_info = mock.MagicMock()
372 environ = {
373 wsgi.EnvironmentMiddleware.METHOD_INFO: method_info
374 }
375 self.assertIsNone(auth_app(environ, _dummy_start_response))
376
377 def test_malformed_authorization_header(self):
378 auth_app = AuthMiddleware(self.UserInfoWsgiApp(), self._mock_authenticator )
379 environ = {
380 "HTTP_AUTHORIZATION": "malformed-auth-token",
381 wsgi.EnvironmentMiddleware.METHOD_INFO: mock.MagicMock(),
382 wsgi.EnvironmentMiddleware.SERVICE_NAME: "service-name"
383 }
384 self._mock_authenticator.authenticate.side_effect = suppliers.Unauthentica tedException()
385 self.assertIsNone(auth_app(environ, _dummy_start_response))
386
387 def test_successful_authentication(self):
388 auth_token = "Bearer test-bearer-token"
389 auth_info = mock.MagicMock()
390 service_name = "test-service-name"
391 method_info = mock.MagicMock()
392 method_info.auth_info = auth_info
393 environ = {
394 "HTTP_AUTHORIZATION": auth_token,
395 wsgi.EnvironmentMiddleware.METHOD_INFO: method_info,
396 wsgi.EnvironmentMiddleware.SERVICE_NAME: service_name
397 }
398
399 user_info = mock.MagicMock()
400 self._mock_authenticator.authenticate.return_value = user_info
401 self._middleware(environ, _dummy_start_response)
402 self.assertEqual(user_info, environ.get(AuthMiddleware.USER_INFO))
403 authenticate_mock = self._mock_authenticator.authenticate
404 authenticate_mock.assert_called_once_with("test-bearer-token", auth_info,
405 service_name)
406
407 def test_auth_token_in_query(self):
408 auth_token = "test-bearer-token"
409 auth_info = mock.MagicMock()
410 service_name = "test-service-name"
411 method_info = mock.MagicMock()
412 method_info.auth_info = auth_info
413 environ = {
414 "QUERY_STRING": "access_token=" + auth_token,
415 wsgi.EnvironmentMiddleware.METHOD_INFO: method_info,
416 wsgi.EnvironmentMiddleware.SERVICE_NAME: service_name
417 }
418
419 user_info = mock.MagicMock()
420 self._mock_authenticator.authenticate.return_value = user_info
421 self._middleware(environ, _dummy_start_response)
422 self.assertEqual(user_info, environ.get(AuthMiddleware.USER_INFO))
423 authenticate_mock = self._mock_authenticator.authenticate
424 authenticate_mock.assert_called_once_with("test-bearer-token", auth_info,
425 service_name)
426
427 patched_environ = {}
428 @mock.patch("os.environ", patched_environ)
429 def test_set_user_info(self):
430 environ = {
431 "QUERY_STRING": "access_token=test-token",
432 wsgi.EnvironmentMiddleware.METHOD_INFO: mock.MagicMock(),
433 wsgi.EnvironmentMiddleware.SERVICE_NAME: "test-service-name"
434 }
435 application = self.UserInfoWsgiApp()
436 auth_middleware = AuthMiddleware(application, self._mock_authenticator)
437 user_info = mock.MagicMock()
438 self._mock_authenticator.authenticate.return_value = user_info
439 self.assertEqual(user_info, auth_middleware(environ,
440 _dummy_start_response))
441 self.assertFalse(self.patched_environ)
442
443 class UserInfoWsgiApp(object):
444 def __call__(self, environ, start_response):
445 return os.environ.get(wsgi.AuthenticationMiddleware.USER_INFO)
446
447
448 class TestCreateAuthenticator(unittest2.TestCase):
449 def test_create_without_service(self):
450 with self.assertRaises(ValueError):
451 wsgi._create_authenticator(None)
452
453 def test_load_service_without_auth(self):
454 service = _read_service_from_json("{}")
455 self.assertIsNone(wsgi._create_authenticator(service))
456
457 def test_load_service(self):
458 json = """{
459 "authentication": {
460 "providers": [{
461 "issuer": "auth-issuer"
462 }]
463 }
464 }"""
465 service = _read_service_from_json(json)
466 self.assertIsNotNone(wsgi._create_authenticator(service))
467
468
469 patched_platform_environ = {}
470 @mock.patch.dict('os.environ', patched_platform_environ, clear=True)
471 class TestPlatformDetection(unittest2.TestCase):
472
473 def test_development(self):
474 os.environ['SERVER_SOFTWARE'] = 'Development/2.0.0'
475 self.assertEqual(report_request.ReportedPlatforms.DEVELOPMENT,
476 wsgi._get_platform())
477
478 def test_gke(self):
479 os.environ['KUBERNETES_SERVICE_HOST'] = 'hostname'
480 self.assertEqual(report_request.ReportedPlatforms.GKE,
481 wsgi._get_platform())
482
483 @mock.patch.object(wsgi, '_running_on_gce', return_value=True)
484 def test_gae_flex(self, _running_on_gce):
485 os.environ['GAE_MODULE_NAME'] = 'gae_module'
486 self.assertEqual(report_request.ReportedPlatforms.GAE_FLEX,
487 wsgi._get_platform())
488
489 @mock.patch.object(wsgi, '_running_on_gce', return_value=True)
490 def test_gce(self, _running_on_gce):
491 self.assertEqual(report_request.ReportedPlatforms.GCE,
492 wsgi._get_platform())
493
494 @mock.patch.object(wsgi, '_running_on_gce', return_value=False)
495 def test_gae_standard(self, _running_on_gce):
496 os.environ['GAE_MODULE_NAME'] = 'gae_module'
497 self.assertEqual(report_request.ReportedPlatforms.GAE_STANDARD,
498 wsgi._get_platform())
499
500 @mock.patch.object(wsgi, '_running_on_gce', return_value=False)
501 def test_unknown(self, _running_on_gce):
502 self.assertEqual(report_request.ReportedPlatforms.UNKNOWN,
503 wsgi._get_platform())
504
505
506 def _read_service_from_json(json):
507 return encoding.JsonToMessage(messages.Service, json)
OLDNEW
« no previous file with comments | « third_party/google-endpoints/test/test_tokens.py ('k') | third_party/google-endpoints/test/token_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698