Don't raise InvalidScope exception when do_raise=False

In the Enforcer.enforce() method there is boolean parameter do_raise.
When it is set to False, enforce() method should return True/False as an
enforcement result and not raise exception. It works like that with
PolicyNotAuthorized exception but since some time this method can also
raise InvalidScope exception and in such case behaviour was different.

This patch changes that behaviour so InvalidScope exception will also
not be raised when do_raise=False.

Closes-bug: #1965315
Change-Id: I37fd682ffa9d6f4c69698e1be42adac28bbfe72a
This commit is contained in:
Slawek Kaplonski 2022-03-17 20:35:45 +01:00
parent 9eef147fc3
commit 9bc1783400
2 changed files with 51 additions and 13 deletions

View File

@ -1042,7 +1042,10 @@ class Enforcer(object):
# If the thing we're given is a Check, we don't know the
# name of the rule, so pass None for current_rule.
if rule.scope_types:
self._enforce_scope(creds, rule)
scope_valid = self._enforce_scope(creds, rule,
do_raise=do_raise)
if not scope_valid:
return False
result = _checks._check(
rule=rule,
target=target,
@ -1067,7 +1070,10 @@ class Enforcer(object):
registered_rule = self.registered_rules.get(rule)
if registered_rule and registered_rule.scope_types:
self._enforce_scope(creds, registered_rule)
scope_valid = self._enforce_scope(creds, registered_rule,
do_raise=do_raise)
if not scope_valid:
return False
result = _checks._check(
rule=to_check,
target=target,
@ -1085,7 +1091,7 @@ class Enforcer(object):
return result
def _enforce_scope(self, creds, rule):
def _enforce_scope(self, creds, rule, do_raise=True):
# Check the scope of the operation against the possible scope
# attributes provided in `creds`.
if creds.get('system'):
@ -1097,11 +1103,15 @@ class Enforcer(object):
# we're dealing with a project-scoped token.
token_scope = 'project' # nosec
result = True
if token_scope not in rule.scope_types:
if self.conf.oslo_policy.enforce_scope:
raise InvalidScope(
rule, rule.scope_types, token_scope
)
if do_raise:
raise InvalidScope(
rule, rule.scope_types, token_scope
)
else:
result = False
# If we don't raise an exception we should at least
# inform operators about policies that are being used
# with improper scopes.
@ -1117,6 +1127,7 @@ class Enforcer(object):
}
)
warnings.warn(msg)
return result
def _map_context_attributes_into_creds(self, context):
creds = {}

View File

@ -923,15 +923,23 @@ class EnforcerTest(base.PolicyBaseTestCase):
target_dict = {}
self.assertRaises(
policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
target_dict, ctx
target_dict, ctx, do_raise=True
)
# and the same should return False if do_raise=False
self.assertFalse(
self.enforcer.enforce(
'fake_rule', target_dict, ctx, do_raise=False))
# model a project-scoped token, which should fail enforcement
ctx = context.RequestContext(project_id='fake')
self.assertRaises(
policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
target_dict, ctx
target_dict, ctx, True
)
# and the same should return False if do_raise=False
self.assertFalse(
self.enforcer.enforce(
'fake_rule', target_dict, ctx, do_raise=False))
def test_enforcer_understands_domain_scope(self):
self.conf.set_override('enforce_scope', True, group='oslo_policy')
@ -956,15 +964,23 @@ class EnforcerTest(base.PolicyBaseTestCase):
target_dict = {}
self.assertRaises(
policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
target_dict, ctx
target_dict, ctx, True
)
# and the same should return False if do_raise=False
self.assertFalse(
self.enforcer.enforce(
'fake_rule', target_dict, ctx, do_raise=False))
# model a project-scoped token, which should fail enforcement
ctx = context.RequestContext(project_id='fake')
self.assertRaises(
policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
target_dict, ctx
target_dict, ctx, True
)
# and the same should return False if do_raise=False
self.assertFalse(
self.enforcer.enforce(
'fake_rule', target_dict, ctx, do_raise=False))
def test_enforcer_understands_project_scope(self):
self.conf.set_override('enforce_scope', True, group='oslo_policy')
@ -989,15 +1005,23 @@ class EnforcerTest(base.PolicyBaseTestCase):
target_dict = {}
self.assertRaises(
policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
target_dict, ctx
target_dict, ctx, True
)
# and the same should return False if do_raise=False
self.assertFalse(
self.enforcer.enforce(
'fake_rule', target_dict, ctx, do_raise=False))
# model a domain-scoped token, which should fail enforcement
ctx = context.RequestContext(domain_id='fake')
self.assertRaises(
policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
target_dict, ctx
target_dict, ctx, True
)
# and the same should return False if do_raise=False
self.assertFalse(
self.enforcer.enforce(
'fake_rule', target_dict, ctx, do_raise=False))
def test_enforce_scope_with_subclassed_checks_when_scope_not_set(self):
self.conf.set_override('enforce_scope', True, group='oslo_policy')
@ -1013,7 +1037,10 @@ class EnforcerTest(base.PolicyBaseTestCase):
ctx = context.RequestContext(system_scope='all', roles=['admin'])
self.assertRaises(
policy.InvalidScope,
self.enforcer.enforce, rule, {}, ctx)
self.enforcer.enforce, rule, {}, ctx, do_raise=True)
# and the same should return False if do_raise=False
self.assertFalse(
self.enforcer.enforce(rule, {}, ctx, do_raise=False))
class EnforcerNoPolicyFileTest(base.PolicyBaseTestCase):