diff --git a/karbor/api/v1/restores.py b/karbor/api/v1/restores.py index fca30da9..3dea082e 100644 --- a/karbor/api/v1/restores.py +++ b/karbor/api/v1/restores.py @@ -232,6 +232,8 @@ class RestoresController(wsgi.Controller): # call restore rpc API of protection service try: self.protection_api.restore(context, restoreobj, restore_auth) + except exception.AccessCheckpointNotAllowed as error: + raise exc.HTTPForbidden(explanation=error.msg) except Exception: # update the status of restore update_dict = { diff --git a/karbor/services/protection/manager.py b/karbor/services/protection/manager.py index c3db38c7..a2de22ee 100644 --- a/karbor/services/protection/manager.py +++ b/karbor/services/protection/manager.py @@ -182,7 +182,8 @@ class ProtectionManager(manager.Manager): exception.CheckpointNotFound, exception.CheckpointNotAvailable, exception.FlowError, - exception.InvalidInput) + exception.InvalidInput, + exception.AccessCheckpointNotAllowed) def restore(self, context, restore, restore_auth): LOG.info("Starting restore service:restore action") @@ -197,6 +198,11 @@ class ProtectionManager(manager.Manager): checkpoint_collection = provider.get_checkpoint_collection() checkpoint = checkpoint_collection.get(checkpoint_id) + if not context.is_admin and ( + checkpoint.project_id != context.project_id): + raise exception.AccessCheckpointNotAllowed( + checkpoint_id=checkpoint_id) + if checkpoint.status != constants.CHECKPOINT_STATUS_AVAILABLE: raise exception.CheckpointNotAvailable( checkpoint_id=checkpoint_id) diff --git a/karbor/tests/unit/api/v1/test_restores.py b/karbor/tests/unit/api/v1/test_restores.py index 8d4b50c9..79fb1771 100644 --- a/karbor/tests/unit/api/v1/test_restores.py +++ b/karbor/tests/unit/api/v1/test_restores.py @@ -75,6 +75,16 @@ class RestoreApiTest(base.TestCase): self.assertRaises(exception.ValidationError, self.controller.create, req, body=body) + @mock.patch('karbor.services.protection.api.API.restore') + def test_restore_create_with_checkpoint_not_allowed_exception( + self, mock_restore): + mock_restore.side_effect = exception.AccessCheckpointNotAllowed + restore = self._restore_in_request_body() + body = {"restore": restore} + req = fakes.HTTPRequest.blank('/v1/restores') + self.assertRaises(exc.HTTPForbidden, self.controller.create, + req, body=body) + @mock.patch( 'karbor.api.v1.restores.RestoresController._get_all') def test_restore_list_detail(self, moak_get_all): diff --git a/karbor/tests/unit/protection/test_manager.py b/karbor/tests/unit/protection/test_manager.py index 7528f024..6ecf2636 100644 --- a/karbor/tests/unit/protection/test_manager.py +++ b/karbor/tests/unit/protection/test_manager.py @@ -146,6 +146,20 @@ class ProtectionServiceTest(base.TestCase): None, fakes.fake_protection_plan()) + @mock.patch.object(provider.ProviderRegistry, 'show_provider') + def test_restore_with_project_id_not_same(self, mock_provider): + mock_provider.return_value = fakes.FakeProvider() + context = mock.MagicMock(project_id='fake_project_id_1', + is_admin=False) + fake_restore = { + 'checkpoint_id': 'fake_checkpoint', + 'provider_id': 'fake_provider_id', + 'parameters': None + } + self.assertRaises( + oslo_messaging.ExpectedException, self.pro_manager.restore, + context, fake_restore, None) + @mock.patch.object(provider.ProviderRegistry, 'show_provider') def test_list_checkpoints(self, mock_provider): fake_provider = fakes.FakeProvider()