From e4e97e23c13807d6949301a6f53fd8686f4b1802 Mon Sep 17 00:00:00 2001 From: Ghanshyam Mann Date: Sun, 5 Apr 2020 01:42:13 -0500 Subject: [PATCH] Correct server shelve policy check_str server shelve API policy is default to admin_or_owner[1] but API is allowed (which is expected) for everyone. This is because API does not pass the project_id in policy target so that oslo policy can decide the ownership[2]. If no target is passed then, policy.py add the default targets which is nothing but context.project_id (allow for everyone try to access) - https://github.com/openstack/nova/blob/c16315165ce307c605cf4b608b2df3aa06f46982/nova/policy.py#L191 Passing the server project_id as target to make it admin_or_owner. [1] https://github.com/openstack/nova/blob/e4ac401d1a9d5fba24bc22141b362a5400d9d096/nova/api/openstack/compute/shelve.py#L89 [2] https://github.com/openstack/nova/blob/e4ac401d1a9d5fba24bc22141b362a5400d9d096/nova/policies/shelve.py#L37 Closes-bug: #1870881 Change-Id: I493062ed0ee632a9c647cf1f3cf497eebc39c4ca --- nova/api/openstack/compute/shelve.py | 3 ++- nova/tests/unit/api/openstack/compute/test_shelve.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/nova/api/openstack/compute/shelve.py b/nova/api/openstack/compute/shelve.py index 680d59265569..3dfda153303a 100644 --- a/nova/api/openstack/compute/shelve.py +++ b/nova/api/openstack/compute/shelve.py @@ -86,8 +86,9 @@ class ShelveController(wsgi.Controller): def _unshelve(self, req, id, body): """Restore an instance from shelved mode.""" context = req.environ["nova.context"] - context.can(shelve_policies.POLICY_ROOT % 'unshelve') instance = common.get_instance(self.compute_api, context, id) + context.can(shelve_policies.POLICY_ROOT % 'unshelve', + target={'project_id': instance.project_id}) new_az = None unshelve_dict = body['unshelve'] diff --git a/nova/tests/unit/api/openstack/compute/test_shelve.py b/nova/tests/unit/api/openstack/compute/test_shelve.py index 87ba2ef2bd8a..522d40ba3ded 100644 --- a/nova/tests/unit/api/openstack/compute/test_shelve.py +++ b/nova/tests/unit/api/openstack/compute/test_shelve.py @@ -181,14 +181,20 @@ class ShelvePolicyEnforcementV21(test.NoDBTestCase): "Policy doesn't allow %s to be performed." % rule_name, exc.format_message()) - def test_unshelve_restricted_by_role(self): + @mock.patch('nova.api.openstack.common.get_instance') + def test_unshelve_restricted_by_role(self, get_instance_mock): + get_instance_mock.return_value = ( + fake_instance.fake_instance_obj(self.req.environ['nova.context'])) rules = {'os_compute_api:os-shelve:unshelve': 'role:admin'} policy.set_rules(oslo_policy.Rules.from_dict(rules)) self.assertRaises(exception.Forbidden, self.controller._unshelve, self.req, uuidsentinel.fake, body={'unshelve': {}}) - def test_unshelve_policy_failed(self): + @mock.patch('nova.api.openstack.common.get_instance') + def test_unshelve_policy_failed(self, get_instance_mock): + get_instance_mock.return_value = ( + fake_instance.fake_instance_obj(self.req.environ['nova.context'])) rule_name = "os_compute_api:os-shelve:unshelve" self.policy.set_rules({rule_name: "project:non_fake"}) exc = self.assertRaises(