Fix policy check in metadata APIs
When a user doesn't have access to a non-public resource, the appropriate response is HTTP 404, not HTTP 403. Change-Id: I62afec521c5cdfdd67ab83da40e69e6a2688c737 Closes-Bug: #2004230 Signed-off-by: Goutham Pacha Ravi <gouthampravi@gmail.com>
This commit is contained in:
parent
22e568d1d3
commit
ad29f8a065
@ -74,7 +74,7 @@ class MetadataController(object):
|
|||||||
for_modification=False, parent_id=None):
|
for_modification=False, parent_id=None):
|
||||||
if self.resource_name in ['share', 'share_network_subnet']:
|
if self.resource_name in ['share', 'share_network_subnet']:
|
||||||
# we would allow retrieving some "public" resources
|
# we would allow retrieving some "public" resources
|
||||||
# across project namespaces excpet share snaphots,
|
# across project namespaces except share snapshots,
|
||||||
# project_only=True is hard coded
|
# project_only=True is hard coded
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
else:
|
else:
|
||||||
@ -87,10 +87,22 @@ class MetadataController(object):
|
|||||||
res = get_res_method(context, resource_id, **kwargs)
|
res = get_res_method(context, resource_id, **kwargs)
|
||||||
|
|
||||||
get_policy = self.resource_policy_get[self.resource_name]
|
get_policy = self.resource_policy_get[self.resource_name]
|
||||||
if res.get('is_public') is False or for_modification:
|
if res.get('is_public') is False:
|
||||||
policy.check_policy(context, self.resource_name,
|
authorized = policy.check_policy(context,
|
||||||
get_policy, res)
|
self.resource_name,
|
||||||
|
get_policy,
|
||||||
|
res,
|
||||||
|
do_raise=False)
|
||||||
|
if not authorized:
|
||||||
|
# Raising NotFound to prevent existence detection
|
||||||
|
raise exception.NotFound()
|
||||||
|
elif for_modification:
|
||||||
|
# a public resource's metadata can be viewed, but not
|
||||||
|
# modified by non owners
|
||||||
|
policy.check_policy(context,
|
||||||
|
self.resource_name,
|
||||||
|
get_policy,
|
||||||
|
res)
|
||||||
except exception.NotFound:
|
except exception.NotFound:
|
||||||
msg = _('%s not found.' % self.resource_name.capitalize())
|
msg = _('%s not found.' % self.resource_name.capitalize())
|
||||||
raise exc.HTTPNotFound(explanation=msg)
|
raise exc.HTTPNotFound(explanation=msg)
|
||||||
|
@ -27,7 +27,7 @@ from manila.tests import db_utils
|
|||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class MetadataAPITest(test.TestCase):
|
class MetadataAPITest(test.TestCase):
|
||||||
|
|
||||||
def _get_request(self, version="2.65", use_admin_context=True):
|
def _get_request(self, version="2.65", use_admin_context=False):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v2/shares/{resource_id}/metadata',
|
'/v2/shares/{resource_id}/metadata',
|
||||||
version=version, use_admin_context=use_admin_context)
|
version=version, use_admin_context=use_admin_context)
|
||||||
@ -38,11 +38,49 @@ class MetadataAPITest(test.TestCase):
|
|||||||
self.controller = (
|
self.controller = (
|
||||||
metadata.MetadataController())
|
metadata.MetadataController())
|
||||||
self.controller.resource_name = 'share'
|
self.controller.resource_name = 'share'
|
||||||
self.admin_context = context.RequestContext('admin', 'fake', True)
|
|
||||||
self.mock_policy_check = self.mock_object(
|
self.mock_policy_check = self.mock_object(
|
||||||
policy, 'check_policy', mock.Mock(return_value=True))
|
policy, 'check_policy', mock.Mock(return_value=True))
|
||||||
self.resource = db_utils.create_share(size=1)
|
self.resource = db_utils.create_share(size=1)
|
||||||
|
|
||||||
|
def test__get_resource_policy_not_authorized_pubic_resource(self):
|
||||||
|
fake_context = context.RequestContext('fake', 'fake', True)
|
||||||
|
policy_exception = exception.PolicyNotAuthorized(action='share:get')
|
||||||
|
mock_policy_check = self.mock_object(
|
||||||
|
policy, 'check_policy', mock.Mock(side_effect=policy_exception))
|
||||||
|
share_obj = db_utils.create_share(size=1, is_public=True)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exception.PolicyNotAuthorized,
|
||||||
|
self.controller._get_resource,
|
||||||
|
fake_context,
|
||||||
|
share_obj['id'],
|
||||||
|
for_modification=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_policy_check.assert_called_once_with(
|
||||||
|
fake_context, 'share', 'get', mock.ANY)
|
||||||
|
policy_resource_obj = mock_policy_check.call_args[0][3]
|
||||||
|
self.assertEqual(share_obj['id'], policy_resource_obj['id'])
|
||||||
|
|
||||||
|
@ddt.data(True, False)
|
||||||
|
def test__get_resource_policy_not_authorized_private_resource(self, formd):
|
||||||
|
fake_context = context.RequestContext('fake', 'fake', True)
|
||||||
|
mock_policy_check = self.mock_object(
|
||||||
|
policy, 'check_policy', mock.Mock(return_value=False))
|
||||||
|
share_obj = db_utils.create_share(size=1, is_public=False)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
webob.exc.HTTPNotFound,
|
||||||
|
self.controller._get_resource,
|
||||||
|
fake_context,
|
||||||
|
share_obj['id'],
|
||||||
|
for_modification=formd,
|
||||||
|
)
|
||||||
|
mock_policy_check.assert_called_once_with(
|
||||||
|
fake_context, 'share', 'get', mock.ANY, do_raise=False)
|
||||||
|
policy_resource_obj = mock_policy_check.call_args[0][3]
|
||||||
|
self.assertEqual(share_obj['id'], policy_resource_obj['id'])
|
||||||
|
|
||||||
def test_create_index_metadata(self):
|
def test_create_index_metadata(self):
|
||||||
url = self._get_request()
|
url = self._get_request()
|
||||||
body = {'metadata': {'test_key1': 'test_v1', 'test_key2': 'test_v2'}}
|
body = {'metadata': {'test_key1': 'test_v1', 'test_key2': 'test_v2'}}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Metadata APIs have been fixed to respond with HTTP 404 / Not Found when
|
||||||
|
the requester does not have access to a resource that the metadata
|
||||||
|
pertains to.
|
Loading…
Reference in New Issue
Block a user