components/openstack/keystone/patches/CVE-2015-7546.patch
changeset 6851 f984e52b96bb
parent 6850 f8d3bc724af7
child 6852 bf55de364b19
equal deleted inserted replaced
6850:f8d3bc724af7 6851:f984e52b96bb
     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