From 1899536f14f0f6561432d7b9246908e8cdcddb09 Mon Sep 17 00:00:00 2001 From: NiallBunting Date: Fri, 4 Dec 2015 17:05:41 +0000 Subject: [PATCH] Halt deletion if image is deactivated This checks if the image is in a 'deactivated' state and the user is not an admin. If so the user is not allowed to delete the image. Change-Id: I19b516ffb90cfd6a1cb8f1c43e7a1ccbb7424a18 Closes-Bug: 1522524 --- glance/api/v1/images.py | 9 +++++++++ glance/api/v2/images.py | 4 ++++ glance/tests/unit/v1/test_api.py | 17 +++++++++++++++++ glance/tests/unit/v2/test_images_resource.py | 22 ++++++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py index 2915c47..d573a90 100644 --- a/glance/api/v1/images.py +++ b/glance/api/v1/images.py @@ -1114,6 +1114,15 @@ class Controller(controller.BaseController): request=req, content_type="text/plain") + if req.context.is_admin is False: + if image['status'] == 'deactivated': + msg = (_("Forbidden to delete a %s image.") % + image['status']) + LOG.warn(msg) + raise HTTPForbidden(explanation=msg, + request=req, + content_type="text/plain") + if image['status'] == 'pending_delete': msg = (_("Forbidden to delete a %s image.") % image['status']) diff --git a/glance/api/v2/images.py b/glance/api/v2/images.py index bb7949c..3f9a210 100644 --- a/glance/api/v2/images.py +++ b/glance/api/v2/images.py @@ -228,6 +228,10 @@ class ImagesController(object): image_repo = self.gateway.get_repo(req.context) try: image = image_repo.get(image_id) + if image.status == 'deactivated' and req.context.is_admin == False: + msg = _("Forbidden to delete a deactivated image.") + LOG.warn(msg) + raise exception.Forbidden(msg=msg) image.delete() image_repo.remove(image) except (glance_store.Forbidden, exception.Forbidden) as e: diff --git a/glance/tests/unit/v1/test_api.py b/glance/tests/unit/v1/test_api.py index 48ff51e..f2aa61c 100644 --- a/glance/tests/unit/v1/test_api.py +++ b/glance/tests/unit/v1/test_api.py @@ -1510,6 +1510,23 @@ class TestGlanceAPI(base.IsolatedUnitTest): res = req.get_response(self.api) self.assertEqual(403, res.status_int) + def test_delete_deactivated_images(self, is_admin=False): + """Tests exception raised trying to download a deactivated image""" + req = webob.Request.blank("/images/%s" % UUID3) + req.method = 'DELETE' + res = req.get_response(self.api) + self.assertEqual(403, res.status_int) + + def test_delete_deactivated_images_admin(self, is_admin=True): + """Tests exception raised trying to download a deactivated image""" + test_router_api = router.API(self.mapper) + self.api = test_utils.FakeAuthMiddleware( + test_router_api, is_admin=True) + req = webob.Request.blank("/images/%s" % UUID3) + req.method = 'DELETE' + res = req.get_response(self.api) + self.assertEqual(200, res.status_int) + def test_update_deleted_image(self): """Tests that exception raised trying to update a deleted image""" req = webob.Request.blank("/images/%s" % UUID2) diff --git a/glance/tests/unit/v2/test_images_resource.py b/glance/tests/unit/v2/test_images_resource.py index c5c5a2e..343654f 100644 --- a/glance/tests/unit/v2/test_images_resource.py +++ b/glance/tests/unit/v2/test_images_resource.py @@ -2056,6 +2056,28 @@ class TestImagesController(base.IsolatedUnitTest): self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete, request, UUID1) + def test_delete_from_deactive_admin(self): + # from deactivated to pending-delete + request = unit_test_utils.get_fake_request(is_admin=True) + self.action_controller.deactivate(request, UUID1) + with mock.patch.object( + glance.domain.proxy.Image, + 'delete', + ): + with mock.patch.object( + glance.domain.proxy.Repo, + 'remove' + ): + self.controller.delete(request, UUID1) + + def test_delete_from_deactive(self): + # from deactivated to pending-delete + request = unit_test_utils.get_fake_request(is_admin=False) + self.action_controller.deactivate(request, UUID1) + + self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete, + request, UUID1) + def test_index_with_invalid_marker(self): fake_uuid = str(uuid.uuid4()) request = unit_test_utils.get_fake_request() -- 1.9.1