diff --git a/nova/policies/base.py b/nova/policies/base.py index b833fcd1a6ef..a8c71f557bef 100644 --- a/nova/policies/base.py +++ b/nova/policies/base.py @@ -16,9 +16,52 @@ RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner' RULE_ADMIN_API = 'rule:admin_api' RULE_ANY = '@' +# TODO(gmann): # Special string ``system_scope:all`` is added for system +# scoped policies for backwards compatibility where ``nova.conf [oslo_policy] +# enforce_scope = False``. +# Otherwise, this might open up APIs to be more permissive unintentionally if a +# deployment isn't enforcing scope. For example, the 'list all servers' +# policy will be System Scoped Reader with ``role:reader`` and +# scope_type=['system'] Until enforce_scope=True by default, it would +# be possible for users with the ``reader`` role on a project to access the +# 'list all servers' API. Once nova defaults ``nova.conf [oslo_policy] +# enforce_scope=True``, the ``system_scope:all`` bits of these check strings +# can be removed since that will be handled automatically by scope_types in +# oslo.policy's RuleDefault objects. +SYSTEM_ADMIN = 'rule:system_admin_api' +SYSTEM_READER = 'rule:system_reader_api' +PROJECT_MEMBER = 'rule:project_member_api' +PROJECT_READER = 'rule:project_reader_api' +PROJECT_MEMBER_OR_SYSTEM_ADMIN = 'rule:system_admin_or_owner' +PROJECT_READER_OR_SYSTEM_READER = 'rule:system_or_project_reader' + +# NOTE(gmann): Below is the mapping of new roles and scope_types +# with legacy roles:: + +# Legacy Rule | New Rules |Operation |scope_type| +# -------------------+----------------------------------+----------+----------- +# |-> SYSTEM_ADMIN |Global | [system] +# RULE_ADMIN_API | Write +# |-> SYSTEM_READER |Global | [system] +# | |Read | +# +# |-> PROJECT_MEMBER_OR_SYSTEM_ADMIN |Project | [system, +# RULE_ADMIN_OR_OWNER| |Write | project] +# |-> PROJECT_READER_OR_SYSTEM_READER|Project | [system, +# |Read | project] + # NOTE(johngarbutt) The base rules here affect so many APIs the list # of related API operations has not been populated. It would be # crazy hard to manually maintain such a list. + +# NOTE(gmann): Keystone already support implied roles means assignment +# of one role implies the assignment of another. New defaults roles +# `reader`, `member` also has been added in bootstrap. If the bootstrap +# process is re-run, and a `reader`, `member`, or `admin` role already +# exists, a role implication chain will be created: `admin` implies +# `member` implies `reader`. +# For example: If we give access to 'reader' it means the 'admin' and +# 'member' also get access. rules = [ policy.RuleDefault( "context_is_admin", @@ -31,7 +74,31 @@ rules = [ policy.RuleDefault( "admin_api", "is_admin:True", - "Default rule for most Admin APIs.") + "Default rule for most Admin APIs."), + policy.RuleDefault( + "system_admin_api", + 'role:admin and system_scope:all', + "Default rule for System Admin APIs."), + policy.RuleDefault( + "system_reader_api", + "role:reader and system_scope:all", + "Default rule for System level read only APIs."), + policy.RuleDefault( + "project_member_api", + "role:member and project_id:%(project_id)s", + "Default rule for Project level non admin APIs."), + policy.RuleDefault( + "project_reader_api", + "role:reader and project_id:%(project_id)s", + "Default rule for Project level read only APIs."), + policy.RuleDefault( + "system_admin_or_owner", + "rule:system_admin_api or rule:project_member_api", + "Default rule for System admin+owner APIs."), + policy.RuleDefault( + "system_or_project_reader", + "rule:system_reader_api or rule:project_reader_api", + "Default rule for System+Project read only APIs.") ] diff --git a/nova/tests/unit/test_policy.py b/nova/tests/unit/test_policy.py index ca5d387ba7ae..b88b10ea46f2 100644 --- a/nova/tests/unit/test_policy.py +++ b/nova/tests/unit/test_policy.py @@ -486,7 +486,10 @@ class RealRolePolicyTestCase(test.NoDBTestCase): # admin=True or quota_class match, this rule won't belong to # admin_only, non_admin, admin_or_user, empty_rule special_rules = ('admin_api', 'admin_or_owner', 'context_is_admin', - 'os_compute_api:os-quota-class-sets:show') + 'os_compute_api:os-quota-class-sets:show', + 'system_admin_api', 'system_reader_api', + 'project_member_api', 'project_reader_api', + 'system_admin_or_owner', 'system_or_project_reader') result = set(rules.keys()) - set(self.admin_only_rules + self.admin_or_owner_rules + self.allow_all_rules + special_rules)