blob: 03333bef1b90646f05467bf2d661cb36eaf4c17a [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
19from tempest import auth
20from tempest.common import http
21from tempest import config
22from tempest import exceptions
23from tempest.openstack.common.fixture import mockpatch
24from tempest.tests import base
Andrea Frittoli7d707a52014-04-06 11:46:32 +010025from tempest.tests import fake_auth_provider
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050026from tempest.tests import fake_config
Andrea Frittoli7d707a52014-04-06 11:46:32 +010027from tempest.tests import fake_credentials
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050028from tempest.tests import fake_http
29from tempest.tests import fake_identity
30
31
32class BaseAuthTestsSetUp(base.TestCase):
33 _auth_provider_class = None
Andrea Frittoli7d707a52014-04-06 11:46:32 +010034 credentials = fake_credentials.FakeCredentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050035
36 def _auth(self, credentials, **params):
37 """
38 returns auth method according to keystone
39 """
40 return self._auth_provider_class(credentials, **params)
41
42 def setUp(self):
43 super(BaseAuthTestsSetUp, self).setUp()
Matthew Treinishff598482014-02-28 16:13:58 -050044 self.useFixture(fake_config.ConfigFixture())
45 self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050046 self.fake_http = fake_http.fake_httplib2(return_type=200)
47 self.stubs.Set(http.ClosingHttp, 'request', self.fake_http.request)
Andrea Frittoli7d707a52014-04-06 11:46:32 +010048 self.stubs.Set(auth, 'get_credentials',
49 fake_auth_provider.get_credentials)
Andrea Frittolib1b04bb2014-04-06 11:57:07 +010050 self.stubs.Set(auth, 'get_default_credentials',
51 fake_auth_provider.get_default_credentials)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050052 self.auth_provider = self._auth(self.credentials)
53
54
55class TestBaseAuthProvider(BaseAuthTestsSetUp):
56 """
57 This tests auth.AuthProvider class which is base for the other so we
58 obviously don't test not implemented method or the ones which strongly
59 depends on them.
60 """
61 _auth_provider_class = auth.AuthProvider
62
Andrea Frittoli7d707a52014-04-06 11:46:32 +010063 def test_check_credentials_class(self):
64 self.assertRaises(NotImplementedError,
65 self.auth_provider.check_credentials,
66 auth.Credentials())
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050067
68 def test_check_credentials_bad_type(self):
69 self.assertFalse(self.auth_provider.check_credentials([]))
70
Andrea Frittoli7d707a52014-04-06 11:46:32 +010071 def test_instantiate_with_dict(self):
72 # Dict credentials are only supported for backward compatibility
73 auth_provider = self._auth(credentials={})
74 self.assertIsInstance(auth_provider.credentials, auth.Credentials)
75
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050076 def test_instantiate_with_bad_credentials_type(self):
77 """
78 Assure that credentials with bad type fail with TypeError
79 """
80 self.assertRaises(TypeError, self._auth, [])
81
82 def test_auth_data_property(self):
83 self.assertRaises(NotImplementedError, getattr, self.auth_provider,
84 'auth_data')
85
86 def test_auth_data_property_when_cache_exists(self):
87 self.auth_provider.cache = 'foo'
88 self.useFixture(mockpatch.PatchObject(self.auth_provider,
89 'is_expired',
90 return_value=False))
91 self.assertEqual('foo', getattr(self.auth_provider, 'auth_data'))
92
93 def test_delete_auth_data_property_through_deleter(self):
94 self.auth_provider.cache = 'foo'
95 del self.auth_provider.auth_data
96 self.assertIsNone(self.auth_provider.cache)
97
98 def test_delete_auth_data_property_through_clear_auth(self):
99 self.auth_provider.cache = 'foo'
100 self.auth_provider.clear_auth()
101 self.assertIsNone(self.auth_provider.cache)
102
103 def test_set_and_reset_alt_auth_data(self):
104 self.auth_provider.set_alt_auth_data('foo', 'bar')
105 self.assertEqual(self.auth_provider.alt_part, 'foo')
106 self.assertEqual(self.auth_provider.alt_auth_data, 'bar')
107
108 self.auth_provider.reset_alt_auth_data()
109 self.assertIsNone(self.auth_provider.alt_part)
110 self.assertIsNone(self.auth_provider.alt_auth_data)
111
Andrea Frittoli2095d242014-03-20 08:36:23 +0000112 def test_fill_credentials(self):
113 self.assertRaises(NotImplementedError,
114 self.auth_provider.fill_credentials)
115
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500116
117class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500118 _endpoints = fake_identity.IDENTITY_V2_RESPONSE['access']['serviceCatalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500119 _auth_provider_class = auth.KeystoneV2AuthProvider
Andrea Frittoli7d707a52014-04-06 11:46:32 +0100120 credentials = fake_credentials.FakeKeystoneV2Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500121
122 def setUp(self):
123 super(TestKeystoneV2AuthProvider, self).setUp()
124 self.stubs.Set(http.ClosingHttp, 'request',
125 fake_identity._fake_v2_response)
126 self.target_url = 'test_api'
127
128 def _get_fake_alt_identity(self):
129 return fake_identity.ALT_IDENTITY_V2_RESPONSE['access']
130
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500131 def _get_result_url_from_endpoint(self, ep, endpoint_type='publicURL',
132 replacement=None):
133 if replacement:
134 return ep[endpoint_type].replace('v2', replacement)
135 return ep[endpoint_type]
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500136
137 def _get_token_from_fake_identity(self):
138 return fake_identity.TOKEN
139
Andrea Frittoli2095d242014-03-20 08:36:23 +0000140 def _get_from_fake_identity(self, attr):
141 access = fake_identity.IDENTITY_V2_RESPONSE['access']
142 if attr == 'user_id':
143 return access['user']['id']
144 elif attr == 'tenant_id':
145 return access['token']['tenant']['id']
146
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500147 def _test_request_helper(self, filters, expected):
148 url, headers, body = self.auth_provider.auth_request('GET',
149 self.target_url,
150 filters=filters)
151
152 self.assertEqual(expected['url'], url)
153 self.assertEqual(expected['token'], headers['X-Auth-Token'])
154 self.assertEqual(expected['body'], body)
155
Andrea Frittolidbd02512014-03-21 10:06:19 +0000156 def _auth_data_with_expiry(self, date_as_string):
157 token, access = self.auth_provider.auth_data
158 access['token']['expires'] = date_as_string
159 return token, access
160
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500161 def test_request(self):
162 filters = {
163 'service': 'compute',
164 'endpoint_type': 'publicURL',
165 'region': 'FakeRegion'
166 }
167
168 url = self._get_result_url_from_endpoint(
169 self._endpoints[0]['endpoints'][1]) + '/' + self.target_url
170
171 expected = {
172 'body': None,
173 'url': url,
174 'token': self._get_token_from_fake_identity(),
175 }
176 self._test_request_helper(filters, expected)
177
178 def test_request_with_alt_auth_cleans_alt(self):
179 self.auth_provider.set_alt_auth_data(
180 'body',
181 (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
182 self.test_request()
183 # Assert alt auth data is clear after it
184 self.assertIsNone(self.auth_provider.alt_part)
185 self.assertIsNone(self.auth_provider.alt_auth_data)
186
187 def test_request_with_alt_part_without_alt_data(self):
188 """
189 Assert that when alt_part is defined, the corresponding original
190 request element is kept the same.
191 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500192 filters = {
193 'service': 'compute',
194 'endpoint_type': 'publicURL',
195 'region': 'fakeRegion'
196 }
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500197 self.auth_provider.set_alt_auth_data('url', None)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500198
199 url, headers, body = self.auth_provider.auth_request('GET',
200 self.target_url,
201 filters=filters)
202
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500203 self.assertEqual(url, self.target_url)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500204 self.assertEqual(self._get_token_from_fake_identity(),
205 headers['X-Auth-Token'])
206 self.assertEqual(body, None)
207
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500208 def test_request_with_bad_service(self):
209 filters = {
210 'service': 'BAD_SERVICE',
211 'endpoint_type': 'publicURL',
212 'region': 'fakeRegion'
213 }
214 self.assertRaises(exceptions.EndpointNotFound,
215 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500216 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500217
218 def test_request_without_service(self):
219 filters = {
220 'service': None,
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_check_credentials_missing_attribute(self):
229 for attr in ['username', 'password']:
230 cred = copy.copy(self.credentials)
231 del cred[attr]
232 self.assertFalse(self.auth_provider.check_credentials(cred))
233
Andrea Frittoli2095d242014-03-20 08:36:23 +0000234 def test_fill_credentials(self):
235 self.auth_provider.fill_credentials()
236 creds = self.auth_provider.credentials
237 for attr in ['user_id', 'tenant_id']:
238 self.assertEqual(self._get_from_fake_identity(attr),
239 getattr(creds, attr))
240
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500241 def _test_base_url_helper(self, expected_url, filters,
242 auth_data=None):
243
244 url = self.auth_provider.base_url(filters, auth_data)
245 self.assertEqual(url, expected_url)
246
247 def test_base_url(self):
248 self.filters = {
249 'service': 'compute',
250 'endpoint_type': 'publicURL',
251 'region': 'FakeRegion'
252 }
253 expected = self._get_result_url_from_endpoint(
254 self._endpoints[0]['endpoints'][1])
255 self._test_base_url_helper(expected, self.filters)
256
257 def test_base_url_to_get_admin_endpoint(self):
258 self.filters = {
259 'service': 'compute',
260 'endpoint_type': 'adminURL',
261 'region': 'FakeRegion'
262 }
263 expected = self._get_result_url_from_endpoint(
264 self._endpoints[0]['endpoints'][1], endpoint_type='adminURL')
265 self._test_base_url_helper(expected, self.filters)
266
267 def test_base_url_unknown_region(self):
268 """
269 Assure that if the region is unknow the first endpoint is returned.
270 """
271 self.filters = {
272 'service': 'compute',
273 'endpoint_type': 'publicURL',
274 'region': 'AintNoBodyKnowThisRegion'
275 }
276 expected = self._get_result_url_from_endpoint(
277 self._endpoints[0]['endpoints'][0])
278 self._test_base_url_helper(expected, self.filters)
279
280 def test_base_url_with_non_existent_service(self):
281 self.filters = {
282 'service': 'BAD_SERVICE',
283 'endpoint_type': 'publicURL',
284 'region': 'FakeRegion'
285 }
286 self.assertRaises(exceptions.EndpointNotFound,
287 self._test_base_url_helper, None, self.filters)
288
289 def test_base_url_without_service(self):
290 self.filters = {
291 'endpoint_type': 'publicURL',
292 'region': 'FakeRegion'
293 }
294 self.assertRaises(exceptions.EndpointNotFound,
295 self._test_base_url_helper, None, self.filters)
296
297 def test_base_url_with_api_version_filter(self):
298 self.filters = {
299 'service': 'compute',
300 'endpoint_type': 'publicURL',
301 'region': 'FakeRegion',
302 'api_version': 'v12'
303 }
304 expected = self._get_result_url_from_endpoint(
305 self._endpoints[0]['endpoints'][1], replacement='v12')
306 self._test_base_url_helper(expected, self.filters)
307
308 def test_base_url_with_skip_path_filter(self):
309 self.filters = {
310 'service': 'compute',
311 'endpoint_type': 'publicURL',
312 'region': 'FakeRegion',
313 'skip_path': True
314 }
315 expected = 'http://fake_url/'
316 self._test_base_url_helper(expected, self.filters)
317
Andrea Frittolidbd02512014-03-21 10:06:19 +0000318 def test_token_not_expired(self):
319 expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
320 auth_data = self._auth_data_with_expiry(
321 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
322 self.assertFalse(self.auth_provider.is_expired(auth_data))
323
324 def test_token_expired(self):
325 expiry_data = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
326 auth_data = self._auth_data_with_expiry(
327 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
328 self.assertTrue(self.auth_provider.is_expired(auth_data))
329
330 def test_token_not_expired_to_be_renewed(self):
331 expiry_data = datetime.datetime.utcnow() + \
332 self.auth_provider.token_expiry_threshold / 2
333 auth_data = self._auth_data_with_expiry(
334 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
335 self.assertTrue(self.auth_provider.is_expired(auth_data))
336
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500337
338class TestKeystoneV3AuthProvider(TestKeystoneV2AuthProvider):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500339 _endpoints = fake_identity.IDENTITY_V3_RESPONSE['token']['catalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500340 _auth_provider_class = auth.KeystoneV3AuthProvider
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100341 credentials = fake_credentials.FakeKeystoneV3Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500342
343 def setUp(self):
344 super(TestKeystoneV3AuthProvider, self).setUp()
345 self.stubs.Set(http.ClosingHttp, 'request',
346 fake_identity._fake_v3_response)
347
348 def _get_fake_alt_identity(self):
349 return fake_identity.ALT_IDENTITY_V3['token']
350
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500351 def _get_result_url_from_endpoint(self, ep, replacement=None):
352 if replacement:
353 return ep['url'].replace('v3', replacement)
354 return ep['url']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500355
Andrea Frittolidbd02512014-03-21 10:06:19 +0000356 def _auth_data_with_expiry(self, date_as_string):
357 token, access = self.auth_provider.auth_data
358 access['expires_at'] = date_as_string
359 return token, access
360
Andrea Frittoli2095d242014-03-20 08:36:23 +0000361 def _get_from_fake_identity(self, attr):
362 token = fake_identity.IDENTITY_V3_RESPONSE['token']
363 if attr == 'user_id':
364 return token['user']['id']
365 elif attr == 'project_id':
366 return token['project']['id']
367 elif attr == 'user_domain_id':
368 return token['user']['domain']['id']
369 elif attr == 'project_domain_id':
370 return token['project']['domain']['id']
371
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100372 def test_check_credentials_missing_attribute(self):
373 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000374 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100375 for attr in ['username', 'password', 'user_domain_name',
376 'project_domain_name']:
377 cred = copy.copy(self.credentials)
378 del cred[attr]
379 self.assertFalse(self.auth_provider.check_credentials(cred),
380 "Credentials should be invalid without %s" % attr)
381
382 def test_check_domain_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 domain_creds = fake_credentials.FakeKeystoneV3DomainCredentials()
386 for attr in ['username', 'password', 'user_domain_name']:
387 cred = copy.copy(domain_creds)
388 del cred[attr]
389 self.assertFalse(self.auth_provider.check_credentials(cred),
390 "Credentials should be invalid without %s" % attr)
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500391
Andrea Frittoli2095d242014-03-20 08:36:23 +0000392 def test_fill_credentials(self):
393 self.auth_provider.fill_credentials()
394 creds = self.auth_provider.credentials
395 for attr in ['user_id', 'project_id', 'user_domain_id',
396 'project_domain_id']:
397 self.assertEqual(self._get_from_fake_identity(attr),
398 getattr(creds, attr))
399
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500400 # Overwrites v2 test
401 def test_base_url_to_get_admin_endpoint(self):
402 self.filters = {
403 'service': 'compute',
404 'endpoint_type': 'admin',
405 'region': 'MiddleEarthRegion'
406 }
407 expected = self._get_result_url_from_endpoint(
408 self._endpoints[0]['endpoints'][2])
409 self._test_base_url_helper(expected, self.filters)