From d851b332a23b132b22d382bf97c27ff9e94f94a1 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichyov Date: Wed, 26 Jun 2013 11:21:51 +0300 Subject: [PATCH] Handle ImageNotAuthorized exception Handle ImageNotAuthorized exception if user have no access to update image metadata Change-Id: I558cc2c31174f7f619061882bfdab6df35203254 Fixes: bug #1194768 --- nova/api/openstack/compute/image_metadata.py | 5 +++- .../compute/plugins/v3/image_metadata.py | 5 +++- .../compute/plugins/v3/test_image_metadata.py | 14 +++++++++++ .../compute/plugins/v3/test_images.py | 25 +++++++++++++++++++ .../openstack/compute/test_image_metadata.py | 14 +++++++++++ .../api/openstack/compute/test_images.py | 24 ++++++++++++++++++ nova/tests/api/openstack/fakes.py | 4 +++ nova/tests/glance/stubs.py | 5 ++++ 8 files changed, 94 insertions(+), 2 deletions(-) diff --git a/nova/api/openstack/compute/image_metadata.py b/nova/api/openstack/compute/image_metadata.py index 65ed72a23ae5..c7b9074f6ca2 100644 --- a/nova/api/openstack/compute/image_metadata.py +++ b/nova/api/openstack/compute/image_metadata.py @@ -87,7 +87,10 @@ class Controller(object): image['properties'][id] = meta[id] common.check_img_metadata_properties_quota(context, image['properties']) - self.image_service.update(context, image_id, image, None) + try: + self.image_service.update(context, image_id, image, None) + except exception.ImageNotAuthorized as e: + raise exc.HTTPForbidden(explanation=str(e)) return dict(meta=meta) @wsgi.serializers(xml=common.MetadataTemplate) diff --git a/nova/api/openstack/compute/plugins/v3/image_metadata.py b/nova/api/openstack/compute/plugins/v3/image_metadata.py index 80e4b695781a..31be2e0e2d7f 100644 --- a/nova/api/openstack/compute/plugins/v3/image_metadata.py +++ b/nova/api/openstack/compute/plugins/v3/image_metadata.py @@ -98,7 +98,10 @@ class ImageMetadataController(object): image['properties'][id] = meta[id] common.check_img_metadata_properties_quota(context, image['properties']) - self.image_service.update(context, image_id, image, None) + try: + self.image_service.update(context, image_id, image, None) + except exception.ImageNotAuthorized as e: + raise exc.HTTPForbidden(explanation=str(e)) return dict(meta=meta) @wsgi.serializers(xml=common.MetadataTemplate) diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_image_metadata.py b/nova/tests/api/openstack/compute/plugins/v3/test_image_metadata.py index 46d71d2fe584..a83a1cb4daff 100644 --- a/nova/tests/api/openstack/compute/plugins/v3/test_image_metadata.py +++ b/nova/tests/api/openstack/compute/plugins/v3/test_image_metadata.py @@ -209,3 +209,17 @@ class ImageMetaDataTest(test.TestCase): self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, self.controller.update, req, '123', 'blah', body) + + def test_image_not_authorized(self): + image_id = 131 + # see nova.tests.api.openstack.fakes:_make_image_fixtures + + req = fakes.HTTPRequestV3.blank( + '/v3/os-images/%s/os-image-metadata/key1' % image_id) + req.method = 'PUT' + body = {"meta": {"key1": "value1"}} + req.body = jsonutils.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPForbidden, + self.controller.update, req, image_id, 'key1', body) diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_images.py b/nova/tests/api/openstack/compute/plugins/v3/test_images.py index 00223192ef35..15f0a5c84c54 100644 --- a/nova/tests/api/openstack/compute/plugins/v3/test_images.py +++ b/nova/tests/api/openstack/compute/plugins/v3/test_images.py @@ -465,6 +465,31 @@ class ImagesControllerTest(test.TestCase): "href": "%s/fake/images/130" % glance.generate_glance_url() }], }, + { + 'id': '131', + 'name': None, + 'metadata': {}, + 'updated': NOW_API_FORMAT, + 'created': NOW_API_FORMAT, + 'status': 'ACTIVE', + 'progress': 100, + "size": 0, + 'minDisk': 0, + 'minRam': 0, + "links": [{ + "rel": "self", + "href": "http://localhost/v3/images/131", + }, + { + "rel": "bookmark", + "href": "http://localhost/images/131", + }, + { + "rel": "alternate", + "type": "application/vnd.openstack.image", + "href": "%s/fake/images/131" % glance.generate_glance_url() + }], + }, ] self.assertThat(expected, matchers.DictListMatches(response_list)) diff --git a/nova/tests/api/openstack/compute/test_image_metadata.py b/nova/tests/api/openstack/compute/test_image_metadata.py index 1330bc202b23..ef044c065c75 100644 --- a/nova/tests/api/openstack/compute/test_image_metadata.py +++ b/nova/tests/api/openstack/compute/test_image_metadata.py @@ -197,3 +197,17 @@ class ImageMetaDataTest(test.TestCase): self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, self.controller.update, req, '123', 'blah', body) + + def test_image_not_authorized(self): + image_id = 131 + # see nova.tests.api.openstack.fakes:_make_image_fixtures + + req = fakes.HTTPRequest.blank('/v2/fake/images/%s/metadata/key1' + % image_id) + req.method = 'PUT' + body = {"meta": {"key1": "value1"}} + req.body = jsonutils.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPForbidden, + self.controller.update, req, image_id, 'key1', body) diff --git a/nova/tests/api/openstack/compute/test_images.py b/nova/tests/api/openstack/compute/test_images.py index a35dc6e51597..1beb5d2b190a 100644 --- a/nova/tests/api/openstack/compute/test_images.py +++ b/nova/tests/api/openstack/compute/test_images.py @@ -455,6 +455,30 @@ class ImagesControllerTest(test.TestCase): "href": "%s/fake/images/130" % glance.generate_glance_url() }], }, + { + 'id': '131', + 'name': None, + 'metadata': {}, + 'updated': NOW_API_FORMAT, + 'created': NOW_API_FORMAT, + 'status': 'ACTIVE', + 'progress': 100, + 'minDisk': 0, + 'minRam': 0, + "links": [{ + "rel": "self", + "href": "http://localhost/v2/fake/images/131", + }, + { + "rel": "bookmark", + "href": "http://localhost/fake/images/131", + }, + { + "rel": "alternate", + "type": "application/vnd.openstack.image", + "href": "%s/fake/images/131" % glance.generate_glance_url() + }], + }, ] self.assertThat(expected, matchers.DictListMatches(response_list)) diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 72f83acd7984..f8520e89bdc2 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -271,6 +271,10 @@ def _make_image_fixtures(): # Image without a name add_fixture(id=image_id, is_public=True, status='active', properties={}) + # Image for permission tests + image_id += 1 + add_fixture(id=image_id, is_public=True, status='active', properties={}, + owner='authorized_fake') return fixtures diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py index 56dae7ffc451..b7f0d13da6a2 100644 --- a/nova/tests/glance/stubs.py +++ b/nova/tests/glance/stubs.py @@ -75,6 +75,11 @@ class StubGlanceClient(object): def update(self, image_id, **metadata): for i, image in enumerate(self._images): if image.id == str(image_id): + # If you try to update a non-authorized image, it raises + # HTTPForbidden + if image.owner == 'authorized_fake': + raise glanceclient.exc.HTTPForbidden + for k, v in metadata.items(): setattr(self._images[i], k, v) return self._images[i]