diff --git a/nova/api/openstack/compute/admin_actions.py b/nova/api/openstack/compute/admin_actions.py index c1208df49925..6de6956bcfde 100644 --- a/nova/api/openstack/compute/admin_actions.py +++ b/nova/api/openstack/compute/admin_actions.py @@ -40,8 +40,9 @@ class AdminActionsController(wsgi.Controller): def _reset_network(self, req, id, body): """Permit admins to reset networking on a server.""" context = req.environ['nova.context'] - context.can(aa_policies.POLICY_ROOT % 'reset_network', target={}) instance = common.get_instance(self.compute_api, context, id) + context.can(aa_policies.POLICY_ROOT % 'reset_network', + target={'project_id': instance.project_id}) try: self.compute_api.reset_network(context, instance) except exception.InstanceIsLocked as e: @@ -53,8 +54,9 @@ class AdminActionsController(wsgi.Controller): def _inject_network_info(self, req, id, body): """Permit admins to inject network info into a server.""" context = req.environ['nova.context'] - context.can(aa_policies.POLICY_ROOT % 'inject_network_info', target={}) instance = common.get_instance(self.compute_api, context, id) + context.can(aa_policies.POLICY_ROOT % 'inject_network_info', + target={'project_id': instance.project_id}) try: self.compute_api.inject_network_info(context, instance) except exception.InstanceIsLocked as e: @@ -67,12 +69,13 @@ class AdminActionsController(wsgi.Controller): def _reset_state(self, req, id, body): """Permit admins to reset the state of a server.""" context = req.environ["nova.context"] - context.can(aa_policies.POLICY_ROOT % 'reset_state', target={}) + instance = common.get_instance(self.compute_api, context, id) + context.can(aa_policies.POLICY_ROOT % 'reset_state', + target={'project_id': instance.project_id}) # Identify the desired state from the body state = state_map[body["os-resetState"]["state"]] - instance = common.get_instance(self.compute_api, context, id) instance.vm_state = state instance.task_state = None instance.save(admin_state_reset=True) diff --git a/nova/policies/admin_actions.py b/nova/policies/admin_actions.py index 77e180c07b0f..bab6bd6452f7 100644 --- a/nova/policies/admin_actions.py +++ b/nova/policies/admin_actions.py @@ -32,7 +32,7 @@ admin_actions_policies = [ 'path': '/servers/{server_id}/action (os-resetState)' } ], - scope_types=['system']), + scope_types=['system', 'project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'inject_network_info', check_str=base.SYSTEM_ADMIN, @@ -43,7 +43,7 @@ admin_actions_policies = [ 'path': '/servers/{server_id}/action (injectNetworkInfo)' } ], - scope_types=['system']), + scope_types=['system', 'project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'reset_network', check_str=base.SYSTEM_ADMIN, @@ -54,7 +54,7 @@ admin_actions_policies = [ 'path': '/servers/{server_id}/action (resetNetwork)' } ], - scope_types=['system']) + scope_types=['system', 'project']) ] diff --git a/nova/policies/evacuate.py b/nova/policies/evacuate.py index c9312d424d93..33b86f7a26e3 100644 --- a/nova/policies/evacuate.py +++ b/nova/policies/evacuate.py @@ -32,7 +32,7 @@ evacuate_policies = [ 'method': 'POST' } ], - scope_types=['system']), + scope_types=['system', 'project']), ] diff --git a/nova/policies/instance_actions.py b/nova/policies/instance_actions.py index 04dc9753e7fc..13586a8fbe5f 100644 --- a/nova/policies/instance_actions.py +++ b/nova/policies/instance_actions.py @@ -53,7 +53,7 @@ but in the other hand it might leak information about the deployment 'path': '/servers/{server_id}/os-instance-actions/{request_id}' } ], - scope_types=['system']), + scope_types=['system', 'project']), policy.DocumentedRuleDefault( name=BASE_POLICY_NAME % 'events', check_str=base.SYSTEM_READER, @@ -70,7 +70,7 @@ passes, the name of the host.""", 'path': '/servers/{server_id}/os-instance-actions/{request_id}' } ], - scope_types=['system']), + scope_types=['system', 'project']), policy.DocumentedRuleDefault( name=BASE_POLICY_NAME % 'list', check_str=base.PROJECT_READER_OR_SYSTEM_READER, diff --git a/nova/policies/rescue.py b/nova/policies/rescue.py index 6e8c83807e38..874e90884bd7 100644 --- a/nova/policies/rescue.py +++ b/nova/policies/rescue.py @@ -35,7 +35,7 @@ for unrescue and keeping old policy for rescue. rescue_policies = [ policy.DocumentedRuleDefault( name=BASE_POLICY_NAME, - check_str=base.RULE_ADMIN_OR_OWNER, + check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, description="Rescue a server", operations=[ { @@ -46,7 +46,7 @@ rescue_policies = [ scope_types=['system', 'project']), policy.DocumentedRuleDefault( name=UNRESCUE_POLICY_NAME, - check_str=base.RULE_ADMIN_OR_OWNER, + check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, description="Unrescue a server", operations=[ { diff --git a/nova/tests/unit/api/openstack/compute/test_server_reset_state.py b/nova/tests/unit/api/openstack/compute/test_server_reset_state.py index c1d598a396b6..591ab493a466 100644 --- a/nova/tests/unit/api/openstack/compute/test_server_reset_state.py +++ b/nova/tests/unit/api/openstack/compute/test_server_reset_state.py @@ -44,6 +44,7 @@ class ResetStateTestsV21(test.NoDBTestCase): instance.uuid = self.uuid instance.vm_state = 'fake' instance.task_state = 'fake' + instance.project_id = self.context.project_id instance.obj_reset_changes() return instance diff --git a/nova/tests/unit/policies/test_admin_actions.py b/nova/tests/unit/policies/test_admin_actions.py index bf0356031e4f..1bcd7faae0f0 100644 --- a/nova/tests/unit/policies/test_admin_actions.py +++ b/nova/tests/unit/policies/test_admin_actions.py @@ -98,6 +98,15 @@ class AdminActionsScopeTypePolicyTest(AdminActionsPolicyTest): super(AdminActionsScopeTypePolicyTest, self).setUp() self.flags(enforce_scope=True, group="oslo_policy") + +class AdminActionsNoLegacyPolicyTest(AdminActionsScopeTypePolicyTest): + """Test Admin Actions APIs policies with system scope enabled, + and no more deprecated rules. + """ + without_deprecated_rules = True + + def setUp(self): + super(AdminActionsScopeTypePolicyTest, self).setUp() # Check that system admin is able to perform the system level actions # on server. self.admin_authorized_contexts = [ diff --git a/nova/tests/unit/policies/test_evacuate.py b/nova/tests/unit/policies/test_evacuate.py index 04643f332ac5..43b9634cddd7 100644 --- a/nova/tests/unit/policies/test_evacuate.py +++ b/nova/tests/unit/policies/test_evacuate.py @@ -130,7 +130,16 @@ class EvacuateScopeTypePolicyTest(EvacuatePolicyTest): super(EvacuateScopeTypePolicyTest, self).setUp() self.flags(enforce_scope=True, group="oslo_policy") - self.user_req.environ['nova.context'].system_scope = 'all' + +class EvacuateNoLegacyPolicyTest(EvacuateScopeTypePolicyTest): + """Test Evacuate APIs policies with system scope enabled, + and no more deprecated rules that allow the legacy admin API to + access system APIs. + """ + without_deprecated_rules = True + + def setUp(self): + super(EvacuateNoLegacyPolicyTest, self).setUp() # Check that system admin is able to evacuate server. self.admin_authorized_contexts = [ @@ -144,11 +153,3 @@ class EvacuateScopeTypePolicyTest(EvacuatePolicyTest): self.other_project_member_context, self.project_foo_context, self.project_reader_context ] - - -class EvacuateNoLegacyPolicyTest(EvacuateScopeTypePolicyTest): - """Test Evacuate APIs policies with system scope enabled, - and no more deprecated rules that allow the legacy admin API to - access system APIs. - """ - without_deprecated_rules = True diff --git a/nova/tests/unit/policies/test_instance_actions.py b/nova/tests/unit/policies/test_instance_actions.py index 5102aa15782b..43b8e2af6f0a 100644 --- a/nova/tests/unit/policies/test_instance_actions.py +++ b/nova/tests/unit/policies/test_instance_actions.py @@ -219,20 +219,6 @@ class InstanceActionsScopeTypePolicyTest(InstanceActionsPolicyTest): super(InstanceActionsScopeTypePolicyTest, self).setUp() self.flags(enforce_scope=True, group="oslo_policy") - # Check that system reader is able to get the - # instance action events - self.system_reader_authorized_contexts = [ - self.system_admin_context, self.system_member_context, - self.system_reader_context] - # Check that non-system-reader is not able to - # get the instance action events - self.system_reader_unauthorized_contexts = [ - self.system_foo_context, self.legacy_admin_context, - self.project_admin_context, self.project_member_context, - self.other_project_member_context, - self.project_foo_context, self.project_reader_context - ] - @mock.patch('nova.objects.InstanceActionEventList.get_by_action') @mock.patch('nova.objects.InstanceAction.get_by_request_id') def test_show_instance_action_policy_with_show_details(