diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml index a0d3922..dc6e8ea 100644 --- a/.github/workflows/pull-request.yaml +++ b/.github/workflows/pull-request.yaml @@ -24,4 +24,6 @@ jobs: - name: Unit Test run: python -m unittest discover - name: Test Generation - run: oslopolicy-policy-generator --namespace unikorn_openstack_policy + run: | + oslopolicy-policy-generator --namespace unikorn_openstack_policy_compute + oslopolicy-policy-generator --namespace unikorn_openstack_policy_network diff --git a/.gitignore b/.gitignore index 85d7516..fe742e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /dist /python_unikorn_openstack_policy.egg-info/ __pycache__ +*.swp diff --git a/README.md b/README.md index 3a4172d..37ccf38 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,8 @@ pip3 install dist/python_unikorn_openstack_policy-0.1.0-py3-none-any.whl ### Generating Policy Files ```bash -oslopolicy-policy-generator --namespace unikorn_openstack_policy +oslopolicy-policy-generator --namespace unikorn_openstack_policy_compute +oslopolicy-policy-generator --namespace unikorn_openstack_policy_network ``` ## Development diff --git a/pyproject.toml b/pyproject.toml index 3e69df2..c7db556 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,16 +25,19 @@ classifiers = [ ] dependencies = [ "oslo.config", - "neutron" + "neutron", + "nova" ] [project.urls] homepage = "https://github.com/unikorn-cloud/python-unikorn-openstack-policy" [project.entry-points."oslo.policy.policies"] -unikorn_openstack_policy = "unikorn_openstack_policy:list_rules" +unikorn_openstack_policy_compute = "unikorn_openstack_policy.compute:list_rules" +unikorn_openstack_policy_network = "unikorn_openstack_policy.network:list_rules" [project.entry-points."oslo.policy.enforcer"] -unikorn_openstack_policy = "unikorn_openstack_policy:get_enforcer" +unikorn_openstack_policy_compute = "unikorn_openstack_policy.compute:get_enforcer" +unikorn_openstack_policy_network = "unikorn_openstack_policy.network:get_enforcer" # vi: ts=4 noet: diff --git a/unikorn_openstack_policy/__init__.py b/unikorn_openstack_policy/__init__.py index ad02980..58eeb25 100644 --- a/unikorn_openstack_policy/__init__.py +++ b/unikorn_openstack_policy/__init__.py @@ -12,31 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -""" -Base library entrypoints. -""" - -import itertools - -from oslo_config import cfg -from oslo_policy import policy - -from unikorn_openstack_policy import network - -def list_rules(): - """Implements the "oslo.policy.policies" entry point""" - - return itertools.chain( - network.list_rules(), - ) - - -def get_enforcer(): - """Implements the "oslo.policy.enforcer" entry point""" - - enforcer = policy.Enforcer(conf=cfg.CONF) - enforcer.register_defaults(list_rules()) - - return enforcer - # vi: ts=4 et: diff --git a/unikorn_openstack_policy/base.py b/unikorn_openstack_policy/base.py new file mode 100644 index 0000000..8209b9c --- /dev/null +++ b/unikorn_openstack_policy/base.py @@ -0,0 +1,150 @@ +# Copyright 2024 the Unikorn Authors. +# +# 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. + +""" +Defines Oslo Policy Rules. +""" + +# pylint: disable=line-too-long + +import itertools +import re + +from oslo_policy import policy + +rules = [ + # The domain manager has the role 'manager', as defined by + # https://docs.scs.community/standards/scs-0302-v1-domain-manager-role/ + policy.RuleDefault( + name='is_domain_manager', + check_str='role:manager', + description='Rule for manager access', + ), + + # A common helper to define that the user is a manager and the resource + # target is in the same domain as the user is scoped to. + policy.RuleDefault( + name='is_project_manager_owner', + check_str='rule:is_domain_manager and project_id:%(project_id)s', + description='Rule for domain manager ownership', + ), +] + + +def list_rules(): + """Implements the "oslo.policy.policies" entry point""" + + return rules + + +class MissingRuleException(Exception): + """ + Raised when a rule cannot be resolved + """ + + +def _find_rule(name, rule_list): + """Return a named rule if it exists or None""" + + for rule in rule_list: + if rule.name == name: + return rule + + raise MissingRuleException('unable to resolve referenced rule ' + name) + + +def _wrap_check_str(tokens): + """If the check string is more than one token, wrap it in parenteses""" + + if len(tokens) > 1: + tokens.insert(0, '(') + tokens.append(')') + + return tokens + + +def _recurse_build_check_str(check_str, rule_list): + """ + Given a check string, this does macro expansion of rule:roo strings + removing and inlining them. + """ + + out = [] + + for token in re.split(r'\s+', check_str): + if token.isspace(): + continue + + # Handle leading parentheses. + clean = token.lstrip('(') + for _ in range(len(token) - len(clean)): + out.append('(') + + # Handle trailing parentheses. + token = clean + + clean = token.rstrip(')') + trail = len(token) - len(clean) + + # If the token is a rule, then expand it. + matches = re.match(r'rule:([\w_]+)', clean) + if matches: + rule = _find_rule(matches.group(1), rule_list) + sub_check_str = _recurse_build_check_str(rule.check_str, rule_list) + out.extend(_wrap_check_str(sub_check_str)) + else: + out.append(clean) + + for _ in range(trail): + out.append(')') + + return out + + +def _build_check_str(check_str, rule_list): + """ + Given a check string, this does macro expansion of rule:roo strings + removing and inlining them. + """ + + check_str = ' '.join(_recurse_build_check_str(check_str, rule_list)) + check_str = re.sub(r'\( ', '(', check_str) + check_str = re.sub(r' \)', ')', check_str) + return check_str + + +def inherit_rules(mine, theirs): + """ + Given my rules, add any from openstack so we can use that as a source of truth. + """ + + expanded = [] + + for rule in mine: + try: + inherited_rule = _find_rule(rule.name, theirs) + + check_str = _build_check_str(inherited_rule.check_str, theirs) + + expanded.append(policy.RuleDefault( + name=rule.name, + check_str=f'{rule.check_str} or ({check_str})', + description=rule.description, + )) + except MissingRuleException: + pass + + return itertools.chain(rules, expanded) + +# vi: ts=4 et: diff --git a/unikorn_openstack_policy/compute.py b/unikorn_openstack_policy/compute.py new file mode 100644 index 0000000..bf0dbd3 --- /dev/null +++ b/unikorn_openstack_policy/compute.py @@ -0,0 +1,55 @@ +# Copyright 2024 the Unikorn Authors. +# +# 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. + +""" +Defines Oslo Policy Rules. +""" + +# pylint: disable=line-too-long + +from nova import policies +from oslo_config import cfg +from oslo_policy import policy +from unikorn_openstack_policy import base + +rules = [ + # The domain manager needs to be able to alter the default quotas + # or it won't we able to fulfill any cluster creation requests. + policy.RuleDefault( + name='os_compute_api:os-quota-sets:update', + check_str='rule:is_project_manager_owner', + description='Update the quotas', + ) +] + + +def list_rules(): + """Implements the "oslo.policy.policies" entry point""" + + # For every defined rule, look for a corresponding one sourced directly + # from nova, this means we can augment the exact rule defined for a + # specific version of nova, + return base.inherit_rules(rules, list(policies.list_rules())) + + +def get_enforcer(): + """Implements the "oslo.policy.enforcer" entry point""" + + enforcer = policy.Enforcer(conf=cfg.CONF) + enforcer.register_defaults(list_rules()) + + return enforcer + + +# vi: ts=4 et: diff --git a/unikorn_openstack_policy/network.py b/unikorn_openstack_policy/network.py index 5d1ab6d..c9cf735 100644 --- a/unikorn_openstack_policy/network.py +++ b/unikorn_openstack_policy/network.py @@ -18,166 +18,64 @@ # pylint: disable=line-too-long -import re - from neutron.conf import policies +from oslo_config import cfg from oslo_policy import policy +from unikorn_openstack_policy import base rules = [ - # The domain manager has the role 'manager', as defined by - # https://docs.scs.community/standards/scs-0302-v1-domain-manager-role/ - policy.RuleDefault( - name='is_domain_manager', - check_str='role:manager', - description='Rule for manager access', - ), - - # A common helper to define that the user is a manager and the resource - # target is in the same domain as the user is scoped to. - policy.RuleDefault( - name='is_project_manager_owner', - check_str='rule:is_domain_manager and project_id:%(project_id)s', - description='Rule for domain manager ownership', - ), - # The domain manager can create and delete networks in its domain. # If the domain manager is able to create a network, it can also create provider networks. # Don't be naive enough here to assume the ability to provision a network is enough to # allow provider networks, if the prior rule changes, then we can open up a security hole. policy.RuleDefault( name='create_network', - check_str='rule:is_project_manager_owner or rule:base_create_network', + check_str='rule:is_project_manager_owner', description='Create a network', ), policy.RuleDefault( name='delete_network', - check_str='rule:is_project_manager_owner or rule:base_delete_network', + check_str='rule:is_project_manager_owner', description='Delete a network', ), policy.RuleDefault( name='create_network:segments', - check_str='rule:is_project_manager_owner or rule:base_create_network:segments', + check_str='rule:is_project_manager_owner', description='Specify ``segments`` attribute when creating a network', ), policy.RuleDefault( name='create_network:provider:network_type', - check_str='rule:is_project_manager_owner or rule:base_create_network:provider:physical_network', + check_str='rule:is_project_manager_owner', description='Specify ``provider:network_type`` when creating a network', ), policy.RuleDefault( name='create_network:provider:physical_network', - check_str='rule:is_project_manager_owner or rule:base_create_network:provider:network_type', + check_str='rule:is_project_manager_owner', description='Specify ``provider:physical_network`` when creating a network', ), policy.RuleDefault( name='create_network:provider:segmentation_id', - check_str='rule:is_project_manager_owner or rule:base_create_network:provider:segmentation_id', + check_str='rule:is_project_manager_owner', description='Specify ``provider:segmentation_id`` when creating a network', ), ] -class MissingRuleException(Exception): - """ - Raised when a rule cannot be resolved - """ - - -def _find_rule(name, rule_list): - """Return a named rule if it exists or None""" - - for rule in rule_list: - if rule.name == name: - return rule - - raise MissingRuleException('unable to resolve referenced rule ' + name) - - -def _wrap_check_str(tokens): - """If the check string is more than one token, wrap it in parenteses""" - - if len(tokens) > 1: - tokens.insert(0, '(') - tokens.append(')') - - return tokens - - -def _recurse_build_check_str(check_str, rule_list): - """ - Given a check string, this does macro expansion of rule:roo strings - removing and inlining them. - """ - - out = [] - - for token in re.split(r'\s+', check_str): - if token.isspace(): - continue - - # Handle leading parentheses. - clean = token.lstrip('(') - for _ in range(len(token) - len(clean)): - out.append('(') - - # Handle trailing parentheses. - token = clean - - clean = token.rstrip(')') - trail = len(token) - len(clean) - - # If the token is a rule, then expand it. - matches = re.match(r'rule:([\w_]+)', clean) - if matches: - rule = _find_rule(matches.group(1), rule_list) - sub_check_str = _recurse_build_check_str(rule.check_str, rule_list) - out.extend(_wrap_check_str(sub_check_str)) - else: - out.append(clean) - - for _ in range(trail): - out.append(')') - - return out - - -def _build_check_str(check_str, rule_list): - """ - Given a check string, this does macro expansion of rule:roo strings - removing and inlining them. - """ - - check_str = ' '.join(_recurse_build_check_str(check_str, rule_list)) - check_str = re.sub(r'\( ', '(', check_str) - check_str = re.sub(r' \)', ')', check_str) - return check_str - - def list_rules(): """Implements the "oslo.policy.policies" entry point""" # For every defined rule, look for a corresponding one sourced directly # from neutron, this means we can augment the exact rule defined for a # specific version of neutron, - network_rules = list(policies.list_rules()) - - inherited_network_rules = [] - - for rule in rules: - try: - network_rule = _find_rule(rule.name, network_rules) + return base.inherit_rules(rules, list(policies.list_rules())) - check_str = _build_check_str(network_rule.check_str, network_rules) - inherited_network_rules.append(policy.RuleDefault( - name='base_' + rule.name, - check_str=check_str, - description=rule.description, - )) - except MissingRuleException: - pass +def get_enforcer(): + """Implements the "oslo.policy.enforcer" entry point""" - return inherited_network_rules + rules + enforcer = policy.Enforcer(conf=cfg.CONF) + enforcer.register_defaults(list_rules()) + return enforcer # vi: ts=4 et: diff --git a/unikorn_openstack_policy/tests/base.py b/unikorn_openstack_policy/tests/base.py new file mode 100644 index 0000000..ec4b5b5 --- /dev/null +++ b/unikorn_openstack_policy/tests/base.py @@ -0,0 +1,114 @@ +# Copyright 2024 the Unikorn Authors. +# +# 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. + +""" +Unit tests for OpenStack policies. +""" + +import unittest +import uuid + +from oslo_policy import policy +from oslo_config import cfg +from oslo_context.context import RequestContext + +class PolicyTestsBase(unittest.TestCase): + """ + Base functionality for all suites. + """ + + # pylint: disable=too-many-instance-attributes + + # This is static across all tests so needs configuring once. + enforcer = None + # The domain of the user, if scoped to it. + domain_id = None + # The project of the user, if scoped to it. + project_id = None + # Project scoped admin context. + project_admin_context = None + # Project scoped manager context. + project_manager_context = None + # Project scoped member context. + project_member_context = None + # Domain scoped admin context. + domain_admin_context = None + # Domain scoped manager context. + domain_manager_context = None + # Domain scoped member context. + domain_member_context = None + # Target that corresponds to the user's scope. + target = None + # Alternate target that isn't in the user's domain or project. + alt_target = None + + def setup(self, enforcer): + """Perform setup actions for all tests""" + + # Setup the configuration, which is required for policy file loading... + cfg.CONF(args=[]) + + # We only expose our rules and rules we've directly inherited in the + # enforcer defaults, so we need to add any base rules. + self.enforcer = enforcer + self.enforcer.load_rules() + + # Set up share helper objects. + self.domain_id = uuid.uuid4().hex + self.project_id = uuid.uuid4().hex + + self._setup_project_scoped_personas() + self._setup_domain_scoped_personas() + + self.target = { + 'domain_id': self.domain_id, + 'project_id': self.project_id, + } + self.alt_target = { + 'domain_id': uuid.uuid4().hex, + 'project_id': uuid.uuid4().hex, + } + + def _setup_project_scoped_personas(self): + """Create project scoped contexts""" + self.project_admin_context = RequestContext( + roles=['admin', 'member', 'reader'], + project_id=self.project_id) + self.project_manager_context = RequestContext( + roles=['manager'], + project_id=self.project_id) + self.project_member_context = RequestContext( + roles=['member', 'reader'], + project_id=self.project_id) + + def _setup_domain_scoped_personas(self): + """Create domain scoped contexts""" + self.domain_admin_context = RequestContext( + roles=['admin', 'member', 'reader'], + domain_id=self.domain_id) + self.domain_manager_context = RequestContext( + roles=['manager'], + domain_id=self.domain_id) + self.domain_member_context = RequestContext( + roles=['member', 'reader'], + domain_id=self.domain_id) + + def enforce(self, action, target, context): + """ + Wraps up common code for enforcement to reduce duplication. + """ + + rule = policy.RuleCheck('rule', action) + + return self.enforcer.enforce(rule=rule, target=target, creds=context, do_raise=True) diff --git a/unikorn_openstack_policy/tests/test_compute.py b/unikorn_openstack_policy/tests/test_compute.py new file mode 100644 index 0000000..469fdac --- /dev/null +++ b/unikorn_openstack_policy/tests/test_compute.py @@ -0,0 +1,133 @@ +# Copyright 2024 the Unikorn Authors. +# +# 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. + +""" +Unit tests for OpenStack policies. +""" + +from oslo_policy import policy + +from unikorn_openstack_policy import compute +from unikorn_openstack_policy.tests import base + +class ProjectAdminComputePolicyTests(base.PolicyTestsBase): + """ + Checks policy enforcement for project scoped admin role. + """ + + # Request context. + context = None + + def setUp(self): + """Perform setup actions for all tests""" + self.setup(compute.get_enforcer()) + self.context = self.project_admin_context + + def test_update_quota_sets(self): + """Admin can update quota sets""" + self.assertTrue(self.enforce( + 'os_compute_api:os-quota-sets:update', self.target, self.context)) + + +class DomainAdminComputePolicyTests(ProjectAdminComputePolicyTests): + """ + Checks policy enforcement for domain scoped admin role + """ + + def setUp(self): + self.setup(compute.get_enforcer()) + self.context = self.domain_admin_context + + +class ProjectManagerComputePolicyTests(base.PolicyTestsBase): + """ + Checks policy enforcement for project scoped manager role + """ + + # Request context. + context = None + + def setUp(self): + """Perform setup actions for all tests""" + self.setup(compute.get_enforcer()) + self.context = self.project_manager_context + + def test_update_quota_sets(self): + """Project manager can update quota sets""" + self.assertTrue(self.enforce( + 'os_compute_api:os-quota-sets:update', self.target, self.context)) + self.assertRaises( + policy.PolicyNotAuthorized, + self.enforce, + 'os_compute_api:os-quota-sets:update', self.alt_target, self.context) + + +class DomainManagerComputePolicyTests(base.PolicyTestsBase): + """ + Checks policy enforcement for the manager role. + """ + + def setUp(self): + """Perform setup actions for all tests""" + self.setup(compute.get_enforcer()) + self.context = self.domain_manager_context + + def test_update_quota_sets(self): + """Domain manager cannot update quota sets""" + self.assertRaises( + policy.PolicyNotAuthorized, + self.enforce, + 'os_compute_api:os-quota-sets:update', self.target, self.context) + self.assertRaises( + policy.PolicyNotAuthorized, + self.enforce, + 'os_compute_api:os-quota-sets:update', self.alt_target, self.context) + + +class ProjectMemberComputePolicyTests(base.PolicyTestsBase): + """ + Checks policy enforcement for the member role. + """ + + def setUp(self): + """Perform setup actions for all tests""" + self.setup(compute.get_enforcer()) + self.context = self.project_member_context + + def test_update_quota_sets(self): + """Project member cannot create quota sets""" + self.assertRaises( + policy.PolicyNotAuthorized, + self.enforce, + 'os_compute_api:os-quota-sets:update', self.target, self.context) + + +class DomainMemberComputePolicyTests(base.PolicyTestsBase): + """ + Checks policy enforcement for the member role. + """ + + def setUp(self): + """Perform setup actions for all tests""" + self.setup(compute.get_enforcer()) + self.context = self.domain_member_context + + def test_update_quota_sets(self): + """Domain member cannot create quota sets""" + self.assertRaises( + policy.PolicyNotAuthorized, + self.enforce, + 'os_compute_api:os-quota-sets:update', self.target, self.context) + +# vi: ts=4 et: diff --git a/unikorn_openstack_policy/tests/test_network.py b/unikorn_openstack_policy/tests/test_network.py index 66457a2..d32b2ea 100644 --- a/unikorn_openstack_policy/tests/test_network.py +++ b/unikorn_openstack_policy/tests/test_network.py @@ -16,110 +16,12 @@ Unit tests for OpenStack policies. """ -import unittest -import uuid - -from neutron.conf.policies import base from oslo_policy import policy -from oslo_config import cfg -from oslo_context.context import RequestContext -from unikorn_openstack_policy import get_enforcer +from unikorn_openstack_policy import network +from unikorn_openstack_policy.tests import base -class NetworkPolicyTestsBase(unittest.TestCase): - """ - Base functionality for all suites. - """ - - # pylint: disable=too-many-instance-attributes - - # This is static across all tests so needs configuring once. - enforcer = None - # The domain of the user, if scoped to it. - domain_id = None - # The project of the user, if scoped to it. - project_id = None - # Project scoped admin context. - project_admin_context = None - # Project scoped manager context. - project_manager_context = None - # Project scoped member context. - project_member_context = None - # Domain scoped admin context. - domain_admin_context = None - # Domain scoped manager context. - domain_manager_context = None - # Domain scoped member context. - domain_member_context = None - # Target that corresponds to the user's scope. - target = None - # Alternate target that isn't in the user's domain or project. - alt_target = None - - def setUp(self): - """Perform setup actions for all tests""" - - # Setup the configuration, which is required for policy file loading... - cfg.CONF(args=[]) - - # We only expose our rules and rules we've directly inherited in the - # enforcer defaults, so we need to add any base rules neutrok defines - # that the inherited rules also refer to. - self.enforcer = get_enforcer() - self.enforcer.register_defaults(base.list_rules()) - self.enforcer.load_rules() - - # Set up share helper objects. - self.domain_id = uuid.uuid4().hex - self.project_id = uuid.uuid4().hex - - self._setup_project_scoped_personas() - self._setup_domain_scoped_personas() - - self.target = { - 'domain_id': self.domain_id, - 'project_id': self.project_id, - } - self.alt_target = { - 'domain_id': uuid.uuid4().hex, - 'project_id': uuid.uuid4().hex, - } - - def _setup_project_scoped_personas(self): - """Create project scoped contexts""" - self.project_admin_context = RequestContext( - roles=['admin', 'member', 'reader'], - project_id=self.project_id) - self.project_manager_context = RequestContext( - roles=['manager'], - project_id=self.project_id) - self.project_member_context = RequestContext( - roles=['member', 'reader'], - project_id=self.project_id) - - def _setup_domain_scoped_personas(self): - """Create domain scoped contexts""" - self.domain_admin_context = RequestContext( - roles=['admin', 'member', 'reader'], - domain_id=self.domain_id) - self.domain_manager_context = RequestContext( - roles=['manager'], - domain_id=self.domain_id) - self.domain_member_context = RequestContext( - roles=['member', 'reader'], - domain_id=self.domain_id) - - def enforce(self, action, target, context): - """ - Wraps up common code for enforcement to reduce duplication. - """ - - rule = policy.RuleCheck('rule', action) - - return self.enforcer.enforce(rule=rule, target=target, creds=context, do_raise=True) - - -class ProjectAdminNeworkPolicyTests(NetworkPolicyTestsBase): +class ProjectAdminNetworkPolicyTests(base.PolicyTestsBase): """ Checks policy enforcement for project scoped admin role. """ @@ -129,7 +31,7 @@ class ProjectAdminNeworkPolicyTests(NetworkPolicyTestsBase): def setUp(self): """Perform setup actions for all tests""" - super().setUp() + self.setup(network.get_enforcer()) self.context = self.project_admin_context def test_create_network(self): @@ -171,17 +73,17 @@ def test_delete_network(self): self.assertTrue(self.enforce('delete_network', self.alt_target, self.context)) -class DomainAdminNeworkPolicyTests(ProjectAdminNeworkPolicyTests): +class DomainAdminNetworkPolicyTests(ProjectAdminNetworkPolicyTests): """ Checks policy enforcement for domain scoped admin role """ def setUp(self): - super().setUp() + self.setup(network.get_enforcer()) self.context = self.domain_admin_context -class ProjectManagerNetworkPolicyTests(NetworkPolicyTestsBase): +class ProjectManagerNetworkPolicyTests(base.PolicyTestsBase): """ Checks policy enforcement for project scoped manager role """ @@ -191,7 +93,7 @@ class ProjectManagerNetworkPolicyTests(NetworkPolicyTestsBase): def setUp(self): """Perform setup actions for all tests""" - super().setUp() + self.setup(network.get_enforcer()) self.context = self.project_manager_context def test_create_network(self): @@ -246,14 +148,14 @@ def test_delete_network(self): 'delete_network', self.alt_target, self.context) -class DomainManagerNeworkPolicyTests(NetworkPolicyTestsBase): +class DomainManagerNetworkPolicyTests(base.PolicyTestsBase): """ Checks policy enforcement for the manager role. """ def setUp(self): """Perform setup actions for all tests""" - super().setUp() + self.setup(network.get_enforcer()) self.context = self.domain_manager_context def test_create_network(self): @@ -311,7 +213,6 @@ def test_create_network_provider_segmentation_id(self): self.enforce, 'create_network:provider:segmentation_id', self.alt_target, self.context) - def test_delete_network(self): """Domain manager cannot delete networks""" self.assertRaises( @@ -324,14 +225,14 @@ def test_delete_network(self): 'delete_network', self.alt_target, self.context) -class ProjectMemberNeworkPolicyTests(NetworkPolicyTestsBase): +class ProjectMemberNetworkPolicyTests(base.PolicyTestsBase): """ Checks policy enforcement for the member role. """ def setUp(self): """Perform setup actions for all tests""" - super().setUp() + self.setup(network.get_enforcer()) self.context = self.project_member_context def test_create_network(self): @@ -379,14 +280,14 @@ def test_delete_network(self): 'delete_network', self.alt_target, self.context) -class DomainMemberNeworkPolicyTests(NetworkPolicyTestsBase): +class DomainMemberNetworkPolicyTests(base.PolicyTestsBase): """ Checks policy enforcement for the member role. """ def setUp(self): """Perform setup actions for all tests""" - super().setUp() + self.setup(network.get_enforcer()) self.context = self.domain_member_context def test_create_network(self):