blob: 0317ad6400bc82c35269547b4035ad29d990e8fb [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
41 def _auth(self, credentials, **params):
42 """
43 returns auth method according to keystone
44 """
45 return self._auth_provider_class(credentials, **params)
46
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)
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
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050084 def test_auth_data_property_when_cache_exists(self):
85 self.auth_provider.cache = 'foo'
86 self.useFixture(mockpatch.PatchObject(self.auth_provider,
87 'is_expired',
88 return_value=False))
89 self.assertEqual('foo', getattr(self.auth_provider, 'auth_data'))
90
91 def test_delete_auth_data_property_through_deleter(self):
92 self.auth_provider.cache = 'foo'
93 del self.auth_provider.auth_data
94 self.assertIsNone(self.auth_provider.cache)
95
96 def test_delete_auth_data_property_through_clear_auth(self):
97 self.auth_provider.cache = 'foo'
98 self.auth_provider.clear_auth()
99 self.assertIsNone(self.auth_provider.cache)
100
101 def test_set_and_reset_alt_auth_data(self):
102 self.auth_provider.set_alt_auth_data('foo', 'bar')
103 self.assertEqual(self.auth_provider.alt_part, 'foo')
104 self.assertEqual(self.auth_provider.alt_auth_data, 'bar')
105
106 self.auth_provider.reset_alt_auth_data()
107 self.assertIsNone(self.auth_provider.alt_part)
108 self.assertIsNone(self.auth_provider.alt_auth_data)
109
Marc Koderer235e4f52014-07-22 10:15:08 +0200110 def test_auth_class(self):
111 self.assertRaises(TypeError,
112 auth.AuthProvider,
113 fake_credentials.FakeCredentials)
Andrea Frittoli2095d242014-03-20 08:36:23 +0000114
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500115
116class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500117 _endpoints = fake_identity.IDENTITY_V2_RESPONSE['access']['serviceCatalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500118 _auth_provider_class = auth.KeystoneV2AuthProvider
Andrea Frittoli7d707a52014-04-06 11:46:32 +0100119 credentials = fake_credentials.FakeKeystoneV2Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500120
121 def setUp(self):
122 super(TestKeystoneV2AuthProvider, self).setUp()
Ken'ichi Ohmichi03010dc2015-01-08 08:16:25 +0000123 self.stubs.Set(v2_client.TokenClientJSON, 'raw_request',
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500124 fake_identity._fake_v2_response)
125 self.target_url = 'test_api'
126
127 def _get_fake_alt_identity(self):
128 return fake_identity.ALT_IDENTITY_V2_RESPONSE['access']
129
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500130 def _get_result_url_from_endpoint(self, ep, endpoint_type='publicURL',
131 replacement=None):
132 if replacement:
133 return ep[endpoint_type].replace('v2', replacement)
134 return ep[endpoint_type]
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500135
136 def _get_token_from_fake_identity(self):
137 return fake_identity.TOKEN
138
Andrea Frittoli2095d242014-03-20 08:36:23 +0000139 def _get_from_fake_identity(self, attr):
140 access = fake_identity.IDENTITY_V2_RESPONSE['access']
141 if attr == 'user_id':
142 return access['user']['id']
143 elif attr == 'tenant_id':
144 return access['token']['tenant']['id']
145
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500146 def _test_request_helper(self, filters, expected):
147 url, headers, body = self.auth_provider.auth_request('GET',
148 self.target_url,
149 filters=filters)
150
151 self.assertEqual(expected['url'], url)
152 self.assertEqual(expected['token'], headers['X-Auth-Token'])
153 self.assertEqual(expected['body'], body)
154
Andrea Frittolidbd02512014-03-21 10:06:19 +0000155 def _auth_data_with_expiry(self, date_as_string):
156 token, access = self.auth_provider.auth_data
157 access['token']['expires'] = date_as_string
158 return token, access
159
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500160 def test_request(self):
161 filters = {
162 'service': 'compute',
163 'endpoint_type': 'publicURL',
164 'region': 'FakeRegion'
165 }
166
167 url = self._get_result_url_from_endpoint(
168 self._endpoints[0]['endpoints'][1]) + '/' + self.target_url
169
170 expected = {
171 'body': None,
172 'url': url,
173 'token': self._get_token_from_fake_identity(),
174 }
175 self._test_request_helper(filters, expected)
176
177 def test_request_with_alt_auth_cleans_alt(self):
178 self.auth_provider.set_alt_auth_data(
179 'body',
180 (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
181 self.test_request()
182 # Assert alt auth data is clear after it
183 self.assertIsNone(self.auth_provider.alt_part)
184 self.assertIsNone(self.auth_provider.alt_auth_data)
185
186 def test_request_with_alt_part_without_alt_data(self):
187 """
188 Assert that when alt_part is defined, the corresponding original
189 request element is kept the same.
190 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500191 filters = {
192 'service': 'compute',
193 'endpoint_type': 'publicURL',
194 'region': 'fakeRegion'
195 }
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500196 self.auth_provider.set_alt_auth_data('url', None)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500197
198 url, headers, body = self.auth_provider.auth_request('GET',
199 self.target_url,
200 filters=filters)
201
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500202 self.assertEqual(url, self.target_url)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500203 self.assertEqual(self._get_token_from_fake_identity(),
204 headers['X-Auth-Token'])
205 self.assertEqual(body, None)
206
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500207 def test_request_with_bad_service(self):
208 filters = {
209 'service': 'BAD_SERVICE',
210 'endpoint_type': 'publicURL',
211 'region': 'fakeRegion'
212 }
213 self.assertRaises(exceptions.EndpointNotFound,
214 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500215 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500216
217 def test_request_without_service(self):
218 filters = {
219 'service': None,
220 'endpoint_type': 'publicURL',
221 'region': 'fakeRegion'
222 }
223 self.assertRaises(exceptions.EndpointNotFound,
224 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500225 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500226
227 def test_check_credentials_missing_attribute(self):
228 for attr in ['username', 'password']:
229 cred = copy.copy(self.credentials)
230 del cred[attr]
231 self.assertFalse(self.auth_provider.check_credentials(cred))
232
Andrea Frittoli2095d242014-03-20 08:36:23 +0000233 def test_fill_credentials(self):
234 self.auth_provider.fill_credentials()
235 creds = self.auth_provider.credentials
236 for attr in ['user_id', 'tenant_id']:
237 self.assertEqual(self._get_from_fake_identity(attr),
238 getattr(creds, attr))
239
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500240 def _test_base_url_helper(self, expected_url, filters,
241 auth_data=None):
242
243 url = self.auth_provider.base_url(filters, auth_data)
244 self.assertEqual(url, expected_url)
245
246 def test_base_url(self):
247 self.filters = {
248 'service': 'compute',
249 'endpoint_type': 'publicURL',
250 'region': 'FakeRegion'
251 }
252 expected = self._get_result_url_from_endpoint(
253 self._endpoints[0]['endpoints'][1])
254 self._test_base_url_helper(expected, self.filters)
255
256 def test_base_url_to_get_admin_endpoint(self):
257 self.filters = {
258 'service': 'compute',
259 'endpoint_type': 'adminURL',
260 'region': 'FakeRegion'
261 }
262 expected = self._get_result_url_from_endpoint(
263 self._endpoints[0]['endpoints'][1], endpoint_type='adminURL')
264 self._test_base_url_helper(expected, self.filters)
265
266 def test_base_url_unknown_region(self):
267 """
268 Assure that if the region is unknow the first endpoint is returned.
269 """
270 self.filters = {
271 'service': 'compute',
272 'endpoint_type': 'publicURL',
273 'region': 'AintNoBodyKnowThisRegion'
274 }
275 expected = self._get_result_url_from_endpoint(
276 self._endpoints[0]['endpoints'][0])
277 self._test_base_url_helper(expected, self.filters)
278
279 def test_base_url_with_non_existent_service(self):
280 self.filters = {
281 'service': 'BAD_SERVICE',
282 'endpoint_type': 'publicURL',
283 'region': 'FakeRegion'
284 }
285 self.assertRaises(exceptions.EndpointNotFound,
286 self._test_base_url_helper, None, self.filters)
287
288 def test_base_url_without_service(self):
289 self.filters = {
290 'endpoint_type': 'publicURL',
291 'region': 'FakeRegion'
292 }
293 self.assertRaises(exceptions.EndpointNotFound,
294 self._test_base_url_helper, None, self.filters)
295
296 def test_base_url_with_api_version_filter(self):
297 self.filters = {
298 'service': 'compute',
299 'endpoint_type': 'publicURL',
300 'region': 'FakeRegion',
301 'api_version': 'v12'
302 }
303 expected = self._get_result_url_from_endpoint(
304 self._endpoints[0]['endpoints'][1], replacement='v12')
305 self._test_base_url_helper(expected, self.filters)
306
307 def test_base_url_with_skip_path_filter(self):
308 self.filters = {
309 'service': 'compute',
310 'endpoint_type': 'publicURL',
311 'region': 'FakeRegion',
312 'skip_path': True
313 }
314 expected = 'http://fake_url/'
315 self._test_base_url_helper(expected, self.filters)
316
Andrea Frittolidbd02512014-03-21 10:06:19 +0000317 def test_token_not_expired(self):
318 expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
319 auth_data = self._auth_data_with_expiry(
320 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
321 self.assertFalse(self.auth_provider.is_expired(auth_data))
322
323 def test_token_expired(self):
324 expiry_data = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
325 auth_data = self._auth_data_with_expiry(
326 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
327 self.assertTrue(self.auth_provider.is_expired(auth_data))
328
329 def test_token_not_expired_to_be_renewed(self):
330 expiry_data = datetime.datetime.utcnow() + \
331 self.auth_provider.token_expiry_threshold / 2
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
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500336
337class TestKeystoneV3AuthProvider(TestKeystoneV2AuthProvider):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500338 _endpoints = fake_identity.IDENTITY_V3_RESPONSE['token']['catalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500339 _auth_provider_class = auth.KeystoneV3AuthProvider
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100340 credentials = fake_credentials.FakeKeystoneV3Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500341
342 def setUp(self):
343 super(TestKeystoneV3AuthProvider, self).setUp()
Ken'ichi Ohmichi03010dc2015-01-08 08:16:25 +0000344 self.stubs.Set(v3_client.V3TokenClientJSON, 'raw_request',
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500345 fake_identity._fake_v3_response)
346
347 def _get_fake_alt_identity(self):
348 return fake_identity.ALT_IDENTITY_V3['token']
349
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500350 def _get_result_url_from_endpoint(self, ep, replacement=None):
351 if replacement:
352 return ep['url'].replace('v3', replacement)
353 return ep['url']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500354
Andrea Frittolidbd02512014-03-21 10:06:19 +0000355 def _auth_data_with_expiry(self, date_as_string):
356 token, access = self.auth_provider.auth_data
357 access['expires_at'] = date_as_string
358 return token, access
359
Andrea Frittoli2095d242014-03-20 08:36:23 +0000360 def _get_from_fake_identity(self, attr):
361 token = fake_identity.IDENTITY_V3_RESPONSE['token']
362 if attr == 'user_id':
363 return token['user']['id']
364 elif attr == 'project_id':
365 return token['project']['id']
366 elif attr == 'user_domain_id':
367 return token['user']['domain']['id']
368 elif attr == 'project_domain_id':
369 return token['project']['domain']['id']
370
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100371 def test_check_credentials_missing_attribute(self):
372 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000373 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100374 for attr in ['username', 'password', 'user_domain_name',
375 'project_domain_name']:
376 cred = copy.copy(self.credentials)
377 del cred[attr]
378 self.assertFalse(self.auth_provider.check_credentials(cred),
379 "Credentials should be invalid without %s" % attr)
380
381 def test_check_domain_credentials_missing_attribute(self):
382 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000383 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100384 domain_creds = fake_credentials.FakeKeystoneV3DomainCredentials()
385 for attr in ['username', 'password', 'user_domain_name']:
386 cred = copy.copy(domain_creds)
387 del cred[attr]
388 self.assertFalse(self.auth_provider.check_credentials(cred),
389 "Credentials should be invalid without %s" % attr)
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500390
Andrea Frittoli2095d242014-03-20 08:36:23 +0000391 def test_fill_credentials(self):
392 self.auth_provider.fill_credentials()
393 creds = self.auth_provider.credentials
394 for attr in ['user_id', 'project_id', 'user_domain_id',
395 'project_domain_id']:
396 self.assertEqual(self._get_from_fake_identity(attr),
397 getattr(creds, attr))
398
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500399 # Overwrites v2 test
400 def test_base_url_to_get_admin_endpoint(self):
401 self.filters = {
402 'service': 'compute',
403 'endpoint_type': 'admin',
404 'region': 'MiddleEarthRegion'
405 }
406 expected = self._get_result_url_from_endpoint(
407 self._endpoints[0]['endpoints'][2])
408 self._test_base_url_helper(expected, self.filters)