Add flag to skip undefined rule check

Some components like neutron-lib builds its own sub-enforcer which
enforces policy rules partially. However even these enforcer may load
the full policy rules in the file and this causes a lot of warnings
about "undefined rules".

This introduces a new flag so that users can disable undefined check,
when they know the undefined rules are "expected".

Note that the flag is not formally exposed, because we don't know if
this requirement is common. If we find similar problems with different
components then we may add an argument to __init__ .

Related-Bug: #2048198
Change-Id: Ibb4e8e877640e8488aaffb40560e930b0cbfcbce
This commit is contained in:
Takashi Kajinami 2024-01-30 20:48:38 +09:00
parent 9b22cf5f8f
commit 973498106f
2 changed files with 29 additions and 1 deletions

View File

@ -556,6 +556,10 @@ class Enforcer(object):
self.suppress_default_change_warnings = False
# FOR TESTING ONLY
self.suppress_deprecation_warnings = False
# NOTE(tkajinam): Some components(eg. neutron-lib) build their own
# enforcers to check only partial rules with the full policy rules, and
# this sometimes causes a lot of undefined warnings
self.skip_undefined_check = False
def set_rules(self, rules, overwrite=True, use_conf=False):
"""Create a new :class:`Rules` based on the provided dict of rules.
@ -693,7 +697,7 @@ class Enforcer(object):
cyclic_checks = []
violation = False
for name, check in self.rules.items():
if self._undefined_check(check):
if not self.skip_undefined_check and self._undefined_check(check):
undefined_checks.append(name)
violation = True
if self._cycle_check(check):

View File

@ -1948,6 +1948,18 @@ class EnforcerCheckRulesTest(base.PolicyBaseTestCase):
self.assertFalse(self.enforcer.check_rules())
mock_log.warning.assert_called()
@mock.patch.object(policy, 'LOG')
def test_undefined_rule_skipped(self, mock_log):
rules = jsonutils.dumps({'foo': 'rule:bar'})
self.create_config_file('policy.json', rules)
self.enforcer.skip_undefined_check = True
self.enforcer.load_rules(True)
self.assertTrue(self.enforcer.check_rules())
# TODO(tkajinam): This fails because of warnings caused by JSON format
# policy file used
# mock_log.warning.assert_not_called()
@mock.patch.object(policy, 'LOG')
def test_undefined_rule_raises(self, mock_log):
rules = jsonutils.dumps({'foo': 'rule:bar'})
@ -1958,6 +1970,18 @@ class EnforcerCheckRulesTest(base.PolicyBaseTestCase):
self.enforcer.check_rules, raise_on_violation=True)
mock_log.warning.assert_called()
@mock.patch.object(policy, 'LOG')
def test_undefined_rule_raises_skipped(self, mock_log):
rules = jsonutils.dumps({'foo': 'rule:bar'})
self.create_config_file('policy.json', rules)
self.enforcer.skip_undefined_check = True
self.enforcer.load_rules(True)
self.assertTrue(self.enforcer.check_rules(raise_on_violation=True))
# TODO(tkajinam): This fails because of warnings caused by JSON format
# policy file used
# mock_log.warning.assert_not_called()
@mock.patch.object(policy, 'LOG')
def test_cyclical_rules(self, mock_log):
rules = jsonutils.dumps({'foo': 'rule:bar', 'bar': 'rule:foo'})