blob: cb05f39156ad6dd48006c7c50e9f4b3087c1b1ac [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):
27
Megan Guiney3a34df72017-05-23 23:04:17 -070028 @decorators.idempotent_id('a9512ac3-3909-48a4-b395-11f438e16260')
29 def test_validate_token(self):
30 creds = self.os_primary.credentials
31 user_id = creds.user_id
32 username = creds.username
33 password = creds.password
34 user_domain_id = creds.user_domain_id
35 # GET and validate token
36 subject_token, token_body = self.non_admin_token.get_token(
37 user_id=user_id,
38 username=username,
39 user_domain_id=user_domain_id,
40 password=password,
41 auth_data=True)
42 authenticated_token = self.non_admin_client.show_token(
43 subject_token)['token']
44 # sanity checking to make sure they are indeed the same token
Sam70672392020-05-21 00:13:38 +000045 # If there are roles in the token, sort the roles
46 authenticated_token_roles = authenticated_token.get("roles")
47 if authenticated_token_roles:
48 authenticated_token["roles"] = authenticated_token_roles.sort(
49 key=operator.itemgetter('id'))
50 token_body_roles = token_body.get("roles")
51 if token_body_roles:
52 token_body["roles"] = token_body_roles.sort(
53 key=operator.itemgetter('id'))
Megan Guiney3a34df72017-05-23 23:04:17 -070054 self.assertEqual(authenticated_token, token_body)
55 # test to see if token has been properly authenticated
56 self.assertEqual(authenticated_token['user']['id'], user_id)
manasa4776b132019-07-12 13:29:39 -040057 # NOTE: resource name that are case-sensitive in keystone
58 # depends on backends such as MySQL or LDAP which are
59 # case-insensitive, case-preserving. Resource name is
60 # returned as it is stored in the backend, not as it is
61 # requested. Verifying the username with both lower-case to
62 # avoid failure on different backends
63 self.assertEqual(
64 authenticated_token['user']['name'].lower(), username.lower())
65
Megan Guiney3a34df72017-05-23 23:04:17 -070066 self.non_admin_client.delete_token(subject_token)
67 self.assertRaises(
68 lib_exc.NotFound, self.non_admin_client.show_token, subject_token)
69
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080070 @decorators.idempotent_id('6f8e4436-fc96-4282-8122-e41df57197a9')
Chris Hoge4f6117a2015-03-20 12:39:33 -050071 def test_create_token(self):
72
Jordan Pittier8160d312017-04-18 11:52:23 +020073 creds = self.os_primary.credentials
Chris Hoge4f6117a2015-03-20 12:39:33 -050074 user_id = creds.user_id
75 username = creds.username
76 password = creds.password
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060077 user_domain_id = creds.user_domain_id
Chris Hoge4f6117a2015-03-20 12:39:33 -050078
Marc Koderer8afdf6c2016-04-28 17:24:15 -050079 # 'user_domain_id' needs to be specified otherwise tempest.lib assumes
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060080 # it to be 'default'
81 token_id, resp = self.non_admin_token.get_token(
82 user_id=user_id,
Brant Knudsondd9f8052016-10-21 13:38:10 -050083 username=username,
Tom Cocozzello5e3cff12016-02-23 14:18:56 -060084 user_domain_id=user_domain_id,
85 password=password,
86 auth_data=True)
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +030087
88 self.assertNotEmpty(token_id)
89 self.assertIsInstance(token_id, six.string_types)
90
91 now = timeutils.utcnow()
92 expires_at = timeutils.normalize_time(
93 timeutils.parse_isotime(resp['expires_at']))
94 self.assertGreater(resp['expires_at'],
95 resp['issued_at'])
96 self.assertGreater(expires_at, now)
97
98 subject_id = resp['user']['id']
Brant Knudsondd9f8052016-10-21 13:38:10 -050099 if user_id:
100 self.assertEqual(subject_id, user_id)
101 else:
102 # Expect a user ID, but don't know what it will be.
Masayuki Igawaf9009b42017-04-10 14:49:29 +0900103 self.assertIsNotNone(subject_id, 'Expected user ID in token.')
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +0300104
105 subject_name = resp['user']['name']
manasa4776b132019-07-12 13:29:39 -0400106
Brant Knudsondd9f8052016-10-21 13:38:10 -0500107 if username:
manasa4776b132019-07-12 13:29:39 -0400108 # NOTE: resource name that are case-sensitive in keystone
109 # depends on backends such as MySQL or LDAP which are
110 # case-insensitive, case-preserving. Resource name is
111 # returned as it is stored in the backend, not as it is
112 # requested. Verifying the username with both lower-case to
113 # avoid failure on different backends
114 self.assertEqual(subject_name.lower(), username.lower())
Brant Knudsondd9f8052016-10-21 13:38:10 -0500115 else:
manasa4776b132019-07-12 13:29:39 -0400116 # Expect a user name, but don't know what it will be
Masayuki Igawaf9009b42017-04-10 14:49:29 +0900117 self.assertIsNotNone(subject_name, 'Expected user name in token.')
Jane Zadorozhnaf7b39732015-06-10 14:19:33 +0300118
119 self.assertEqual(resp['methods'][0], 'password')
Trevor McCasland285b3f82017-11-22 13:36:04 -0600120
121 @decorators.idempotent_id('0f9f5a5f-d5cd-4a86-8a5b-c5ded151f212')
122 def test_token_auth_creation_existence_deletion(self):
123 # Tests basic token auth functionality in a way that is compatible with
124 # pre-provisioned credentials. The default user is used for token
125 # authentication.
126
127 # Valid user's token is authenticated
128 user = self.os_primary.credentials
129 # Perform Authentication
130 resp = self.non_admin_token.auth(
131 user_id=user.user_id, password=user.password).response
132 subject_token = resp['x-subject-token']
133 self.non_admin_client.check_token_existence(subject_token)
134 # Perform GET Token
135 token_details = self.non_admin_client.show_token(
136 subject_token)['token']
137 self.assertEqual(resp['x-subject-token'], subject_token)
138 self.assertEqual(token_details['user']['id'], user.user_id)
manasa4776b132019-07-12 13:29:39 -0400139 # NOTE: resource name that are case-sensitive in keystone
140 # depends on backends such as MySQL or LDAP which are
141 # case-insensitive, case-preserving. Resource name is
142 # returned as it is stored in the backend, not as it is
143 # requested. Verifying the username with both lower-case to
144 # avoid failure on different backends
145 self.assertEqual(
146 token_details['user']['name'].lower(),
147 user.username.lower())
Trevor McCasland285b3f82017-11-22 13:36:04 -0600148 # Perform Delete Token
149 self.non_admin_client.delete_token(subject_token)
150 self.assertRaises(lib_exc.NotFound,
151 self.non_admin_client.check_token_existence,
152 subject_token)