Skip to content

Commit

Permalink
Ensure OAuth1 authorized roles are respected
Browse files Browse the repository at this point in the history
Without this patch, when an OAuth1 request token is authorized with a
limited set of roles, the roles for the access token are ignored when
the user uses it to request a keystone token. This means that user of an
access token can use it to escallate their role assignments beyond what
was authorized by the creator. This patch fixes the issue by ensuring
the token model accounts for an OAuth1-scoped token and correctly
populating the roles for it.

Change-Id: I02f9836fbd4d7e629653977fc341476cfd89859e
Closes-bug: #1873290
  • Loading branch information
cmurphy committed May 1, 2020
1 parent 3ec9940 commit 6c73690
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
18 changes: 18 additions & 0 deletions keystone/models/token_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"""Unified in-memory token model."""

from oslo_log import log
from oslo_serialization import jsonutils
from oslo_serialization import msgpackutils
from oslo_utils import reflection

Expand Down Expand Up @@ -327,6 +328,21 @@ def _get_trust_roles(self):

return roles

def _get_oauth_roles(self):
roles = []
access_token_roles = self.access_token['role_ids']
access_token_roles = [
{'role_id': r} for r in jsonutils.loads(access_token_roles)]
effective_access_token_roles = (
PROVIDERS.assignment_api.add_implied_roles(access_token_roles)
)
user_roles = [r['id'] for r in self._get_project_roles()]
for role in effective_access_token_roles:
if role['role_id'] in user_roles:
role = PROVIDERS.role_api.get_role(role['role_id'])
roles.append({'id': role['id'], 'name': role['name']})
return roles

def _get_federated_roles(self):
roles = []
group_ids = [group['id'] for group in self.federated_groups]
Expand Down Expand Up @@ -430,6 +446,8 @@ def roles(self):
roles = self._get_system_roles()
elif self.trust_scoped:
roles = self._get_trust_roles()
elif self.oauth_scoped:
roles = self._get_oauth_roles()
elif self.is_federated and not self.unscoped:
roles = self._get_federated_roles()
elif self.domain_scoped:
Expand Down
13 changes: 13 additions & 0 deletions keystone/tests/unit/test_v3_oauth1.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,19 @@ def test_oauth_flow(self):
self.keystone_token = content.result['token']
self.assertIsNotNone(self.keystone_token_id)

# add a new role assignment to ensure it is ignored in the access token
new_role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
PROVIDERS.role_api.create_role(new_role['id'], new_role)
PROVIDERS.assignment_api.add_role_to_user_and_project(
user_id=self.user_id,
project_id=self.project_id,
role_id=new_role['id'])
content = self.post(url, headers=headers, body=body)
token = content.result['token']
token_roles = [r['id'] for r in token['roles']]
self.assertIn(self.role_id, token_roles)
self.assertNotIn(new_role['id'], token_roles)


class AccessTokenCRUDTests(OAuthFlowTests):
def test_delete_access_token_dne(self):
Expand Down
19 changes: 19 additions & 0 deletions releasenotes/notes/bug-1873290-ff7f8e4cee15b75a.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
security:
- |
[`bug 1873290 <https://bugs.launchpad.net/keystone/+bug/1873290>`_]
[`bug 1872735 <https://bugs.launchpad.net/keystone/+bug/1872735>`_]
Fixed the token model to respect the roles authorized OAuth1 access tokens.
Previously, the list of roles authorized for an OAuth1 access token were
ignored, so when an access token was used to request a keystone token, the
keystone token would contain every role assignment the creator had for the
project. This also fixed EC2 credentials to respect those roles as well.
fixes:
- |
[`bug 1873290 <https://bugs.launchpad.net/keystone/+bug/1873290>`_]
[`bug 1872735 <https://bugs.launchpad.net/keystone/+bug/1872735>`_]
Fixed the token model to respect the roles authorized OAuth1 access tokens.
Previously, the list of roles authorized for an OAuth1 access token were
ignored, so when an access token was used to request a keystone token, the
keystone token would contain every role assignment the creator had for the
project. This also fixed EC2 credentials to respect those roles as well.

0 comments on commit 6c73690

Please # to comment.