diff options
-rw-r--r-- | nova/policies/base.py | 5 | ||||
-rw-r--r-- | nova/policies/server_groups.py | 21 | ||||
-rw-r--r-- | nova/tests/unit/policies/base.py | 2 | ||||
-rw-r--r-- | nova/tests/unit/policies/test_server_groups.py | 114 |
4 files changed, 123 insertions, 19 deletions
diff --git a/nova/policies/base.py b/nova/policies/base.py index 96b9d8e91a..c54848e3b5 100644 --- a/nova/policies/base.py +++ b/nova/policies/base.py @@ -115,7 +115,10 @@ rules = [ policy.RuleDefault( "project_member_api", "role:member and project_id:%(project_id)s", - "Default rule for Project level non admin APIs."), + "Default rule for Project level non admin APIs.", + deprecated_rule=DEPRECATED_ADMIN_OR_OWNER_POLICY, + deprecated_reason=DEPRECATED_REASON, + deprecated_since='21.0.0'), policy.RuleDefault( "project_reader_api", "role:reader and project_id:%(project_id)s", diff --git a/nova/policies/server_groups.py b/nova/policies/server_groups.py index e9b95d316d..55176b8a6a 100644 --- a/nova/policies/server_groups.py +++ b/nova/policies/server_groups.py @@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:os-server-groups:%s' server_groups_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'create', - check_str=base.RULE_ADMIN_OR_OWNER, + check_str=base.PROJECT_MEMBER, description="Create a new server group", operations=[ { @@ -32,11 +32,20 @@ server_groups_policies = [ 'method': 'POST' } ], - scope_types=['system', 'project'] + # (NOTE)gmann: Reason for 'project' only scope: + # POST SG need project_id to create the serve groups + # system scope members do not have project id for which + # SG needs to be created. + # If we allow system scope role also then created SG will have + # project_id of system role, not the one he/she wants to create the SG + # for (nobody can create the SG for other projects because API does + # not take project id in request ). So keeping this scoped to project + # only as these roles are the only ones who will be creating SG. + scope_types=['project'] ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete', - check_str=base.RULE_ADMIN_OR_OWNER, + check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, description="Delete a server group", operations=[ { @@ -48,7 +57,7 @@ server_groups_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str=base.RULE_ADMIN_OR_OWNER, + check_str=base.PROJECT_READER_OR_SYSTEM_READER, description="List all server groups", operations=[ { @@ -60,7 +69,7 @@ server_groups_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index:all_projects', - check_str=base.RULE_ADMIN_API, + check_str=base.SYSTEM_READER, description="List all server groups for all projects", operations=[ { @@ -72,7 +81,7 @@ server_groups_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show', - check_str=base.RULE_ADMIN_OR_OWNER, + check_str=base.PROJECT_READER_OR_SYSTEM_READER, description="Show details of a server group", operations=[ { diff --git a/nova/tests/unit/policies/base.py b/nova/tests/unit/policies/base.py index b0076e17c5..6825edffaa 100644 --- a/nova/tests/unit/policies/base.py +++ b/nova/tests/unit/policies/base.py @@ -114,6 +114,8 @@ class BasePolicyTest(test.TestCase): "role:admin and system_scope:all", "system_reader_api": "role:reader and system_scope:all", + "project_member_api": + "role:member and project_id:%(project_id)s", }) self.policy.set_rules(self.rules_without_deprecation, overwrite=False) diff --git a/nova/tests/unit/policies/test_server_groups.py b/nova/tests/unit/policies/test_server_groups.py index babdab3f75..73d8c0f12e 100644 --- a/nova/tests/unit/policies/test_server_groups.py +++ b/nova/tests/unit/policies/test_server_groups.py @@ -45,22 +45,35 @@ class ServerGroupPolicyTest(base.BasePolicyTest): user_id='u2', policies=[], members=[])] self.mock_get.return_value = self.sg[0] - # Check that admin or and owner is able to get and delete + # Check that admin or and owner is able to delete # the server group. self.admin_or_owner_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context, self.project_member_context, self.project_reader_context, self.project_foo_context] - # Check that non-admin/owner is not able to get and delete + # Check that non-admin/owner is not able to delete # the server group. self.admin_or_owner_unauthorized_contexts = [ self.system_member_context, self.system_reader_context, self.system_foo_context, self.other_project_member_context ] - - # Check that everyone is able to list and create - # theie own server group. + # Check that system reader or owner is able to get + # the server group. Due to old default everyone + # is allowed to perform this operation. + self.system_reader_or_owner_authorized_contexts = [ + self.legacy_admin_context, self.system_admin_context, + self.project_admin_context, self.project_member_context, + self.project_reader_context, self.system_member_context, + self.system_reader_context, self.project_foo_context + ] + self.system_reader_or_owner_unauthorized_contexts = [ + self.system_foo_context, + self.other_project_member_context + ] + # Check that everyone is able to list + # theie own server group. Due to old defaults everyone + # is able to list their server groups. self.everyone_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context, self.project_member_context, @@ -70,6 +83,16 @@ class ServerGroupPolicyTest(base.BasePolicyTest): self.other_project_member_context] self.everyone_unauthorized_contexts = [ ] + # Check that project member is able to create server group. + # Due to old defaults everyone is able to list their server groups. + self.project_member_authorized_contexts = [ + self.legacy_admin_context, self.system_admin_context, + self.project_admin_context, self.project_member_context, + self.system_member_context, self.project_reader_context, + self.project_foo_context, self.system_reader_context, + self.system_foo_context, + self.other_project_member_context] + self.project_member_unauthorized_contexts = [] @mock.patch('nova.objects.InstanceGroupList.get_by_project_id') def test_index_server_groups_policy(self, mock_get): @@ -105,19 +128,20 @@ class ServerGroupPolicyTest(base.BasePolicyTest): def test_show_server_groups_policy(self): rule_name = policies.POLICY_ROOT % 'show' - self.common_policy_check(self.admin_or_owner_authorized_contexts, - self.admin_or_owner_unauthorized_contexts, - rule_name, - self.controller.show, - self.req, uuids.fake_id) + self.common_policy_check( + self.system_reader_or_owner_authorized_contexts, + self.system_reader_or_owner_unauthorized_contexts, + rule_name, + self.controller.show, + self.req, uuids.fake_id) @mock.patch('nova.objects.Quotas.check_deltas') def test_create_server_groups_policy(self, mock_quota): rule_name = policies.POLICY_ROOT % 'create' body = {'server_group': {'name': 'fake', 'policies': ['affinity']}} - self.common_policy_check(self.everyone_authorized_contexts, - self.everyone_unauthorized_contexts, + self.common_policy_check(self.project_member_authorized_contexts, + self.project_member_unauthorized_contexts, rule_name, self.controller.create, self.req, body=body) @@ -146,6 +170,19 @@ class ServerGroupScopeTypePolicyTest(ServerGroupPolicyTest): super(ServerGroupScopeTypePolicyTest, self).setUp() self.flags(enforce_scope=True, group="oslo_policy") + # Check if project scoped can create the server group. + self.project_member_authorized_contexts = [ + self.legacy_admin_context, self.project_admin_context, + self.project_member_context, self.project_reader_context, + self.project_foo_context, + self.other_project_member_context + ] + # Check if non-project scoped cannot create the server group. + self.project_member_unauthorized_contexts = [ + self.system_admin_context, self.system_member_context, + self.system_reader_context, self.system_foo_context + ] + # TODO(gmann): Test this with system scope once we remove # the hardcoded admin check def test_index_all_project_server_groups_policy(self): @@ -158,3 +195,56 @@ class ServerGroupNoLegacyPolicyTest(ServerGroupScopeTypePolicyTest): access system APIs. """ without_deprecated_rules = True + + def setUp(self): + super(ServerGroupNoLegacyPolicyTest, self).setUp() + + # Check that system admin or and owner is able to delete + # the server group. + self.admin_or_owner_authorized_contexts = [ + self.system_admin_context, + self.project_admin_context, self.project_member_context, + ] + # Check that non-system admin/owner is not able to delete + # the server group. + self.admin_or_owner_unauthorized_contexts = [ + self.legacy_admin_context, self.system_member_context, + self.system_reader_context, self.system_foo_context, + self.project_reader_context, self.project_foo_context, + self.other_project_member_context + ] + # Check that system reader or owner is able to get + # the server group. + self.system_reader_or_owner_authorized_contexts = [ + self.system_admin_context, + self.project_admin_context, self.project_member_context, + self.project_reader_context, self.system_member_context, + self.system_reader_context + ] + self.system_reader_or_owner_unauthorized_contexts = [ + self.legacy_admin_context, self.system_foo_context, + self.other_project_member_context, self.project_foo_context + ] + self.everyone_authorized_contexts = [ + self.legacy_admin_context, self.system_admin_context, + self.project_admin_context, + self.project_member_context, self.project_reader_context, + self.system_member_context, self.system_reader_context, + self.other_project_member_context + ] + self.everyone_unauthorized_contexts = [ + self.project_foo_context, + self.system_foo_context + ] + # Check if project member can create the server group. + self.project_member_authorized_contexts = [ + self.legacy_admin_context, self.project_admin_context, + self.project_member_context, self.other_project_member_context + ] + # Check if non-project member cannot create the server group. + self.project_member_unauthorized_contexts = [ + self.system_admin_context, + self.system_member_context, self.system_reader_context, + self.system_foo_context, self.project_reader_context, + self.project_foo_context, + ] |