diff --git a/nova/api/openstack/compute/limits.py b/nova/api/openstack/compute/limits.py index a6e9dd41907b..7b9016b972be 100644 --- a/nova/api/openstack/compute/limits.py +++ b/nova/api/openstack/compute/limits.py @@ -82,7 +82,8 @@ class LimitsController(wsgi.Controller): 'project_id': project_id, 'user_id': context.user_id } - context.can(limits_policies.USED_LIMIT_POLICY_NAME, target) + context.can(limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME, + target) quotas = QUOTAS.get_project_quotas(context, project_id, usages=True) diff --git a/nova/policies/limits.py b/nova/policies/limits.py index 43ae2ac785e4..39ee46397535 100644 --- a/nova/policies/limits.py +++ b/nova/policies/limits.py @@ -19,8 +19,17 @@ from nova.policies import base BASE_POLICY_NAME = 'os_compute_api:limits' -USED_LIMIT_POLICY_NAME = 'os_compute_api:os-used-limits' +OTHER_PROJECT_LIMIT_POLICY_NAME = 'os_compute_api:limits:other_project' +DEPRECATED_POLICY = policy.DeprecatedRule( + 'os_compute_api:os-used-limits', + base.RULE_ADMIN_API, +) +DEPRECATED_REASON = """ +Nova API policies are introducing new default roles with scope_type +capabilities. Old policies are deprecated and silently going to be ignored +in nova 23.0.0 release. +""" limits_policies = [ policy.DocumentedRuleDefault( @@ -35,12 +44,10 @@ limits_policies = [ } ], scope_types=['system', 'project']), - # TODO(aunnam): Remove this rule after we separate the scope check from - # policies, as this is only checking the scope. policy.DocumentedRuleDefault( - name=USED_LIMIT_POLICY_NAME, - check_str=base.RULE_ADMIN_API, - description="""Show rate and absolute limits for the project. + name=OTHER_PROJECT_LIMIT_POLICY_NAME, + check_str=base.SYSTEM_READER, + description="""Show rate and absolute limits of other project. This policy only checks if the user has access to the requested project limits. And this check is performed only after the check @@ -51,7 +58,10 @@ os_compute_api:limits passes""", 'path': '/limits' } ], - scope_types=['system']), + scope_types=['system'], + deprecated_rule=DEPRECATED_POLICY, + deprecated_reason=DEPRECATED_REASON, + deprecated_since='21.0.0'), ] diff --git a/nova/tests/unit/api/openstack/compute/test_limits.py b/nova/tests/unit/api/openstack/compute/test_limits.py index 123de77d5b38..ba479be378c7 100644 --- a/nova/tests/unit/api/openstack/compute/test_limits.py +++ b/nova/tests/unit/api/openstack/compute/test_limits.py @@ -214,8 +214,9 @@ class LimitsControllerTestV21(BaseLimitTestSuite): return_value={}) as mock_get_quotas: fake_req.get_response(self.controller) self.assertEqual(2, self.mock_can.call_count) - self.mock_can.assert_called_with(l_policies.USED_LIMIT_POLICY_NAME, - target) + self.mock_can.assert_called_with( + l_policies.OTHER_PROJECT_LIMIT_POLICY_NAME, + target) mock_get_quotas.assert_called_once_with(context, tenant_id, usages=True) diff --git a/nova/tests/unit/policies/test_limits.py b/nova/tests/unit/policies/test_limits.py index 3231339f49b4..8ff7667936b5 100644 --- a/nova/tests/unit/policies/test_limits.py +++ b/nova/tests/unit/policies/test_limits.py @@ -13,6 +13,7 @@ import mock from nova.api.openstack.compute import limits +from nova.policies import base as base_policy from nova.policies import limits as limits_policies from nova import quota from nova.tests.unit.api.openstack import fakes @@ -62,13 +63,18 @@ class LimitsPolicyTest(base.BasePolicyTest): self.project_foo_context, self.project_reader_context] self.everyone_unauthorized_contexts = [] - # Check that admin is able to get other projects limit. - self.admin_authorized_contexts = [ + # Check that system reader is able to get other projects limit. + # NOTE(gmann): Until old default rule which is admin_api is + # deprecated and not removed, project admin and legacy admin + # will be able to read the agent data. This make sure that existing + # tokens will keep working even we have changed this policy defaults + # to reader role. + self.reader_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, - self.project_admin_context] + self.project_admin_context, self.system_member_context, + self.system_reader_context] # Check that non-admin is not able to get other projects limit. - self.admin_unauthorized_contexts = [ - self.system_member_context, self.system_reader_context, + self.reader_unauthorized_contexts = [ self.system_foo_context, self.project_member_context, self.other_project_member_context, self.project_foo_context, self.project_reader_context @@ -83,9 +89,9 @@ class LimitsPolicyTest(base.BasePolicyTest): def test_get_other_limits_policy(self): req = fakes.HTTPRequest.blank('/?tenant_id=faketenant') - rule_name = limits_policies.USED_LIMIT_POLICY_NAME - self.common_policy_check(self.admin_authorized_contexts, - self.admin_unauthorized_contexts, + rule_name = limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME + self.common_policy_check(self.reader_authorized_contexts, + self.reader_unauthorized_contexts, rule_name, self.controller.index, req) @@ -105,15 +111,26 @@ class LimitsScopeTypePolicyTest(LimitsPolicyTest): super(LimitsScopeTypePolicyTest, self).setUp() self.flags(enforce_scope=True, group="oslo_policy") - # Check that system admin is able to get other projects limit. - self.admin_authorized_contexts = [ - self.system_admin_context] - # Check that non-system or non-admin is not able toget other + # Check that system reader is able to get other projects limit. + self.reader_authorized_contexts = [ + self.system_admin_context, self.system_member_context, + self.system_reader_context] + # Check that non-system reader is not able toget other # projects limit. - self.admin_unauthorized_contexts = [ - self.legacy_admin_context, self.system_member_context, - self.system_reader_context, self.system_foo_context, + self.reader_unauthorized_contexts = [ + self.legacy_admin_context, self.system_foo_context, self.project_admin_context, self.project_member_context, self.other_project_member_context, self.project_foo_context, self.project_reader_context ] + + +class LimitsNoLegacyPolicyTest(LimitsScopeTypePolicyTest): + """Test Limits APIs policies with system scope enabled, + and no more deprecated rules that allow the legacy admin API to + access system APIs. + """ + without_deprecated_rules = True + rules_without_deprecation = { + limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME: + base_policy.SYSTEM_READER} diff --git a/nova/tests/unit/test_policy.py b/nova/tests/unit/test_policy.py index 8ac81a744a7a..b89fd675d5dc 100644 --- a/nova/tests/unit/test_policy.py +++ b/nova/tests/unit/test_policy.py @@ -355,7 +355,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase): "os_compute_api:os-shelve:shelve_offload", "os_compute_api:os-simple-tenant-usage:list", "os_compute_api:os-availability-zone:detail", -"os_compute_api:os-used-limits", "os_compute_api:os-assisted-volume-snapshots:create", "os_compute_api:os-assisted-volume-snapshots:delete", "os_compute_api:os-console-auth-tokens", @@ -468,6 +467,7 @@ class RealRolePolicyTestCase(test.NoDBTestCase): "os_compute_api:os-hypervisors:uptime", "os_compute_api:os-hypervisors:search", "os_compute_api:os-hypervisors:servers", +"os_compute_api:limits:other_project", ) self.system_reader_or_owner_rules = (