1 |
commit: b75ed6011f4f176bd9c73b013fc58b222f5ad258 |
2 |
Author: Matthew Thode <prometheanfire <AT> gentoo <DOT> org> |
3 |
AuthorDate: Thu Oct 6 18:34:01 2016 +0000 |
4 |
Commit: Matt Thode <prometheanfire <AT> gentoo <DOT> org> |
5 |
CommitDate: Thu Oct 6 18:34:47 2016 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=b75ed601 |
7 |
|
8 |
app-admin/glance: cleanup |
9 |
|
10 |
Package-Manager: portage-2.3.0 |
11 |
|
12 |
.../files/cve-2016-0757-stable-liberty.patch | 332 --------------------- |
13 |
1 file changed, 332 deletions(-) |
14 |
|
15 |
diff --git a/app-admin/glance/files/cve-2016-0757-stable-liberty.patch b/app-admin/glance/files/cve-2016-0757-stable-liberty.patch |
16 |
deleted file mode 100644 |
17 |
index 19c8365..00000000 |
18 |
--- a/app-admin/glance/files/cve-2016-0757-stable-liberty.patch |
19 |
+++ /dev/null |
20 |
@@ -1,332 +0,0 @@ |
21 |
-From c6021e9b3642340036347026a3f251e066e53094 Mon Sep 17 00:00:00 2001 |
22 |
-From: Erno Kuvaja <jokke@×××.fi> |
23 |
-Date: Tue, 19 Jan 2016 13:37:05 +0000 |
24 |
-Subject: [PATCH] Prevent user to remove last location of the image |
25 |
- |
26 |
-If the last location of the image is removed, image transitions back to queued. |
27 |
-This allows user to upload new data into the existing image record. By |
28 |
-preventing removal of the last location we prevent the image transition back to |
29 |
-queued. |
30 |
- |
31 |
-This change also prevents doing the same operation via replacing the locations |
32 |
-with empty list. |
33 |
- |
34 |
-SecurityImpact |
35 |
-DocImpact |
36 |
-APIImpact |
37 |
- |
38 |
-Conflicts: |
39 |
- glance/tests/unit/v2/test_images_resource.py |
40 |
- |
41 |
-Change-Id: Ieb03aaba887492819f9c58aa67f7acfcea81720e |
42 |
-Closes-Bug: #1525915 |
43 |
-(cherry picked from commit 2f4504da2149697bcdb93ed855e15025d2a08f8c) |
44 |
---- |
45 |
- glance/api/v2/images.py | 19 +++- |
46 |
- glance/tests/functional/v2/test_images.py | 14 --- |
47 |
- glance/tests/unit/v2/test_images_resource.py | 122 ++++----------------- |
48 |
- ...oving-last-image-location-d5ee3e00efe14f34.yaml | 10 ++ |
49 |
- 4 files changed, 44 insertions(+), 121 deletions(-) |
50 |
- create mode 100644 releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml |
51 |
- |
52 |
-diff --git a/glance/api/v2/images.py b/glance/api/v2/images.py |
53 |
-index 17678f2..cf667bf 100644 |
54 |
---- a/glance/api/v2/images.py |
55 |
-+++ b/glance/api/v2/images.py |
56 |
-@@ -181,7 +181,10 @@ class ImagesController(object): |
57 |
- path = change['path'] |
58 |
- path_root = path[0] |
59 |
- value = change['value'] |
60 |
-- if path_root == 'locations': |
61 |
-+ if path_root == 'locations' and value == []: |
62 |
-+ msg = _("Cannot set locations to empty list.") |
63 |
-+ raise webob.exc.HTTPForbidden(message=msg) |
64 |
-+ elif path_root == 'locations' and value != []: |
65 |
- self._do_replace_locations(image, value) |
66 |
- elif path_root == 'owner' and req.context.is_admin == False: |
67 |
- msg = _("Owner can't be updated by non admin.") |
68 |
-@@ -217,7 +220,10 @@ class ImagesController(object): |
69 |
- path = change['path'] |
70 |
- path_root = path[0] |
71 |
- if path_root == 'locations': |
72 |
-- self._do_remove_locations(image, path[1]) |
73 |
-+ try: |
74 |
-+ self._do_remove_locations(image, path[1]) |
75 |
-+ except exception.Forbidden as e: |
76 |
-+ raise webob.exc.HTTPForbidden(e.msg) |
77 |
- else: |
78 |
- if hasattr(image, path_root): |
79 |
- msg = _("Property %s may not be removed.") |
80 |
-@@ -306,6 +312,11 @@ class ImagesController(object): |
81 |
- explanation=encodeutils.exception_to_unicode(ve)) |
82 |
- |
83 |
- def _do_remove_locations(self, image, path_pos): |
84 |
-+ if len(image.locations) == 1: |
85 |
-+ LOG.debug("User forbidden to remove last location of image %s", |
86 |
-+ image.image_id) |
87 |
-+ msg = _("Cannot remove last location in the image.") |
88 |
-+ raise exception.Forbidden(message=msg) |
89 |
- pos = self._get_locations_op_pos(path_pos, |
90 |
- len(image.locations), False) |
91 |
- if pos is None: |
92 |
-@@ -315,11 +326,11 @@ class ImagesController(object): |
93 |
- # NOTE(zhiyan): this actually deletes the location |
94 |
- # from the backend store. |
95 |
- image.locations.pop(pos) |
96 |
-+ # TODO(jokke): Fix this, we should catch what store throws and |
97 |
-+ # provide definitely something else than IternalServerError to user. |
98 |
- except Exception as e: |
99 |
- raise webob.exc.HTTPInternalServerError( |
100 |
- explanation=encodeutils.exception_to_unicode(e)) |
101 |
-- if len(image.locations) == 0 and image.status == 'active': |
102 |
-- image.status = 'queued' |
103 |
- |
104 |
- |
105 |
- class RequestDeserializer(wsgi.JSONRequestDeserializer): |
106 |
-diff --git a/glance/tests/functional/v2/test_images.py b/glance/tests/functional/v2/test_images.py |
107 |
-index aabc567..f199787 100644 |
108 |
---- a/glance/tests/functional/v2/test_images.py |
109 |
-+++ b/glance/tests/functional/v2/test_images.py |
110 |
-@@ -522,20 +522,6 @@ class TestImages(functional.FunctionalTest): |
111 |
- response = requests.patch(path, headers=headers, data=data) |
112 |
- self.assertEqual(200, response.status_code, response.text) |
113 |
- |
114 |
-- # Remove all locations of the image then the image size shouldn't be |
115 |
-- # able to access |
116 |
-- path = self._url('/v2/images/%s' % image2_id) |
117 |
-- media_type = 'application/openstack-images-v2.1-json-patch' |
118 |
-- headers = self._headers({'content-type': media_type}) |
119 |
-- doc = [{'op': 'replace', 'path': '/locations', 'value': []}] |
120 |
-- data = jsonutils.dumps(doc) |
121 |
-- response = requests.patch(path, headers=headers, data=data) |
122 |
-- self.assertEqual(200, response.status_code, response.text) |
123 |
-- image = jsonutils.loads(response.text) |
124 |
-- self.assertIsNone(image['size']) |
125 |
-- self.assertIsNone(image['virtual_size']) |
126 |
-- self.assertEqual('queued', image['status']) |
127 |
-- |
128 |
- # Deletion should work. Deleting image-1 |
129 |
- path = self._url('/v2/images/%s' % image_id) |
130 |
- response = requests.delete(path, headers=self._headers()) |
131 |
-diff --git a/glance/tests/unit/v2/test_images_resource.py b/glance/tests/unit/v2/test_images_resource.py |
132 |
-index 698c284..ee09ee7 100644 |
133 |
---- a/glance/tests/unit/v2/test_images_resource.py |
134 |
-+++ b/glance/tests/unit/v2/test_images_resource.py |
135 |
-@@ -1417,26 +1417,6 @@ class TestImagesController(base.IsolatedUnitTest): |
136 |
- self.assertRaises(webob.exc.HTTPConflict, self.controller.update, |
137 |
- another_request, created_image.image_id, changes) |
138 |
- |
139 |
-- def test_update_replace_locations(self): |
140 |
-- self.stubs.Set(store, 'get_size_from_backend', |
141 |
-- unit_test_utils.fake_get_size_from_backend) |
142 |
-- request = unit_test_utils.get_fake_request() |
143 |
-- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] |
144 |
-- output = self.controller.update(request, UUID1, changes) |
145 |
-- self.assertEqual(UUID1, output.image_id) |
146 |
-- self.assertEqual(0, len(output.locations)) |
147 |
-- self.assertEqual('queued', output.status) |
148 |
-- self.assertIsNone(output.size) |
149 |
-- |
150 |
-- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} |
151 |
-- changes = [{'op': 'replace', 'path': ['locations'], |
152 |
-- 'value': [new_location]}] |
153 |
-- output = self.controller.update(request, UUID1, changes) |
154 |
-- self.assertEqual(UUID1, output.image_id) |
155 |
-- self.assertEqual(1, len(output.locations)) |
156 |
-- self.assertEqual(new_location, output.locations[0]) |
157 |
-- self.assertEqual('active', output.status) |
158 |
-- |
159 |
- def test_update_replace_locations_non_empty(self): |
160 |
- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} |
161 |
- request = unit_test_utils.get_fake_request() |
162 |
-@@ -1448,35 +1428,9 @@ class TestImagesController(base.IsolatedUnitTest): |
163 |
- def test_update_replace_locations_invalid(self): |
164 |
- request = unit_test_utils.get_fake_request() |
165 |
- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] |
166 |
-- output = self.controller.update(request, UUID1, changes) |
167 |
-- self.assertEqual(UUID1, output.image_id) |
168 |
-- self.assertEqual(0, len(output.locations)) |
169 |
-- self.assertEqual('queued', output.status) |
170 |
-- |
171 |
-- request = unit_test_utils.get_fake_request() |
172 |
-- changes = [{'op': 'replace', 'path': ['locations'], |
173 |
-- 'value': [{'url': 'unknow://foo', 'metadata': {}}]}] |
174 |
-- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, |
175 |
-+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.update, |
176 |
- request, UUID1, changes) |
177 |
- |
178 |
-- def test_update_replace_locations_status_exception(self): |
179 |
-- self.stubs.Set(store, 'get_size_from_backend', |
180 |
-- unit_test_utils.fake_get_size_from_backend) |
181 |
-- request = unit_test_utils.get_fake_request() |
182 |
-- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] |
183 |
-- output = self.controller.update(request, UUID2, changes) |
184 |
-- self.assertEqual(UUID2, output.image_id) |
185 |
-- self.assertEqual(0, len(output.locations)) |
186 |
-- self.assertEqual('queued', output.status) |
187 |
-- |
188 |
-- self.db.image_update(None, UUID2, {'disk_format': None}) |
189 |
-- |
190 |
-- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} |
191 |
-- changes = [{'op': 'replace', 'path': ['locations'], |
192 |
-- 'value': [new_location]}] |
193 |
-- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, |
194 |
-- request, UUID2, changes) |
195 |
-- |
196 |
- def test_update_add_property(self): |
197 |
- request = unit_test_utils.get_fake_request() |
198 |
- |
199 |
-@@ -1600,24 +1554,6 @@ class TestImagesController(base.IsolatedUnitTest): |
200 |
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, |
201 |
- request, UUID1, changes) |
202 |
- |
203 |
-- def test_update_add_locations_status_exception(self): |
204 |
-- self.stubs.Set(store, 'get_size_from_backend', |
205 |
-- unit_test_utils.fake_get_size_from_backend) |
206 |
-- request = unit_test_utils.get_fake_request() |
207 |
-- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] |
208 |
-- output = self.controller.update(request, UUID2, changes) |
209 |
-- self.assertEqual(UUID2, output.image_id) |
210 |
-- self.assertEqual(0, len(output.locations)) |
211 |
-- self.assertEqual('queued', output.status) |
212 |
-- |
213 |
-- self.db.image_update(None, UUID2, {'disk_format': None}) |
214 |
-- |
215 |
-- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} |
216 |
-- changes = [{'op': 'add', 'path': ['locations', '-'], |
217 |
-- 'value': new_location}] |
218 |
-- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, |
219 |
-- request, UUID2, changes) |
220 |
-- |
221 |
- def test_update_add_duplicate_locations(self): |
222 |
- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} |
223 |
- request = unit_test_utils.get_fake_request() |
224 |
-@@ -1631,23 +1567,6 @@ class TestImagesController(base.IsolatedUnitTest): |
225 |
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, |
226 |
- request, UUID1, changes) |
227 |
- |
228 |
-- def test_update_replace_duplicate_locations(self): |
229 |
-- self.stubs.Set(store, 'get_size_from_backend', |
230 |
-- unit_test_utils.fake_get_size_from_backend) |
231 |
-- request = unit_test_utils.get_fake_request() |
232 |
-- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] |
233 |
-- output = self.controller.update(request, UUID1, changes) |
234 |
-- self.assertEqual(UUID1, output.image_id) |
235 |
-- self.assertEqual(0, len(output.locations)) |
236 |
-- self.assertEqual('queued', output.status) |
237 |
-- |
238 |
-- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} |
239 |
-- changes = [{'op': 'replace', 'path': ['locations'], |
240 |
-- 'value': [new_location, new_location]}] |
241 |
-- |
242 |
-- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, |
243 |
-- request, UUID1, changes) |
244 |
-- |
245 |
- def test_update_add_too_many_locations(self): |
246 |
- self.config(image_location_quota=1) |
247 |
- request = unit_test_utils.get_fake_request() |
248 |
-@@ -1748,9 +1667,12 @@ class TestImagesController(base.IsolatedUnitTest): |
249 |
- {'op': 'add', 'path': ['locations', '-'], |
250 |
- 'value': {'url': '%s/fake_location_1' % BASE_URI, |
251 |
- 'metadata': {}}}, |
252 |
-+ {'op': 'add', 'path': ['locations', '-'], |
253 |
-+ 'value': {'url': '%s/fake_location_2' % BASE_URI, |
254 |
-+ 'metadata': {}}}, |
255 |
- ] |
256 |
- self.controller.update(request, UUID1, changes) |
257 |
-- self.config(image_location_quota=1) |
258 |
-+ self.config(image_location_quota=2) |
259 |
- |
260 |
- # We must remove two properties to avoid being |
261 |
- # over the limit of 1 property |
262 |
-@@ -1763,8 +1685,8 @@ class TestImagesController(base.IsolatedUnitTest): |
263 |
- ] |
264 |
- output = self.controller.update(request, UUID1, changes) |
265 |
- self.assertEqual(UUID1, output.image_id) |
266 |
-- self.assertEqual(1, len(output.locations)) |
267 |
-- self.assertIn('fake_location_3', output.locations[0]['url']) |
268 |
-+ self.assertEqual(2, len(output.locations)) |
269 |
-+ self.assertIn('fake_location_3', output.locations[1]['url']) |
270 |
- self.assertNotEqual(output.created_at, output.updated_at) |
271 |
- |
272 |
- def test_update_remove_base_property(self): |
273 |
-@@ -1805,24 +1727,23 @@ class TestImagesController(base.IsolatedUnitTest): |
274 |
- unit_test_utils.fake_get_size_from_backend) |
275 |
- |
276 |
- request = unit_test_utils.get_fake_request() |
277 |
-- changes = [{'op': 'remove', 'path': ['locations', '0']}] |
278 |
-- output = self.controller.update(request, UUID1, changes) |
279 |
-- self.assertEqual(output.image_id, UUID1) |
280 |
-- self.assertEqual(0, len(output.locations)) |
281 |
-- self.assertEqual('queued', output.status) |
282 |
-- self.assertIsNone(output.size) |
283 |
-- |
284 |
- new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}} |
285 |
- changes = [{'op': 'add', 'path': ['locations', '-'], |
286 |
- 'value': new_location}] |
287 |
-+ self.controller.update(request, UUID1, changes) |
288 |
-+ changes = [{'op': 'remove', 'path': ['locations', '0']}] |
289 |
- output = self.controller.update(request, UUID1, changes) |
290 |
- self.assertEqual(UUID1, output.image_id) |
291 |
- self.assertEqual(1, len(output.locations)) |
292 |
-- self.assertEqual(new_location, output.locations[0]) |
293 |
- self.assertEqual('active', output.status) |
294 |
- |
295 |
- def test_update_remove_location_invalid_pos(self): |
296 |
- request = unit_test_utils.get_fake_request() |
297 |
-+ changes = [ |
298 |
-+ {'op': 'add', 'path': ['locations', '-'], |
299 |
-+ 'value': {'url': '%s/fake_location' % BASE_URI, |
300 |
-+ 'metadata': {}}}] |
301 |
-+ self.controller.update(request, UUID1, changes) |
302 |
- changes = [{'op': 'remove', 'path': ['locations', None]}] |
303 |
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, |
304 |
- request, UUID1, changes) |
305 |
-@@ -1844,6 +1765,11 @@ class TestImagesController(base.IsolatedUnitTest): |
306 |
- fake_delete_image_location_from_backend) |
307 |
- |
308 |
- request = unit_test_utils.get_fake_request() |
309 |
-+ changes = [ |
310 |
-+ {'op': 'add', 'path': ['locations', '-'], |
311 |
-+ 'value': {'url': '%s/fake_location' % BASE_URI, |
312 |
-+ 'metadata': {}}}] |
313 |
-+ self.controller.update(request, UUID1, changes) |
314 |
- changes = [{'op': 'remove', 'path': ['locations', '0']}] |
315 |
- self.assertRaises(webob.exc.HTTPInternalServerError, |
316 |
- self.controller.update, request, UUID1, changes) |
317 |
-@@ -2137,16 +2063,6 @@ class TestImagesControllerPolicies(base.IsolatedUnitTest): |
318 |
- self.assertRaises(webob.exc.HTTPForbidden, self.controller.update, |
319 |
- request, UUID1, changes) |
320 |
- |
321 |
-- self.stubs.Set(self.store_utils, 'delete_image_location_from_backend', |
322 |
-- fake_delete_image_location_from_backend) |
323 |
-- |
324 |
-- changes = [{'op': 'replace', 'path': ['locations'], 'value': []}] |
325 |
-- self.controller.update(request, UUID1, changes) |
326 |
-- changes = [{'op': 'replace', 'path': ['locations'], |
327 |
-- 'value': [new_location]}] |
328 |
-- self.assertRaises(webob.exc.HTTPForbidden, self.controller.update, |
329 |
-- request, UUID1, changes) |
330 |
-- |
331 |
- def test_update_delete_image_location_unauthorized(self): |
332 |
- rules = {"delete_image_location": False} |
333 |
- self.policy.set_rules(rules) |
334 |
-diff --git a/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml b/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml |
335 |
-new file mode 100644 |
336 |
-index 0000000..344e6e5 |
337 |
---- /dev/null |
338 |
-+++ b/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml |
339 |
-@@ -0,0 +1,10 @@ |
340 |
-+--- |
341 |
-+security: |
342 |
-+ - Fixing bug 1525915; image might be transitioning |
343 |
-+ from active to queued by regular user by removing |
344 |
-+ last location of image (or replacing locations |
345 |
-+ with empty list). This allows user to re-upload |
346 |
-+ data to the image breaking Glance's promise of |
347 |
-+ image data immutability. From now on, last |
348 |
-+ location cannot be removed and locations cannot |
349 |
-+ be replaced with empty list. |
350 |
--- |
351 |
-1.9.1 |
352 |
- |