diff --git a/neutron_lib/context.py b/neutron_lib/context.py index f323222ea..922d8e4ee 100644 --- a/neutron_lib/context.py +++ b/neutron_lib/context.py @@ -20,8 +20,8 @@ import warnings from oslo_context import context as oslo_context from oslo_db.sqlalchemy import enginefacade -from neutron_lib import _policy as policy from neutron_lib.db import api as db_api +from neutron_lib.policy import _engine as policy_engine class ContextBase(oslo_context.RequestContext): @@ -50,9 +50,10 @@ class ContextBase(oslo_context.RequestContext): self.timestamp = timestamp self.is_advsvc = is_advsvc if self.is_advsvc is None: - self.is_advsvc = self.is_admin or policy.check_is_advsvc(self) + self.is_advsvc = (self.is_admin or + policy_engine.check_is_advsvc(self)) if self.is_admin is None: - self.is_admin = policy.check_is_admin(self) + self.is_admin = policy_engine.check_is_admin(self) @property def tenant_id(self): diff --git a/neutron_lib/policy/__init__.py b/neutron_lib/policy/__init__.py new file mode 100644 index 000000000..191d134f3 --- /dev/null +++ b/neutron_lib/policy/__init__.py @@ -0,0 +1,29 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +def policy_and(*args): + return ' and '.join(args) + + +def policy_or(*args): + return ' or '.join(args) + + +RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner' +RULE_ADMIN_ONLY = 'rule:admin_only' +RULE_ANY = 'rule:regular_user' +RULE_ADVSVC = 'rule:context_is_advsvc' +RULE_ADMIN_OR_NET_OWNER = 'rule:admin_or_network_owner' +RULE_ADMIN_OR_NET_OWNER_OR_ADVSVC = policy_or(RULE_ADMIN_OR_NET_OWNER, + RULE_ADVSVC) +RULE_ADMIN_OR_PARENT_OWNER = 'rule:admin_or_ext_parent_owner' diff --git a/neutron_lib/_policy.py b/neutron_lib/policy/_engine.py similarity index 100% rename from neutron_lib/_policy.py rename to neutron_lib/policy/_engine.py diff --git a/neutron_lib/tests/unit/policy/__init__.py b/neutron_lib/tests/unit/policy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neutron_lib/tests/unit/test__policy.py b/neutron_lib/tests/unit/policy/test__engine.py similarity index 64% rename from neutron_lib/tests/unit/test__policy.py rename to neutron_lib/tests/unit/policy/test__engine.py index 21af2d561..ae7a101b6 100644 --- a/neutron_lib/tests/unit/test__policy.py +++ b/neutron_lib/tests/unit/policy/test__engine.py @@ -13,8 +13,8 @@ import mock -from neutron_lib import _policy as policy from neutron_lib import context +from neutron_lib.policy import _engine as policy_engine from neutron_lib.tests import _base as base @@ -23,52 +23,52 @@ class TestPolicyEnforcer(base.BaseTestCase): def setUp(self): super(TestPolicyEnforcer, self).setUp() # Isolate one _ROLE_ENFORCER per test case - mock.patch.object(policy, '_ROLE_ENFORCER', None).start() + mock.patch.object(policy_engine, '_ROLE_ENFORCER', None).start() def test_init_reset(self): - self.assertIsNone(policy._ROLE_ENFORCER) - policy.init() - self.assertIsNotNone(policy._ROLE_ENFORCER) + self.assertIsNone(policy_engine._ROLE_ENFORCER) + policy_engine.init() + self.assertIsNotNone(policy_engine._ROLE_ENFORCER) def test_check_user_is_not_admin(self): ctx = context.Context('me', 'my_project') - self.assertFalse(policy.check_is_admin(ctx)) + self.assertFalse(policy_engine.check_is_admin(ctx)) def test_check_user_elevated_is_admin(self): ctx = context.Context('me', 'my_project', roles=['user']).elevated() - self.assertTrue(policy.check_is_admin(ctx)) + self.assertTrue(policy_engine.check_is_admin(ctx)) def test_check_is_admin_no_roles_no_admin(self): - policy.init(policy_file='dummy_policy.json') + policy_engine.init(policy_file='dummy_policy.json') ctx = context.Context('me', 'my_project', roles=['user']).elevated() # With no admin role, elevated() should not work. - self.assertFalse(policy.check_is_admin(ctx)) + self.assertFalse(policy_engine.check_is_admin(ctx)) def test_check_user_elevated_is_admin_with_default_policy(self): - policy.init(policy_file='no_policy.json') + policy_engine.init(policy_file='no_policy.json') ctx = context.Context('me', 'my_project', roles=['user']).elevated() - self.assertTrue(policy.check_is_admin(ctx)) + self.assertTrue(policy_engine.check_is_admin(ctx)) def test_check_is_advsvc_role(self): ctx = context.Context('me', 'my_project', roles=['advsvc']) - self.assertTrue(policy.check_is_advsvc(ctx)) + self.assertTrue(policy_engine.check_is_advsvc(ctx)) def test_check_is_not_advsvc_user(self): ctx = context.Context('me', 'my_project', roles=['user']) - self.assertFalse(policy.check_is_advsvc(ctx)) + self.assertFalse(policy_engine.check_is_advsvc(ctx)) def test_check_is_not_advsvc_admin(self): ctx = context.Context('me', 'my_project').elevated() - self.assertTrue(policy.check_is_admin(ctx)) - self.assertFalse(policy.check_is_advsvc(ctx)) + self.assertTrue(policy_engine.check_is_admin(ctx)) + self.assertFalse(policy_engine.check_is_advsvc(ctx)) def test_check_is_advsvc_no_roles_no_advsvc(self): - policy.init(policy_file='dummy_policy.json') + policy_engine.init(policy_file='dummy_policy.json') ctx = context.Context('me', 'my_project', roles=['advsvc']) # No advsvc role in the policy file, so cannot assume the role. - self.assertFalse(policy.check_is_advsvc(ctx)) + self.assertFalse(policy_engine.check_is_advsvc(ctx)) def test_check_is_advsvc_role_with_default_policy(self): - policy.init(policy_file='no_policy.json') + policy_engine.init(policy_file='no_policy.json') ctx = context.Context('me', 'my_project', roles=['advsvc']) - self.assertTrue(policy.check_is_advsvc(ctx)) + self.assertTrue(policy_engine.check_is_advsvc(ctx)) diff --git a/releasenotes/notes/new-policy-module-f5638e23fe91a287.yaml b/releasenotes/notes/new-policy-module-f5638e23fe91a287.yaml new file mode 100644 index 000000000..b04f70202 --- /dev/null +++ b/releasenotes/notes/new-policy-module-f5638e23fe91a287.yaml @@ -0,0 +1,10 @@ +--- +other: + - | + New module ``neutron_lib.policy`` was added. + It contains constants: ``RULE_ADMIN_OR_OWNER``, ``RULE_ADMIN_ONLY``, + ``RULE_ANY``, ``RULE_ADVSVC``, ``RULE_ADMIN_OR_NET_OWNER``, + ``RULE_ADMIN_OR_NET_OWNER_OR_ADVSVC`` and ``RULE_ADMIN_OR_PARENT_OWNER``. + It contains also helper functions ``policy_and`` and ``policy_or``. + Those constants and functions can be used in policy modules in Neutron + related projects.