Check for circular references when expanding implied roles

closes-bug #1536321

Change-Id: I30d4f54135864d10093437a0541d6f40255e40e2
This commit is contained in:
Adam Young 2016-01-21 23:14:41 -05:00 committed by Steve Martinelli
parent dc01e06ab4
commit 2a5599811e
2 changed files with 42 additions and 4 deletions

View File

@ -28,7 +28,7 @@ from keystone.common import driver_hints
from keystone.common import manager
from keystone import exception
from keystone.i18n import _
from keystone.i18n import _LI
from keystone.i18n import _LI, _LE
from keystone import notifications
@ -612,8 +612,10 @@ class Manager(manager.Manager):
implied_roles_cache = {}
role_refs_to_check = list(role_refs)
ref_results = list(role_refs)
checked_role_refs = list()
while(role_refs_to_check):
next_ref = role_refs_to_check.pop()
checked_role_refs.append(next_ref)
next_role_id = next_ref['role_id']
if next_role_id in implied_roles_cache:
implied_roles = implied_roles_cache[next_role_id]
@ -625,8 +627,13 @@ class Manager(manager.Manager):
implied_ref = (
_make_implied_ref_copy(
next_ref, implied_role['implied_role_id']))
ref_results.append(implied_ref)
role_refs_to_check.append(implied_ref)
if implied_ref in checked_role_refs:
msg = _LE('Circular reference found '
'role inference rules - %(prior_role_id)s.')
LOG.error(msg, {'prior_role_id': next_ref['role_id']})
else:
ref_results.append(implied_ref)
role_refs_to_check.append(implied_ref)
except exception.NotImplemented:
LOG.error('Role driver does not support implied roles.')

View File

@ -6560,6 +6560,37 @@ class ImpliedRoleTests(AssignmentTestHelperMixin):
}
self.execute_assignment_plan(test_plan)
def test_circular_inferences(self):
"""Test that implied roles are expanded out."""
test_plan = {
'entities': {'domains': {'users': 1, 'projects': 1},
'roles': 4},
# Three level tree of implied roles
'implied_roles': [{'role': 0, 'implied_roles': [1]},
{'role': 1, 'implied_roles': [2, 3]},
{'role': 3, 'implied_roles': [0]}],
'assignments': [{'user': 0, 'role': 0, 'project': 0}],
'tests': [
# List all direct assignments for user[0], this should just
# show the one top level role assignment
{'params': {'user': 0},
'results': [{'user': 0, 'role': 0, 'project': 0}]},
# Listing in effective mode should show the implied roles
# expanded out
{'params': {'user': 0, 'effective': True},
'results': [{'user': 0, 'role': 0, 'project': 0},
{'user': 0, 'role': 0, 'project': 0,
'indirect': {'role': 3}},
{'user': 0, 'role': 1, 'project': 0,
'indirect': {'role': 0}},
{'user': 0, 'role': 2, 'project': 0,
'indirect': {'role': 1}},
{'user': 0, 'role': 3, 'project': 0,
'indirect': {'role': 1}}]},
]
}
self.execute_assignment_plan(test_plan)
def test_role_assignments_directed_graph_of_implied_roles(self):
"""Test that a role can have multiple, different prior roles."""
test_plan = {
@ -6570,7 +6601,7 @@ class ImpliedRoleTests(AssignmentTestHelperMixin):
'implied_roles': [{'role': 0, 'implied_roles': [1, 2]},
{'role': 1, 'implied_roles': [3, 4]},
{'role': 5, 'implied_roles': 4}],
# The use gets both top level roles
# The user gets both top level roles
'assignments': [{'user': 0, 'role': 0, 'project': 0},
{'user': 0, 'role': 5, 'project': 0}],
'tests': [