diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py index b127c35f15..55d7cc2823 100644 --- a/glance/api/v1/images.py +++ b/glance/api/v1/images.py @@ -821,22 +821,28 @@ def delete(self, req, id): request=req, content_type="text/plain") - status = 'deleted' + if image['location'] and CONF.delayed_delete: + status = 'pending_delete' + else: + status = 'deleted' + try: + # Delete the image from the registry first, since we rely on it + # for authorization checks. + # See https://bugs.launchpad.net/glance/+bug/1065187 + registry.update_image_metadata(req.context, id, {'status': status}) + registry.delete_image_metadata(req.context, id) + # The image's location field may be None in the case # of a saving or queued image, therefore don't ask a backend # to delete the image if the backend doesn't yet store it. # See https://bugs.launchpad.net/glance/+bug/747799 if image['location']: if CONF.delayed_delete: - status = 'pending_delete' schedule_delayed_delete_from_backend(image['location'], id) else: safe_delete_from_backend(image['location'], req.context, id) - - registry.update_image_metadata(req.context, id, {'status': status}) - registry.delete_image_metadata(req.context, id) except exception.NotFound, e: msg = ("Failed to find image to delete: %(e)s" % locals()) for line in msg.split('\n'): diff --git a/glance/tests/stubs.py b/glance/tests/stubs.py index 669c9a9fd9..a1c62443a2 100644 --- a/glance/tests/stubs.py +++ b/glance/tests/stubs.py @@ -60,7 +60,13 @@ def request(self, method, url, body=None, headers=None): def getresponse(self): mapper = routes.Mapper() - api = context.UnauthenticatedContextMiddleware(rserver.API(mapper)) + server = rserver.API(mapper) + # NOTE(markwash): we need to pass through context auth information if + # we have it. + if 'X-Auth-Token' in self.req.headers: + api = utils.FakeAuthMiddleware(server) + else: + api = context.UnauthenticatedContextMiddleware(server) webob_res = self.req.get_response(api) return utils.FakeHTTPResponse(status=webob_res.status_int, diff --git a/glance/tests/unit/v1/test_api.py b/glance/tests/unit/v1/test_api.py index de226575dd..1589b50776 100644 --- a/glance/tests/unit/v1/test_api.py +++ b/glance/tests/unit/v1/test_api.py @@ -2930,6 +2930,26 @@ def test_delete_non_exists_image(self): res = req.get_response(self.api) self.assertEquals(res.status_int, webob.exc.HTTPNotFound.code) + def test_delete_not_allowed(self): + # Verify we can get the image data + req = webob.Request.blank("/images/%s" % UUID2) + req.method = 'GET' + req.headers['X-Auth-Token'] = 'user:tenant:' + res = req.get_response(self.api) + self.assertEqual(res.status_int, 200) + self.assertEqual(len(res.body), 19) + + # Verify we cannot delete the image + req.method = 'DELETE' + res = req.get_response(self.api) + self.assertEqual(res.status_int, 403) + + # Verify the image data is still there + req.method = 'GET' + res = req.get_response(self.api) + self.assertEqual(res.status_int, 200) + self.assertEqual(len(res.body), 19) + def test_delete_queued_image(self): """Delete an image in a queued state diff --git a/glance/tests/utils.py b/glance/tests/utils.py index 92b6500ba7..514f90eef0 100644 --- a/glance/tests/utils.py +++ b/glance/tests/utils.py @@ -368,6 +368,7 @@ def process_request(self, req): 'tenant': tenant, 'roles': roles, 'is_admin': self.is_admin, + 'auth_tok': auth_tok, } req.context = context.RequestContext(**kwargs)