diff --git a/ironic/common/policy.py b/ironic/common/policy.py index 2ff00fb786..89150845b8 100644 --- a/ironic/common/policy.py +++ b/ironic/common/policy.py @@ -15,6 +15,8 @@ """Policy Engine For Ironic.""" +import sys + from oslo_concurrency import lockutils from oslo_config import cfg from oslo_log import log @@ -227,6 +229,27 @@ def get_enforcer(): return _ENFORCER +def get_oslo_policy_enforcer(): + # This method is for use by oslopolicy CLI scripts. Those scripts need the + # 'output-file' and 'namespace' options, but having those in sys.argv means + # loading the Ironic config options will fail as those are not expected to + # be present. So we pass in an arg list with those stripped out. + + conf_args = [] + # Start at 1 because cfg.CONF expects the equivalent of sys.argv[1:] + i = 1 + while i < len(sys.argv): + if sys.argv[i].strip('-') in ['namespace', 'output-file']: + i += 2 + continue + conf_args.append(sys.argv[i]) + i += 1 + + cfg.CONF(conf_args, project='ironic') + + return get_enforcer() + + # NOTE(deva): We can't call these methods from within decorators because the # 'target' and 'creds' parameter must be fetched from the call time # context-local pecan.request magic variable, but decorators are compiled diff --git a/ironic/tests/unit/common/test_policy.py b/ironic/tests/unit/common/test_policy.py index 97d3375580..db0a3e437c 100644 --- a/ironic/tests/unit/common/test_policy.py +++ b/ironic/tests/unit/common/test_policy.py @@ -15,6 +15,10 @@ # License for the specific language governing permissions and limitations # under the License. +import sys + +import mock +from oslo_config import cfg from oslo_policy import policy as oslo_policy from ironic.common import exception @@ -119,3 +123,34 @@ class PolicyTestCase(base.TestCase): exception.IronicException, policy.enforce, 'has_foo_role', creds, creds, True, exception.IronicException) + + @mock.patch.object(cfg, 'CONF', autospec=True) + @mock.patch.object(policy, 'get_enforcer', autospec=True) + def test_get_oslo_policy_enforcer_no_args(self, mock_gpe, mock_cfg): + mock_gpe.return_value = mock.Mock() + args = [] + with mock.patch.object(sys, 'argv', args): + policy.get_oslo_policy_enforcer() + mock_cfg.assert_called_once_with([], project='ironic') + self.assertEqual(1, mock_gpe.call_count) + + @mock.patch.object(cfg, 'CONF', autospec=True) + @mock.patch.object(policy, 'get_enforcer', autospec=True) + def test_get_oslo_policy_enforcer_namespace(self, mock_gpe, mock_cfg): + mock_gpe.return_value = mock.Mock() + args = ['opg', '--namespace', 'ironic'] + with mock.patch.object(sys, 'argv', args): + policy.get_oslo_policy_enforcer() + mock_cfg.assert_called_once_with([], project='ironic') + self.assertEqual(1, mock_gpe.call_count) + + @mock.patch.object(cfg, 'CONF', autospec=True) + @mock.patch.object(policy, 'get_enforcer', autospec=True) + def test_get_oslo_policy_enforcer_config_file(self, mock_gpe, mock_cfg): + mock_gpe.return_value = mock.Mock() + args = ['opg', '--namespace', 'ironic', '--config-file', 'my.cfg'] + with mock.patch.object(sys, 'argv', args): + policy.get_oslo_policy_enforcer() + mock_cfg.assert_called_once_with(['--config-file', 'my.cfg'], + project='ironic') + self.assertEqual(1, mock_gpe.call_count) diff --git a/releasenotes/notes/oslopolicy-scripts-bdcaeaf7dd9ce2ac.yaml b/releasenotes/notes/oslopolicy-scripts-bdcaeaf7dd9ce2ac.yaml new file mode 100644 index 0000000000..d510f0fb7e --- /dev/null +++ b/releasenotes/notes/oslopolicy-scripts-bdcaeaf7dd9ce2ac.yaml @@ -0,0 +1,14 @@ +--- +features: + - Ironic is now configured to work with two oslo.policy CLI scripts that have + been added. + + The first of these can be called like + "oslopolicy-list-redundant --namespace ironic" and will output a list of + policy rules in policy.[json|yaml] that match the project defaults. These + rules can be removed from the policy file as they have no effect there. + + The second script can be called like + "oslopolicy-policy-generator --namespace ironic --output-file policy-merged.yaml" + and will populate the policy-merged.yaml file with the effective policy. + This is the merged results of project defaults and config file overrides. diff --git a/setup.cfg b/setup.cfg index 2d89debf52..1a29d88edc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -25,6 +25,9 @@ packages = oslo.config.opts = ironic = ironic.conf.opts:list_opts +oslo.policy.enforcer = + ironic = ironic.common.policy:get_oslo_policy_enforcer + oslo.policy.policies = ironic.api = ironic.common.policy:list_policies