blob: 6a2e3358a07d3df5946b5a2f6142e71bcfc44da3 [file] [log] [blame]
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -05001# Copyright 2014 IBM Corp.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16import copy
Andrea Frittolidbd02512014-03-21 10:06:19 +000017import datetime
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050018
Matthew Treinish89900172014-03-03 20:45:02 -050019from oslotest import mockpatch
20
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050021from tempest import auth
22from tempest.common import http
23from tempest import config
24from tempest import exceptions
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050025from tempest.tests import base
Andrea Frittoli7d707a52014-04-06 11:46:32 +010026from tempest.tests import fake_auth_provider
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050027from tempest.tests import fake_config
Andrea Frittoli7d707a52014-04-06 11:46:32 +010028from tempest.tests import fake_credentials
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050029from tempest.tests import fake_http
30from tempest.tests import fake_identity
31
32
33class BaseAuthTestsSetUp(base.TestCase):
34 _auth_provider_class = None
Andrea Frittoli7d707a52014-04-06 11:46:32 +010035 credentials = fake_credentials.FakeCredentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050036
37 def _auth(self, credentials, **params):
38 """
39 returns auth method according to keystone
40 """
41 return self._auth_provider_class(credentials, **params)
42
43 def setUp(self):
44 super(BaseAuthTestsSetUp, self).setUp()
Matthew Treinishff598482014-02-28 16:13:58 -050045 self.useFixture(fake_config.ConfigFixture())
46 self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050047 self.fake_http = fake_http.fake_httplib2(return_type=200)
48 self.stubs.Set(http.ClosingHttp, 'request', self.fake_http.request)
Andrea Frittoli7d707a52014-04-06 11:46:32 +010049 self.stubs.Set(auth, 'get_credentials',
50 fake_auth_provider.get_credentials)
Andrea Frittolib1b04bb2014-04-06 11:57:07 +010051 self.stubs.Set(auth, 'get_default_credentials',
52 fake_auth_provider.get_default_credentials)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050053 self.auth_provider = self._auth(self.credentials)
54
55
56class TestBaseAuthProvider(BaseAuthTestsSetUp):
57 """
58 This tests auth.AuthProvider class which is base for the other so we
59 obviously don't test not implemented method or the ones which strongly
60 depends on them.
61 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050062
Marc Koderer235e4f52014-07-22 10:15:08 +020063 class FakeAuthProviderImpl(auth.AuthProvider):
64 def _decorate_request():
65 pass
66
67 def _fill_credentials():
68 pass
69
70 def _get_auth():
71 pass
72
73 def base_url():
74 pass
75
76 def is_expired():
77 pass
78
79 _auth_provider_class = FakeAuthProviderImpl
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050080
81 def test_check_credentials_bad_type(self):
82 self.assertFalse(self.auth_provider.check_credentials([]))
83
Andrea Frittoli7d707a52014-04-06 11:46:32 +010084 def test_instantiate_with_dict(self):
85 # Dict credentials are only supported for backward compatibility
86 auth_provider = self._auth(credentials={})
87 self.assertIsInstance(auth_provider.credentials, auth.Credentials)
88
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050089 def test_auth_data_property_when_cache_exists(self):
90 self.auth_provider.cache = 'foo'
91 self.useFixture(mockpatch.PatchObject(self.auth_provider,
92 'is_expired',
93 return_value=False))
94 self.assertEqual('foo', getattr(self.auth_provider, 'auth_data'))
95
96 def test_delete_auth_data_property_through_deleter(self):
97 self.auth_provider.cache = 'foo'
98 del self.auth_provider.auth_data
99 self.assertIsNone(self.auth_provider.cache)
100
101 def test_delete_auth_data_property_through_clear_auth(self):
102 self.auth_provider.cache = 'foo'
103 self.auth_provider.clear_auth()
104 self.assertIsNone(self.auth_provider.cache)
105
106 def test_set_and_reset_alt_auth_data(self):
107 self.auth_provider.set_alt_auth_data('foo', 'bar')
108 self.assertEqual(self.auth_provider.alt_part, 'foo')
109 self.assertEqual(self.auth_provider.alt_auth_data, 'bar')
110
111 self.auth_provider.reset_alt_auth_data()
112 self.assertIsNone(self.auth_provider.alt_part)
113 self.assertIsNone(self.auth_provider.alt_auth_data)
114
Marc Koderer235e4f52014-07-22 10:15:08 +0200115 def test_auth_class(self):
116 self.assertRaises(TypeError,
117 auth.AuthProvider,
118 fake_credentials.FakeCredentials)
Andrea Frittoli2095d242014-03-20 08:36:23 +0000119
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500120
121class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500122 _endpoints = fake_identity.IDENTITY_V2_RESPONSE['access']['serviceCatalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500123 _auth_provider_class = auth.KeystoneV2AuthProvider
Andrea Frittoli7d707a52014-04-06 11:46:32 +0100124 credentials = fake_credentials.FakeKeystoneV2Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500125
126 def setUp(self):
127 super(TestKeystoneV2AuthProvider, self).setUp()
128 self.stubs.Set(http.ClosingHttp, 'request',
129 fake_identity._fake_v2_response)
130 self.target_url = 'test_api'
131
132 def _get_fake_alt_identity(self):
133 return fake_identity.ALT_IDENTITY_V2_RESPONSE['access']
134
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500135 def _get_result_url_from_endpoint(self, ep, endpoint_type='publicURL',
136 replacement=None):
137 if replacement:
138 return ep[endpoint_type].replace('v2', replacement)
139 return ep[endpoint_type]
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500140
141 def _get_token_from_fake_identity(self):
142 return fake_identity.TOKEN
143
Andrea Frittoli2095d242014-03-20 08:36:23 +0000144 def _get_from_fake_identity(self, attr):
145 access = fake_identity.IDENTITY_V2_RESPONSE['access']
146 if attr == 'user_id':
147 return access['user']['id']
148 elif attr == 'tenant_id':
149 return access['token']['tenant']['id']
150
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500151 def _test_request_helper(self, filters, expected):
152 url, headers, body = self.auth_provider.auth_request('GET',
153 self.target_url,
154 filters=filters)
155
156 self.assertEqual(expected['url'], url)
157 self.assertEqual(expected['token'], headers['X-Auth-Token'])
158 self.assertEqual(expected['body'], body)
159
Andrea Frittolidbd02512014-03-21 10:06:19 +0000160 def _auth_data_with_expiry(self, date_as_string):
161 token, access = self.auth_provider.auth_data
162 access['token']['expires'] = date_as_string
163 return token, access
164
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500165 def test_request(self):
166 filters = {
167 'service': 'compute',
168 'endpoint_type': 'publicURL',
169 'region': 'FakeRegion'
170 }
171
172 url = self._get_result_url_from_endpoint(
173 self._endpoints[0]['endpoints'][1]) + '/' + self.target_url
174
175 expected = {
176 'body': None,
177 'url': url,
178 'token': self._get_token_from_fake_identity(),
179 }
180 self._test_request_helper(filters, expected)
181
182 def test_request_with_alt_auth_cleans_alt(self):
183 self.auth_provider.set_alt_auth_data(
184 'body',
185 (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
186 self.test_request()
187 # Assert alt auth data is clear after it
188 self.assertIsNone(self.auth_provider.alt_part)
189 self.assertIsNone(self.auth_provider.alt_auth_data)
190
191 def test_request_with_alt_part_without_alt_data(self):
192 """
193 Assert that when alt_part is defined, the corresponding original
194 request element is kept the same.
195 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500196 filters = {
197 'service': 'compute',
198 'endpoint_type': 'publicURL',
199 'region': 'fakeRegion'
200 }
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500201 self.auth_provider.set_alt_auth_data('url', None)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500202
203 url, headers, body = self.auth_provider.auth_request('GET',
204 self.target_url,
205 filters=filters)
206
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500207 self.assertEqual(url, self.target_url)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500208 self.assertEqual(self._get_token_from_fake_identity(),
209 headers['X-Auth-Token'])
210 self.assertEqual(body, None)
211
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500212 def test_request_with_bad_service(self):
213 filters = {
214 'service': 'BAD_SERVICE',
215 'endpoint_type': 'publicURL',
216 'region': 'fakeRegion'
217 }
218 self.assertRaises(exceptions.EndpointNotFound,
219 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500220 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500221
222 def test_request_without_service(self):
223 filters = {
224 'service': None,
225 'endpoint_type': 'publicURL',
226 'region': 'fakeRegion'
227 }
228 self.assertRaises(exceptions.EndpointNotFound,
229 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500230 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500231
232 def test_check_credentials_missing_attribute(self):
233 for attr in ['username', 'password']:
234 cred = copy.copy(self.credentials)
235 del cred[attr]
236 self.assertFalse(self.auth_provider.check_credentials(cred))
237
Andrea Frittoli2095d242014-03-20 08:36:23 +0000238 def test_fill_credentials(self):
239 self.auth_provider.fill_credentials()
240 creds = self.auth_provider.credentials
241 for attr in ['user_id', 'tenant_id']:
242 self.assertEqual(self._get_from_fake_identity(attr),
243 getattr(creds, attr))
244
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500245 def _test_base_url_helper(self, expected_url, filters,
246 auth_data=None):
247
248 url = self.auth_provider.base_url(filters, auth_data)
249 self.assertEqual(url, expected_url)
250
251 def test_base_url(self):
252 self.filters = {
253 'service': 'compute',
254 'endpoint_type': 'publicURL',
255 'region': 'FakeRegion'
256 }
257 expected = self._get_result_url_from_endpoint(
258 self._endpoints[0]['endpoints'][1])
259 self._test_base_url_helper(expected, self.filters)
260
261 def test_base_url_to_get_admin_endpoint(self):
262 self.filters = {
263 'service': 'compute',
264 'endpoint_type': 'adminURL',
265 'region': 'FakeRegion'
266 }
267 expected = self._get_result_url_from_endpoint(
268 self._endpoints[0]['endpoints'][1], endpoint_type='adminURL')
269 self._test_base_url_helper(expected, self.filters)
270
271 def test_base_url_unknown_region(self):
272 """
273 Assure that if the region is unknow the first endpoint is returned.
274 """
275 self.filters = {
276 'service': 'compute',
277 'endpoint_type': 'publicURL',
278 'region': 'AintNoBodyKnowThisRegion'
279 }
280 expected = self._get_result_url_from_endpoint(
281 self._endpoints[0]['endpoints'][0])
282 self._test_base_url_helper(expected, self.filters)
283
284 def test_base_url_with_non_existent_service(self):
285 self.filters = {
286 'service': 'BAD_SERVICE',
287 'endpoint_type': 'publicURL',
288 'region': 'FakeRegion'
289 }
290 self.assertRaises(exceptions.EndpointNotFound,
291 self._test_base_url_helper, None, self.filters)
292
293 def test_base_url_without_service(self):
294 self.filters = {
295 'endpoint_type': 'publicURL',
296 'region': 'FakeRegion'
297 }
298 self.assertRaises(exceptions.EndpointNotFound,
299 self._test_base_url_helper, None, self.filters)
300
301 def test_base_url_with_api_version_filter(self):
302 self.filters = {
303 'service': 'compute',
304 'endpoint_type': 'publicURL',
305 'region': 'FakeRegion',
306 'api_version': 'v12'
307 }
308 expected = self._get_result_url_from_endpoint(
309 self._endpoints[0]['endpoints'][1], replacement='v12')
310 self._test_base_url_helper(expected, self.filters)
311
312 def test_base_url_with_skip_path_filter(self):
313 self.filters = {
314 'service': 'compute',
315 'endpoint_type': 'publicURL',
316 'region': 'FakeRegion',
317 'skip_path': True
318 }
319 expected = 'http://fake_url/'
320 self._test_base_url_helper(expected, self.filters)
321
Andrea Frittolidbd02512014-03-21 10:06:19 +0000322 def test_token_not_expired(self):
323 expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
324 auth_data = self._auth_data_with_expiry(
325 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
326 self.assertFalse(self.auth_provider.is_expired(auth_data))
327
328 def test_token_expired(self):
329 expiry_data = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
330 auth_data = self._auth_data_with_expiry(
331 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
332 self.assertTrue(self.auth_provider.is_expired(auth_data))
333
334 def test_token_not_expired_to_be_renewed(self):
335 expiry_data = datetime.datetime.utcnow() + \
336 self.auth_provider.token_expiry_threshold / 2
337 auth_data = self._auth_data_with_expiry(
338 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
339 self.assertTrue(self.auth_provider.is_expired(auth_data))
340
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500341
342class TestKeystoneV3AuthProvider(TestKeystoneV2AuthProvider):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500343 _endpoints = fake_identity.IDENTITY_V3_RESPONSE['token']['catalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500344 _auth_provider_class = auth.KeystoneV3AuthProvider
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100345 credentials = fake_credentials.FakeKeystoneV3Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500346
347 def setUp(self):
348 super(TestKeystoneV3AuthProvider, self).setUp()
349 self.stubs.Set(http.ClosingHttp, 'request',
350 fake_identity._fake_v3_response)
351
352 def _get_fake_alt_identity(self):
353 return fake_identity.ALT_IDENTITY_V3['token']
354
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500355 def _get_result_url_from_endpoint(self, ep, replacement=None):
356 if replacement:
357 return ep['url'].replace('v3', replacement)
358 return ep['url']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500359
Andrea Frittolidbd02512014-03-21 10:06:19 +0000360 def _auth_data_with_expiry(self, date_as_string):
361 token, access = self.auth_provider.auth_data
362 access['expires_at'] = date_as_string
363 return token, access
364
Andrea Frittoli2095d242014-03-20 08:36:23 +0000365 def _get_from_fake_identity(self, attr):
366 token = fake_identity.IDENTITY_V3_RESPONSE['token']
367 if attr == 'user_id':
368 return token['user']['id']
369 elif attr == 'project_id':
370 return token['project']['id']
371 elif attr == 'user_domain_id':
372 return token['user']['domain']['id']
373 elif attr == 'project_domain_id':
374 return token['project']['domain']['id']
375
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100376 def test_check_credentials_missing_attribute(self):
377 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000378 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100379 for attr in ['username', 'password', 'user_domain_name',
380 'project_domain_name']:
381 cred = copy.copy(self.credentials)
382 del cred[attr]
383 self.assertFalse(self.auth_provider.check_credentials(cred),
384 "Credentials should be invalid without %s" % attr)
385
386 def test_check_domain_credentials_missing_attribute(self):
387 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000388 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100389 domain_creds = fake_credentials.FakeKeystoneV3DomainCredentials()
390 for attr in ['username', 'password', 'user_domain_name']:
391 cred = copy.copy(domain_creds)
392 del cred[attr]
393 self.assertFalse(self.auth_provider.check_credentials(cred),
394 "Credentials should be invalid without %s" % attr)
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500395
Andrea Frittoli2095d242014-03-20 08:36:23 +0000396 def test_fill_credentials(self):
397 self.auth_provider.fill_credentials()
398 creds = self.auth_provider.credentials
399 for attr in ['user_id', 'project_id', 'user_domain_id',
400 'project_domain_id']:
401 self.assertEqual(self._get_from_fake_identity(attr),
402 getattr(creds, attr))
403
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500404 # Overwrites v2 test
405 def test_base_url_to_get_admin_endpoint(self):
406 self.filters = {
407 'service': 'compute',
408 'endpoint_type': 'admin',
409 'region': 'MiddleEarthRegion'
410 }
411 expected = self._get_result_url_from_endpoint(
412 self._endpoints[0]['endpoints'][2])
413 self._test_base_url_helper(expected, self.filters)