blob: c236dbe9aad4882ff423b2c918b35955a8bed408 [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
ghanshyamc0edda02015-02-06 15:51:40 +090024from tempest.services.identity.json import token_client as v2_client
25from tempest.services.identity.v3.json import token_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
Andrea Frittoli878d5ab2015-01-30 13:22:50 +000033def fake_get_credentials(fill_in=True, identity_version='v2', **kwargs):
Ken'ichi Ohmichic5d607d2015-01-15 07:02:06 +000034 return fake_credentials.FakeCredentials()
35
36
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050037class BaseAuthTestsSetUp(base.TestCase):
38 _auth_provider_class = None
Andrea Frittoli7d707a52014-04-06 11:46:32 +010039 credentials = fake_credentials.FakeCredentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050040
ghanshyam5ff763f2015-02-18 16:15:58 +090041 def _auth(self, credentials, auth_url, **params):
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050042 """
43 returns auth method according to keystone
44 """
ghanshyam5ff763f2015-02-18 16:15:58 +090045 return self._auth_provider_class(credentials, auth_url, **params)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050046
47 def setUp(self):
48 super(BaseAuthTestsSetUp, self).setUp()
Matthew Treinishff598482014-02-28 16:13:58 -050049 self.useFixture(fake_config.ConfigFixture())
50 self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050051 self.fake_http = fake_http.fake_httplib2(return_type=200)
Ken'ichi Ohmichic5d607d2015-01-15 07:02:06 +000052 self.stubs.Set(auth, 'get_credentials', fake_get_credentials)
ghanshyam5ff763f2015-02-18 16:15:58 +090053 self.auth_provider = self._auth(self.credentials,
54 fake_identity.FAKE_AUTH_URL)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050055
56
57class TestBaseAuthProvider(BaseAuthTestsSetUp):
58 """
59 This tests auth.AuthProvider class which is base for the other so we
60 obviously don't test not implemented method or the ones which strongly
61 depends on them.
62 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050063
Marc Koderer235e4f52014-07-22 10:15:08 +020064 class FakeAuthProviderImpl(auth.AuthProvider):
65 def _decorate_request():
66 pass
67
68 def _fill_credentials():
69 pass
70
71 def _get_auth():
72 pass
73
74 def base_url():
75 pass
76
77 def is_expired():
78 pass
79
80 _auth_provider_class = FakeAuthProviderImpl
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050081
ghanshyam5ff763f2015-02-18 16:15:58 +090082 def _auth(self, credentials, auth_url, **params):
83 """
84 returns auth method according to keystone
85 """
86 return self._auth_provider_class(credentials, **params)
87
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050088 def test_check_credentials_bad_type(self):
89 self.assertFalse(self.auth_provider.check_credentials([]))
90
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050091 def test_auth_data_property_when_cache_exists(self):
92 self.auth_provider.cache = 'foo'
93 self.useFixture(mockpatch.PatchObject(self.auth_provider,
94 'is_expired',
95 return_value=False))
96 self.assertEqual('foo', getattr(self.auth_provider, 'auth_data'))
97
98 def test_delete_auth_data_property_through_deleter(self):
99 self.auth_provider.cache = 'foo'
100 del self.auth_provider.auth_data
101 self.assertIsNone(self.auth_provider.cache)
102
103 def test_delete_auth_data_property_through_clear_auth(self):
104 self.auth_provider.cache = 'foo'
105 self.auth_provider.clear_auth()
106 self.assertIsNone(self.auth_provider.cache)
107
108 def test_set_and_reset_alt_auth_data(self):
109 self.auth_provider.set_alt_auth_data('foo', 'bar')
110 self.assertEqual(self.auth_provider.alt_part, 'foo')
111 self.assertEqual(self.auth_provider.alt_auth_data, 'bar')
112
113 self.auth_provider.reset_alt_auth_data()
114 self.assertIsNone(self.auth_provider.alt_part)
115 self.assertIsNone(self.auth_provider.alt_auth_data)
116
Marc Koderer235e4f52014-07-22 10:15:08 +0200117 def test_auth_class(self):
118 self.assertRaises(TypeError,
119 auth.AuthProvider,
120 fake_credentials.FakeCredentials)
Andrea Frittoli2095d242014-03-20 08:36:23 +0000121
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500122
123class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500124 _endpoints = fake_identity.IDENTITY_V2_RESPONSE['access']['serviceCatalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500125 _auth_provider_class = auth.KeystoneV2AuthProvider
Andrea Frittoli7d707a52014-04-06 11:46:32 +0100126 credentials = fake_credentials.FakeKeystoneV2Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500127
128 def setUp(self):
129 super(TestKeystoneV2AuthProvider, self).setUp()
Ken'ichi Ohmichi03010dc2015-01-08 08:16:25 +0000130 self.stubs.Set(v2_client.TokenClientJSON, 'raw_request',
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500131 fake_identity._fake_v2_response)
132 self.target_url = 'test_api'
133
134 def _get_fake_alt_identity(self):
135 return fake_identity.ALT_IDENTITY_V2_RESPONSE['access']
136
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500137 def _get_result_url_from_endpoint(self, ep, endpoint_type='publicURL',
138 replacement=None):
139 if replacement:
140 return ep[endpoint_type].replace('v2', replacement)
141 return ep[endpoint_type]
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500142
143 def _get_token_from_fake_identity(self):
144 return fake_identity.TOKEN
145
Andrea Frittoli2095d242014-03-20 08:36:23 +0000146 def _get_from_fake_identity(self, attr):
147 access = fake_identity.IDENTITY_V2_RESPONSE['access']
148 if attr == 'user_id':
149 return access['user']['id']
150 elif attr == 'tenant_id':
151 return access['token']['tenant']['id']
152
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500153 def _test_request_helper(self, filters, expected):
154 url, headers, body = self.auth_provider.auth_request('GET',
155 self.target_url,
156 filters=filters)
157
158 self.assertEqual(expected['url'], url)
159 self.assertEqual(expected['token'], headers['X-Auth-Token'])
160 self.assertEqual(expected['body'], body)
161
Andrea Frittolidbd02512014-03-21 10:06:19 +0000162 def _auth_data_with_expiry(self, date_as_string):
163 token, access = self.auth_provider.auth_data
164 access['token']['expires'] = date_as_string
165 return token, access
166
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500167 def test_request(self):
168 filters = {
169 'service': 'compute',
170 'endpoint_type': 'publicURL',
171 'region': 'FakeRegion'
172 }
173
174 url = self._get_result_url_from_endpoint(
175 self._endpoints[0]['endpoints'][1]) + '/' + self.target_url
176
177 expected = {
178 'body': None,
179 'url': url,
180 'token': self._get_token_from_fake_identity(),
181 }
182 self._test_request_helper(filters, expected)
183
184 def test_request_with_alt_auth_cleans_alt(self):
185 self.auth_provider.set_alt_auth_data(
186 'body',
187 (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
188 self.test_request()
189 # Assert alt auth data is clear after it
190 self.assertIsNone(self.auth_provider.alt_part)
191 self.assertIsNone(self.auth_provider.alt_auth_data)
192
193 def test_request_with_alt_part_without_alt_data(self):
194 """
195 Assert that when alt_part is defined, the corresponding original
196 request element is kept the same.
197 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500198 filters = {
199 'service': 'compute',
200 'endpoint_type': 'publicURL',
201 'region': 'fakeRegion'
202 }
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500203 self.auth_provider.set_alt_auth_data('url', None)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500204
205 url, headers, body = self.auth_provider.auth_request('GET',
206 self.target_url,
207 filters=filters)
208
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500209 self.assertEqual(url, self.target_url)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500210 self.assertEqual(self._get_token_from_fake_identity(),
211 headers['X-Auth-Token'])
212 self.assertEqual(body, None)
213
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500214 def test_request_with_bad_service(self):
215 filters = {
216 'service': 'BAD_SERVICE',
217 'endpoint_type': 'publicURL',
218 'region': 'fakeRegion'
219 }
220 self.assertRaises(exceptions.EndpointNotFound,
221 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500222 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500223
224 def test_request_without_service(self):
225 filters = {
226 'service': None,
227 'endpoint_type': 'publicURL',
228 'region': 'fakeRegion'
229 }
230 self.assertRaises(exceptions.EndpointNotFound,
231 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500232 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500233
234 def test_check_credentials_missing_attribute(self):
235 for attr in ['username', 'password']:
236 cred = copy.copy(self.credentials)
237 del cred[attr]
238 self.assertFalse(self.auth_provider.check_credentials(cred))
239
Andrea Frittoli2095d242014-03-20 08:36:23 +0000240 def test_fill_credentials(self):
241 self.auth_provider.fill_credentials()
242 creds = self.auth_provider.credentials
243 for attr in ['user_id', 'tenant_id']:
244 self.assertEqual(self._get_from_fake_identity(attr),
245 getattr(creds, attr))
246
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500247 def _test_base_url_helper(self, expected_url, filters,
248 auth_data=None):
249
250 url = self.auth_provider.base_url(filters, auth_data)
251 self.assertEqual(url, expected_url)
252
253 def test_base_url(self):
254 self.filters = {
255 'service': 'compute',
256 'endpoint_type': 'publicURL',
257 'region': 'FakeRegion'
258 }
259 expected = self._get_result_url_from_endpoint(
260 self._endpoints[0]['endpoints'][1])
261 self._test_base_url_helper(expected, self.filters)
262
263 def test_base_url_to_get_admin_endpoint(self):
264 self.filters = {
265 'service': 'compute',
266 'endpoint_type': 'adminURL',
267 'region': 'FakeRegion'
268 }
269 expected = self._get_result_url_from_endpoint(
270 self._endpoints[0]['endpoints'][1], endpoint_type='adminURL')
271 self._test_base_url_helper(expected, self.filters)
272
273 def test_base_url_unknown_region(self):
274 """
275 Assure that if the region is unknow the first endpoint is returned.
276 """
277 self.filters = {
278 'service': 'compute',
279 'endpoint_type': 'publicURL',
280 'region': 'AintNoBodyKnowThisRegion'
281 }
282 expected = self._get_result_url_from_endpoint(
283 self._endpoints[0]['endpoints'][0])
284 self._test_base_url_helper(expected, self.filters)
285
286 def test_base_url_with_non_existent_service(self):
287 self.filters = {
288 'service': 'BAD_SERVICE',
289 'endpoint_type': 'publicURL',
290 'region': 'FakeRegion'
291 }
292 self.assertRaises(exceptions.EndpointNotFound,
293 self._test_base_url_helper, None, self.filters)
294
295 def test_base_url_without_service(self):
296 self.filters = {
297 'endpoint_type': 'publicURL',
298 'region': 'FakeRegion'
299 }
300 self.assertRaises(exceptions.EndpointNotFound,
301 self._test_base_url_helper, None, self.filters)
302
303 def test_base_url_with_api_version_filter(self):
304 self.filters = {
305 'service': 'compute',
306 'endpoint_type': 'publicURL',
307 'region': 'FakeRegion',
308 'api_version': 'v12'
309 }
310 expected = self._get_result_url_from_endpoint(
311 self._endpoints[0]['endpoints'][1], replacement='v12')
312 self._test_base_url_helper(expected, self.filters)
313
314 def test_base_url_with_skip_path_filter(self):
315 self.filters = {
316 'service': 'compute',
317 'endpoint_type': 'publicURL',
318 'region': 'FakeRegion',
319 'skip_path': True
320 }
321 expected = 'http://fake_url/'
322 self._test_base_url_helper(expected, self.filters)
323
Andrea Frittolidbd02512014-03-21 10:06:19 +0000324 def test_token_not_expired(self):
325 expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
326 auth_data = self._auth_data_with_expiry(
327 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
328 self.assertFalse(self.auth_provider.is_expired(auth_data))
329
330 def test_token_expired(self):
331 expiry_data = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
332 auth_data = self._auth_data_with_expiry(
333 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
334 self.assertTrue(self.auth_provider.is_expired(auth_data))
335
336 def test_token_not_expired_to_be_renewed(self):
337 expiry_data = datetime.datetime.utcnow() + \
338 self.auth_provider.token_expiry_threshold / 2
339 auth_data = self._auth_data_with_expiry(
340 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
341 self.assertTrue(self.auth_provider.is_expired(auth_data))
342
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500343
344class TestKeystoneV3AuthProvider(TestKeystoneV2AuthProvider):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500345 _endpoints = fake_identity.IDENTITY_V3_RESPONSE['token']['catalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500346 _auth_provider_class = auth.KeystoneV3AuthProvider
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100347 credentials = fake_credentials.FakeKeystoneV3Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500348
349 def setUp(self):
350 super(TestKeystoneV3AuthProvider, self).setUp()
Ken'ichi Ohmichi03010dc2015-01-08 08:16:25 +0000351 self.stubs.Set(v3_client.V3TokenClientJSON, 'raw_request',
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500352 fake_identity._fake_v3_response)
353
354 def _get_fake_alt_identity(self):
355 return fake_identity.ALT_IDENTITY_V3['token']
356
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500357 def _get_result_url_from_endpoint(self, ep, replacement=None):
358 if replacement:
359 return ep['url'].replace('v3', replacement)
360 return ep['url']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500361
Andrea Frittolidbd02512014-03-21 10:06:19 +0000362 def _auth_data_with_expiry(self, date_as_string):
363 token, access = self.auth_provider.auth_data
364 access['expires_at'] = date_as_string
365 return token, access
366
Andrea Frittoli2095d242014-03-20 08:36:23 +0000367 def _get_from_fake_identity(self, attr):
368 token = fake_identity.IDENTITY_V3_RESPONSE['token']
369 if attr == 'user_id':
370 return token['user']['id']
371 elif attr == 'project_id':
372 return token['project']['id']
373 elif attr == 'user_domain_id':
374 return token['user']['domain']['id']
375 elif attr == 'project_domain_id':
376 return token['project']['domain']['id']
377
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100378 def test_check_credentials_missing_attribute(self):
379 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000380 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100381 for attr in ['username', 'password', 'user_domain_name',
382 'project_domain_name']:
383 cred = copy.copy(self.credentials)
384 del cred[attr]
385 self.assertFalse(self.auth_provider.check_credentials(cred),
386 "Credentials should be invalid without %s" % attr)
387
388 def test_check_domain_credentials_missing_attribute(self):
389 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000390 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100391 domain_creds = fake_credentials.FakeKeystoneV3DomainCredentials()
392 for attr in ['username', 'password', 'user_domain_name']:
393 cred = copy.copy(domain_creds)
394 del cred[attr]
395 self.assertFalse(self.auth_provider.check_credentials(cred),
396 "Credentials should be invalid without %s" % attr)
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500397
Andrea Frittoli2095d242014-03-20 08:36:23 +0000398 def test_fill_credentials(self):
399 self.auth_provider.fill_credentials()
400 creds = self.auth_provider.credentials
401 for attr in ['user_id', 'project_id', 'user_domain_id',
402 'project_domain_id']:
403 self.assertEqual(self._get_from_fake_identity(attr),
404 getattr(creds, attr))
405
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500406 # Overwrites v2 test
407 def test_base_url_to_get_admin_endpoint(self):
408 self.filters = {
409 'service': 'compute',
410 'endpoint_type': 'admin',
411 'region': 'MiddleEarthRegion'
412 }
413 expected = self._get_result_url_from_endpoint(
414 self._endpoints[0]['endpoints'][2])
415 self._test_base_url_helper(expected, self.filters)