components/openstack/keystone/patches/05-CVE-2014-2237.patch
changeset 1944 56ac2df1785b
parent 1943 1a27f000029f
child 1945 3dc1935a2189
equal deleted inserted replaced
1943:1a27f000029f 1944:56ac2df1785b
     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