Enable enforce_scope and enforce_new_defaults by default
As per the RBAc goal timeline, we agreed to enable enforce_scope as well as the enforce_new_defaults by default - https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#id4 Also, marking enforce_scope deprecated and to be removed in 2025.2 (SLURP) cycle. Change-Id: I23ccdfd810ba8290aa49a47471eabdb65fea2128
This commit is contained in:
@@ -25,7 +25,14 @@ _option_group = 'oslo_policy'
|
||||
|
||||
_options = [
|
||||
cfg.BoolOpt('enforce_scope',
|
||||
default=False,
|
||||
default=True,
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason='This configuration was added temporarily '
|
||||
'to facilitate a smooth transition to the '
|
||||
'new RBAC. OpenStack will always enforce '
|
||||
'scope checks. This configuration option '
|
||||
'is deprecated and will be removed in the '
|
||||
'2025.2 cycle.',
|
||||
help=_('This option controls whether or not to enforce scope '
|
||||
'when evaluating policies. If ``True``, the scope of '
|
||||
'the token used in the request is compared to the '
|
||||
@@ -35,7 +42,7 @@ _options = [
|
||||
'logged informing operators that policies are being '
|
||||
'invoked with mismatching scope.')),
|
||||
cfg.BoolOpt('enforce_new_defaults',
|
||||
default=False,
|
||||
default=True,
|
||||
help=_('This option controls whether or not to use old '
|
||||
'deprecated defaults when evaluating policies. If '
|
||||
'``True``, the old deprecated defaults are not going '
|
||||
|
@@ -40,21 +40,21 @@ class OptsTestCase(test_base.BaseTestCase):
|
||||
|
||||
def test_set_defaults_enforce_scope(self):
|
||||
opts._register(self.conf)
|
||||
self.assertEqual(False,
|
||||
self.conf.oslo_policy.enforce_scope)
|
||||
opts.set_defaults(self.conf, enforce_scope=True)
|
||||
self.assertEqual(True,
|
||||
self.conf.oslo_policy.enforce_scope)
|
||||
opts.set_defaults(self.conf, enforce_scope=False)
|
||||
self.assertEqual(False,
|
||||
self.conf.oslo_policy.enforce_scope)
|
||||
|
||||
def test_set_defaults_two_opts(self):
|
||||
opts._register(self.conf)
|
||||
self.assertEqual(False,
|
||||
self.conf.oslo_policy.enforce_scope)
|
||||
self.assertEqual(False,
|
||||
self.conf.oslo_policy.enforce_new_defaults)
|
||||
opts.set_defaults(self.conf, enforce_scope=True,
|
||||
enforce_new_defaults=True)
|
||||
self.assertEqual(True,
|
||||
self.conf.oslo_policy.enforce_scope)
|
||||
self.assertEqual(True,
|
||||
self.conf.oslo_policy.enforce_new_defaults)
|
||||
opts.set_defaults(self.conf, enforce_scope=False,
|
||||
enforce_new_defaults=False)
|
||||
self.assertEqual(False,
|
||||
self.conf.oslo_policy.enforce_scope)
|
||||
self.assertEqual(False,
|
||||
self.conf.oslo_policy.enforce_new_defaults)
|
||||
|
@@ -1271,7 +1271,6 @@ class RuleDefaultTestCase(base.PolicyBaseTestCase):
|
||||
|
||||
class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
|
||||
@mock.patch('warnings.warn', new=mock.Mock())
|
||||
def test_deprecate_a_policy_check_string(self):
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:create_bar',
|
||||
@@ -1285,33 +1284,24 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
check_str='role:bang',
|
||||
description='Create a bar.',
|
||||
operations=[{'path': '/v1/bars', 'method': 'POST'}],
|
||||
scope_types=['project'],
|
||||
deprecated_rule=deprecated_rule,
|
||||
)]
|
||||
enforcer = policy.Enforcer(self.conf)
|
||||
enforcer.register_defaults(rule_list)
|
||||
expected_msg = (
|
||||
'Policy "foo:create_bar":"role:fizz" was deprecated in N in favor '
|
||||
'of "foo:create_bar":"role:bang". Reason: "role:bang" is a better '
|
||||
'default. Either ensure your deployment is ready for the new '
|
||||
'default or copy/paste the deprecated policy into your policy '
|
||||
'file and maintain it manually.'
|
||||
)
|
||||
|
||||
with mock.patch('warnings.warn') as mock_warn:
|
||||
enforcer.load_rules()
|
||||
mock_warn.assert_called_once_with(expected_msg)
|
||||
enforcer.load_rules()
|
||||
|
||||
self.assertTrue(
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['bang']})
|
||||
)
|
||||
self.assertTrue(
|
||||
self.assertFalse(
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['fizz']})
|
||||
)
|
||||
self.assertFalse(
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['baz']})
|
||||
)
|
||||
|
||||
@mock.patch('warnings.warn', new=mock.Mock())
|
||||
def test_deprecate_an_empty_policy_check_string(self):
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:create_bar',
|
||||
@@ -1325,21 +1315,18 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
check_str='role:bang',
|
||||
description='Create a bar.',
|
||||
operations=[{'path': '/v1/bars', 'method': 'POST'}],
|
||||
scope_types=['project'],
|
||||
deprecated_rule=deprecated_rule,
|
||||
)]
|
||||
enforcer = policy.Enforcer(self.conf)
|
||||
enforcer.register_defaults(rule_list)
|
||||
|
||||
with mock.patch('warnings.warn') as mock_warn:
|
||||
enforcer.load_rules()
|
||||
mock_warn.assert_called_once()
|
||||
enforcer.load_rules()
|
||||
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['bang']},
|
||||
do_raise=True)
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['fizz']},
|
||||
do_raise=True)
|
||||
self.assertFalse(
|
||||
self.enforcer.enforce('foo:create_bar', {}, {'roles': ['fizz']}))
|
||||
|
||||
@mock.patch('warnings.warn', new=mock.Mock())
|
||||
def test_deprecate_replace_with_empty_policy_check_string(self):
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:create_bar',
|
||||
@@ -1353,14 +1340,12 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
check_str='',
|
||||
description='Create a bar.',
|
||||
operations=[{'path': '/v1/bars', 'method': 'POST'}],
|
||||
scope_types=['project'],
|
||||
deprecated_rule=deprecated_rule,
|
||||
)]
|
||||
enforcer = policy.Enforcer(self.conf)
|
||||
enforcer.register_defaults(rule_list)
|
||||
|
||||
with mock.patch('warnings.warn') as mock_warn:
|
||||
enforcer.load_rules()
|
||||
mock_warn.assert_called_once()
|
||||
enforcer.load_rules()
|
||||
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['fizz']},
|
||||
do_raise=True)
|
||||
@@ -1387,6 +1372,7 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
check_str='role:baz',
|
||||
description='Create a bar.',
|
||||
operations=[{'path': '/v1/bars/', 'method': 'POST'}],
|
||||
scope_types=['project'],
|
||||
deprecated_rule=deprecated_rule,
|
||||
)]
|
||||
expected_msg = (
|
||||
@@ -1459,6 +1445,8 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
mock_warn.assert_not_called()
|
||||
|
||||
def test_deprecate_check_str_suppress_does_not_log_warning(self):
|
||||
self.conf.set_override('enforce_new_defaults', False,
|
||||
group='oslo_policy')
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:create_bar',
|
||||
check_str='role:fizz',
|
||||
@@ -1481,6 +1469,8 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
mock_warn.assert_not_called()
|
||||
|
||||
def test_deprecate_name_suppress_does_not_log_warning(self):
|
||||
self.conf.set_override('enforce_new_defaults', False,
|
||||
group='oslo_policy')
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:bar',
|
||||
check_str='role:baz',
|
||||
@@ -1507,6 +1497,9 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
mock_warn.assert_not_called()
|
||||
|
||||
def test_deprecate_for_removal_suppress_does_not_log_warning(self):
|
||||
self.conf.set_override('enforce_new_defaults', False,
|
||||
group='oslo_policy')
|
||||
|
||||
rule_list = [policy.DocumentedRuleDefault(
|
||||
name='foo:bar',
|
||||
check_str='role:baz',
|
||||
@@ -1529,6 +1522,9 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
mock_warn.assert_not_called()
|
||||
|
||||
def test_suppress_default_change_warnings_flag_not_log_warning(self):
|
||||
self.conf.set_override('enforce_new_defaults', False,
|
||||
group='oslo_policy')
|
||||
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:create_bar',
|
||||
check_str='role:fizz',
|
||||
@@ -1759,8 +1755,6 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
self.assertEqual('bang', self.enforcer.rules['new_rule'].match)
|
||||
|
||||
def test_enforce_new_defaults_no_old_check_string(self):
|
||||
self.conf.set_override('enforce_new_defaults', True,
|
||||
group='oslo_policy')
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:create_bar',
|
||||
check_str='role:fizz',
|
||||
@@ -1791,6 +1785,43 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['baz']})
|
||||
)
|
||||
|
||||
def test_disable_enforce_new_defaults_add_old_check_string(self):
|
||||
self.conf.set_override('enforce_new_defaults', False,
|
||||
group='oslo_policy')
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:create_bar',
|
||||
check_str='role:fizz',
|
||||
deprecated_reason='"role:bang" is a better default',
|
||||
deprecated_since='N',
|
||||
)
|
||||
|
||||
rule_list = [policy.DocumentedRuleDefault(
|
||||
name='foo:create_bar',
|
||||
check_str='role:bang',
|
||||
description='Create a bar.',
|
||||
operations=[{'path': '/v1/bars', 'method': 'POST'}],
|
||||
deprecated_rule=deprecated_rule,
|
||||
)]
|
||||
enforcer = policy.Enforcer(self.conf)
|
||||
enforcer.register_defaults(rule_list)
|
||||
enforcer.load_rules()
|
||||
|
||||
expected_check = policy.OrCheck([
|
||||
_parser.parse_rule(cs) for cs in
|
||||
[rule_list[0].check_str, deprecated_rule.check_str]
|
||||
])
|
||||
self.assertEqual(
|
||||
str(enforcer.rules['foo:create_bar']), str(expected_check))
|
||||
self.assertTrue(
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['bang']})
|
||||
)
|
||||
self.assertTrue(
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['fizz']})
|
||||
)
|
||||
self.assertFalse(
|
||||
enforcer.enforce('foo:create_bar', {}, {'roles': ['baz']})
|
||||
)
|
||||
|
||||
def test_deprecation_logic_is_only_performed_once_per_rule(self):
|
||||
deprecated_rule = policy.DeprecatedRule(
|
||||
name='foo:create_bar',
|
||||
@@ -1817,15 +1848,12 @@ class DocumentedRuleDefaultDeprecationTestCase(base.PolicyBaseTestCase):
|
||||
enforcer.load_rules()
|
||||
|
||||
# Loading the rules will store a version of the rule check string
|
||||
# logically ORed with the check string of the deprecated value. Make
|
||||
# sure this is happening but that the original rule check is unchanged
|
||||
expected_check = policy.OrCheck([
|
||||
_parser.parse_rule(cs) for cs in
|
||||
[rule.check_str, deprecated_rule.check_str]
|
||||
])
|
||||
# but as enforce_new_defaults is True it will not logically ORed with
|
||||
# the check string of the deprecated value. Make sure this is happening
|
||||
# and the original rule check is unchanged
|
||||
self.assertIn('foo:create_bar', enforcer.rules)
|
||||
self.assertEqual(
|
||||
str(enforcer.rules['foo:create_bar']), str(expected_check))
|
||||
self.assertEqual(rule.check_str,
|
||||
str(enforcer.rules['foo:create_bar']))
|
||||
self.assertEqual(check, rule.check)
|
||||
# Hacky way to check whether _handle_deprecated_rule was called again.
|
||||
# If a second call to load_rules doesn't overwrite our dummy rule then
|
||||
|
@@ -0,0 +1,23 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
The default value of config options ``enforce_scope`` and
|
||||
``enforce_new_defaults`` have been changed to ``True``.
|
||||
|
||||
Most of the OpenStack services have enabled these options by
|
||||
default, and now it's time to change the default in the oslo
|
||||
policy itself.
|
||||
|
||||
If you want to disable them, modify the values of these config
|
||||
options in the service configuration file (for example, "nova.conf")::
|
||||
|
||||
[oslo_policy]
|
||||
enforce_new_defaults=False
|
||||
enforce_scope=False
|
||||
deprecations:
|
||||
- |
|
||||
The ``enforce_scope`` configuration option was added temporarily
|
||||
to facilitate a smooth transition to the new RBAC. OpenStack will
|
||||
always enforce the scope checks, and they will not be configurable.
|
||||
This configuration option is marked as deprecated and will be removed
|
||||
in the 2025.2 cycle.
|
Reference in New Issue
Block a user