blob: a19178195b62459bb0efbc177a5710f1325974f3 [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
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050022from tempest import config
23from tempest import exceptions
Ken'ichi Ohmichi03010dc2015-01-08 08:16:25 +000024from tempest.services.identity.json import identity_client as v2_client
25from tempest.services.identity.v3.json import identity_client as v3_client
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050026from tempest.tests import base
27from 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
Ken'ichi Ohmichic5d607d2015-01-15 07:02:06 +000033def fake_get_default_credentials(credential_type, fill_in=True):
34 return fake_credentials.FakeCredentials()
35
36
37def fake_get_credentials(credential_type=None, fill_in=True, **kwargs):
38 return fake_credentials.FakeCredentials()
39
40
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050041class BaseAuthTestsSetUp(base.TestCase):
42 _auth_provider_class = None
Andrea Frittoli7d707a52014-04-06 11:46:32 +010043 credentials = fake_credentials.FakeCredentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050044
45 def _auth(self, credentials, **params):
46 """
47 returns auth method according to keystone
48 """
49 return self._auth_provider_class(credentials, **params)
50
51 def setUp(self):
52 super(BaseAuthTestsSetUp, self).setUp()
Matthew Treinishff598482014-02-28 16:13:58 -050053 self.useFixture(fake_config.ConfigFixture())
54 self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050055 self.fake_http = fake_http.fake_httplib2(return_type=200)
Ken'ichi Ohmichic5d607d2015-01-15 07:02:06 +000056 self.stubs.Set(auth, 'get_credentials', fake_get_credentials)
Andrea Frittolib1b04bb2014-04-06 11:57:07 +010057 self.stubs.Set(auth, 'get_default_credentials',
Ken'ichi Ohmichic5d607d2015-01-15 07:02:06 +000058 fake_get_default_credentials)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050059 self.auth_provider = self._auth(self.credentials)
60
61
62class TestBaseAuthProvider(BaseAuthTestsSetUp):
63 """
64 This tests auth.AuthProvider class which is base for the other so we
65 obviously don't test not implemented method or the ones which strongly
66 depends on them.
67 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050068
Marc Koderer235e4f52014-07-22 10:15:08 +020069 class FakeAuthProviderImpl(auth.AuthProvider):
70 def _decorate_request():
71 pass
72
73 def _fill_credentials():
74 pass
75
76 def _get_auth():
77 pass
78
79 def base_url():
80 pass
81
82 def is_expired():
83 pass
84
85 _auth_provider_class = FakeAuthProviderImpl
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050086
87 def test_check_credentials_bad_type(self):
88 self.assertFalse(self.auth_provider.check_credentials([]))
89
Andrea Frittoli7d707a52014-04-06 11:46:32 +010090 def test_instantiate_with_dict(self):
91 # Dict credentials are only supported for backward compatibility
92 auth_provider = self._auth(credentials={})
93 self.assertIsInstance(auth_provider.credentials, auth.Credentials)
94
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050095 def test_auth_data_property_when_cache_exists(self):
96 self.auth_provider.cache = 'foo'
97 self.useFixture(mockpatch.PatchObject(self.auth_provider,
98 'is_expired',
99 return_value=False))
100 self.assertEqual('foo', getattr(self.auth_provider, 'auth_data'))
101
102 def test_delete_auth_data_property_through_deleter(self):
103 self.auth_provider.cache = 'foo'
104 del self.auth_provider.auth_data
105 self.assertIsNone(self.auth_provider.cache)
106
107 def test_delete_auth_data_property_through_clear_auth(self):
108 self.auth_provider.cache = 'foo'
109 self.auth_provider.clear_auth()
110 self.assertIsNone(self.auth_provider.cache)
111
112 def test_set_and_reset_alt_auth_data(self):
113 self.auth_provider.set_alt_auth_data('foo', 'bar')
114 self.assertEqual(self.auth_provider.alt_part, 'foo')
115 self.assertEqual(self.auth_provider.alt_auth_data, 'bar')
116
117 self.auth_provider.reset_alt_auth_data()
118 self.assertIsNone(self.auth_provider.alt_part)
119 self.assertIsNone(self.auth_provider.alt_auth_data)
120
Marc Koderer235e4f52014-07-22 10:15:08 +0200121 def test_auth_class(self):
122 self.assertRaises(TypeError,
123 auth.AuthProvider,
124 fake_credentials.FakeCredentials)
Andrea Frittoli2095d242014-03-20 08:36:23 +0000125
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500126
127class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500128 _endpoints = fake_identity.IDENTITY_V2_RESPONSE['access']['serviceCatalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500129 _auth_provider_class = auth.KeystoneV2AuthProvider
Andrea Frittoli7d707a52014-04-06 11:46:32 +0100130 credentials = fake_credentials.FakeKeystoneV2Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500131
132 def setUp(self):
133 super(TestKeystoneV2AuthProvider, self).setUp()
Ken'ichi Ohmichi03010dc2015-01-08 08:16:25 +0000134 self.stubs.Set(v2_client.TokenClientJSON, 'raw_request',
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500135 fake_identity._fake_v2_response)
136 self.target_url = 'test_api'
137
138 def _get_fake_alt_identity(self):
139 return fake_identity.ALT_IDENTITY_V2_RESPONSE['access']
140
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500141 def _get_result_url_from_endpoint(self, ep, endpoint_type='publicURL',
142 replacement=None):
143 if replacement:
144 return ep[endpoint_type].replace('v2', replacement)
145 return ep[endpoint_type]
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500146
147 def _get_token_from_fake_identity(self):
148 return fake_identity.TOKEN
149
Andrea Frittoli2095d242014-03-20 08:36:23 +0000150 def _get_from_fake_identity(self, attr):
151 access = fake_identity.IDENTITY_V2_RESPONSE['access']
152 if attr == 'user_id':
153 return access['user']['id']
154 elif attr == 'tenant_id':
155 return access['token']['tenant']['id']
156
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500157 def _test_request_helper(self, filters, expected):
158 url, headers, body = self.auth_provider.auth_request('GET',
159 self.target_url,
160 filters=filters)
161
162 self.assertEqual(expected['url'], url)
163 self.assertEqual(expected['token'], headers['X-Auth-Token'])
164 self.assertEqual(expected['body'], body)
165
Andrea Frittolidbd02512014-03-21 10:06:19 +0000166 def _auth_data_with_expiry(self, date_as_string):
167 token, access = self.auth_provider.auth_data
168 access['token']['expires'] = date_as_string
169 return token, access
170
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500171 def test_request(self):
172 filters = {
173 'service': 'compute',
174 'endpoint_type': 'publicURL',
175 'region': 'FakeRegion'
176 }
177
178 url = self._get_result_url_from_endpoint(
179 self._endpoints[0]['endpoints'][1]) + '/' + self.target_url
180
181 expected = {
182 'body': None,
183 'url': url,
184 'token': self._get_token_from_fake_identity(),
185 }
186 self._test_request_helper(filters, expected)
187
188 def test_request_with_alt_auth_cleans_alt(self):
189 self.auth_provider.set_alt_auth_data(
190 'body',
191 (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
192 self.test_request()
193 # Assert alt auth data is clear after it
194 self.assertIsNone(self.auth_provider.alt_part)
195 self.assertIsNone(self.auth_provider.alt_auth_data)
196
197 def test_request_with_alt_part_without_alt_data(self):
198 """
199 Assert that when alt_part is defined, the corresponding original
200 request element is kept the same.
201 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500202 filters = {
203 'service': 'compute',
204 'endpoint_type': 'publicURL',
205 'region': 'fakeRegion'
206 }
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500207 self.auth_provider.set_alt_auth_data('url', None)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500208
209 url, headers, body = self.auth_provider.auth_request('GET',
210 self.target_url,
211 filters=filters)
212
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500213 self.assertEqual(url, self.target_url)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500214 self.assertEqual(self._get_token_from_fake_identity(),
215 headers['X-Auth-Token'])
216 self.assertEqual(body, None)
217
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500218 def test_request_with_bad_service(self):
219 filters = {
220 'service': 'BAD_SERVICE',
221 'endpoint_type': 'publicURL',
222 'region': 'fakeRegion'
223 }
224 self.assertRaises(exceptions.EndpointNotFound,
225 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500226 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500227
228 def test_request_without_service(self):
229 filters = {
230 'service': None,
231 'endpoint_type': 'publicURL',
232 'region': 'fakeRegion'
233 }
234 self.assertRaises(exceptions.EndpointNotFound,
235 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500236 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500237
238 def test_check_credentials_missing_attribute(self):
239 for attr in ['username', 'password']:
240 cred = copy.copy(self.credentials)
241 del cred[attr]
242 self.assertFalse(self.auth_provider.check_credentials(cred))
243
Andrea Frittoli2095d242014-03-20 08:36:23 +0000244 def test_fill_credentials(self):
245 self.auth_provider.fill_credentials()
246 creds = self.auth_provider.credentials
247 for attr in ['user_id', 'tenant_id']:
248 self.assertEqual(self._get_from_fake_identity(attr),
249 getattr(creds, attr))
250
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500251 def _test_base_url_helper(self, expected_url, filters,
252 auth_data=None):
253
254 url = self.auth_provider.base_url(filters, auth_data)
255 self.assertEqual(url, expected_url)
256
257 def test_base_url(self):
258 self.filters = {
259 'service': 'compute',
260 'endpoint_type': 'publicURL',
261 'region': 'FakeRegion'
262 }
263 expected = self._get_result_url_from_endpoint(
264 self._endpoints[0]['endpoints'][1])
265 self._test_base_url_helper(expected, self.filters)
266
267 def test_base_url_to_get_admin_endpoint(self):
268 self.filters = {
269 'service': 'compute',
270 'endpoint_type': 'adminURL',
271 'region': 'FakeRegion'
272 }
273 expected = self._get_result_url_from_endpoint(
274 self._endpoints[0]['endpoints'][1], endpoint_type='adminURL')
275 self._test_base_url_helper(expected, self.filters)
276
277 def test_base_url_unknown_region(self):
278 """
279 Assure that if the region is unknow the first endpoint is returned.
280 """
281 self.filters = {
282 'service': 'compute',
283 'endpoint_type': 'publicURL',
284 'region': 'AintNoBodyKnowThisRegion'
285 }
286 expected = self._get_result_url_from_endpoint(
287 self._endpoints[0]['endpoints'][0])
288 self._test_base_url_helper(expected, self.filters)
289
290 def test_base_url_with_non_existent_service(self):
291 self.filters = {
292 'service': 'BAD_SERVICE',
293 'endpoint_type': 'publicURL',
294 'region': 'FakeRegion'
295 }
296 self.assertRaises(exceptions.EndpointNotFound,
297 self._test_base_url_helper, None, self.filters)
298
299 def test_base_url_without_service(self):
300 self.filters = {
301 'endpoint_type': 'publicURL',
302 'region': 'FakeRegion'
303 }
304 self.assertRaises(exceptions.EndpointNotFound,
305 self._test_base_url_helper, None, self.filters)
306
307 def test_base_url_with_api_version_filter(self):
308 self.filters = {
309 'service': 'compute',
310 'endpoint_type': 'publicURL',
311 'region': 'FakeRegion',
312 'api_version': 'v12'
313 }
314 expected = self._get_result_url_from_endpoint(
315 self._endpoints[0]['endpoints'][1], replacement='v12')
316 self._test_base_url_helper(expected, self.filters)
317
318 def test_base_url_with_skip_path_filter(self):
319 self.filters = {
320 'service': 'compute',
321 'endpoint_type': 'publicURL',
322 'region': 'FakeRegion',
323 'skip_path': True
324 }
325 expected = 'http://fake_url/'
326 self._test_base_url_helper(expected, self.filters)
327
Andrea Frittolidbd02512014-03-21 10:06:19 +0000328 def test_token_not_expired(self):
329 expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
330 auth_data = self._auth_data_with_expiry(
331 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
332 self.assertFalse(self.auth_provider.is_expired(auth_data))
333
334 def test_token_expired(self):
335 expiry_data = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
336 auth_data = self._auth_data_with_expiry(
337 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
338 self.assertTrue(self.auth_provider.is_expired(auth_data))
339
340 def test_token_not_expired_to_be_renewed(self):
341 expiry_data = datetime.datetime.utcnow() + \
342 self.auth_provider.token_expiry_threshold / 2
343 auth_data = self._auth_data_with_expiry(
344 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
345 self.assertTrue(self.auth_provider.is_expired(auth_data))
346
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500347
348class TestKeystoneV3AuthProvider(TestKeystoneV2AuthProvider):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500349 _endpoints = fake_identity.IDENTITY_V3_RESPONSE['token']['catalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500350 _auth_provider_class = auth.KeystoneV3AuthProvider
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100351 credentials = fake_credentials.FakeKeystoneV3Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500352
353 def setUp(self):
354 super(TestKeystoneV3AuthProvider, self).setUp()
Ken'ichi Ohmichi03010dc2015-01-08 08:16:25 +0000355 self.stubs.Set(v3_client.V3TokenClientJSON, 'raw_request',
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500356 fake_identity._fake_v3_response)
357
358 def _get_fake_alt_identity(self):
359 return fake_identity.ALT_IDENTITY_V3['token']
360
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500361 def _get_result_url_from_endpoint(self, ep, replacement=None):
362 if replacement:
363 return ep['url'].replace('v3', replacement)
364 return ep['url']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500365
Andrea Frittolidbd02512014-03-21 10:06:19 +0000366 def _auth_data_with_expiry(self, date_as_string):
367 token, access = self.auth_provider.auth_data
368 access['expires_at'] = date_as_string
369 return token, access
370
Andrea Frittoli2095d242014-03-20 08:36:23 +0000371 def _get_from_fake_identity(self, attr):
372 token = fake_identity.IDENTITY_V3_RESPONSE['token']
373 if attr == 'user_id':
374 return token['user']['id']
375 elif attr == 'project_id':
376 return token['project']['id']
377 elif attr == 'user_domain_id':
378 return token['user']['domain']['id']
379 elif attr == 'project_domain_id':
380 return token['project']['domain']['id']
381
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100382 def test_check_credentials_missing_attribute(self):
383 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000384 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100385 for attr in ['username', 'password', 'user_domain_name',
386 'project_domain_name']:
387 cred = copy.copy(self.credentials)
388 del cred[attr]
389 self.assertFalse(self.auth_provider.check_credentials(cred),
390 "Credentials should be invalid without %s" % attr)
391
392 def test_check_domain_credentials_missing_attribute(self):
393 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000394 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100395 domain_creds = fake_credentials.FakeKeystoneV3DomainCredentials()
396 for attr in ['username', 'password', 'user_domain_name']:
397 cred = copy.copy(domain_creds)
398 del cred[attr]
399 self.assertFalse(self.auth_provider.check_credentials(cred),
400 "Credentials should be invalid without %s" % attr)
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500401
Andrea Frittoli2095d242014-03-20 08:36:23 +0000402 def test_fill_credentials(self):
403 self.auth_provider.fill_credentials()
404 creds = self.auth_provider.credentials
405 for attr in ['user_id', 'project_id', 'user_domain_id',
406 'project_domain_id']:
407 self.assertEqual(self._get_from_fake_identity(attr),
408 getattr(creds, attr))
409
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500410 # Overwrites v2 test
411 def test_base_url_to_get_admin_endpoint(self):
412 self.filters = {
413 'service': 'compute',
414 'endpoint_type': 'admin',
415 'region': 'MiddleEarthRegion'
416 }
417 expected = self._get_result_url_from_endpoint(
418 self._endpoints[0]['endpoints'][2])
419 self._test_base_url_helper(expected, self.filters)