blob: b201285aa438965b8e802e8764f100e07ed41813 [file] [log] [blame]
Chris Hoge4f6117a2015-03-20 12:39:33 -05001# Copyright 2015 OpenStack Foundation
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
Sam70672392020-05-21 00:13:38 +000016import operator
17
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +030018from oslo_utils import timeutils
19import six
Megan Guiney3a34df72017-05-23 23:04:17 -070020
Chris Hoge4f6117a2015-03-20 12:39:33 -050021from tempest.api.identity import base
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080022from tempest.lib import decorators
Megan Guiney3a34df72017-05-23 23:04:17 -070023from tempest.lib import exceptions as lib_exc
Chris Hoge4f6117a2015-03-20 12:39:33 -050024
25
26class TokensV3Test(base.BaseIdentityV3Test):
zhufl8e3aacd2020-04-27 14:46:46 +080027 """Test identity tokens"""
Chris Hoge4f6117a2015-03-20 12:39:33 -050028
Megan Guiney3a34df72017-05-23 23:04:17 -070029 @decorators.idempotent_id('a9512ac3-3909-48a4-b395-11f438e16260')
30 def test_validate_token(self):
zhufl8e3aacd2020-04-27 14:46:46 +080031 """Test validating token for user"""
Megan Guiney3a34df72017-05-23 23:04:17 -070032 creds = self.os_primary.credentials
33 user_id = creds.user_id
34 username = creds.username
35 password = creds.password
36 user_domain_id = creds.user_domain_id
37 # GET and validate token
38 subject_token, token_body = self.non_admin_token.get_token(
39 user_id=user_id,
40 username=username,
41 user_domain_id=user_domain_id,
42 password=password,
43 auth_data=True)
44 authenticated_token = self.non_admin_client.show_token(
45 subject_token)['token']
46 # sanity checking to make sure they are indeed the same token
Sam70672392020-05-21 00:13:38 +000047 # If there are roles in the token, sort the roles
48 authenticated_token_roles = authenticated_token.get("roles")
49 if authenticated_token_roles:
50 authenticated_token["roles"] = authenticated_token_roles.sort(
51 key=operator.itemgetter('id'))
52 token_body_roles = token_body.get("roles")
53 if token_body_roles:
54 token_body["roles"] = token_body_roles.sort(
55 key=operator.itemgetter('id'))
Megan Guiney3a34df72017-05-23 23:04:17 -070056 self.assertEqual(authenticated_token, token_body)
57 # test to see if token has been properly authenticated
58 self.assertEqual(authenticated_token['user']['id'], user_id)
manasa4776b132019-07-12 13:29:39 -040059 # NOTE: resource name that are case-sensitive in keystone
60 # depends on backends such as MySQL or LDAP which are
61 # case-insensitive, case-preserving. Resource name is
62 # returned as it is stored in the backend, not as it is
63 # requested. Verifying the username with both lower-case to
64 # avoid failure on different backends
65 self.assertEqual(
66 authenticated_token['user']['name'].lower(), username.lower())
67
Megan Guiney3a34df72017-05-23 23:04:17 -070068 self.non_admin_client.delete_token(subject_token)
69 self.assertRaises(
70 lib_exc.NotFound, self.non_admin_client.show_token, subject_token)
71
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080072 @decorators.idempotent_id('6f8e4436-fc96-4282-8122-e41df57197a9')
Chris Hoge4f6117a2015-03-20 12:39:33 -050073 def test_create_token(self):
zhufl8e3aacd2020-04-27 14:46:46 +080074 """Test creating token for user"""
Jordan Pittier8160d312017-04-18 11:52:23 +020075 creds = self.os_primary.credentials
Chris Hoge4f6117a2015-03-20 12:39:33 -050076 user_id = creds.user_id
77 username = creds.username
78 password = creds.password
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060079 user_domain_id = creds.user_domain_id
Chris Hoge4f6117a2015-03-20 12:39:33 -050080
Marc Koderer8afdf6c2016-04-28 17:24:15 -050081 # 'user_domain_id' needs to be specified otherwise tempest.lib assumes
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060082 # it to be 'default'
83 token_id, resp = self.non_admin_token.get_token(
84 user_id=user_id,
Brant Knudsondd9f8052016-10-21 13:38:10 -050085 username=username,
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060086 user_domain_id=user_domain_id,
87 password=password,
88 auth_data=True)
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +030089
90 self.assertNotEmpty(token_id)
91 self.assertIsInstance(token_id, six.string_types)
92
93 now = timeutils.utcnow()
94 expires_at = timeutils.normalize_time(
95 timeutils.parse_isotime(resp['expires_at']))
96 self.assertGreater(resp['expires_at'],
97 resp['issued_at'])
98 self.assertGreater(expires_at, now)
99
100 subject_id = resp['user']['id']
Brant Knudsondd9f8052016-10-21 13:38:10 -0500101 if user_id:
102 self.assertEqual(subject_id, user_id)
103 else:
104 # Expect a user ID, but don't know what it will be.
Masayuki Igawaf9009b42017-04-10 14:49:29 +0900105 self.assertIsNotNone(subject_id, 'Expected user ID in token.')
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +0300106
107 subject_name = resp['user']['name']
manasa4776b132019-07-12 13:29:39 -0400108
Brant Knudsondd9f8052016-10-21 13:38:10 -0500109 if username:
manasa4776b132019-07-12 13:29:39 -0400110 # NOTE: resource name that are case-sensitive in keystone
111 # depends on backends such as MySQL or LDAP which are
112 # case-insensitive, case-preserving. Resource name is
113 # returned as it is stored in the backend, not as it is
114 # requested. Verifying the username with both lower-case to
115 # avoid failure on different backends
116 self.assertEqual(subject_name.lower(), username.lower())
Brant Knudsondd9f8052016-10-21 13:38:10 -0500117 else:
manasa4776b132019-07-12 13:29:39 -0400118 # Expect a user name, but don't know what it will be
Masayuki Igawaf9009b42017-04-10 14:49:29 +0900119 self.assertIsNotNone(subject_name, 'Expected user name in token.')
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +0300120
121 self.assertEqual(resp['methods'][0], 'password')
Trevor McCasland285b3f82017-11-22 13:36:04 -0600122
123 @decorators.idempotent_id('0f9f5a5f-d5cd-4a86-8a5b-c5ded151f212')
124 def test_token_auth_creation_existence_deletion(self):
zhufl8e3aacd2020-04-27 14:46:46 +0800125 """Test auth/check existence/delete token for user
126
127 Tests basic token auth functionality in a way that is compatible with
128 pre-provisioned credentials. The default user is used for token
129 authentication.
130 """
Trevor McCasland285b3f82017-11-22 13:36:04 -0600131
132 # Valid user's token is authenticated
133 user = self.os_primary.credentials
134 # Perform Authentication
135 resp = self.non_admin_token.auth(
136 user_id=user.user_id, password=user.password).response
137 subject_token = resp['x-subject-token']
138 self.non_admin_client.check_token_existence(subject_token)
139 # Perform GET Token
140 token_details = self.non_admin_client.show_token(
141 subject_token)['token']
142 self.assertEqual(resp['x-subject-token'], subject_token)
143 self.assertEqual(token_details['user']['id'], user.user_id)
manasa4776b132019-07-12 13:29:39 -0400144 # NOTE: resource name that are case-sensitive in keystone
145 # depends on backends such as MySQL or LDAP which are
146 # case-insensitive, case-preserving. Resource name is
147 # returned as it is stored in the backend, not as it is
148 # requested. Verifying the username with both lower-case to
149 # avoid failure on different backends
150 self.assertEqual(
151 token_details['user']['name'].lower(),
152 user.username.lower())
Trevor McCasland285b3f82017-11-22 13:36:04 -0600153 # Perform Delete Token
154 self.non_admin_client.delete_token(subject_token)
155 self.assertRaises(lib_exc.NotFound,
156 self.non_admin_client.check_token_existence,
157 subject_token)