blob: fb27e020f123c0d9b33f6155e2f0a23f8db98106 [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
112
113class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500114 _endpoints = fake_identity.IDENTITY_V2_RESPONSE['access']['serviceCatalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500115 _auth_provider_class = auth.KeystoneV2AuthProvider
Andrea Frittoli7d707a52014-04-06 11:46:32 +0100116 credentials = fake_credentials.FakeKeystoneV2Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500117
118 def setUp(self):
119 super(TestKeystoneV2AuthProvider, self).setUp()
120 self.stubs.Set(http.ClosingHttp, 'request',
121 fake_identity._fake_v2_response)
122 self.target_url = 'test_api'
123
124 def _get_fake_alt_identity(self):
125 return fake_identity.ALT_IDENTITY_V2_RESPONSE['access']
126
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500127 def _get_result_url_from_endpoint(self, ep, endpoint_type='publicURL',
128 replacement=None):
129 if replacement:
130 return ep[endpoint_type].replace('v2', replacement)
131 return ep[endpoint_type]
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500132
133 def _get_token_from_fake_identity(self):
134 return fake_identity.TOKEN
135
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500136 def _test_request_helper(self, filters, expected):
137 url, headers, body = self.auth_provider.auth_request('GET',
138 self.target_url,
139 filters=filters)
140
141 self.assertEqual(expected['url'], url)
142 self.assertEqual(expected['token'], headers['X-Auth-Token'])
143 self.assertEqual(expected['body'], body)
144
Andrea Frittolidbd02512014-03-21 10:06:19 +0000145 def _auth_data_with_expiry(self, date_as_string):
146 token, access = self.auth_provider.auth_data
147 access['token']['expires'] = date_as_string
148 return token, access
149
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500150 def test_request(self):
151 filters = {
152 'service': 'compute',
153 'endpoint_type': 'publicURL',
154 'region': 'FakeRegion'
155 }
156
157 url = self._get_result_url_from_endpoint(
158 self._endpoints[0]['endpoints'][1]) + '/' + self.target_url
159
160 expected = {
161 'body': None,
162 'url': url,
163 'token': self._get_token_from_fake_identity(),
164 }
165 self._test_request_helper(filters, expected)
166
167 def test_request_with_alt_auth_cleans_alt(self):
168 self.auth_provider.set_alt_auth_data(
169 'body',
170 (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
171 self.test_request()
172 # Assert alt auth data is clear after it
173 self.assertIsNone(self.auth_provider.alt_part)
174 self.assertIsNone(self.auth_provider.alt_auth_data)
175
176 def test_request_with_alt_part_without_alt_data(self):
177 """
178 Assert that when alt_part is defined, the corresponding original
179 request element is kept the same.
180 """
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500181 filters = {
182 'service': 'compute',
183 'endpoint_type': 'publicURL',
184 'region': 'fakeRegion'
185 }
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500186 self.auth_provider.set_alt_auth_data('url', None)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500187
188 url, headers, body = self.auth_provider.auth_request('GET',
189 self.target_url,
190 filters=filters)
191
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500192 self.assertEqual(url, self.target_url)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500193 self.assertEqual(self._get_token_from_fake_identity(),
194 headers['X-Auth-Token'])
195 self.assertEqual(body, None)
196
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500197 def test_request_with_bad_service(self):
198 filters = {
199 'service': 'BAD_SERVICE',
200 'endpoint_type': 'publicURL',
201 'region': 'fakeRegion'
202 }
203 self.assertRaises(exceptions.EndpointNotFound,
204 self.auth_provider.auth_request, 'GET',
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500205 self.target_url, filters=filters)
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500206
207 def test_request_without_service(self):
208 filters = {
209 'service': None,
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_check_credentials_missing_attribute(self):
218 for attr in ['username', 'password']:
219 cred = copy.copy(self.credentials)
220 del cred[attr]
221 self.assertFalse(self.auth_provider.check_credentials(cred))
222
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500223 def _test_base_url_helper(self, expected_url, filters,
224 auth_data=None):
225
226 url = self.auth_provider.base_url(filters, auth_data)
227 self.assertEqual(url, expected_url)
228
229 def test_base_url(self):
230 self.filters = {
231 'service': 'compute',
232 'endpoint_type': 'publicURL',
233 'region': 'FakeRegion'
234 }
235 expected = self._get_result_url_from_endpoint(
236 self._endpoints[0]['endpoints'][1])
237 self._test_base_url_helper(expected, self.filters)
238
239 def test_base_url_to_get_admin_endpoint(self):
240 self.filters = {
241 'service': 'compute',
242 'endpoint_type': 'adminURL',
243 'region': 'FakeRegion'
244 }
245 expected = self._get_result_url_from_endpoint(
246 self._endpoints[0]['endpoints'][1], endpoint_type='adminURL')
247 self._test_base_url_helper(expected, self.filters)
248
249 def test_base_url_unknown_region(self):
250 """
251 Assure that if the region is unknow the first endpoint is returned.
252 """
253 self.filters = {
254 'service': 'compute',
255 'endpoint_type': 'publicURL',
256 'region': 'AintNoBodyKnowThisRegion'
257 }
258 expected = self._get_result_url_from_endpoint(
259 self._endpoints[0]['endpoints'][0])
260 self._test_base_url_helper(expected, self.filters)
261
262 def test_base_url_with_non_existent_service(self):
263 self.filters = {
264 'service': 'BAD_SERVICE',
265 'endpoint_type': 'publicURL',
266 'region': 'FakeRegion'
267 }
268 self.assertRaises(exceptions.EndpointNotFound,
269 self._test_base_url_helper, None, self.filters)
270
271 def test_base_url_without_service(self):
272 self.filters = {
273 'endpoint_type': 'publicURL',
274 'region': 'FakeRegion'
275 }
276 self.assertRaises(exceptions.EndpointNotFound,
277 self._test_base_url_helper, None, self.filters)
278
279 def test_base_url_with_api_version_filter(self):
280 self.filters = {
281 'service': 'compute',
282 'endpoint_type': 'publicURL',
283 'region': 'FakeRegion',
284 'api_version': 'v12'
285 }
286 expected = self._get_result_url_from_endpoint(
287 self._endpoints[0]['endpoints'][1], replacement='v12')
288 self._test_base_url_helper(expected, self.filters)
289
290 def test_base_url_with_skip_path_filter(self):
291 self.filters = {
292 'service': 'compute',
293 'endpoint_type': 'publicURL',
294 'region': 'FakeRegion',
295 'skip_path': True
296 }
297 expected = 'http://fake_url/'
298 self._test_base_url_helper(expected, self.filters)
299
Andrea Frittolidbd02512014-03-21 10:06:19 +0000300 def test_token_not_expired(self):
301 expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
302 auth_data = self._auth_data_with_expiry(
303 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
304 self.assertFalse(self.auth_provider.is_expired(auth_data))
305
306 def test_token_expired(self):
307 expiry_data = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
308 auth_data = self._auth_data_with_expiry(
309 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
310 self.assertTrue(self.auth_provider.is_expired(auth_data))
311
312 def test_token_not_expired_to_be_renewed(self):
313 expiry_data = datetime.datetime.utcnow() + \
314 self.auth_provider.token_expiry_threshold / 2
315 auth_data = self._auth_data_with_expiry(
316 expiry_data.strftime(self.auth_provider.EXPIRY_DATE_FORMAT))
317 self.assertTrue(self.auth_provider.is_expired(auth_data))
318
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500319
320class TestKeystoneV3AuthProvider(TestKeystoneV2AuthProvider):
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500321 _endpoints = fake_identity.IDENTITY_V3_RESPONSE['token']['catalog']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500322 _auth_provider_class = auth.KeystoneV3AuthProvider
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100323 credentials = fake_credentials.FakeKeystoneV3Credentials()
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500324
325 def setUp(self):
326 super(TestKeystoneV3AuthProvider, self).setUp()
327 self.stubs.Set(http.ClosingHttp, 'request',
328 fake_identity._fake_v3_response)
329
330 def _get_fake_alt_identity(self):
331 return fake_identity.ALT_IDENTITY_V3['token']
332
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500333 def _get_result_url_from_endpoint(self, ep, replacement=None):
334 if replacement:
335 return ep['url'].replace('v3', replacement)
336 return ep['url']
Mauro S. M. Rodriguesc3e573c2014-02-19 07:59:29 -0500337
Andrea Frittolidbd02512014-03-21 10:06:19 +0000338 def _auth_data_with_expiry(self, date_as_string):
339 token, access = self.auth_provider.auth_data
340 access['expires_at'] = date_as_string
341 return token, access
342
Andrea Frittolib1b04bb2014-04-06 11:57:07 +0100343 def test_check_credentials_missing_attribute(self):
344 # reset credentials to fresh ones
345 self.credentials = fake_credentials.FakeKeystoneV3Credentials()
346 for attr in ['username', 'password', 'user_domain_name',
347 'project_domain_name']:
348 cred = copy.copy(self.credentials)
349 del cred[attr]
350 self.assertFalse(self.auth_provider.check_credentials(cred),
351 "Credentials should be invalid without %s" % attr)
352
353 def test_check_domain_credentials_missing_attribute(self):
354 # reset credentials to fresh ones
355 self.credentials = fake_credentials.FakeKeystoneV3Credentials()
356 domain_creds = fake_credentials.FakeKeystoneV3DomainCredentials()
357 for attr in ['username', 'password', 'user_domain_name']:
358 cred = copy.copy(domain_creds)
359 del cred[attr]
360 self.assertFalse(self.auth_provider.check_credentials(cred),
361 "Credentials should be invalid without %s" % attr)
Mauro S. M. Rodrigues4e23c452014-02-24 15:21:58 -0500362
363 # Overwrites v2 test
364 def test_base_url_to_get_admin_endpoint(self):
365 self.filters = {
366 'service': 'compute',
367 'endpoint_type': 'admin',
368 'region': 'MiddleEarthRegion'
369 }
370 expected = self._get_result_url_from_endpoint(
371 self._endpoints[0]['endpoints'][2])
372 self._test_base_url_helper(expected, self.filters)