diff --git a/nova/api/openstack/compute/multinic.py b/nova/api/openstack/compute/multinic.py index f5363f913496..afe11e0baa11 100644 --- a/nova/api/openstack/compute/multinic.py +++ b/nova/api/openstack/compute/multinic.py @@ -42,7 +42,7 @@ class MultinicController(wsgi.Controller): """Adds an IP on a given network to an instance.""" context = req.environ['nova.context'] instance = common.get_instance(self.compute_api, context, id) - context.can(multinic_policies.BASE_POLICY_NAME, + context.can(multinic_policies.BASE_POLICY_NAME % 'add', target={'project_id': instance.project_id}) network_id = body['addFixedIp']['networkId'] @@ -60,7 +60,7 @@ class MultinicController(wsgi.Controller): """Removes an IP from an instance.""" context = req.environ['nova.context'] instance = common.get_instance(self.compute_api, context, id) - context.can(multinic_policies.BASE_POLICY_NAME, + context.can(multinic_policies.BASE_POLICY_NAME % 'remove', target={'project_id': instance.project_id}) address = body['removeFixedIp']['address'] diff --git a/nova/policies/multinic.py b/nova/policies/multinic.py index 0a45e78400ea..b6585008d99b 100644 --- a/nova/policies/multinic.py +++ b/nova/policies/multinic.py @@ -18,28 +18,56 @@ from oslo_policy import policy from nova.policies import base -BASE_POLICY_NAME = 'os_compute_api:os-multinic' +ROOT_POLICY = 'os_compute_api:os-multinic' +BASE_POLICY_NAME = 'os_compute_api:os-multinic:%s' + +DEPRECATED_POLICY = policy.DeprecatedRule( + ROOT_POLICY, + base.RULE_ADMIN_OR_OWNER, +) + +DEPRECATED_REASON = """ +Nova API policies are introducing new default roles with scope_type +capabilities. Old policies are deprecated and silently going to be ignored +in nova 23.0.0 release. +""" multinic_policies = [ policy.DocumentedRuleDefault( - name=BASE_POLICY_NAME, - check_str=base.RULE_ADMIN_OR_OWNER, - description="""Add or remove a fixed IP address from a server. + name=BASE_POLICY_NAME % 'add', + check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, + description="""Add a fixed IP address to a server. -These APIs are proxy calls to the Network service. These are all +This API is proxy calls to the Network service. This is deprecated.""", operations=[ { 'method': 'POST', 'path': '/servers/{server_id}/action (addFixedIp)' - }, + } + ], + scope_types=['system', 'project'], + deprecated_rule=DEPRECATED_POLICY, + deprecated_reason=DEPRECATED_REASON, + deprecated_since='22.0.0'), + policy.DocumentedRuleDefault( + name=BASE_POLICY_NAME % 'remove', + check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, + description="""Remove a fixed IP address from a server. + +This API is proxy calls to the Network service. This is +deprecated.""", + operations=[ { 'method': 'POST', 'path': '/servers/{server_id}/action (removeFixedIp)' } ], - scope_types=['system', 'project']), + scope_types=['system', 'project'], + deprecated_rule=DEPRECATED_POLICY, + deprecated_reason=DEPRECATED_REASON, + deprecated_since='22.0.0'), ] diff --git a/nova/tests/unit/fake_policy.py b/nova/tests/unit/fake_policy.py index 0cd64dfd992c..0bf67161ba12 100644 --- a/nova/tests/unit/fake_policy.py +++ b/nova/tests/unit/fake_policy.py @@ -124,7 +124,8 @@ policy_data = """ "os_compute_api:os-migrate-server:migrate": "", "os_compute_api:os-migrate-server:migrate_live": "", "os_compute_api:os-migrations:index": "", - "os_compute_api:os-multinic": "", + "os_compute_api:os-multinic:add": "", + "os_compute_api:os-multinic:remove": "", "os_compute_api:os-networks:view": "", "os_compute_api:os-tenant-networks:list": "", "os_compute_api:os-tenant-networks:show": "", diff --git a/nova/tests/unit/policies/test_multinic.py b/nova/tests/unit/policies/test_multinic.py index 4e445c3bb009..06a734f0bae7 100644 --- a/nova/tests/unit/policies/test_multinic.py +++ b/nova/tests/unit/policies/test_multinic.py @@ -17,6 +17,8 @@ from oslo_utils import timeutils from nova.api.openstack.compute import multinic from nova.compute import vm_states +from nova.policies import base as base_policy +from nova.policies import multinic as policies from nova.tests.unit.api.openstack import fakes from nova.tests.unit import fake_instance from nova.tests.unit.policies import base @@ -59,7 +61,7 @@ class MultinicPolicyTest(base.BasePolicyTest): @mock.patch('nova.compute.api.API.add_fixed_ip') def test_add_fixed_ip_policy(self, mock_add): - rule_name = "os_compute_api:os-multinic" + rule_name = "os_compute_api:os-multinic:add" body = dict(addFixedIp=dict(networkId='test_net')) self.common_policy_check(self.admin_or_owner_authorized_contexts, self.admin_or_owner_unauthorized_contexts, @@ -69,7 +71,7 @@ class MultinicPolicyTest(base.BasePolicyTest): @mock.patch('nova.compute.api.API.remove_fixed_ip') def test_remove_fixed_ip_policy(self, mock_remove): - rule_name = "os_compute_api:os-multinic" + rule_name = "os_compute_api:os-multinic:remove" body = dict(removeFixedIp=dict(address='1.2.3.4')) self.common_policy_check(self.admin_or_owner_authorized_contexts, self.admin_or_owner_unauthorized_contexts, @@ -92,3 +94,33 @@ class MultinicScopeTypePolicyTest(MultinicPolicyTest): def setUp(self): super(MultinicScopeTypePolicyTest, self).setUp() self.flags(enforce_scope=True, group="oslo_policy") + + +class MultinicNoLegacyPolicyTest(MultinicScopeTypePolicyTest): + """Test Multinic APIs policies with system scope enabled, + and no more deprecated rules. + """ + without_deprecated_rules = True + rules_without_deprecation = { + policies.BASE_POLICY_NAME % 'add': + base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN, + policies.BASE_POLICY_NAME % 'remove': + base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN} + + def setUp(self): + super(MultinicNoLegacyPolicyTest, self).setUp() + # Check that system admin or owner is able to + # add/delete Fixed IP to server. + self.admin_or_owner_authorized_contexts = [ + self.system_admin_context, + self.project_admin_context, self.project_member_context, + ] + # Check that non-system and non-admin/owner is not able + # to add/delete Fixed IP to server. + self.admin_or_owner_unauthorized_contexts = [ + self.legacy_admin_context, self.system_member_context, + self.system_reader_context, self.project_reader_context, + self.project_foo_context, + self.system_foo_context, self.other_project_member_context, + self.other_project_reader_context + ] diff --git a/nova/tests/unit/test_policy.py b/nova/tests/unit/test_policy.py index 293f773d361c..b16c5a7ccebb 100644 --- a/nova/tests/unit/test_policy.py +++ b/nova/tests/unit/test_policy.py @@ -429,7 +429,8 @@ class RealRolePolicyTestCase(test.NoDBTestCase): "os_compute_api:os-flavor-extra-specs:show", "os_compute_api:os-floating-ip-pools", "os_compute_api:os-floating-ips", -"os_compute_api:os-multinic", +"os_compute_api:os-multinic:add", +"os_compute_api:os-multinic:remove", "os_compute_api:os-networks:view", "os_compute_api:os-rescue", "os_compute_api:os-unrescue",