Blob Blame History Raw
From 364937ac46caf9e27b1b6700222a6b8e98fb956f Mon Sep 17 00:00:00 2001
From: Jamie Lennox <jamielennox@redhat.com>
Date: Thu, 19 Jun 2014 14:41:22 +1000
Subject: [PATCH] Ensure that in v2 auth tenant_id matches trust

Previously if a trustee requests a trust scoped token for a project that
is different to the one in the trust, however the trustor has the
appropriate roles then a token would be issued.

Ensure that the trust that was given matches the project that was
specified in the scope.

Change-Id: I00ad783bcb93cea9e5622965f81b91c80f4570cc
Closes-Bug: #1331912
(cherry picked from commit 79ad85a8ed9b7a3403367e2b6affe30ee69d21c5)
---
 keystone/tests/test_auth.py   | 17 +++++++++++++++--
 keystone/token/controllers.py |  6 +++++-
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/keystone/tests/test_auth.py b/keystone/tests/test_auth.py
index 9f41aba..c9e6747 100644
--- a/keystone/tests/test_auth.py
+++ b/keystone/tests/test_auth.py
@@ -679,12 +679,15 @@ class AuthWithTrust(AuthTest):
         body_dict = _build_user_auth(username=username, password=password)
         return self.controller.authenticate({}, body_dict)
 
-    def build_v2_token_request(self, username, password, trust):
+    def build_v2_token_request(self, username, password, trust,
+                               tenant_id=None):
+        if not tenant_id:
+            tenant_id = self.tenant_bar['id']
         unscoped_token = self.get_unscoped_token(username, password)
         unscoped_token_id = unscoped_token['access']['token']['id']
         request_body = _build_user_auth(token={'id': unscoped_token_id},
                                         trust_id=trust['id'],
-                                        tenant_id=self.tenant_bar['id'])
+                                        tenant_id=tenant_id)
         return request_body
 
     def test_create_trust_bad_data_fails(self):
@@ -796,6 +799,16 @@ class AuthWithTrust(AuthTest):
         self.assertRaises(exception.Forbidden, self.controller.authenticate,
                           {}, request_body)
 
+    def test_token_from_trust_wrong_project_fails(self):
+        for assigned_role in self.assigned_roles:
+            self.assignment_api.add_role_to_user_and_project(
+                self.trustor['id'], self.tenant_baz['id'], assigned_role)
+        new_trust = self.create_trust(self.sample_data, self.trustor['name'])
+        request_body = self.build_v2_token_request('TWO', 'two2', new_trust,
+                                                   self.tenant_baz['id'])
+        self.assertRaises(exception.Forbidden, self.controller.authenticate,
+                          {}, request_body)
+
     def fetch_v2_token_from_trust(self, trust):
         request_body = self.build_v2_token_request('TWO', 'two2', trust)
         auth_response = self.controller.authenticate({}, request_body)
diff --git a/keystone/token/controllers.py b/keystone/token/controllers.py
index 997abd6..30d941f 100644
--- a/keystone/token/controllers.py
+++ b/keystone/token/controllers.py
@@ -164,6 +164,8 @@ class Auth(controller.V2Controller):
 
         user_ref = old_token_ref['user']
         user_id = user_ref['id']
+        tenant_id = self._get_project_id_from_auth(auth)
+
         if not CONF.trust.enabled and 'trust_id' in auth:
             raise exception.Forbidden('Trusts are disabled.')
         elif CONF.trust.enabled and 'trust_id' in auth:
@@ -172,6 +174,9 @@ class Auth(controller.V2Controller):
                 raise exception.Forbidden()
             if user_id != trust_ref['trustee_user_id']:
                 raise exception.Forbidden()
+            if (trust_ref['project_id'] and
+                    tenant_id != trust_ref['project_id']):
+                raise exception.Forbidden()
             if ('expires' in trust_ref) and (trust_ref['expires']):
                 expiry = trust_ref['expires']
                 if expiry < timeutils.parse_isotime(timeutils.isotime()):
@@ -196,7 +201,6 @@ class Auth(controller.V2Controller):
             current_user_ref = self.identity_api.get_user(user_id)
 
         metadata_ref = {}
-        tenant_id = self._get_project_id_from_auth(auth)
         tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref(
             user_id, tenant_id)