From 94714e761a894049534e22894c5e8b097876e677 Mon Sep 17 00:00:00 2001 From: Nate Potter Date: Mon, 19 Oct 2015 16:24:29 +0000 Subject: [PATCH] Return volume_type extra specs based on policy Currently extra specs are only shown to the admin user when showing volume types. This patch grants the flexibility to grant other users privelages to see them based on policy. It also hides the extra_specs entry in the dictionary from users who can't see it rather than just showing "None" as the value. Closes-Bug: #1504577 APIImpact Change-Id: Ia8f71180f048ba9b253e35ee136915812ef8df0c --- cinder/api/v2/types.py | 20 ++++++++++++++++++++ cinder/api/v2/views/types.py | 2 +- cinder/tests/unit/api/v2/test_types.py | 4 +--- etc/cinder/policy.json | 1 + 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/cinder/api/v2/types.py b/cinder/api/v2/types.py index 4109ec54135..c6816447aa0 100644 --- a/cinder/api/v2/types.py +++ b/cinder/api/v2/types.py @@ -21,11 +21,14 @@ from webob import exc from cinder.api.openstack import wsgi from cinder.api.v2.views import types as views_types from cinder.api import xmlutil +from cinder import context as ctx from cinder import exception from cinder.i18n import _ from cinder import utils from cinder.volume import volume_types +import cinder.policy + def make_voltype(elem): elem.set('id') @@ -57,6 +60,18 @@ class VolumeTypesController(wsgi.Controller): _view_builder_class = views_types.ViewBuilder + def _validate_policy(self, context): + target = { + 'project_id': context.project_id, + 'user_id': context.user_id, + } + try: + action = 'volume_extension:access_types_extra_specs' + cinder.policy.enforce(context, action, target) + return True + except Exception: + return False + @wsgi.serializers(xml=VolumeTypesTemplate) def index(self, req): """Returns the list of volume types.""" @@ -69,6 +84,9 @@ class VolumeTypesController(wsgi.Controller): """Return a single volume type item.""" context = req.environ['cinder.context'] + if not context.is_admin and self._validate_policy(context): + context = ctx.get_admin_context() + # get default volume type if id is not None and id == 'default': vol_type = volume_types.get_default_volume_type() @@ -109,6 +127,8 @@ class VolumeTypesController(wsgi.Controller): """Helper function that returns a list of type dicts.""" filters = {} context = req.environ['cinder.context'] + if not context.is_admin and self._validate_policy(context): + context = ctx.get_admin_context() if context.is_admin: # Only admin has query access to all volume types filters['is_public'] = self._parse_is_public( diff --git a/cinder/api/v2/views/types.py b/cinder/api/v2/views/types.py index af8a0495427..6c93f01b912 100644 --- a/cinder/api/v2/views/types.py +++ b/cinder/api/v2/views/types.py @@ -25,10 +25,10 @@ class ViewBuilder(common.ViewBuilder): trimmed = dict(id=volume_type.get('id'), name=volume_type.get('name'), is_public=volume_type.get('is_public'), - extra_specs=volume_type.get('extra_specs'), description=volume_type.get('description')) if context.is_admin: trimmed['qos_specs_id'] = volume_type.get('qos_specs_id') + trimmed['extra_specs'] = volume_type.get('extra_specs') return trimmed if brief else dict(volume_type=trimmed) def index(self, request, volume_types): diff --git a/cinder/tests/unit/api/v2/test_types.py b/cinder/tests/unit/api/v2/test_types.py index e9287d5baa8..d05e28d99e6 100644 --- a/cinder/tests/unit/api/v2/test_types.py +++ b/cinder/tests/unit/api/v2/test_types.py @@ -85,7 +85,7 @@ class VolumeTypesApiTest(test.TestCase): self.stubs.Set(volume_types, 'get_all_types', return_volume_types_get_all_types) - req = fakes.HTTPRequest.blank('/v2/fake/types') + req = fakes.HTTPRequest.blank('/v2/fake/types', use_admin_context=True) res_dict = self.controller.index(req) self.assertEqual(3, len(res_dict['volume_types'])) @@ -171,7 +171,6 @@ class VolumeTypesApiTest(test.TestCase): name='new_type', description='new_type_desc', is_public=True, - extra_specs={}, id=42, ) self.assertDictMatch(output['volume_type'], expected_volume_type) @@ -237,7 +236,6 @@ class VolumeTypesApiTest(test.TestCase): name='new_type', description='new_type_desc', is_public=True, - extra_specs={}, id=42 + i ) self.assertDictMatch(output['volume_types'][i], diff --git a/etc/cinder/policy.json b/etc/cinder/policy.json index 4c8a8aa5079..1b07629a9a8 100644 --- a/etc/cinder/policy.json +++ b/etc/cinder/policy.json @@ -25,6 +25,7 @@ "volume_extension:types_manage": "rule:admin_api", "volume_extension:types_extra_specs": "rule:admin_api", + "volume_extension:access_types_extra_specs": "rule:admin_api", "volume_extension:volume_type_access": "rule:admin_or_owner", "volume_extension:volume_type_access:addProjectAccess": "rule:admin_api", "volume_extension:volume_type_access:removeProjectAccess": "rule:admin_api",