From 59c60b68fb459bea9c5832b29323eca7366f8a80 Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Tue, 12 Feb 2019 23:16:30 +0100 Subject: [PATCH] Add policy module to neutron-lib This module contains some constants and helper functions which may be used in neutron, neutron staduim and neutron 3rd party projects. Also already existing module _policy with policy engine implementation for internal use of neutron-lib for moved to the new neutron_lib.policy module and is now named neutron_lib.policy._engine Partially Implements: blueprint neutron-policy-in-code Change-Id: Ie581788f78f6d83ae470981830df9e90a7cb72e8 --- neutron_lib/context.py | 7 ++-- neutron_lib/policy/__init__.py | 29 ++++++++++++++ neutron_lib/{_policy.py => policy/_engine.py} | 0 neutron_lib/tests/unit/policy/__init__.py | 0 .../test__engine.py} | 38 +++++++++---------- .../new-policy-module-f5638e23fe91a287.yaml | 10 +++++ 6 files changed, 62 insertions(+), 22 deletions(-) create mode 100644 neutron_lib/policy/__init__.py rename neutron_lib/{_policy.py => policy/_engine.py} (100%) create mode 100644 neutron_lib/tests/unit/policy/__init__.py rename neutron_lib/tests/unit/{test__policy.py => policy/test__engine.py} (64%) create mode 100644 releasenotes/notes/new-policy-module-f5638e23fe91a287.yaml 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.