1 From 9c9c1331e0c004897d5f4c5847f7143b56373f10 Mon Sep 17 00:00:00 2001 |
|
2 From: Brant Knudson <[email protected]> |
|
3 Date: Tue, 1 Dec 2015 11:09:14 -0600 |
|
4 Subject: [PATCH] Add audit IDs to revocation events |
|
5 |
|
6 The revoked tokens' audit ID is now included in the data returned in |
|
7 the revocation list. |
|
8 |
|
9 Closes-Bug: 1490804 |
|
10 Change-Id: Ifcf88f1158bebddc4f927121fbf4136fb53b659f |
|
11 (cherry picked from commit d5378f173da14a34ca010271477337879002d6d0) |
|
12 Conflicts: |
|
13 keystone/tests/unit/test_backend.py |
|
14 --- |
|
15 keystone/tests/unit/test_backend.py | 39 ++++++++++++++++++++---------- |
|
16 keystone/tests/unit/test_backend_sql.py | 3 ++- |
|
17 keystone/token/persistence/backends/kvs.py | 9 +++++++ |
|
18 keystone/token/persistence/backends/sql.py | 12 ++++++++- |
|
19 4 files changed, 48 insertions(+), 15 deletions(-) |
|
20 |
|
21 diff --git a/keystone/tests/unit/test_backend.py b/keystone/tests/unit/test_backend.py |
|
22 index 6cf0649..9c82502 100644 |
|
23 --- a/keystone/tests/unit/test_backend.py |
|
24 +++ b/keystone/tests/unit/test_backend.py |
|
25 @@ -3778,7 +3778,9 @@ class TokenTests(object): |
|
26 token_id = self._create_token_id() |
|
27 data = {'id': token_id, 'a': 'b', |
|
28 'trust_id': None, |
|
29 - 'user': {'id': 'testuserid'}} |
|
30 + 'user': {'id': 'testuserid'}, |
|
31 + 'token_data': {'access': {'token': { |
|
32 + 'audit_ids': [uuid.uuid4().hex]}}}} |
|
33 data_ref = self.token_provider_api._persistence.create_token(token_id, |
|
34 data) |
|
35 expires = data_ref.pop('expires') |
|
36 @@ -3813,7 +3815,8 @@ class TokenTests(object): |
|
37 # FIXME(morganfainberg): These tokens look nothing like "Real" tokens. |
|
38 # This should be fixed when token issuance is cleaned up. |
|
39 data = {'id': token_id, 'a': 'b', |
|
40 - 'user': {'id': user_id}} |
|
41 + 'user': {'id': user_id}, |
|
42 + 'access': {'token': {'audit_ids': [uuid.uuid4().hex]}}} |
|
43 if tenant_id is not None: |
|
44 data['tenant'] = {'id': tenant_id, 'name': tenant_id} |
|
45 if tenant_id is NULL_OBJECT: |
|
46 @@ -3822,7 +3825,7 @@ class TokenTests(object): |
|
47 data['expires'] = expires |
|
48 if trust_id is not None: |
|
49 data['trust_id'] = trust_id |
|
50 - data.setdefault('access', {}).setdefault('trust', {}) |
|
51 + data['access'].setdefault('trust', {}) |
|
52 # Testuserid2 is used here since a trustee will be different in |
|
53 # the cases of impersonation and therefore should not match the |
|
54 # token's user_id. |
|
55 @@ -3988,17 +3991,21 @@ class TokenTests(object): |
|
56 |
|
57 self.assertEqual(data_ref, new_data_ref) |
|
58 |
|
59 - def check_list_revoked_tokens(self, token_ids): |
|
60 - revoked_ids = [x['id'] |
|
61 - for x in self.token_provider_api.list_revoked_tokens()] |
|
62 + def check_list_revoked_tokens(self, token_infos): |
|
63 + revocation_list = self.token_provider_api.list_revoked_tokens() |
|
64 + revoked_ids = [x['id'] for x in revocation_list] |
|
65 + revoked_audit_ids = [x['audit_id'] for x in revocation_list] |
|
66 self._assert_revoked_token_list_matches_token_persistence(revoked_ids) |
|
67 - for token_id in token_ids: |
|
68 + for token_id, audit_id in token_infos: |
|
69 self.assertIn(token_id, revoked_ids) |
|
70 + self.assertIn(audit_id, revoked_audit_ids) |
|
71 |
|
72 def delete_token(self): |
|
73 token_id = uuid.uuid4().hex |
|
74 + audit_id = uuid.uuid4().hex |
|
75 data = {'id_hash': token_id, 'id': token_id, 'a': 'b', |
|
76 - 'user': {'id': 'testuserid'}} |
|
77 + 'user': {'id': 'testuserid'}, |
|
78 + 'token_data': {'token': {'audit_ids': [audit_id]}}} |
|
79 data_ref = self.token_provider_api._persistence.create_token(token_id, |
|
80 data) |
|
81 self.token_provider_api._persistence.delete_token(token_id) |
|
82 @@ -4010,7 +4017,7 @@ class TokenTests(object): |
|
83 exception.TokenNotFound, |
|
84 self.token_provider_api._persistence.delete_token, |
|
85 data_ref['id']) |
|
86 - return token_id |
|
87 + return (token_id, audit_id) |
|
88 |
|
89 def test_list_revoked_tokens_returns_empty_list(self): |
|
90 revoked_ids = [x['id'] |
|
91 @@ -4061,12 +4068,16 @@ class TokenTests(object): |
|
92 token_data = {'id_hash': token_id, 'id': token_id, 'a': 'b', |
|
93 'expires': expire_time, |
|
94 'trust_id': None, |
|
95 - 'user': {'id': 'testuserid'}} |
|
96 + 'user': {'id': 'testuserid'}, |
|
97 + 'token_data': {'token': { |
|
98 + 'audit_ids': [uuid.uuid4().hex]}}} |
|
99 token2_id = uuid.uuid4().hex |
|
100 token2_data = {'id_hash': token2_id, 'id': token2_id, 'a': 'b', |
|
101 'expires': expire_time, |
|
102 'trust_id': None, |
|
103 - 'user': {'id': 'testuserid'}} |
|
104 + 'user': {'id': 'testuserid'}, |
|
105 + 'token_data': {'token': { |
|
106 + 'audit_ids': [uuid.uuid4().hex]}}} |
|
107 # Create 2 Tokens. |
|
108 self.token_provider_api._persistence.create_token(token_id, |
|
109 token_data) |
|
110 @@ -4101,7 +4112,8 @@ class TokenTests(object): |
|
111 def _test_predictable_revoked_pki_token_id(self, hash_fn): |
|
112 token_id = self._create_token_id() |
|
113 token_id_hash = hash_fn(token_id).hexdigest() |
|
114 - token = {'user': {'id': uuid.uuid4().hex}} |
|
115 + token = {'user': {'id': uuid.uuid4().hex}, |
|
116 + 'token_data': {'token': {'audit_ids': [uuid.uuid4().hex]}}} |
|
117 |
|
118 self.token_provider_api._persistence.create_token(token_id, token) |
|
119 self.token_provider_api._persistence.delete_token(token_id) |
|
120 @@ -4123,7 +4135,8 @@ class TokenTests(object): |
|
121 |
|
122 def test_predictable_revoked_uuid_token_id(self): |
|
123 token_id = uuid.uuid4().hex |
|
124 - token = {'user': {'id': uuid.uuid4().hex}} |
|
125 + token = {'user': {'id': uuid.uuid4().hex}, |
|
126 + 'token_data': {'token': {'audit_ids': [uuid.uuid4().hex]}}} |
|
127 |
|
128 self.token_provider_api._persistence.create_token(token_id, token) |
|
129 self.token_provider_api._persistence.delete_token(token_id) |
|
130 diff --git a/keystone/tests/unit/test_backend_sql.py b/keystone/tests/unit/test_backend_sql.py |
|
131 index a7c63bf..7adc936 100644 |
|
132 --- a/keystone/tests/unit/test_backend_sql.py |
|
133 +++ b/keystone/tests/unit/test_backend_sql.py |
|
134 @@ -441,7 +441,8 @@ class SqlToken(SqlTests, test_backend.TokenTests): |
|
135 # necessary. |
|
136 |
|
137 expected_query_args = (token_sql.TokenModel.id, |
|
138 - token_sql.TokenModel.expires) |
|
139 + token_sql.TokenModel.expires, |
|
140 + token_sql.TokenModel.extra,) |
|
141 |
|
142 with mock.patch.object(token_sql, 'sql') as mock_sql: |
|
143 tok = token_sql.Token() |
|
144 diff --git a/keystone/token/persistence/backends/kvs.py b/keystone/token/persistence/backends/kvs.py |
|
145 index b4807bf..9a7ccea 100644 |
|
146 --- a/keystone/token/persistence/backends/kvs.py |
|
147 +++ b/keystone/token/persistence/backends/kvs.py |
|
148 @@ -211,6 +211,15 @@ class Token(token.persistence.Driver): |
|
149 subsecond=True) |
|
150 revoked_token_data['id'] = data['id'] |
|
151 |
|
152 + token_data = data['token_data'] |
|
153 + if 'access' in token_data: |
|
154 + # It's a v2 token. |
|
155 + audit_ids = token_data['access']['token']['audit_ids'] |
|
156 + else: |
|
157 + # It's a v3 token. |
|
158 + audit_ids = token_data['token']['audit_ids'] |
|
159 + revoked_token_data['audit_id'] = audit_ids[0] |
|
160 + |
|
161 token_list = self._get_key_or_default(self.revocation_key, default=[]) |
|
162 if not isinstance(token_list, list): |
|
163 # NOTE(morganfainberg): In the case that the revocation list is not |
|
164 diff --git a/keystone/token/persistence/backends/sql.py b/keystone/token/persistence/backends/sql.py |
|
165 index 08c3a21..7c5c11d 100644 |
|
166 --- a/keystone/token/persistence/backends/sql.py |
|
167 +++ b/keystone/token/persistence/backends/sql.py |
|
168 @@ -228,13 +228,23 @@ class Token(token.persistence.Driver): |
|
169 session = sql.get_session() |
|
170 tokens = [] |
|
171 now = timeutils.utcnow() |
|
172 - query = session.query(TokenModel.id, TokenModel.expires) |
|
173 + query = session.query(TokenModel.id, TokenModel.expires, |
|
174 + TokenModel.extra) |
|
175 query = query.filter(TokenModel.expires > now) |
|
176 token_references = query.filter_by(valid=False) |
|
177 for token_ref in token_references: |
|
178 + token_data = token_ref[2]['token_data'] |
|
179 + if 'access' in token_data: |
|
180 + # It's a v2 token. |
|
181 + audit_ids = token_data['access']['token']['audit_ids'] |
|
182 + else: |
|
183 + # It's a v3 token. |
|
184 + audit_ids = token_data['token']['audit_ids'] |
|
185 + |
|
186 record = { |
|
187 'id': token_ref[0], |
|
188 'expires': token_ref[1], |
|
189 + 'audit_id': audit_ids[0], |
|
190 } |
|
191 tokens.append(record) |
|
192 return tokens |
|
193 -- |
|
194 1.9.1 |
|
195 |
|