blob: 55fceadcd964c829a3f855b16dd0b2a9c03d9a1c [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
Megan Guiney3a34df72017-05-23 23:04:17 -070019
Chris Hoge4f6117a2015-03-20 12:39:33 -050020from tempest.api.identity import base
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080021from tempest.lib import decorators
Megan Guiney3a34df72017-05-23 23:04:17 -070022from tempest.lib import exceptions as lib_exc
Chris Hoge4f6117a2015-03-20 12:39:33 -050023
24
25class TokensV3Test(base.BaseIdentityV3Test):
zhufl8e3aacd2020-04-27 14:46:46 +080026 """Test identity tokens"""
Chris Hoge4f6117a2015-03-20 12:39:33 -050027
Megan Guiney3a34df72017-05-23 23:04:17 -070028 @decorators.idempotent_id('a9512ac3-3909-48a4-b395-11f438e16260')
29 def test_validate_token(self):
zhufl8e3aacd2020-04-27 14:46:46 +080030 """Test validating token for user"""
Megan Guiney3a34df72017-05-23 23:04:17 -070031 creds = self.os_primary.credentials
32 user_id = creds.user_id
33 username = creds.username
34 password = creds.password
35 user_domain_id = creds.user_domain_id
36 # GET and validate token
37 subject_token, token_body = self.non_admin_token.get_token(
38 user_id=user_id,
39 username=username,
40 user_domain_id=user_domain_id,
41 password=password,
42 auth_data=True)
43 authenticated_token = self.non_admin_client.show_token(
44 subject_token)['token']
45 # sanity checking to make sure they are indeed the same token
Sam70672392020-05-21 00:13:38 +000046 # If there are roles in the token, sort the roles
47 authenticated_token_roles = authenticated_token.get("roles")
48 if authenticated_token_roles:
49 authenticated_token["roles"] = authenticated_token_roles.sort(
50 key=operator.itemgetter('id'))
51 token_body_roles = token_body.get("roles")
52 if token_body_roles:
53 token_body["roles"] = token_body_roles.sort(
54 key=operator.itemgetter('id'))
Megan Guiney3a34df72017-05-23 23:04:17 -070055 self.assertEqual(authenticated_token, token_body)
56 # test to see if token has been properly authenticated
57 self.assertEqual(authenticated_token['user']['id'], user_id)
manasa4776b132019-07-12 13:29:39 -040058 # NOTE: resource name that are case-sensitive in keystone
59 # depends on backends such as MySQL or LDAP which are
60 # case-insensitive, case-preserving. Resource name is
61 # returned as it is stored in the backend, not as it is
62 # requested. Verifying the username with both lower-case to
63 # avoid failure on different backends
64 self.assertEqual(
65 authenticated_token['user']['name'].lower(), username.lower())
66
Megan Guiney3a34df72017-05-23 23:04:17 -070067 self.non_admin_client.delete_token(subject_token)
68 self.assertRaises(
69 lib_exc.NotFound, self.non_admin_client.show_token, subject_token)
70
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080071 @decorators.idempotent_id('6f8e4436-fc96-4282-8122-e41df57197a9')
Chris Hoge4f6117a2015-03-20 12:39:33 -050072 def test_create_token(self):
zhufl8e3aacd2020-04-27 14:46:46 +080073 """Test creating token for user"""
Jordan Pittier8160d312017-04-18 11:52:23 +020074 creds = self.os_primary.credentials
Chris Hoge4f6117a2015-03-20 12:39:33 -050075 user_id = creds.user_id
76 username = creds.username
77 password = creds.password
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060078 user_domain_id = creds.user_domain_id
Chris Hoge4f6117a2015-03-20 12:39:33 -050079
Marc Koderer8afdf6c2016-04-28 17:24:15 -050080 # 'user_domain_id' needs to be specified otherwise tempest.lib assumes
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060081 # it to be 'default'
82 token_id, resp = self.non_admin_token.get_token(
83 user_id=user_id,
Brant Knudsondd9f8052016-10-21 13:38:10 -050084 username=username,
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060085 user_domain_id=user_domain_id,
86 password=password,
87 auth_data=True)
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +030088
89 self.assertNotEmpty(token_id)
songwenpinga6ee2d12021-02-22 10:24:16 +080090 self.assertIsInstance(token_id, str)
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +030091
92 now = timeutils.utcnow()
93 expires_at = timeutils.normalize_time(
94 timeutils.parse_isotime(resp['expires_at']))
95 self.assertGreater(resp['expires_at'],
96 resp['issued_at'])
97 self.assertGreater(expires_at, now)
98
99 subject_id = resp['user']['id']
Brant Knudsondd9f8052016-10-21 13:38:10 -0500100 if user_id:
101 self.assertEqual(subject_id, user_id)
102 else:
103 # Expect a user ID, but don't know what it will be.
Masayuki Igawaf9009b42017-04-10 14:49:29 +0900104 self.assertIsNotNone(subject_id, 'Expected user ID in token.')
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +0300105
106 subject_name = resp['user']['name']
manasa4776b132019-07-12 13:29:39 -0400107
Brant Knudsondd9f8052016-10-21 13:38:10 -0500108 if username:
manasa4776b132019-07-12 13:29:39 -0400109 # NOTE: resource name that are case-sensitive in keystone
110 # depends on backends such as MySQL or LDAP which are
111 # case-insensitive, case-preserving. Resource name is
112 # returned as it is stored in the backend, not as it is
113 # requested. Verifying the username with both lower-case to
114 # avoid failure on different backends
115 self.assertEqual(subject_name.lower(), username.lower())
Brant Knudsondd9f8052016-10-21 13:38:10 -0500116 else:
manasa4776b132019-07-12 13:29:39 -0400117 # Expect a user name, but don't know what it will be
Masayuki Igawaf9009b42017-04-10 14:49:29 +0900118 self.assertIsNotNone(subject_name, 'Expected user name in token.')
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +0300119
120 self.assertEqual(resp['methods'][0], 'password')
Trevor McCasland285b3f82017-11-22 13:36:04 -0600121
122 @decorators.idempotent_id('0f9f5a5f-d5cd-4a86-8a5b-c5ded151f212')
123 def test_token_auth_creation_existence_deletion(self):
zhufl8e3aacd2020-04-27 14:46:46 +0800124 """Test auth/check existence/delete token for user
125
126 Tests basic token auth functionality in a way that is compatible with
127 pre-provisioned credentials. The default user is used for token
128 authentication.
129 """
Trevor McCasland285b3f82017-11-22 13:36:04 -0600130
131 # Valid user's token is authenticated
132 user = self.os_primary.credentials
133 # Perform Authentication
134 resp = self.non_admin_token.auth(
135 user_id=user.user_id, password=user.password).response
136 subject_token = resp['x-subject-token']
137 self.non_admin_client.check_token_existence(subject_token)
138 # Perform GET Token
139 token_details = self.non_admin_client.show_token(
140 subject_token)['token']
141 self.assertEqual(resp['x-subject-token'], subject_token)
142 self.assertEqual(token_details['user']['id'], user.user_id)
manasa4776b132019-07-12 13:29:39 -0400143 # NOTE: resource name that are case-sensitive in keystone
144 # depends on backends such as MySQL or LDAP which are
145 # case-insensitive, case-preserving. Resource name is
146 # returned as it is stored in the backend, not as it is
147 # requested. Verifying the username with both lower-case to
148 # avoid failure on different backends
149 self.assertEqual(
150 token_details['user']['name'].lower(),
151 user.username.lower())
Trevor McCasland285b3f82017-11-22 13:36:04 -0600152 # Perform Delete Token
153 self.non_admin_client.delete_token(subject_token)
154 self.assertRaises(lib_exc.NotFound,
155 self.non_admin_client.check_token_existence,
156 subject_token)