From b75ed6011f4f176bd9c73b013fc58b222f5ad258 Mon Sep 17 00:00:00 2001 From: Matthew Thode Date: Thu, 6 Oct 2016 13:34:01 -0500 Subject: app-admin/glance: cleanup Package-Manager: portage-2.3.0 --- .../files/cve-2016-0757-stable-liberty.patch | 332 --------------------- 1 file changed, 332 deletions(-) delete mode 100644 app-admin/glance/files/cve-2016-0757-stable-liberty.patch (limited to 'app-admin') diff --git a/app-admin/glance/files/cve-2016-0757-stable-liberty.patch b/app-admin/glance/files/cve-2016-0757-stable-liberty.patch deleted file mode 100644 index 19c8365eb018..000000000000 --- a/app-admin/glance/files/cve-2016-0757-stable-liberty.patch +++ /dev/null @@ -1,332 +0,0 @@ -From c6021e9b3642340036347026a3f251e066e53094 Mon Sep 17 00:00:00 2001 -From: Erno Kuvaja -Date: Tue, 19 Jan 2016 13:37:05 +0000 -Subject: [PATCH] Prevent user to remove last location of the image - -If the last location of the image is removed, image transitions back to queued. -This allows user to upload new data into the existing image record. By -preventing removal of the last location we prevent the image transition back to -queued. - -This change also prevents doing the same operation via replacing the locations -with empty list. - -SecurityImpact -DocImpact -APIImpact - -Conflicts: - glance/tests/unit/v2/test_images_resource.py - -Change-Id: Ieb03aaba887492819f9c58aa67f7acfcea81720e -Closes-Bug: #1525915 -(cherry picked from commit 2f4504da2149697bcdb93ed855e15025d2a08f8c) ---- - glance/api/v2/images.py | 19 +++- - glance/tests/functional/v2/test_images.py | 14 --- - glance/tests/unit/v2/test_images_resource.py | 122 ++++----------------- - ...oving-last-image-location-d5ee3e00efe14f34.yaml | 10 ++ - 4 files changed, 44 insertions(+), 121 deletions(-) - create mode 100644 releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml - -diff --git a/glance/api/v2/images.py b/glance/api/v2/images.py -index 17678f2..cf667bf 100644 ---- a/glance/api/v2/images.py -+++ b/glance/api/v2/images.py -@@ -181,7 +181,10 @@ class ImagesController(object): - path = change['path'] - path_root = path[0] - value = change['value'] -- if path_root == 'locations': -+ if path_root == 'locations' and value == []: -+ msg = _("Cannot set locations to empty list.") -+ raise webob.exc.HTTPForbidden(message=msg) -+ elif path_root == 'locations' and value != []: - self._do_replace_locations(image, value) - elif path_root == 'owner' and req.context.is_admin == False: - msg = _("Owner can't be updated by non admin.") -@@ -217,7 +220,10 @@ class ImagesController(object): - path = change['path'] - path_root = path[0] - if path_root == 'locations': -- self._do_remove_locations(image, path[1]) -+ try: -+ self._do_remove_locations(image, path[1]) -+ except exception.Forbidden as e: -+ raise webob.exc.HTTPForbidden(e.msg) - else: - if hasattr(image, path_root): - msg = _("Property %s may not be removed.") -@@ -306,6 +312,11 @@ class ImagesController(object): - explanation=encodeutils.exception_to_unicode(ve)) - - def _do_remove_locations(self, image, path_pos): -+ if len(image.locations) == 1: -+ LOG.debug("User forbidden to remove last location of image %s", -+ image.image_id) -+ msg = _("Cannot remove last location in the image.") -+ raise exception.Forbidden(message=msg) - pos = self._get_locations_op_pos(path_pos, - len(image.locations), False) - if pos is None: -@@ -315,11 +326,11 @@ class ImagesController(object): - # NOTE(zhiyan): this actually deletes the location - # from the backend store. - image.locations.pop(pos) -+ # TODO(jokke): Fix this, we should catch what store throws and -+ # provide definitely something else than IternalServerError to user. - except Exception as e: - raise webob.exc.HTTPInternalServerError( - explanation=encodeutils.exception_to_unicode(e)) -- if len(image.locations) == 0 and image.status == 'active': -- image.status = 'queued' - - - class RequestDeserializer(wsgi.JSONRequestDeserializer): -diff --git a/glance/tests/functional/v2/test_images.py b/glance/tests/functional/v2/test_images.py -index aabc567..f199787 100644 ---- a/glance/tests/functional/v2/test_images.py -+++ b/glance/tests/functional/v2/test_images.py -@@ -522,20 +522,6 @@ class TestImages(functional.FunctionalTest): - response = requests.patch(path, headers=headers, data=data) - self.assertEqual(200, response.status_code, response.text) - -- # Remove all locations of the image then the image size shouldn't be -- # able to access -- path = self._url('/v2/images/%s' % image2_id) -- media_type = 'application/openstack-images-v2.1-json-patch' -- headers = self._headers({'content-type': media_type}) -- doc = [{'op': 'replace', 'path': '/locations', 'value': []}] -- data = jsonutils.dumps(doc) -- response = requests.patch(path, headers=headers, data=data) -- self.assertEqual(200, response.status_code, response.text) -- image = jsonutils.loads(response.text) -- self.assertIsNone(image['size']) -- self.assertIsNone(image['virtual_size']) -- self.assertEqual('queued', image['status']) -- - # Deletion should work. Deleting image-1 - path = self._url('/v2/images/%s' % image_id) - response = requests.delete(path, headers=self._headers()) -diff --git a/glance/tests/unit/v2/test_images_resource.py b/glance/tests/unit/v2/test_images_resource.py -index 698c284..ee09ee7 100644 ---- a/glance/tests/unit/v2/test_images_resource.py -+++ b/glance/tests/unit/v2/test_images_resource.py -@@ -1417,26 +1417,6 @@ class TestImagesController(base.IsolatedUnitTest): - self.assertRaises(webob.exc.HTTPConflict, self.controller.update, - another_request, created_image.image_id, changes) - -- def test_update_replace_locations(self): -- self.stubs.Set(store, 'get_size_from_backend', -- unit_test_utils.fake_get_size_from_backend) -- request = unit_test_utils.get_fake_request() -- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] -- output = self.controller.update(request, UUID1, changes) -- self.assertEqual(UUID1, output.image_id) -- self.assertEqual(0, len(output.locations)) -- self.assertEqual('queued', output.status) -- self.assertIsNone(output.size) -- -- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} -- changes = [{'op': 'replace', 'path': ['locations'], -- 'value': [new_location]}] -- output = self.controller.update(request, UUID1, changes) -- self.assertEqual(UUID1, output.image_id) -- self.assertEqual(1, len(output.locations)) -- self.assertEqual(new_location, output.locations[0]) -- self.assertEqual('active', output.status) -- - def test_update_replace_locations_non_empty(self): - new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} - request = unit_test_utils.get_fake_request() -@@ -1448,35 +1428,9 @@ class TestImagesController(base.IsolatedUnitTest): - def test_update_replace_locations_invalid(self): - request = unit_test_utils.get_fake_request() - changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] -- output = self.controller.update(request, UUID1, changes) -- self.assertEqual(UUID1, output.image_id) -- self.assertEqual(0, len(output.locations)) -- self.assertEqual('queued', output.status) -- -- request = unit_test_utils.get_fake_request() -- changes = [{'op': 'replace', 'path': ['locations'], -- 'value': [{'url': 'unknow://foo', 'metadata': {}}]}] -- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, -+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.update, - request, UUID1, changes) - -- def test_update_replace_locations_status_exception(self): -- self.stubs.Set(store, 'get_size_from_backend', -- unit_test_utils.fake_get_size_from_backend) -- request = unit_test_utils.get_fake_request() -- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] -- output = self.controller.update(request, UUID2, changes) -- self.assertEqual(UUID2, output.image_id) -- self.assertEqual(0, len(output.locations)) -- self.assertEqual('queued', output.status) -- -- self.db.image_update(None, UUID2, {'disk_format': None}) -- -- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} -- changes = [{'op': 'replace', 'path': ['locations'], -- 'value': [new_location]}] -- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, -- request, UUID2, changes) -- - def test_update_add_property(self): - request = unit_test_utils.get_fake_request() - -@@ -1600,24 +1554,6 @@ class TestImagesController(base.IsolatedUnitTest): - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, - request, UUID1, changes) - -- def test_update_add_locations_status_exception(self): -- self.stubs.Set(store, 'get_size_from_backend', -- unit_test_utils.fake_get_size_from_backend) -- request = unit_test_utils.get_fake_request() -- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] -- output = self.controller.update(request, UUID2, changes) -- self.assertEqual(UUID2, output.image_id) -- self.assertEqual(0, len(output.locations)) -- self.assertEqual('queued', output.status) -- -- self.db.image_update(None, UUID2, {'disk_format': None}) -- -- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} -- changes = [{'op': 'add', 'path': ['locations', '-'], -- 'value': new_location}] -- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, -- request, UUID2, changes) -- - def test_update_add_duplicate_locations(self): - new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} - request = unit_test_utils.get_fake_request() -@@ -1631,23 +1567,6 @@ class TestImagesController(base.IsolatedUnitTest): - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, - request, UUID1, changes) - -- def test_update_replace_duplicate_locations(self): -- self.stubs.Set(store, 'get_size_from_backend', -- unit_test_utils.fake_get_size_from_backend) -- request = unit_test_utils.get_fake_request() -- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] -- output = self.controller.update(request, UUID1, changes) -- self.assertEqual(UUID1, output.image_id) -- self.assertEqual(0, len(output.locations)) -- self.assertEqual('queued', output.status) -- -- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} -- changes = [{'op': 'replace', 'path': ['locations'], -- 'value': [new_location, new_location]}] -- -- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, -- request, UUID1, changes) -- - def test_update_add_too_many_locations(self): - self.config(image_location_quota=1) - request = unit_test_utils.get_fake_request() -@@ -1748,9 +1667,12 @@ class TestImagesController(base.IsolatedUnitTest): - {'op': 'add', 'path': ['locations', '-'], - 'value': {'url': '%s/fake_location_1' % BASE_URI, - 'metadata': {}}}, -+ {'op': 'add', 'path': ['locations', '-'], -+ 'value': {'url': '%s/fake_location_2' % BASE_URI, -+ 'metadata': {}}}, - ] - self.controller.update(request, UUID1, changes) -- self.config(image_location_quota=1) -+ self.config(image_location_quota=2) - - # We must remove two properties to avoid being - # over the limit of 1 property -@@ -1763,8 +1685,8 @@ class TestImagesController(base.IsolatedUnitTest): - ] - output = self.controller.update(request, UUID1, changes) - self.assertEqual(UUID1, output.image_id) -- self.assertEqual(1, len(output.locations)) -- self.assertIn('fake_location_3', output.locations[0]['url']) -+ self.assertEqual(2, len(output.locations)) -+ self.assertIn('fake_location_3', output.locations[1]['url']) - self.assertNotEqual(output.created_at, output.updated_at) - - def test_update_remove_base_property(self): -@@ -1805,24 +1727,23 @@ class TestImagesController(base.IsolatedUnitTest): - unit_test_utils.fake_get_size_from_backend) - - request = unit_test_utils.get_fake_request() -- changes = [{'op': 'remove', 'path': ['locations', '0']}] -- output = self.controller.update(request, UUID1, changes) -- self.assertEqual(output.image_id, UUID1) -- self.assertEqual(0, len(output.locations)) -- self.assertEqual('queued', output.status) -- self.assertIsNone(output.size) -- - new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} - changes = [{'op': 'add', 'path': ['locations', '-'], - 'value': new_location}] -+ self.controller.update(request, UUID1, changes) -+ changes = [{'op': 'remove', 'path': ['locations', '0']}] - output = self.controller.update(request, UUID1, changes) - self.assertEqual(UUID1, output.image_id) - self.assertEqual(1, len(output.locations)) -- self.assertEqual(new_location, output.locations[0]) - self.assertEqual('active', output.status) - - def test_update_remove_location_invalid_pos(self): - request = unit_test_utils.get_fake_request() -+ changes = [ -+ {'op': 'add', 'path': ['locations', '-'], -+ 'value': {'url': '%s/fake_location' % BASE_URI, -+ 'metadata': {}}}] -+ self.controller.update(request, UUID1, changes) - changes = [{'op': 'remove', 'path': ['locations', None]}] - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, - request, UUID1, changes) -@@ -1844,6 +1765,11 @@ class TestImagesController(base.IsolatedUnitTest): - fake_delete_image_location_from_backend) - - request = unit_test_utils.get_fake_request() -+ changes = [ -+ {'op': 'add', 'path': ['locations', '-'], -+ 'value': {'url': '%s/fake_location' % BASE_URI, -+ 'metadata': {}}}] -+ self.controller.update(request, UUID1, changes) - changes = [{'op': 'remove', 'path': ['locations', '0']}] - self.assertRaises(webob.exc.HTTPInternalServerError, - self.controller.update, request, UUID1, changes) -@@ -2137,16 +2063,6 @@ class TestImagesControllerPolicies(base.IsolatedUnitTest): - self.assertRaises(webob.exc.HTTPForbidden, self.controller.update, - request, UUID1, changes) - -- self.stubs.Set(self.store_utils, 'delete_image_location_from_backend', -- fake_delete_image_location_from_backend) -- -- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] -- self.controller.update(request, UUID1, changes) -- changes = [{'op': 'replace', 'path': ['locations'], -- 'value': [new_location]}] -- self.assertRaises(webob.exc.HTTPForbidden, self.controller.update, -- request, UUID1, changes) -- - def test_update_delete_image_location_unauthorized(self): - rules = {"delete_image_location": False} - self.policy.set_rules(rules) -diff --git a/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml b/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml -new file mode 100644 -index 0000000..344e6e5 ---- /dev/null -+++ b/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml -@@ -0,0 +1,10 @@ -+--- -+security: -+ - Fixing bug 1525915; image might be transitioning -+ from active to queued by regular user by removing -+ last location of image (or replacing locations -+ with empty list). This allows user to re-upload -+ data to the image breaking Glance's promise of -+ image data immutability. From now on, last -+ location cannot be removed and locations cannot -+ be replaced with empty list. --- -1.9.1 - -- cgit v1.2.3-65-gdbad