diff -Nru glance-2015.1.4/debian/changelog glance-2015.1.4/debian/changelog --- glance-2015.1.4/debian/changelog 2016-05-11 09:03:09.000000000 -0300 +++ glance-2015.1.4/debian/changelog 2017-06-28 17:23:05.000000000 -0400 @@ -1,3 +1,11 @@ +glance (1:2015.1.4-0ubuntu2) trusty-kilo; urgency=medium + + * d/p/allow-image-list-if-access-to-attrs-is-forbidden.patch: + Allow to list images in v2 if get_image_location policy is set + to role:admin and user is not admin. (LP: #1502136). + + -- Jorge Niedbalski Wed, 28 Jun 2017 17:21:53 -0400 + glance (1:2015.1.4-0ubuntu1) trusty-kilo; urgency=medium * New upstream stable release (LP: #1580334). diff -Nru glance-2015.1.4/debian/patches/allow-image-list-if-access-to-attrs-is-forbidden.patch glance-2015.1.4/debian/patches/allow-image-list-if-access-to-attrs-is-forbidden.patch --- glance-2015.1.4/debian/patches/allow-image-list-if-access-to-attrs-is-forbidden.patch 1969-12-31 21:00:00.000000000 -0300 +++ glance-2015.1.4/debian/patches/allow-image-list-if-access-to-attrs-is-forbidden.patch 2017-06-28 17:27:00.000000000 -0400 @@ -0,0 +1,129 @@ +From f07f36fa3789a4997b84639530e5d6ab1c603983 Mon Sep 17 00:00:00 2001 +From: kairat_kushaev +Date: Mon, 12 Oct 2015 15:56:58 +0300 +Subject: [PATCH] Allow image-list if access to attrs is forbidden + +If access to some attributes is forbidden (f.e. get_image_location +policy is set to role:admin and user is not admin) glance should +just exclude these attributes from image-show, image-list output +instead of generating Forbidden exception. +Otherwise, the policies such as get_image_location is not useful. + +APIImpact +SecurityImpact +Change-Id: I5a6f587086e926a1f7e9b3f1dac9d7e10710d72a +Closes-bug: #1502136 +--- + glance/api/v2/images.py | 17 ++++++++---- + glance/tests/functional/v2/test_images.py | 46 +++++++++++++++++++++++++++++++ + 2 files changed, 58 insertions(+), 5 deletions(-) + +Index: glance-2015.1.4/glance/api/v2/images.py +=================================================================== +--- glance-2015.1.4.orig/glance/api/v2/images.py ++++ glance-2015.1.4/glance/api/v2/images.py +@@ -713,7 +713,13 @@ class ResponseSerializer(wsgi.JSONRespon + return base_href + + def _format_image(self, image): +- image_view = dict() ++ ++ def _get_image_locations(image): ++ try: ++ return list(image.locations) ++ except exception.Forbidden: ++ return [] ++ + try: + image_view = dict(image.extra_properties) + attributes = ['name', 'disk_format', 'container_format', +@@ -727,7 +733,7 @@ class ResponseSerializer(wsgi.JSONRespon + image_view['updated_at'] = timeutils.isotime(image.updated_at) + + if CONF.show_multiple_locations: +- locations = list(image.locations) ++ locations = _get_image_locations(image) + if locations: + image_view['locations'] = [] + for loc in locations: +@@ -744,9 +750,10 @@ class ResponseSerializer(wsgi.JSONRespon + "for image %s" % image.image_id) + + if CONF.show_image_direct_url: +- if image.locations: ++ locations = _get_image_locations(image) ++ if locations: + # Choose best location configured strategy +- l = location_strategy.choose_best_location(image.locations) ++ l = location_strategy.choose_best_location(locations) + image_view['direct_url'] = l['url'] + else: + LOG.debug("There is not available location " +@@ -757,9 +764,9 @@ class ResponseSerializer(wsgi.JSONRespon + image_view['file'] = self._get_image_href(image, 'file') + image_view['schema'] = '/v2/schemas/image' + image_view = self.schema.filter(image_view) # domain ++ return image_view + except exception.Forbidden as e: + raise webob.exc.HTTPForbidden(explanation=e.msg) +- return image_view + + def create(self, response, image): + response.status_int = 201 +Index: glance-2015.1.4/glance/tests/functional/v2/test_images.py +=================================================================== +--- glance-2015.1.4.orig/glance/tests/functional/v2/test_images.py ++++ glance-2015.1.4/glance/tests/functional/v2/test_images.py +@@ -1112,6 +1112,52 @@ class TestImages(functional.FunctionalTe + response = requests.delete(path, headers=headers) + self.assertEqual(204, response.status_code) + ++ def test_list_show_ok_when_get_location_allowed_for_admins(self): ++ self.api_server.show_image_direct_url = True ++ self.api_server.show_multiple_locations = True ++ # setup context to allow a list locations by admin only ++ rules = { ++ "context_is_admin": "role:admin", ++ "default": "", ++ "add_image": "", ++ "get_image": "", ++ "modify_image": "", ++ "upload_image": "", ++ "get_image_location": "role:admin", ++ "delete_image": "", ++ "restricted": "", ++ "download_image": "", ++ "add_member": "", ++ } ++ ++ self.set_policy_rules(rules) ++ self.start_servers(**self.__dict__.copy()) ++ ++ # Create an image ++ path = self._url('/v2/images') ++ headers = self._headers({'content-type': 'application/json', ++ 'X-Tenant-Id': TENANT1}) ++ data = jsonutils.dumps({'name': 'image-1', 'disk_format': 'aki', ++ 'container_format': 'aki'}) ++ response = requests.post(path, headers=headers, data=data) ++ self.assertEqual(201, response.status_code) ++ ++ # Get the image's ID ++ image = jsonutils.loads(response.text) ++ image_id = image['id'] ++ ++ # Can retrieve the image as TENANT1 ++ path = self._url('/v2/images/%s' % image_id) ++ response = requests.get(path, headers=headers) ++ self.assertEqual(200, response.status_code) ++ ++ # Can list images as TENANT1 ++ path = self._url('/v2/images') ++ response = requests.get(path, headers=headers) ++ self.assertEqual(200, response.status_code) ++ ++ self.stop_servers() ++ + def test_image_size_cap(self): + self.api_server.image_size_cap = 128 + self.start_servers(**self.__dict__.copy()) diff -Nru glance-2015.1.4/debian/patches/series glance-2015.1.4/debian/patches/series --- glance-2015.1.4/debian/patches/series 2016-05-10 17:29:39.000000000 -0300 +++ glance-2015.1.4/debian/patches/series 2017-06-28 17:21:44.000000000 -0400 @@ -2,3 +2,4 @@ skip-glance-search-tests.patch fix-test-artifacts-plugin-loader.patch skip-online-tests.patch +allow-image-list-if-access-to-attrs-is-forbidden.patch