blob: 1dcddad87b22c4ae65bc35abb11317109610db77 [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 """
62 _auth_provider_class = auth.AuthProvider
63
Andrea Frittoli7d707a52014-04-06 11:46:32 +010064 def test_check_credentials_class(self):
65 self.assertRaises(NotImplementedError,
66 self.auth_provider.check_credentials,
67 auth.Credentials())
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050068
69 def test_check_credentials_bad_type(self):
70 self.assertFalse(self.auth_provider.check_credentials([]))
71
Andrea Frittoli7d707a52014-04-06 11:46:32 +010072 def test_instantiate_with_dict(self):
73 # Dict credentials are only supported for backward compatibility
74 auth_provider = self._auth(credentials={})
75 self.assertIsInstance(auth_provider.credentials, auth.Credentials)
76
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -050077 def test_instantiate_with_bad_credentials_type(self):
78 """
79 Assure that credentials with bad type fail with TypeError
80 """
81 self.assertRaises(TypeError, self._auth, [])
82
83 def test_auth_data_property(self):
84 self.assertRaises(NotImplementedError, getattr, self.auth_provider,
85 'auth_data')
86
87 def test_auth_data_property_when_cache_exists(self):
88 self.auth_provider.cache = 'foo'
89 self.useFixture(mockpatch.PatchObject(self.auth_provider,
90 'is_expired',
91 return_value=False))
92 self.assertEqual('foo', getattr(self.auth_provider, 'auth_data'))
93
94 def test_delete_auth_data_property_through_deleter(self):
95 self.auth_provider.cache = 'foo'
96 del self.auth_provider.auth_data
97 self.assertIsNone(self.auth_provider.cache)
98
99 def test_delete_auth_data_property_through_clear_auth(self):
100 self.auth_provider.cache = 'foo'
101 self.auth_provider.clear_auth()
102 self.assertIsNone(self.auth_provider.cache)
103
104 def test_set_and_reset_alt_auth_data(self):
105 self.auth_provider.set_alt_auth_data('foo', 'bar')
106 self.assertEqual(self.auth_provider.alt_part, 'foo')
107 self.assertEqual(self.auth_provider.alt_auth_data, 'bar')
108
109 self.auth_provider.reset_alt_auth_data()
110 self.assertIsNone(self.auth_provider.alt_part)
111 self.assertIsNone(self.auth_provider.alt_auth_data)
112
Andrea Frittoli2095d242014-03-20 08:36:23 +0000113 def test_fill_credentials(self):
114 self.assertRaises(NotImplementedError,
115 self.auth_provider.fill_credentials)
116
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500117
118class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500119 _endpoints = fake_identity.IDENTITY_V2_RESPONSE['access']['serviceCatalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500120 _auth_provider_class = auth.KeystoneV2AuthProvider
Andrea Frittoli7d707a52014-04-06 11:46:32 +0100121 credentials = fake_credentials.FakeKeystoneV2Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500122
123 def setUp(self):
124 super(TestKeystoneV2AuthProvider, self).setUp()
125 self.stubs.Set(http.ClosingHttp, 'request',
126 fake_identity._fake_v2_response)
127 self.target_url = 'test_api'
128
129 def _get_fake_alt_identity(self):
130 return fake_identity.ALT_IDENTITY_V2_RESPONSE['access']
131
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500132 def _get_result_url_from_endpoint(self, ep, endpoint_type='publicURL',
133 replacement=None):
134 if replacement:
135 return ep[endpoint_type].replace('v2', replacement)
136 return ep[endpoint_type]
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500137
138 def _get_token_from_fake_identity(self):
139 return fake_identity.TOKEN
140
Andrea Frittoli2095d242014-03-20 08:36:23 +0000141 def _get_from_fake_identity(self, attr):
142 access = fake_identity.IDENTITY_V2_RESPONSE['access']
143 if attr == 'user_id':
144 return access['user']['id']
145 elif attr == 'tenant_id':
146 return access['token']['tenant']['id']
147
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500148 def _test_request_helper(self, filters, expected):
149 url, headers, body = self.auth_provider.auth_request('GET',
150 self.target_url,
151 filters=filters)
152
153 self.assertEqual(expected['url'], url)
154 self.assertEqual(expected['token'], headers['X-Auth-Token'])
155 self.assertEqual(expected['body'], body)
156
Andrea Frittolidbd02512014-03-21 10:06:19 +0000157 def _auth_data_with_expiry(self, date_as_string):
158 token, access = self.auth_provider.auth_data
159 access['token']['expires'] = date_as_string
160 return token, access
161
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500162 def test_request(self):
163 filters = {
164 'service': 'compute',
165 'endpoint_type': 'publicURL',
166 'region': 'FakeRegion'
167 }
168
169 url = self._get_result_url_from_endpoint(
170 self._endpoints[0]['endpoints'][1]) + '/' + self.target_url
171
172 expected = {
173 'body': None,
174 'url': url,
175 'token': self._get_token_from_fake_identity(),
176 }
177 self._test_request_helper(filters, expected)
178
179 def test_request_with_alt_auth_cleans_alt(self):
180 self.auth_provider.set_alt_auth_data(
181 'body',
182 (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
183 self.test_request()
184 # Assert alt auth data is clear after it
185 self.assertIsNone(self.auth_provider.alt_part)
186 self.assertIsNone(self.auth_provider.alt_auth_data)
187
188 def test_request_with_alt_part_without_alt_data(self):
189 """
190 Assert that when alt_part is defined, the corresponding original
191 request element is kept the same.
192 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500193 filters = {
194 'service': 'compute',
195 'endpoint_type': 'publicURL',
196 'region': 'fakeRegion'
197 }
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500198 self.auth_provider.set_alt_auth_data('url', None)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500199
200 url, headers, body = self.auth_provider.auth_request('GET',
201 self.target_url,
202 filters=filters)
203
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500204 self.assertEqual(url, self.target_url)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500205 self.assertEqual(self._get_token_from_fake_identity(),
206 headers['X-Auth-Token'])
207 self.assertEqual(body, None)
208
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500209 def test_request_with_bad_service(self):
210 filters = {
211 'service': 'BAD_SERVICE',
212 'endpoint_type': 'publicURL',
213 'region': 'fakeRegion'
214 }
215 self.assertRaises(exceptions.EndpointNotFound,
216 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500217 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500218
219 def test_request_without_service(self):
220 filters = {
221 'service': None,
222 'endpoint_type': 'publicURL',
223 'region': 'fakeRegion'
224 }
225 self.assertRaises(exceptions.EndpointNotFound,
226 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500227 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500228
229 def test_check_credentials_missing_attribute(self):
230 for attr in ['username', 'password']:
231 cred = copy.copy(self.credentials)
232 del cred[attr]
233 self.assertFalse(self.auth_provider.check_credentials(cred))
234
Andrea Frittoli2095d242014-03-20 08:36:23 +0000235 def test_fill_credentials(self):
236 self.auth_provider.fill_credentials()
237 creds = self.auth_provider.credentials
238 for attr in ['user_id', 'tenant_id']:
239 self.assertEqual(self._get_from_fake_identity(attr),
240 getattr(creds, attr))
241
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500242 def _test_base_url_helper(self, expected_url, filters,
243 auth_data=None):
244
245 url = self.auth_provider.base_url(filters, auth_data)
246 self.assertEqual(url, expected_url)
247
248 def test_base_url(self):
249 self.filters = {
250 'service': 'compute',
251 'endpoint_type': 'publicURL',
252 'region': 'FakeRegion'
253 }
254 expected = self._get_result_url_from_endpoint(
255 self._endpoints[0]['endpoints'][1])
256 self._test_base_url_helper(expected, self.filters)
257
258 def test_base_url_to_get_admin_endpoint(self):
259 self.filters = {
260 'service': 'compute',
261 'endpoint_type': 'adminURL',
262 'region': 'FakeRegion'
263 }
264 expected = self._get_result_url_from_endpoint(
265 self._endpoints[0]['endpoints'][1], endpoint_type='adminURL')
266 self._test_base_url_helper(expected, self.filters)
267
268 def test_base_url_unknown_region(self):
269 """
270 Assure that if the region is unknow the first endpoint is returned.
271 """
272 self.filters = {
273 'service': 'compute',
274 'endpoint_type': 'publicURL',
275 'region': 'AintNoBodyKnowThisRegion'
276 }
277 expected = self._get_result_url_from_endpoint(
278 self._endpoints[0]['endpoints'][0])
279 self._test_base_url_helper(expected, self.filters)
280
281 def test_base_url_with_non_existent_service(self):
282 self.filters = {
283 'service': 'BAD_SERVICE',
284 'endpoint_type': 'publicURL',
285 'region': 'FakeRegion'
286 }
287 self.assertRaises(exceptions.EndpointNotFound,
288 self._test_base_url_helper, None, self.filters)
289
290 def test_base_url_without_service(self):
291 self.filters = {
292 'endpoint_type': 'publicURL',
293 'region': 'FakeRegion'
294 }
295 self.assertRaises(exceptions.EndpointNotFound,
296 self._test_base_url_helper, None, self.filters)
297
298 def test_base_url_with_api_version_filter(self):
299 self.filters = {
300 'service': 'compute',
301 'endpoint_type': 'publicURL',
302 'region': 'FakeRegion',
303 'api_version': 'v12'
304 }
305 expected = self._get_result_url_from_endpoint(
306 self._endpoints[0]['endpoints'][1], replacement='v12')
307 self._test_base_url_helper(expected, self.filters)
308
309 def test_base_url_with_skip_path_filter(self):
310 self.filters = {
311 'service': 'compute',
312 'endpoint_type': 'publicURL',
313 'region': 'FakeRegion',
314 'skip_path': True
315 }
316 expected = 'http://fake_url/'
317 self._test_base_url_helper(expected, self.filters)
318
Andrea Frittolidbd02512014-03-21 10:06:19 +0000319 def test_token_not_expired(self):
320 expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
321 auth_data = self._auth_data_with_expiry(
322 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
323 self.assertFalse(self.auth_provider.is_expired(auth_data))
324
325 def test_token_expired(self):
326 expiry_data = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
327 auth_data = self._auth_data_with_expiry(
328 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
329 self.assertTrue(self.auth_provider.is_expired(auth_data))
330
331 def test_token_not_expired_to_be_renewed(self):
332 expiry_data = datetime.datetime.utcnow() + \
333 self.auth_provider.token_expiry_threshold / 2
334 auth_data = self._auth_data_with_expiry(
335 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
336 self.assertTrue(self.auth_provider.is_expired(auth_data))
337
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500338
339class TestKeystoneV3AuthProvider(TestKeystoneV2AuthProvider):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500340 _endpoints = fake_identity.IDENTITY_V3_RESPONSE['token']['catalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500341 _auth_provider_class = auth.KeystoneV3AuthProvider
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100342 credentials = fake_credentials.FakeKeystoneV3Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500343
344 def setUp(self):
345 super(TestKeystoneV3AuthProvider, self).setUp()
346 self.stubs.Set(http.ClosingHttp, 'request',
347 fake_identity._fake_v3_response)
348
349 def _get_fake_alt_identity(self):
350 return fake_identity.ALT_IDENTITY_V3['token']
351
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500352 def _get_result_url_from_endpoint(self, ep, replacement=None):
353 if replacement:
354 return ep['url'].replace('v3', replacement)
355 return ep['url']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500356
Andrea Frittolidbd02512014-03-21 10:06:19 +0000357 def _auth_data_with_expiry(self, date_as_string):
358 token, access = self.auth_provider.auth_data
359 access['expires_at'] = date_as_string
360 return token, access
361
Andrea Frittoli2095d242014-03-20 08:36:23 +0000362 def _get_from_fake_identity(self, attr):
363 token = fake_identity.IDENTITY_V3_RESPONSE['token']
364 if attr == 'user_id':
365 return token['user']['id']
366 elif attr == 'project_id':
367 return token['project']['id']
368 elif attr == 'user_domain_id':
369 return token['user']['domain']['id']
370 elif attr == 'project_domain_id':
371 return token['project']['domain']['id']
372
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100373 def test_check_credentials_missing_attribute(self):
374 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000375 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100376 for attr in ['username', 'password', 'user_domain_name',
377 'project_domain_name']:
378 cred = copy.copy(self.credentials)
379 del cred[attr]
380 self.assertFalse(self.auth_provider.check_credentials(cred),
381 "Credentials should be invalid without %s" % attr)
382
383 def test_check_domain_credentials_missing_attribute(self):
384 # reset credentials to fresh ones
Andrea Frittoli2095d242014-03-20 08:36:23 +0000385 self.credentials.reset()
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100386 domain_creds = fake_credentials.FakeKeystoneV3DomainCredentials()
387 for attr in ['username', 'password', 'user_domain_name']:
388 cred = copy.copy(domain_creds)
389 del cred[attr]
390 self.assertFalse(self.auth_provider.check_credentials(cred),
391 "Credentials should be invalid without %s" % attr)
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500392
Andrea Frittoli2095d242014-03-20 08:36:23 +0000393 def test_fill_credentials(self):
394 self.auth_provider.fill_credentials()
395 creds = self.auth_provider.credentials
396 for attr in ['user_id', 'project_id', 'user_domain_id',
397 'project_domain_id']:
398 self.assertEqual(self._get_from_fake_identity(attr),
399 getattr(creds, attr))
400
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500401 # Overwrites v2 test
402 def test_base_url_to_get_admin_endpoint(self):
403 self.filters = {
404 'service': 'compute',
405 'endpoint_type': 'admin',
406 'region': 'MiddleEarthRegion'
407 }
408 expected = self._get_result_url_from_endpoint(
409 self._endpoints[0]['endpoints'][2])
410 self._test_base_url_helper(expected, self.filters)