diff --git a/etc/nova/policy.json b/etc/nova/policy.json index d63934994b37..d2f9046b1010 100644 --- a/etc/nova/policy.json +++ b/etc/nova/policy.json @@ -33,7 +33,8 @@ "compute_extension:security_groups": [], "compute_extension:server_action_list": [["rule:admin_api"]], "compute_extension:server_diagnostics": [["rule:admin_api"]], - "compute_extension:simple_tenant_usage": [["rule:admin_api"]], + "compute_extension:simple_tenant_usage:show": [["rule:admin_or_owner"]], + "compute_extension:simple_tenant_usage:list": [["rule:admin_api"]], "compute_extension:users": [["rule:admin_api"]], "compute_extension:virtual_interfaces": [], "compute_extension:virtual_storage_arrays": [], diff --git a/nova/api/openstack/compute/contrib/simple_tenant_usage.py b/nova/api/openstack/compute/contrib/simple_tenant_usage.py index 576f37fd8142..eb32e9f08bb0 100644 --- a/nova/api/openstack/compute/contrib/simple_tenant_usage.py +++ b/nova/api/openstack/compute/contrib/simple_tenant_usage.py @@ -29,7 +29,10 @@ from nova import flags FLAGS = flags.FLAGS -authorize = extensions.extension_authorizer('compute', 'simple_tenant_usage') +authorize_show = extensions.extension_authorizer('compute', + 'simple_tenant_usage:show') +authorize_list = extensions.extension_authorizer('compute', + 'simple_tenant_usage:list') def make_usage(elem): @@ -110,8 +113,6 @@ class SimpleTenantUsageController(object): period_start, period_stop, tenant_id) - from nova import log as logging - logging.info(instances) rval = {} flavors = {} @@ -212,10 +213,8 @@ class SimpleTenantUsageController(object): def index(self, req): """Retrive tenant_usage for all tenants""" context = req.environ['nova.context'] - authorize(context) - if not context.is_admin: - return webob.Response(status_int=403) + authorize_list(context) (period_start, period_stop, detailed) = self._get_datetime_range(req) usages = self._tenant_usages_for_period(context, @@ -229,11 +228,8 @@ class SimpleTenantUsageController(object): """Retrive tenant_usage for a specified tenant""" tenant_id = id context = req.environ['nova.context'] - authorize(context) - if not context.is_admin: - if tenant_id != context.project_id: - return webob.Response(status_int=403) + authorize_show(context, {'project_id': tenant_id}) (period_start, period_stop, ignore) = self._get_datetime_range(req) usage = self._tenant_usages_for_period(context, diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py index bf415765c962..b40920f40f46 100644 --- a/nova/api/openstack/extensions.py +++ b/nova/api/openstack/extensions.py @@ -379,9 +379,11 @@ def load_standard_extensions(ext_mgr, logger, path, package): def extension_authorizer(api_name, extension_name): - def authorize(context): + def authorize(context, target=None): + if target == None: + target = {} action = '%s_extension:%s' % (api_name, extension_name) - nova.policy.enforce(context, action, {}) + nova.policy.enforce(context, action, target) return authorize diff --git a/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py b/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py index 60ec7b8bb64b..5e67c7b50bb4 100644 --- a/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py +++ b/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py @@ -22,6 +22,8 @@ from lxml import etree import webob from nova.api.openstack.compute.contrib import simple_tenant_usage +from nova import policy +from nova.common import policy as common_policy from nova.compute import api from nova import context from nova import flags @@ -133,18 +135,6 @@ class SimpleTenantUsageTest(test.TestCase): for j in xrange(SERVERS): self.assertEqual(int(servers[j]['hours']), HOURS) - def test_verify_index_fails_for_nonadmin(self): - req = webob.Request.blank( - '/v2/faketenant_0/os-simple-tenant-usage?' - 'detailed=1&start=%s&end=%s' % - (START.isoformat(), STOP.isoformat())) - req.method = "GET" - req.headers["content-type"] = "application/json" - - res = req.get_response(fakes.wsgi_app( - fake_auth_context=self.user_context)) - self.assertEqual(res.status_int, 403) - def test_verify_show(self): req = webob.Request.blank( '/v2/faketenant_0/os-simple-tenant-usage/' @@ -175,9 +165,18 @@ class SimpleTenantUsageTest(test.TestCase): req.method = "GET" req.headers["content-type"] = "application/json" - res = req.get_response(fakes.wsgi_app( - fake_auth_context=self.alt_user_context)) - self.assertEqual(res.status_int, 403) + rules = { + "compute_extension:simple_tenant_usage:show": + [["role:admin"], ["project_id:%(project_id)s"]] + } + common_policy.set_brain(common_policy.HttpBrain(rules)) + + try: + res = req.get_response(fakes.wsgi_app( + fake_auth_context=self.alt_user_context)) + self.assertEqual(res.status_int, 403) + finally: + policy.reset() class SimpleTenantUsageSerializerTest(test.TestCase): diff --git a/nova/tests/policy.json b/nova/tests/policy.json index 737e98f68f4a..c1497c99940c 100644 --- a/nova/tests/policy.json +++ b/nova/tests/policy.json @@ -92,7 +92,8 @@ "compute_extension:security_groups": [], "compute_extension:server_action_list": [], "compute_extension:server_diagnostics": [], - "compute_extension:simple_tenant_usage": [], + "compute_extension:simple_tenant_usage:show": [], + "compute_extension:simple_tenant_usage:list": [], "compute_extension:users": [], "compute_extension:virtual_interfaces": [], "compute_extension:virtual_storage_arrays": [],