1 Upstream patch fixed in Grizzly 2013.1.5, Havana 2013.2.2, Icehouse |
|
2 |
|
3 From a411c944af78c36f2fdb87d305ba452dc52d7ed3 Mon Sep 17 00:00:00 2001 |
|
4 From: Morgan Fainberg <[email protected]> |
|
5 Date: Fri, 21 Feb 2014 14:09:04 -0800 |
|
6 Subject: [PATCH] Ensure tokens are added to both Trustor and Trustee indexes |
|
7 |
|
8 Tokens are now added to both the Trustor and Trustee user-token-index |
|
9 so that bulk token revocations (e.g. password change) of the trustee |
|
10 will work as expected. This is a backport of the basic code that was |
|
11 used in the Icehouse-vintage Dogpile Token KVS backend that resolves |
|
12 this issue by merging the handling of memcache and KVS backends into |
|
13 the same logic. |
|
14 |
|
15 Change-Id: I3e19e4a8fc1e11cef6db51d364e80061e97befa7 |
|
16 Closes-Bug: #1260080 |
|
17 |
|
18 --- |
|
19 keystone/token/backends/memcache.py | 27 +++++++++++++++++------ |
|
20 tests/test_backend.py | 41 ++++++++++++++++++++++++++++++++++- |
|
21 tests/test_backend_kvs.py | 2 ++ |
|
22 tests/test_backend_memcache.py | 3 +++ |
|
23 4 files changed, 65 insertions(+), 8 deletions(-) |
|
24 |
|
25 diff --git a/keystone/token/backends/memcache.py b/keystone/token/backends/memcache.py |
|
26 index c2c9b51..dc5c34e 100644 |
|
27 --- a/keystone/token/backends/memcache.py |
|
28 +++ b/keystone/token/backends/memcache.py |
|
29 @@ -62,6 +62,15 @@ class Token(token.Driver): |
|
30 return token_ref |
|
31 |
|
32 def create_token(self, token_id, data): |
|
33 + |
|
34 + def update_index(user_id, token_data): |
|
35 + user_key = self._prefix_user_id(user_id) |
|
36 + if not self.client.append(user_key, ',%s' % token_data): |
|
37 + if not self.client.add(user_key, token_data): |
|
38 + if not self.client.append(user_key, ',%s' % token_data): |
|
39 + msg = _('Unable to add token user list.') |
|
40 + raise exception.UnexpectedError(msg) |
|
41 + |
|
42 data_copy = copy.deepcopy(data) |
|
43 ptk = self._prefix_token_id(token.unique_id(token_id)) |
|
44 if not data_copy.get('expires'): |
|
45 @@ -73,15 +82,19 @@ class Token(token.Driver): |
|
46 expires_ts = utils.unixtime(data_copy['expires']) |
|
47 kwargs['time'] = expires_ts |
|
48 self.client.set(ptk, data_copy, **kwargs) |
|
49 + token_data = jsonutils.dumps(token_id) |
|
50 if 'id' in data['user']: |
|
51 - token_data = jsonutils.dumps(token_id) |
|
52 user_id = data['user']['id'] |
|
53 - user_key = self._prefix_user_id(user_id) |
|
54 - if not self.client.append(user_key, ',%s' % token_data): |
|
55 - if not self.client.add(user_key, token_data): |
|
56 - if not self.client.append(user_key, ',%s' % token_data): |
|
57 - msg = _('Unable to add token user list.') |
|
58 - raise exception.UnexpectedError(msg) |
|
59 + update_index(user_id, token_data) |
|
60 + |
|
61 + if CONF.trust.enabled and data.get('trust_id'): |
|
62 + if 'access' in data_copy: |
|
63 + trustee_user_id = data_copy['access']['trust'][ |
|
64 + 'trustee_user_id'] |
|
65 + else: |
|
66 + trustee_user_id = data_copy['OS-TRUST:trust'][ |
|
67 + 'trustee_user_id'] |
|
68 + update_index(trustee_user_id, token_data) |
|
69 return copy.deepcopy(data_copy) |
|
70 |
|
71 def _add_to_revocation_list(self, token_id, token_data): |
|
72 diff --git a/tests/test_backend.py b/tests/test_backend.py |
|
73 index 1af3c16..19caa0c 100644 |
|
74 --- a/tests/test_backend.py |
|
75 +++ b/tests/test_backend.py |
|
76 @@ -2096,7 +2096,8 @@ class TokenTests(object): |
|
77 self.token_api.delete_token, token_id) |
|
78 |
|
79 def create_token_sample_data(self, tenant_id=None, trust_id=None, |
|
80 - user_id="testuserid"): |
|
81 + user_id='testuserid', |
|
82 + trustee_user_id='testuserid2'): |
|
83 token_id = self._create_token_id() |
|
84 data = {'id': token_id, 'a': 'b', |
|
85 'user': {'id': user_id}} |
|
86 @@ -2104,6 +2105,11 @@ class TokenTests(object): |
|
87 data['tenant'] = {'id': tenant_id, 'name': tenant_id} |
|
88 if trust_id is not None: |
|
89 data['trust_id'] = trust_id |
|
90 + data.setdefault('access', {}).setdefault('trust', {}) |
|
91 + # Testuserid2 is used here since a trustee will be different in |
|
92 + # the cases of impersonation and therefore should not match the |
|
93 + # token's user_id. |
|
94 + data['access']['trust']['trustee_user_id'] = trustee_user_id |
|
95 self.token_api.create_token(token_id, data) |
|
96 return token_id |
|
97 |
|
98 @@ -2290,6 +2296,39 @@ class TokenTests(object): |
|
99 for t in self.token_api.list_revoked_tokens(): |
|
100 self.assertIn('expires', t) |
|
101 |
|
102 + def test_token_in_trustee_and_trustor_token_list(self): |
|
103 + self.opt_in_group('trust', |
|
104 + enabled=True) |
|
105 + trustor = self.user_foo |
|
106 + trustee = self.user_two |
|
107 + trust_id = uuid.uuid4().hex |
|
108 + trust_info = {'trustor_user_id': trustor['id'], |
|
109 + 'trustee_user_id': trustee['id'], |
|
110 + 'project_id': self.tenant_bar['id'], |
|
111 + 'expires_at': timeutils. |
|
112 + parse_isotime('2031-02-18T18:10:00Z'), |
|
113 + 'impersonation': True} |
|
114 + self.trust_api.create_trust(trust_id, trust_info, |
|
115 + roles=[{'id': 'member'}, |
|
116 + {'id': 'other'}, |
|
117 + {'id': 'browser'}]) |
|
118 + |
|
119 + token_id = self.create_token_sample_data( |
|
120 + tenant_id=self.tenant_bar['id'], |
|
121 + trust_id=trust_id, |
|
122 + user_id=trustor['id'], |
|
123 + trustee_user_id=trustee['id']) |
|
124 + |
|
125 + # Ensure the token id exists in both the trustor and trustee token |
|
126 + # lists |
|
127 + |
|
128 + self.assertIn(token_id, |
|
129 + self.token_api.list_tokens(self.user_two['id'], |
|
130 + trust_id=trust_id)) |
|
131 + self.assertIn(token_id, |
|
132 + self.token_api.list_tokens(self.user_foo['id'], |
|
133 + trust_id=trust_id)) |
|
134 + |
|
135 |
|
136 class TrustTests(object): |
|
137 def create_sample_trust(self, new_id): |
|
138 diff --git a/tests/test_backend_kvs.py b/tests/test_backend_kvs.py |
|
139 index f3a8ece..15a87b5 100644 |
|
140 --- a/tests/test_backend_kvs.py |
|
141 +++ b/tests/test_backend_kvs.py |
|
142 @@ -73,6 +73,8 @@ class KvsToken(test.TestCase, test_backend.TokenTests): |
|
143 def setUp(self): |
|
144 super(KvsToken, self).setUp() |
|
145 self.token_api = token_kvs.Token(db={}) |
|
146 + self.load_backends() |
|
147 + self.load_fixtures(default_fixtures) |
|
148 |
|
149 |
|
150 class KvsTrust(test.TestCase, test_backend.TrustTests): |
|
151 diff --git a/tests/test_backend_memcache.py b/tests/test_backend_memcache.py |
|
152 index 9fbaeb9..6339e6f 100644 |
|
153 --- a/tests/test_backend_memcache.py |
|
154 +++ b/tests/test_backend_memcache.py |
|
155 @@ -18,6 +18,7 @@ import uuid |
|
156 |
|
157 import memcache |
|
158 |
|
159 +import default_fixtures |
|
160 from keystone.common import utils |
|
161 from keystone.openstack.common import timeutils |
|
162 from keystone import test |
|
163 @@ -75,8 +76,10 @@ class MemcacheClient(object): |
|
164 class MemcacheToken(test.TestCase, test_backend.TokenTests): |
|
165 def setUp(self): |
|
166 super(MemcacheToken, self).setUp() |
|
167 + self.load_backends() |
|
168 fake_client = MemcacheClient() |
|
169 self.token_api = token_memcache.Token(client=fake_client) |
|
170 + self.load_fixtures(default_fixtures) |
|
171 |
|
172 def test_create_unicode_token_id(self): |
|
173 token_id = unicode(self._create_token_id()) |
|
174 -- |
|
175 1.7.9.5 |
|
176 |
|
177 |
|