summaryrefslogtreecommitdiff
path: root/nova/tests/unit/policies
diff options
context:
space:
mode:
Diffstat (limited to 'nova/tests/unit/policies')
-rw-r--r--nova/tests/unit/policies/base.py165
-rw-r--r--nova/tests/unit/policies/test_admin_actions.py75
-rw-r--r--nova/tests/unit/policies/test_admin_password.py77
-rw-r--r--nova/tests/unit/policies/test_aggregates.py157
-rw-r--r--nova/tests/unit/policies/test_assisted_volume_snapshots.py68
-rw-r--r--nova/tests/unit/policies/test_attach_interfaces.py158
-rw-r--r--nova/tests/unit/policies/test_availability_zone.py85
-rw-r--r--nova/tests/unit/policies/test_baremetal_nodes.py79
-rw-r--r--nova/tests/unit/policies/test_console_auth_tokens.py61
-rw-r--r--nova/tests/unit/policies/test_console_output.py73
-rw-r--r--nova/tests/unit/policies/test_create_backup.py77
-rw-r--r--nova/tests/unit/policies/test_deferred_delete.py95
-rw-r--r--nova/tests/unit/policies/test_evacuate.py63
-rw-r--r--nova/tests/unit/policies/test_extensions.py13
-rw-r--r--nova/tests/unit/policies/test_flavor_access.py165
-rw-r--r--nova/tests/unit/policies/test_flavor_extra_specs.py329
-rw-r--r--nova/tests/unit/policies/test_flavor_manage.py70
-rw-r--r--nova/tests/unit/policies/test_floating_ip_pools.py12
-rw-r--r--nova/tests/unit/policies/test_floating_ips.py194
-rw-r--r--nova/tests/unit/policies/test_hosts.py160
-rw-r--r--nova/tests/unit/policies/test_hypervisors.py130
-rw-r--r--nova/tests/unit/policies/test_instance_actions.py141
-rw-r--r--nova/tests/unit/policies/test_instance_usage_audit_log.py78
-rw-r--r--nova/tests/unit/policies/test_keypairs.py159
-rw-r--r--nova/tests/unit/policies/test_limits.py113
-rw-r--r--nova/tests/unit/policies/test_lock_server.py163
-rw-r--r--nova/tests/unit/policies/test_migrate_server.py92
-rw-r--r--nova/tests/unit/policies/test_migrations.py55
-rw-r--r--nova/tests/unit/policies/test_multinic.py91
-rw-r--r--nova/tests/unit/policies/test_networks.py71
-rw-r--r--nova/tests/unit/policies/test_pause_server.py86
-rw-r--r--nova/tests/unit/policies/test_quota_class_sets.py104
-rw-r--r--nova/tests/unit/policies/test_quota_sets.py205
-rw-r--r--nova/tests/unit/policies/test_remote_consoles.py73
-rw-r--r--nova/tests/unit/policies/test_rescue.py94
-rw-r--r--nova/tests/unit/policies/test_security_groups.py336
-rw-r--r--nova/tests/unit/policies/test_server_diagnostics.py77
-rw-r--r--nova/tests/unit/policies/test_server_external_events.py52
-rw-r--r--nova/tests/unit/policies/test_server_groups.py277
-rw-r--r--nova/tests/unit/policies/test_server_ips.py77
-rw-r--r--nova/tests/unit/policies/test_server_metadata.py155
-rw-r--r--nova/tests/unit/policies/test_server_migrations.py150
-rw-r--r--nova/tests/unit/policies/test_server_password.py129
-rw-r--r--nova/tests/unit/policies/test_server_tags.py150
-rw-r--r--nova/tests/unit/policies/test_server_topology.py103
-rw-r--r--nova/tests/unit/policies/test_servers.py864
-rw-r--r--nova/tests/unit/policies/test_services.py171
-rw-r--r--nova/tests/unit/policies/test_shelve.py128
-rw-r--r--nova/tests/unit/policies/test_simple_tenant_usage.py101
-rw-r--r--nova/tests/unit/policies/test_suspend_server.py89
-rw-r--r--nova/tests/unit/policies/test_tenant_networks.py80
-rw-r--r--nova/tests/unit/policies/test_volumes.py436
52 files changed, 3385 insertions, 3821 deletions
diff --git a/nova/tests/unit/policies/base.py b/nova/tests/unit/policies/base.py
index aff01d14f6..7490441d92 100644
--- a/nova/tests/unit/policies/base.py
+++ b/nova/tests/unit/policies/base.py
@@ -24,6 +24,23 @@ from nova.tests import fixtures
LOG = logging.getLogger(__name__)
+def rule_if_system(system_rule, non_system_rule, context):
+ """Helper function to pick a rule based on system-ness of context.
+
+ This can be used (with functools.partial) to choose between two
+ rule names, based on whether or not the context has system
+ scope. Specifically if we will fail the parent of a nested policy
+ check based on scope_types=['project'], this can be used to choose
+ the parent rule name for the error message check in
+ common_policy_check().
+
+ """
+ if context.system_scope:
+ return system_rule
+ else:
+ return non_system_rule
+
+
class BasePolicyTest(test.TestCase):
# NOTE(gmann): Set this flag to True if you would like to tests the
# new behaviour of policy without deprecated rules.
@@ -36,11 +53,21 @@ class BasePolicyTest(test.TestCase):
# For Example:
# rules_without_deprecation{
# "os_compute_api:os-deferred-delete:restore":
- # "rule:system_admin_or_owner"}
+ # "rule:project_admin_api"}
rules_without_deprecation = {}
def setUp(self):
super(BasePolicyTest, self).setUp()
+ # TODO(gmann): enforce_scope and enforce_new_defaults are enabled
+ # by default in the code so disable them in base test class until
+ # we have deprecated rules and their tests. We have enforce_scope
+ # and no-legacy tests which are explicitly enabling scope and new
+ # defaults to test the new defaults and scope. In future, once
+ # we remove the deprecated rules, along with refactoring the unit
+ # tests we can remove overriding the oslo policy flags.
+ self.flags(enforce_scope=False, group="oslo_policy")
+ if not self.without_deprecated_rules:
+ self.flags(enforce_new_defaults=False, group="oslo_policy")
self.useFixture(fixtures.NeutronFixture(self))
self.policy = self.useFixture(fixtures.RealPolicyFixture())
@@ -95,33 +122,135 @@ class BasePolicyTest(test.TestCase):
project_id=self.project_id_other,
roles=['reader'])
- self.all_contexts = [
+ self.all_contexts = set([
self.legacy_admin_context, self.system_admin_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.other_project_member_context,
self.project_foo_context, self.other_project_reader_context
- ]
+ ])
+
+ # All the project contexts for easy access.
+ self.all_project_contexts = set([
+ 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,
+ self.other_project_reader_context,
+ ])
+ # All the system contexts for easy access.
+ self.all_system_contexts = set([
+ self.system_admin_context, self.system_foo_context,
+ self.system_member_context, self.system_reader_context,
+ ])
+ # A few commmon set of contexts to be used in tests
+ #
+ # With scope disable and no legacy rule, any admin,
+ # project members have access. No other role in that project
+ # will have access.
+ self.project_member_or_admin_with_no_scope_no_legacy = set([
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ ])
+ # With scope enable and legacy rule, only project scoped admin
+ # and any role in that project will have access.
+ self.project_m_r_or_admin_with_scope_and_legacy = set([
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context, self.project_reader_context,
+ self.project_foo_context
+ ])
+ # With scope enable and no legacy rule, only project scoped admin
+ # and project members have access. No other role in that project
+ # or system scoped token will have access.
+ self.project_member_or_admin_with_scope_no_legacy = set([
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context
+ ])
+ # With scope disable and no legacy rule, any admin,
+ # project members, and project reader have access. No other
+ # role in that project will have access.
+ self.project_reader_or_admin_with_no_scope_no_legacy = set([
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context
+ ])
+ # With scope enable and no legacy rule, only project scoped admin,
+ # project members, and project reader have access. No other role
+ # in that project or system scoped token will have access.
+ self.project_reader_or_admin_with_scope_no_legacy = set([
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context, self.project_reader_context
+ ])
if self.without_deprecated_rules:
# To simulate the new world, remove deprecations by overriding
# rules which has the deprecated rules.
self.rules_without_deprecation.update({
- "system_admin_or_owner":
- "rule:system_admin_api or rule:project_member_api",
- "system_or_project_reader":
- "rule:system_reader_api or rule:project_reader_api",
- "system_admin_api":
- "role:admin and system_scope:all",
- "system_reader_api":
- "role:reader and system_scope:all",
+ "context_is_admin":
+ "role:admin",
+ "project_reader_or_admin":
+ "rule:project_reader_api or rule:context_is_admin",
+ "project_admin_api":
+ "role:admin and project_id:%(project_id)s",
"project_member_api":
"role:member and project_id:%(project_id)s",
+ "project_reader_api":
+ "role:reader and project_id:%(project_id)s",
+ "project_member_or_admin":
+ "rule:project_member_api or rule:context_is_admin",
+ "project_reader_or_admin":
+ "rule:project_reader_api or rule:context_is_admin",
})
self.policy.set_rules(self.rules_without_deprecation,
overwrite=False)
+ def reduce_set(self, name, new_set):
+ """Reduce a named set of contexts in a subclass.
+
+ This removes things from a set in a child test class by taking
+ a new set, but asserts that no *new* contexts are added over
+ what is defined in the parent.
+
+ :param name: The name of a set of contexts on self
+ (i.e. 'project' for self.project_contexts
+ :param new_set: The new set of contexts that should be used in
+ the above set. The new_set is asserted to be a
+ perfect subset of the existing set
+ """
+ current = getattr(self, '%s_contexts' % name)
+
+ errors = ','.join(x.user_id for x in new_set - current)
+ self.assertEqual('', errors,
+ 'Attempt to reduce set would add %s' % errors)
+
+ LOG.info('%s.%s_contexts: removing %s',
+ self.__class__.__name__,
+ name,
+ ','.join(x.user_id for x in current - new_set))
+ setattr(self, '%s_contexts' % name, new_set)
+
+ def common_policy_auth(self, authorized_contexts,
+ rule_name,
+ func, req, *arg, **kwarg):
+ """Check a policy rule against a set of authorized contexts.
+
+ This is exactly like common_policy_check, except that it
+ assumes any contexts not in the authorized set are in the
+ unauthorized set.
+ """
+ # The unauthorized users are any not in the authorized set.
+ unauth = list(set(self.all_contexts) - set(authorized_contexts))
+ # In case a set was passed in, convert to list for stable ordering.
+ authorized_contexts = list(authorized_contexts)
+ # Log both sets in the order we will test them to aid debugging of
+ # fatal=False responses.
+ LOG.info('Authorized users: %s', list(
+ x.user_id for x in authorized_contexts))
+ LOG.info('Unauthorized users: %s', list(x.user_id for x in unauth))
+ return self.common_policy_check(authorized_contexts, unauth,
+ rule_name, func, req, *arg, **kwarg)
+
def common_policy_check(self, authorized_contexts,
unauthorized_contexts, rule_name,
func, req, *arg, **kwarg):
@@ -146,15 +275,25 @@ class BasePolicyTest(test.TestCase):
def ensure_raises(req, *args, **kwargs):
exc = self.assertRaises(
exception.PolicyNotAuthorized, func, req, *arg, **kwarg)
+ # NOTE(danms): We may need to check a different rule_name
+ # as the enforced policy, based on the context we are
+ # using. Examples are multi-policy APIs for similar
+ # reasons as below. If we are passed a function for
+ # rule_name, call it with the context being used to
+ # determine the rule_name we should verify.
+ if callable(rule_name):
+ actual_rule_name = rule_name(req.environ['nova.context'])
+ else:
+ actual_rule_name = rule_name
# NOTE(gmann): In case of multi-policy APIs, PolicyNotAuthorized
# exception can be raised from either of the policy so checking
# the error message, which includes the rule name, can mismatch.
# Tests verifying the multi policy can pass rule_name as None
# to skip the error message assert.
- if rule_name is not None:
+ if actual_rule_name is not None:
self.assertEqual(
"Policy doesn't allow %s to be performed." %
- rule_name, exc.format_message())
+ actual_rule_name, exc.format_message())
# Verify all the context having allowed scope and roles pass
# the policy check.
for context in authorized_contexts:
diff --git a/nova/tests/unit/policies/test_admin_actions.py b/nova/tests/unit/policies/test_admin_actions.py
index c5522616ff..21157fd832 100644
--- a/nova/tests/unit/policies/test_admin_actions.py
+++ b/nova/tests/unit/policies/test_admin_actions.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -40,40 +41,42 @@ class AdminActionsPolicyTest(base.BasePolicyTest):
uuid = uuids.fake_id
self.instance = fake_instance.fake_instance_obj(
self.project_member_context,
- id=1, uuid=uuid, vm_state=vm_states.ACTIVE,
- task_state=None, launched_at=timeutils.utcnow())
+ id=1, uuid=uuid, project_id=self.project_id,
+ vm_state=vm_states.ACTIVE, task_state=None,
+ launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin is able to change the service
- self.admin_authorized_contexts = [
+ # By default, legacy rule are enable and scope check is disabled.
+ # system admin, legacy admin, and project admin is able to perform
+ # server admin actions
+ self.project_action_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to change the service
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
@mock.patch('nova.objects.Instance.save')
def test_reset_state_policy(self, mock_save):
rule_name = "os_compute_api:os-admin-actions:reset_state"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._reset_state,
- self.req, self.instance.uuid,
- body={'os-resetState': {'state': 'active'}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name, self.controller._reset_state,
+ self.req, self.instance.uuid,
+ body={'os-resetState': {'state': 'active'}})
def test_inject_network_info_policy(self):
rule_name = "os_compute_api:os-admin-actions:inject_network_info"
with mock.patch.object(self.controller.compute_api,
"inject_network_info"):
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller._inject_network_info,
- self.req, self.instance.uuid, body={})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._inject_network_info,
+ self.req, self.instance.uuid, body={})
+
+
+class AdminActionsNoLegacyNoScopePolicyTest(AdminActionsPolicyTest):
+ """Test Admin Actions APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
class AdminActionsScopeTypePolicyTest(AdminActionsPolicyTest):
@@ -90,27 +93,15 @@ class AdminActionsScopeTypePolicyTest(AdminActionsPolicyTest):
def setUp(self):
super(AdminActionsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope enable, system admin will not be able to
+ # perform server admin actions.
+ self.project_action_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class AdminActionsNoLegacyPolicyTest(AdminActionsScopeTypePolicyTest):
+class AdminActionsScopeTypeNoLegacyPolicyTest(AdminActionsScopeTypePolicyTest):
"""Test Admin Actions APIs policies with system scope enabled,
- and no more deprecated rules.
+ and no more deprecated rules which means scope + new defaults so
+ only project admin is able to perform admin action on their server.
"""
without_deprecated_rules = True
-
- def setUp(self):
- super(AdminActionsScopeTypePolicyTest, self).setUp()
- # Check that system admin is able to perform the system level actions
- # on server.
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system or non-admin is not able to perform the system
- # level actions on server.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
diff --git a/nova/tests/unit/policies/test_admin_password.py b/nova/tests/unit/policies/test_admin_password.py
index b733f83e5d..01cce2950e 100644
--- a/nova/tests/unit/policies/test_admin_password.py
+++ b/nova/tests/unit/policies/test_admin_password.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -47,28 +48,23 @@ class AdminPasswordPolicyTest(base.BasePolicyTest):
user_id=user_id, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or and server owner is able to change the password
- self.admin_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to change
+ # the password for their server.
+ self.project_action_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 is not able to change the password
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.compute.api.API.set_admin_password')
def test_change_paassword_policy(self, mock_password):
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- self.rule_name,
- self.controller.change_password,
- self.req, self.instance.uuid,
- body={'changePassword': {
- 'adminPass': '1234pass'}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ self.rule_name,
+ self.controller.change_password,
+ self.req, self.instance.uuid,
+ body={'changePassword': {
+ 'adminPass': '1234pass'}})
def test_change_password_overridden_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -93,6 +89,22 @@ class AdminPasswordPolicyTest(base.BasePolicyTest):
mock.ANY, '1234pass')
+class AdminPasswordNoLegacyNoScopePolicyTest(AdminPasswordPolicyTest):
+ """Test Admin Password APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(AdminPasswordNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to change the server password.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+
+
class AdminPasswordScopeTypePolicyTest(AdminPasswordPolicyTest):
"""Test Admin Password APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -106,31 +118,24 @@ class AdminPasswordScopeTypePolicyTest(AdminPasswordPolicyTest):
def setUp(self):
super(AdminPasswordScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin to change password.
+ self.project_action_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class AdminPasswordNoLegacyPolicyTest(AdminPasswordPolicyTest):
+class AdminPasswordScopeTypeNoLegacyTest(AdminPasswordScopeTypePolicyTest):
"""Test Admin Password APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules which means scope + new defaults so
+ only project admin and member is able to change their server password.
"""
+
without_deprecated_rules = True
def setUp(self):
- super(AdminPasswordNoLegacyPolicyTest, self).setUp()
+ super(AdminPasswordScopeTypeNoLegacyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system or projct admin or owner is able to change
- # the password.
- self.admin_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context]
- # Check that non-system and non-admin/owner is not able to change the
- # password.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_reader_context,
- self.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ # With scope enable and no legacy rule only project admin/member
+ # will be able to change password for the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_aggregates.py b/nova/tests/unit/policies/test_aggregates.py
index ce3c00f30b..6ac7b6e010 100644
--- a/nova/tests/unit/policies/test_aggregates.py
+++ b/nova/tests/unit/policies/test_aggregates.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import aggregates
@@ -31,39 +32,19 @@ class AggregatesPolicyTest(base.BasePolicyTest):
super(AggregatesPolicyTest, self).setUp()
self.controller = aggregates.AggregateController()
self.req = fakes.HTTPRequest.blank('')
- # Check that admin is able to perform Aggregate Operations
- self.admin_authorized_contexts = [
+ # With legacy rule and scope check disabled by default, system admin,
+ # legacy admin, and project admin will be able to perform Aggregate
+ # Operations.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to perform Aggregate Operations
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
- # Check that system reader is able to get Aggregate
- self.system_reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-admin is not able to get Aggregate
- self.system_reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
@mock.patch('nova.compute.api.AggregateAPI.get_aggregate_list')
def test_list_aggregate_policy(self, mock_list):
rule_name = "os_compute_api:os-aggregates:index"
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
@mock.patch('nova.compute.api.AggregateAPI.create_aggregate')
def test_create_aggregate_policy(self, mock_create):
@@ -74,66 +55,59 @@ class AggregatesPolicyTest(base.BasePolicyTest):
"hosts": ["host1", "host2"]})
body = {"aggregate": {"name": "test",
"availability_zone": "nova1"}}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ self.req, body=body)
@mock.patch('nova.compute.api.AggregateAPI.update_aggregate')
def test_update_aggregate_policy(self, mock_update):
rule_name = "os_compute_api:os-aggregates:update"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.update,
- self.req, 1,
- body={"aggregate": {"name": "new_name"}})
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.update,
+ self.req, 1,
+ body={"aggregate": {"name": "new_name"}})
@mock.patch('nova.compute.api.AggregateAPI.delete_aggregate')
def test_delete_aggregate_policy(self, mock_delete):
rule_name = "os_compute_api:os-aggregates:delete"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, 1)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ self.req, 1)
@mock.patch('nova.compute.api.AggregateAPI.get_aggregate')
def test_show_aggregate_policy(self, mock_show):
rule_name = "os_compute_api:os-aggregates:show"
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, 1)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, 1)
@mock.patch('nova.compute.api.AggregateAPI.update_aggregate_metadata')
def test_set_metadata_aggregate_policy(self, mock_metadata):
rule_name = "os_compute_api:os-aggregates:set_metadata"
body = {"set_metadata": {"metadata": {"foo": "bar"}}}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller._set_metadata,
- self.req, 1, body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller._set_metadata,
+ self.req, 1, body=body)
@mock.patch('nova.compute.api.AggregateAPI.add_host_to_aggregate')
def test_add_host_aggregate_policy(self, mock_add):
rule_name = "os_compute_api:os-aggregates:add_host"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._add_host,
- self.req, 1,
- body={"add_host": {"host": "host1"}})
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller._add_host,
+ self.req, 1,
+ body={"add_host": {"host": "host1"}})
@mock.patch('nova.compute.api.AggregateAPI.remove_host_from_aggregate')
def test_remove_host_aggregate_policy(self, mock_remove):
rule_name = "os_compute_api:os-aggregates:remove_host"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller._remove_host,
- self.req, 1,
- body={"remove_host": {"host": "host1"}})
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller._remove_host,
+ self.req, 1,
+ body={"remove_host": {"host": "host1"}})
@mock.patch('nova.compute.api.AggregateAPI.get_aggregate')
def test_images_aggregate_policy(self, mock_get):
@@ -144,10 +118,21 @@ class AggregatesPolicyTest(base.BasePolicyTest):
body = {'cache': [{'id': uuids.fake_id}]}
req = fakes.HTTPRequest.blank('', version='2.81')
with mock.patch('nova.conductor.api.ComputeTaskAPI.cache_images'):
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.images,
- req, 1, body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.images,
+ req, 1, body=body)
+
+
+class AggregatesNoLegacyNoScopePolicyTest(AggregatesPolicyTest):
+ """Test Aggregates APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only. In this case
+ system admin, legacy admin, and project admin will be able to
+ perform Aggregate Operations. Legacy admin will be allowed as policy
+ is just admin if no scope checks.
+
+ """
+
+ without_deprecated_rules = True
class AggregatesScopeTypePolicyTest(AggregatesPolicyTest):
@@ -164,28 +149,16 @@ class AggregatesScopeTypePolicyTest(AggregatesPolicyTest):
super(AggregatesScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to perform Aggregate Operations.
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system or non-admin is not able to perform
- # Aggregate Operations.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
- # Check that system reader is able to get Aggregate
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-admin is not able to get Aggregate
- self.system_reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
+ # With scope checks enabled, only project-scoped admins are
+ # able to perform Aggregate Operations.
+ self.project_admin_authorized_contexts = [self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class AggregatesScopeTypeNoLegacyPolicyTest(AggregatesScopeTypePolicyTest):
+ """Test Aggregates APIs policies with no legacy deprecated rules
+ and scope checks enabled which means scope + new defaults so
+ only system admin is able to perform aggregates Operations.
+ """
+
+ without_deprecated_rules = True
diff --git a/nova/tests/unit/policies/test_assisted_volume_snapshots.py b/nova/tests/unit/policies/test_assisted_volume_snapshots.py
index 3c9836e07b..dce62e5bcc 100644
--- a/nova/tests/unit/policies/test_assisted_volume_snapshots.py
+++ b/nova/tests/unit/policies/test_assisted_volume_snapshots.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_serialization import jsonutils
from oslo_utils.fixture import uuidsentinel as uuids
import urllib
@@ -32,18 +33,12 @@ class AssistedVolumeSnapshotPolicyTest(base.BasePolicyTest):
super(AssistedVolumeSnapshotPolicyTest, self).setUp()
self.controller = snapshots.AssistedVolumeSnapshotsController()
self.req = fakes.HTTPRequest.blank('')
- # Check that admin is able to take volume snapshot.
- self.admin_authorized_contexts = [
+ # By default, legacy rule are enable and scope check is disabled.
+ # system admin, legacy admin, and project admin is able to
+ # take volume snapshot.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to take volume snapshot.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
@mock.patch('nova.compute.api.API.volume_snapshot_create')
def test_assisted_create_policy(self, mock_create):
@@ -52,10 +47,9 @@ class AssistedVolumeSnapshotPolicyTest(base.BasePolicyTest):
'create_info': {'type': 'qcow2',
'new_file': 'new_file',
'snapshot_id': 'snapshot_id'}}}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.create,
+ self.req, body=body)
@mock.patch('nova.compute.api.API.volume_snapshot_delete')
def test_assisted_delete_policy(self, mock_delete):
@@ -64,11 +58,20 @@ class AssistedVolumeSnapshotPolicyTest(base.BasePolicyTest):
'delete_info': jsonutils.dumps({'volume_id': '1'}),
}
req = fakes.HTTPRequest.blank('?%s' % urllib.parse.urlencode(params))
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- req, 1)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ req, 1)
+
+
+class AssistedSnapshotNoLegacyNoScopePolicyTest(
+ AssistedVolumeSnapshotPolicyTest):
+ """Test Assisted Snapshot APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
class AssistedSnapshotScopeTypePolicyTest(AssistedVolumeSnapshotPolicyTest):
@@ -85,16 +88,15 @@ class AssistedSnapshotScopeTypePolicyTest(AssistedVolumeSnapshotPolicyTest):
super(AssistedSnapshotScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to take volume snapshot.
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system or non-admin is not able to take volume
- # snapshot.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
+ # With scope check enabled, system admin is not able to
+ # take volume snapshot.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+
+
+class AssistedSnapshotScopeTypeNoLegacyPolicyTest(
+ AssistedSnapshotScopeTypePolicyTest):
+ """Test os-volume-attachments APIs policies with system scope enabled,
+ and no legacy deprecated rules.
+ """
+ without_deprecated_rules = True
diff --git a/nova/tests/unit/policies/test_attach_interfaces.py b/nova/tests/unit/policies/test_attach_interfaces.py
index 05f62d5cf0..33c531c9c7 100644
--- a/nova/tests/unit/policies/test_attach_interfaces.py
+++ b/nova/tests/unit/policies/test_attach_interfaces.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -47,40 +48,25 @@ class AttachInterfacesPolicyTest(base.BasePolicyTest):
vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- self.admin_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.project_foo_context,
- self.project_reader_context, self.project_member_context
- ]
-
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
-
- self.reader_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to attach,
+ # detach an interface from a server.
+ self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_member_context, self.project_foo_context
- ]
-
- self.reader_unauthorized_contexts = [
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context, self.project_foo_context]
+ # and they can get their own server attached interfaces.
+ self.project_reader_authorized_contexts = (
+ self.project_member_authorized_contexts)
@mock.patch('nova.compute.api.API.get')
@mock.patch('nova.network.neutron.API.list_ports')
def test_index_interfaces_policy(self, mock_port, mock_get):
rule_name = "os_compute_api:os-attach-interfaces:list"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req, uuids.fake_id)
@mock.patch('nova.compute.api.API.get')
@mock.patch('nova.network.neutron.API.show_port')
@@ -97,11 +83,10 @@ class AttachInterfacesPolicyTest(base.BasePolicyTest):
"fixed_ips": ["10.0.2.2"],
"device_id": server_id,
}}
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, server_id, port_id)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, server_id, port_id)
@mock.patch('nova.compute.api.API.get')
@mock.patch('nova.api.openstack.compute.attach_interfaces'
@@ -110,19 +95,43 @@ class AttachInterfacesPolicyTest(base.BasePolicyTest):
def test_attach_interface(self, mock_interface, mock_port, mock_get):
rule_name = "os_compute_api:os-attach-interfaces:create"
body = {'interfaceAttachment': {'net_id': uuids.fake_id}}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.create,
- self.req, uuids.fake_id, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller.create,
+ self.req, uuids.fake_id, body=body)
@mock.patch('nova.compute.api.API.get')
@mock.patch('nova.compute.api.API.detach_interface')
def test_delete_interface(self, mock_detach, mock_get):
rule_name = "os_compute_api:os-attach-interfaces:delete"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.delete,
- self.req, uuids.fake_id, uuids.fake_id)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller.delete,
+ self.req, uuids.fake_id, uuids.fake_id)
+
+
+class AttachInterfacesNoLegacyNoScopePolicyTest(AttachInterfacesPolicyTest):
+ """Test Attach Interfaces APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ ai_policies.POLICY_ROOT % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ ai_policies.POLICY_ROOT % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ ai_policies.POLICY_ROOT % 'create':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ ai_policies.POLICY_ROOT % 'delete':
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
+
+ def setUp(self):
+ super(AttachInterfacesNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, legacy admin loose power.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
class AttachInterfacesScopeTypePolicyTest(AttachInterfacesPolicyTest):
@@ -138,6 +147,11 @@ class AttachInterfacesScopeTypePolicyTest(AttachInterfacesPolicyTest):
def setUp(self):
super(AttachInterfacesScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With Scope enable, system users no longer allowed.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
class AttachInterfacesDeprecatedPolicyTest(base.BasePolicyTest):
@@ -173,12 +187,12 @@ class AttachInterfacesDeprecatedPolicyTest(base.BasePolicyTest):
@mock.patch('nova.network.neutron.API.list_ports')
def test_deprecated_policy_overridden_rule_is_checked(self, mock_port,
mock_get):
- # Test to verify if deprecatd overridden policy is working.
+ # Test to verify if deprecated overridden policy is working.
# check for success as admin role. Deprecated rule
# has been overridden with admin checks in policy.yaml
# If admin role pass it means overridden rule is enforced by
- # olso.policy because new default is system or project reader and the
+ # oslo.policy because new default is system or project reader and the
# old default is admin.
self.controller.index(self.admin_req, uuids.fake_id)
@@ -192,55 +206,27 @@ class AttachInterfacesDeprecatedPolicyTest(base.BasePolicyTest):
exc.format_message())
-class AttachInterfacesNoLegacyPolicyTest(AttachInterfacesPolicyTest):
+class AttachInterfacesScopeTypeNoLegacyPolicyTest(
+ AttachInterfacesScopeTypePolicyTest):
"""Test Attach Interfaces APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
ai_policies.POLICY_ROOT % 'list':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
ai_policies.POLICY_ROOT % 'show':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
ai_policies.POLICY_ROOT % 'create':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
ai_policies.POLICY_ROOT % 'delete':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
def setUp(self):
- super(AttachInterfacesNoLegacyPolicyTest, self).setUp()
- self.flags(enforce_scope=True, group="oslo_policy")
-
- # Check that system or projct admin or owner is able to
- # create or delete interfaces.
- self.admin_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context]
- # Check that non-system and non-admin/owner is not able to
- # create or delete interfaces.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_reader_context,
- self.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
-
- # Check that system reader or projct is able to
- # create or delete interfaces.
- self.reader_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_member_context
- ]
-
- # Check that non-system reader nd non-admin/owner is not able to
- # create or delete interfaces.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ super(AttachInterfacesScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With no legacy and scope enable, only project admin, member,
+ # and reader will be able to allowed operation on server interface.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_availability_zone.py b/nova/tests/unit/policies/test_availability_zone.py
index 454692fde8..1852f8444c 100644
--- a/nova/tests/unit/policies/test_availability_zone.py
+++ b/nova/tests/unit/policies/test_availability_zone.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import availability_zone
from nova.tests.unit.api.openstack import fakes
@@ -31,49 +31,38 @@ class AvailabilityZonePolicyTest(base.BasePolicyTest):
self.controller = availability_zone.AvailabilityZoneController()
self.req = fakes.HTTPRequest.blank('')
- # Check that everyone is able to list the AZ
- self.everyone_authorized_contexts = [
+ # With legacy rule and scope check disabled by default, system admin,
+ # legacy admin, and project admin will be able to get AZ with host
+ # information.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_member_context, self.other_project_member_context,
- self.project_foo_context, self.project_reader_context,
- self.other_project_reader_context,
- ]
- self.everyone_unauthorized_contexts = []
-
- # Check that system reader is able to list the AZ Detail
- # NOTE(gmann): Until old default rule which is admin_api is
- # deprecated and not removed, project admin and legacy admin
- # will be able to list the AZ. This make sure that existing
- # tokens will keep working even we have changed this policy defaults
- # to reader role.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.legacy_admin_context,
self.project_admin_context]
- # Check that non-system-reader are not able to list the AZ.
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context,
- self.other_project_reader_context,
- ]
+ self.project_authorized_contexts = self.all_contexts
@mock.patch('nova.objects.Instance.save')
def test_availability_zone_list_policy(self, mock_save):
rule_name = "os_compute_api:os-availability-zone:list"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
def test_availability_zone_detail_policy(self):
rule_name = "os_compute_api:os-availability-zone:detail"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.detail,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.detail,
+ self.req)
+
+
+class AvailabilityZoneNoLegacyNoScopePolicyTest(AvailabilityZonePolicyTest):
+ """Test Availability Zones APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only. In this case
+ system admin, legacy admin, and project admin will be able to get
+ AZ with host information. Legacy admin will be allowed as policy
+ is just admin if no scope checks.
+
+ """
+
+ without_deprecated_rules = True
class AvailabilityZoneScopeTypePolicyTest(AvailabilityZonePolicyTest):
@@ -91,15 +80,17 @@ class AvailabilityZoneScopeTypePolicyTest(AvailabilityZonePolicyTest):
super(AvailabilityZoneScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system reader is able to list the AZ.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system-reader is not able to list AZ.
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.legacy_admin_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.project_foo_context, self.project_reader_context,
- self.other_project_reader_context,
- ]
+ # With scope checks enable, only project-scoped admins are
+ # able to get AZ with host information.
+ self.project_admin_authorized_contexts = [self.legacy_admin_context,
+ self.project_admin_context]
+ self.project_authorized_contexts = self.all_project_contexts
+
+
+class AZScopeTypeNoLegacyPolicyTest(AvailabilityZoneScopeTypePolicyTest):
+ """Test Availability Zones APIs policies with no legacy deprecated rules
+ and scope checks enabled which means scope + new defaults so
+ only system admin is able to get AZ with host information.
+ """
+
+ without_deprecated_rules = True
diff --git a/nova/tests/unit/policies/test_baremetal_nodes.py b/nova/tests/unit/policies/test_baremetal_nodes.py
index 77e6def26d..68f02087c4 100644
--- a/nova/tests/unit/policies/test_baremetal_nodes.py
+++ b/nova/tests/unit/policies/test_baremetal_nodes.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import baremetal_nodes
@@ -40,25 +41,17 @@ class BaremetalNodesPolicyTest(base.BasePolicyTest):
self.stub_out('nova.api.openstack.compute.'
'baremetal_nodes._get_ironic_client',
lambda *_: FAKE_IRONIC_CLIENT)
- # Check that system reader is able to get baremetal nodes.
- self.system_reader_authorized_contexts = [
+ # With legacy rule and scope check disabled by default, system admin,
+ # legacy admin, and project admin will be able to get baremetal nodes.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system-reader is not able to get baremetal nodes.
- self.system_reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.project_foo_context, self.project_reader_context,
- self.other_project_reader_context
- ]
+ self.project_admin_context]
def test_index_nodes_policy(self):
rule_name = "os_compute_api:os-baremetal-nodes:list"
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
@mock.patch.object(FAKE_IRONIC_CLIENT.node, 'list_ports')
@mock.patch.object(FAKE_IRONIC_CLIENT.node, 'get')
@@ -69,11 +62,22 @@ class BaremetalNodesPolicyTest(base.BasePolicyTest):
mock_get.return_value = node
mock_port.return_value = []
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, uuids.fake_id)
+
+
+class BaremetalNodesNoLegacyNoScopePolicyTest(BaremetalNodesPolicyTest):
+ """Test Baremetal Nodes APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only. In that case
+ system admin, legacy admin, and project admin will be able to get
+ Baremetal nodes Legacy admin will be allowed as policy is just admin if
+ no scope checks.
+
+ """
+
+ without_deprecated_rules = True
class BaremetalNodesScopeTypePolicyTest(BaremetalNodesPolicyTest):
@@ -91,28 +95,21 @@ class BaremetalNodesScopeTypePolicyTest(BaremetalNodesPolicyTest):
super(BaremetalNodesScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system reader is able to get baremetal nodes.
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system or non-reader is not able to get
- # baremetal nodes.
- self.system_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,
- self.other_project_reader_context
- ]
-
-
-class BaremetalNodesNoLegacyPolicyTest(BaremetalNodesScopeTypePolicyTest):
- """Test Baremetal Nodes APIs policies with system scope enabled,
- and no more deprecated rules.
+ # With scope checks enable, only project-scoped admins are
+ # able to get baremetal nodes.
+ self.project_admin_authorized_contexts = [self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class BNScopeTypeNoLegacyPolicyTest(BaremetalNodesScopeTypePolicyTest):
+ """Test Baremetal Nodes APIs policies with no legacy deprecated rules
+ and scope checks enabled which means scope + new defaults so
+ only system admin is able to get baremetal nodes.
"""
+
without_deprecated_rules = True
rules_without_deprecation = {
policies.BASE_POLICY_NAME % 'list':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
policies.BASE_POLICY_NAME % 'show':
- base_policy.SYSTEM_READER}
+ base_policy.ADMIN}
diff --git a/nova/tests/unit/policies/test_console_auth_tokens.py b/nova/tests/unit/policies/test_console_auth_tokens.py
index 27dbd59540..a658816538 100644
--- a/nova/tests/unit/policies/test_console_auth_tokens.py
+++ b/nova/tests/unit/policies/test_console_auth_tokens.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import console_auth_tokens
from nova.tests.unit.api.openstack import fakes
@@ -31,33 +31,29 @@ class ConsoleAuthTokensPolicyTest(base.BasePolicyTest):
self.controller = console_auth_tokens.ConsoleAuthTokensController()
self.req = fakes.HTTPRequest.blank('', version='2.31')
- # Check that system reader is able to get console connection
- # information.
+ # With legacy rule, any admin can get console connection
# NOTE(gmann): Until old default rule which is admin_api is
# deprecated and not removed, project admin and legacy admin
# will be able to get console. This make sure that existing
- # tokens will keep working even we have changed this policy defaults
- # to reader role.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.legacy_admin_context,
+ # tokens will keep working.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to get console connection
- # information.
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.objects.ConsoleAuthToken.validate')
def test_console_connect_info_token_policy(self, mock_validate):
rule_name = "os_compute_api:os-console-auth-tokens"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, fakes.FAKE_UUID)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, fakes.FAKE_UUID)
+
+
+class ConsoleAuthTokensNoLegacyNoScopeTest(ConsoleAuthTokensPolicyTest):
+ """Test Console Auth Tokens API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
class ConsoleAuthTokensScopeTypePolicyTest(ConsoleAuthTokensPolicyTest):
@@ -75,17 +71,14 @@ class ConsoleAuthTokensScopeTypePolicyTest(ConsoleAuthTokensPolicyTest):
super(ConsoleAuthTokensScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system reader is able to get console connection
- # information.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system-reader is not able to get console connection
- # information.
- 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,
- self.other_project_reader_context,
- ]
+ # With scope enabled, system admin is not allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+
+
+class ConsoleAuthTokensScopeTypeNoLegacyPolicyTest(
+ ConsoleAuthTokensScopeTypePolicyTest):
+ """Test Console Auth Tokens APIs policies with system scope enabled,
+ and no more deprecated rules.
+ """
+ without_deprecated_rules = True
diff --git a/nova/tests/unit/policies/test_console_output.py b/nova/tests/unit/policies/test_console_output.py
index 3c16f5c1fa..c1bccf1d55 100644
--- a/nova/tests/unit/policies/test_console_output.py
+++ b/nova/tests/unit/policies/test_console_output.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -43,30 +44,37 @@ class ConsoleOutputPolicyTest(base.BasePolicyTest):
id=1, uuid=uuid, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or owner is able to get the server console.
- self.admin_authorized_contexts = [
+ # With legacy rule, any admin and role in project
+ # can get the server console.
+ self.project_member_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 and non-owner is not able to get the server
- # console.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_reader_context, self.project_foo_context]
@mock.patch('nova.compute.api.API.get_console_output')
def test_console_output_policy(self, mock_console):
mock_console.return_value = '\n'.join([str(i) for i in range(2)])
rule_name = "os_compute_api:os-console-output"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.get_console_output,
- self.req, self.instance.uuid,
- body={'os-getConsoleOutput': {}})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller.get_console_output,
+ self.req, self.instance.uuid,
+ body={'os-getConsoleOutput': {}})
+
+
+class ConsoleOutputNoLegacyNoScopePolicyTest(ConsoleOutputPolicyTest):
+ """Test Server Console Output APIs policies with no legacy deprecated
+ rule and no scope check.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(ConsoleOutputNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member is able to
+ # get the server console.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
class ConsoleOutputScopeTypePolicyTest(ConsoleOutputPolicyTest):
@@ -83,31 +91,22 @@ class ConsoleOutputScopeTypePolicyTest(ConsoleOutputPolicyTest):
def setUp(self):
super(ConsoleOutputScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class ConsoleOutputNoLegacyPolicyTest(ConsoleOutputPolicyTest):
+class ConsoleOutputScopeTypeNoLegacyPolicyTest(
+ ConsoleOutputScopeTypePolicyTest):
"""Test Console Output APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
- super(ConsoleOutputNoLegacyPolicyTest, self).setUp()
- self.flags(enforce_scope=True, group="oslo_policy")
+ super(ConsoleOutputScopeTypeNoLegacyPolicyTest, self).setUp()
- # Check that system or projct admin or owner is able to
- # get the server console.
- self.admin_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context]
- # Check that non-system and non-admin/owner is not able to
+ # With scope enable and no legacy rule, only project admin/member can
# get the server console.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_reader_context,
- self.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_create_backup.py b/nova/tests/unit/policies/test_create_backup.py
index 4985119201..b54ed366df 100644
--- a/nova/tests/unit/policies/test_create_backup.py
+++ b/nova/tests/unit/policies/test_create_backup.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -43,20 +44,14 @@ class CreateBackupPolicyTest(base.BasePolicyTest):
id=1, uuid=uuid, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or owner is able to create server backup.
- self.admin_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to create
+ # server backup.
+ self.project_member_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 and non-owner is not able to create server
- # backup.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_reader_context, self.project_foo_context]
@mock.patch('nova.compute.api.API.backup')
def test_create_backup_policy(self, mock_backup):
@@ -68,11 +63,26 @@ class CreateBackupPolicyTest(base.BasePolicyTest):
'rotation': 1,
},
}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._create_backup,
- self.req, self.instance.uuid,
- body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller._create_backup,
+ self.req, self.instance.uuid,
+ body=body)
+
+
+class CreateBackupNoLegacyNoScopePolicyTest(CreateBackupPolicyTest):
+ """Test Create Backup server APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(CreateBackupNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to create the server backup.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
class CreateBackupScopeTypePolicyTest(CreateBackupPolicyTest):
@@ -89,31 +99,20 @@ class CreateBackupScopeTypePolicyTest(CreateBackupPolicyTest):
def setUp(self):
super(CreateBackupScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system users to create the server.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class CreateBackupNoLegacyPolicyTest(CreateBackupPolicyTest):
+class CreateBackupScopeTypeNoLegacyPolicyTest(CreateBackupScopeTypePolicyTest):
"""Test Create Backup APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
- super(CreateBackupNoLegacyPolicyTest, self).setUp()
- self.flags(enforce_scope=True, group="oslo_policy")
-
- # Check that system or projct admin or owner is able to create
- # server backup.
- self.admin_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context]
- # Check that non-system and non-admin/owner is not able to
- # create server backup.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_reader_context,
- self.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ super(CreateBackupScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enable and no legacy rule, only project admin/member
+ # will be able to create the server backup.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_deferred_delete.py b/nova/tests/unit/policies/test_deferred_delete.py
index ca2253df54..08bb0213f4 100644
--- a/nova/tests/unit/policies/test_deferred_delete.py
+++ b/nova/tests/unit/policies/test_deferred_delete.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -47,37 +48,29 @@ class DeferredDeletePolicyTest(base.BasePolicyTest):
id=1, uuid=uuid, user_id=user_id, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or owner is able to force delete or restore server.
- self.admin_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to force
+ # delete or restore server.
+ self.project_member_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 and non-owner is not able to force delete or
- # restore server.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_reader_context, self.project_foo_context]
@mock.patch('nova.compute.api.API.restore')
def test_restore_server_policy(self, mock_restore):
rule_name = dd_policies.BASE_POLICY_NAME % 'restore'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._restore,
- self.req, self.instance.uuid,
- body={'restore': {}})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller._restore,
+ self.req, self.instance.uuid,
+ body={'restore': {}})
def test_force_delete_server_policy(self):
rule_name = dd_policies.BASE_POLICY_NAME % 'force'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._force_delete,
- self.req, self.instance.uuid,
- body={'forceDelete': {}})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller._force_delete,
+ self.req, self.instance.uuid,
+ body={'forceDelete': {}})
def test_force_delete_server_policy_failed_with_other_user(self):
rule_name = dd_policies.BASE_POLICY_NAME % 'force'
@@ -103,6 +96,27 @@ class DeferredDeletePolicyTest(base.BasePolicyTest):
self.req.environ['nova.context'], self.instance)
+class DeferredDeleteNoLegacyNoScopePolicyTest(DeferredDeletePolicyTest):
+ """Test Deferred Delete server APIs policies with no legacy deprecated
+ rule and no scope check.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ dd_policies.BASE_POLICY_NAME % 'restore':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ dd_policies.BASE_POLICY_NAME % 'force':
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
+
+ def setUp(self):
+ super(DeferredDeleteNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member is able to force
+ # delete or restore server.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+
+
class DeferredDeleteScopeTypePolicyTest(DeferredDeletePolicyTest):
"""Test Deferred Delete APIs policies with system scope enabled.
@@ -117,36 +131,27 @@ class DeferredDeleteScopeTypePolicyTest(DeferredDeletePolicyTest):
def setUp(self):
super(DeferredDeleteScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class DeferredDeleteNoLegacyPolicyTest(DeferredDeletePolicyTest):
+class DeferredDeleteScopeTypeNoLegacyPolicyTest(
+ DeferredDeleteScopeTypePolicyTest):
"""Test Deferred Delete APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
dd_policies.BASE_POLICY_NAME % 'restore':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
dd_policies.BASE_POLICY_NAME % 'force':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
def setUp(self):
- super(DeferredDeleteNoLegacyPolicyTest, self).setUp()
+ super(DeferredDeleteScopeTypeNoLegacyPolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
-
- # Check that system or projct admin or owner is able to
- # force delete or restore server.
- self.admin_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context]
- # Check that non-system and non-admin/owner is not able to
- # force delete or restore server.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_reader_context,
- self.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ # With scope enable and no legacy rule, only project admin/member is
+ # able to force delete or restore server.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_evacuate.py b/nova/tests/unit/policies/test_evacuate.py
index 203cc136e9..b9e4c29dba 100644
--- a/nova/tests/unit/policies/test_evacuate.py
+++ b/nova/tests/unit/policies/test_evacuate.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -55,18 +56,12 @@ class EvacuatePolicyTest(base.BasePolicyTest):
id=1, uuid=uuid, user_id=user_id, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin is able to evacuate the server
- self.admin_authorized_contexts = [
+ # By default, legacy rule are enable and scope check is disabled.
+ # system admin, legacy admin, and project admin is able to evacuate
+ # the server.
+ self.project_action_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to evacuate the server
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
@mock.patch('nova.compute.api.API.evacuate')
def test_evacuate_policy(self, mock_evacuate):
@@ -75,11 +70,10 @@ class EvacuatePolicyTest(base.BasePolicyTest):
'onSharedStorage': 'False',
'adminPass': 'admin_pass'}
}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._evacuate,
- self.req, uuids.fake_id,
- body=body)
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name, self.controller._evacuate,
+ self.req, uuids.fake_id,
+ body=body)
def test_evacuate_policy_failed_with_other_user(self):
rule_name = "os_compute_api:os-evacuate"
@@ -109,7 +103,16 @@ class EvacuatePolicyTest(base.BasePolicyTest):
evacuate_mock.assert_called_once_with(
self.user_req.environ['nova.context'],
mock.ANY, 'my-host', False,
- 'MyNewPass', None)
+ 'MyNewPass', None, None)
+
+
+class EvacuateNoLegacyNoScopePolicyTest(EvacuatePolicyTest):
+ """Test Evacuate APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
class EvacuateScopeTypePolicyTest(EvacuatePolicyTest):
@@ -126,28 +129,14 @@ class EvacuateScopeTypePolicyTest(EvacuatePolicyTest):
def setUp(self):
super(EvacuateScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope enable, system admin will not be able to
+ # evacuate the server.
+ self.project_action_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class EvacuateNoLegacyPolicyTest(EvacuateScopeTypePolicyTest):
+class EvacuateScopeTypeNoLegacyPolicyTest(EvacuateScopeTypePolicyTest):
"""Test Evacuate APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system APIs.
+ and no more deprecated rules which means scope + new defaults.
"""
without_deprecated_rules = True
-
- def setUp(self):
- super(EvacuateNoLegacyPolicyTest, self).setUp()
-
- # Check that system admin is able to evacuate server.
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system or non-admin is not able to evacuate
- # server.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
diff --git a/nova/tests/unit/policies/test_extensions.py b/nova/tests/unit/policies/test_extensions.py
index 35f451087d..d2e3c6adde 100644
--- a/nova/tests/unit/policies/test_extensions.py
+++ b/nova/tests/unit/policies/test_extensions.py
@@ -71,11 +71,20 @@ class ExtensionsScopeTypePolicyTest(ExtensionsPolicyTest):
def setUp(self):
super(ExtensionsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ self.everyone_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_reader_context,
+ self.other_project_member_context
+ ]
+ self.everyone_unauthorized_contexts = [
+ self.system_admin_context, self.system_member_context,
+ self.system_reader_context, self.system_foo_context]
class ExtensionsNoLegacyPolicyTest(ExtensionsScopeTypePolicyTest):
"""Test Extensions APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
diff --git a/nova/tests/unit/policies/test_flavor_access.py b/nova/tests/unit/policies/test_flavor_access.py
index 46d9368c4b..cfdbbd2470 100644
--- a/nova/tests/unit/policies/test_flavor_access.py
+++ b/nova/tests/unit/policies/test_flavor_access.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import flavor_access
@@ -49,62 +50,61 @@ class FlavorAccessPolicyTest(base.BasePolicyTest):
self.stub_out('nova.objects.flavor._get_projects_from_db',
lambda context, flavorid: [])
- # Check that admin is able to add/remove flavor access
- # to a tenant.
+ # With legacy rule and no scope checks, all admin is able to
+ # add/remove flavor access to a tenant.
self.admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to add/remove flavor access
- # to a tenant.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
- # Check that everyone is able to list flavor access
- # information which is nothing but bug#1867840.
- self.reader_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,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
- self.reader_unauthorized_contexts = [
- ]
+ # With legacy rule, anyone can access flavor access info.
+ self.admin_index_authorized_contexts = self.all_contexts
def test_list_flavor_access_policy(self):
rule_name = fa_policy.BASE_POLICY_NAME
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller_index.index,
- self.req, '1')
+ self.common_policy_auth(self.admin_index_authorized_contexts,
+ rule_name, self.controller_index.index,
+ self.req, '1')
@mock.patch('nova.objects.Flavor.add_access')
def test_add_tenant_access_policy(self, mock_add):
rule_name = fa_policy.POLICY_ROOT % "add_tenant_access"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller._add_tenant_access,
- self.req, '1',
- body={'addTenantAccess': {'tenant': 't1'}})
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller._add_tenant_access,
+ self.req, '1',
+ body={'addTenantAccess': {'tenant': 't1'}})
@mock.patch('nova.objects.Flavor.remove_access')
def test_remove_tenant_access_policy(self, mock_remove):
rule_name = fa_policy.POLICY_ROOT % "remove_tenant_access"
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller._remove_tenant_access,
- self.req, '1',
- body={'removeTenantAccess': {'tenant': 't1'}})
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller._remove_tenant_access,
+ self.req, '1',
+ body={'removeTenantAccess': {'tenant': 't1'}})
+
+
+class FlavorAccessNoLegacyNoScopeTest(FlavorAccessPolicyTest):
+ """Test Flavor Access API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ fa_policy.POLICY_ROOT % "add_tenant_access":
+ base_policy.ADMIN,
+ fa_policy.POLICY_ROOT % "remove_tenant_access":
+ base_policy.ADMIN,
+ fa_policy.BASE_POLICY_NAME:
+ base_policy.ADMIN}
+
+ def setUp(self):
+ super(FlavorAccessNoLegacyNoScopeTest, self).setUp()
+
+ # with no legacy rule means all admin is able to list access info.
+ self.admin_index_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context]
class FlavorAccessScopeTypePolicyTest(FlavorAccessPolicyTest):
@@ -122,81 +122,32 @@ class FlavorAccessScopeTypePolicyTest(FlavorAccessPolicyTest):
super(FlavorAccessScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to add/remove flavor access
- # to a tenant.
+ # Scope checks remove system users' power.
self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system-admin is not able to add/remove flavor access
- # to a tenant.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
- # Check that system user is able to list flavor access
- # information.
- self.reader_authorized_contexts = [
- self.system_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context]
- # Check that non-system is not able to list flavor access
- # information.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.other_project_member_context,
- self.project_admin_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_reader_context,
- ]
-
-
-class FlavorAccessNoLegacyPolicyTest(FlavorAccessPolicyTest):
+ self.legacy_admin_context,
+ self.project_admin_context]
+ self.admin_index_authorized_contexts = self.all_project_contexts
+
+
+class FlavorAccessScopeTypeNoLegacyPolicyTest(FlavorAccessScopeTypePolicyTest):
"""Test FlavorAccess APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_redear APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
fa_policy.POLICY_ROOT % "add_tenant_access":
- base_policy.SYSTEM_ADMIN,
+ base_policy.ADMIN,
fa_policy.POLICY_ROOT % "remove_tenant_access":
- base_policy.SYSTEM_ADMIN,
+ base_policy.ADMIN,
fa_policy.BASE_POLICY_NAME:
- base_policy.SYSTEM_READER}
+ base_policy.ADMIN}
def setUp(self):
- super(FlavorAccessNoLegacyPolicyTest, self).setUp()
+ super(FlavorAccessScopeTypeNoLegacyPolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to add/remove flavor access
- # to a tenant.
+ # New defaults make this admin-only
self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system-admin is not able to add/remove flavor access
- # to a tenant.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
- # Check that system reader is able to list flavor access
- # information.
- self.reader_authorized_contexts = [
- self.system_admin_context,
- self.system_member_context, self.system_reader_context]
- # Check that non-system-reader is not able to list flavor access
- # information.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.other_project_member_context,
- self.project_admin_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.system_foo_context,
- self.other_project_reader_context,
- ]
+ self.legacy_admin_context,
+ self.project_admin_context]
+ self.admin_index_authorized_contexts = self.admin_authorized_contexts
diff --git a/nova/tests/unit/policies/test_flavor_extra_specs.py b/nova/tests/unit/policies/test_flavor_extra_specs.py
index 3129cb6213..f3c8cacd57 100644
--- a/nova/tests/unit/policies/test_flavor_extra_specs.py
+++ b/nova/tests/unit/policies/test_flavor_extra_specs.py
@@ -10,22 +10,17 @@
# License for the specific language governing permissions and limitations
# under the License.
-import fixtures
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import flavor_manage
from nova.api.openstack.compute import flavors
from nova.api.openstack.compute import flavors_extraspecs
-from nova.api.openstack.compute import servers
-from nova.compute import vm_states
-from nova import objects
from nova.policies import flavor_extra_specs as policies
from nova.policies import flavor_manage as fm_policies
-from nova.policies import servers as s_policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit import fake_flavor
-from nova.tests.unit import fake_instance
from nova.tests.unit.policies import base
@@ -42,30 +37,7 @@ class FlavorExtraSpecsPolicyTest(base.BasePolicyTest):
self.controller = flavors_extraspecs.FlavorExtraSpecsController()
self.flavor_ctrl = flavors.FlavorsController()
self.fm_ctrl = flavor_manage.FlavorManageController()
- self.server_ctrl = servers.ServersController()
self.req = fakes.HTTPRequest.blank('')
- self.server_ctrl._view_builder._add_security_grps = mock.MagicMock()
- self.server_ctrl._view_builder._get_metadata = mock.MagicMock()
- self.server_ctrl._view_builder._get_addresses = mock.MagicMock()
- self.server_ctrl._view_builder._get_host_id = mock.MagicMock()
- self.server_ctrl._view_builder._get_fault = mock.MagicMock()
- self.server_ctrl._view_builder._add_host_status = mock.MagicMock()
-
- self.instance = fake_instance.fake_instance_obj(
- self.project_member_context,
- id=1, uuid=uuids.fake_id, project_id=self.project_id,
- vm_state=vm_states.ACTIVE)
-
- self.mock_get = self.useFixture(
- fixtures.MockPatch('nova.api.openstack.common.get_instance')).mock
- self.mock_get.return_value = self.instance
-
- fakes.stub_out_secgroup_api(
- self, security_groups=[{'name': 'default'}])
- self.mock_get_all = self.useFixture(fixtures.MockPatchObject(
- self.server_ctrl.compute_api, 'get_all')).mock
- self.mock_get_all.return_value = objects.InstanceList(
- objects=[self.instance])
def get_flavor_extra_specs(context, flavor_id):
return fake_flavor.fake_flavor_obj(
@@ -77,99 +49,72 @@ class FlavorExtraSpecsPolicyTest(base.BasePolicyTest):
self.stub_out('nova.api.openstack.common.get_flavor',
get_flavor_extra_specs)
- # Check that all are able to get flavor extra specs.
- self.all_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,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- self.all_unauthorized_contexts = []
- # Check that all system scoped are able to get flavor extra specs.
- self.all_system_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,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- self.all_system_unauthorized_contexts = []
-
- # Check that admin is able to create, update and delete flavor
- # extra specs.
- self.admin_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context]
- # Check that non-admin is not able to create, update and
- # delete flavor extra specs.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
+ # In the base/legacy case, all project and system contexts are
+ # authorized in the "anyone" case.
+ self.all_authorized_contexts = (self.all_project_contexts |
+ self.all_system_contexts)
+
+ # In the base/legacy case, all project and system contexts are
+ # authorized in the case of things that distinguish between
+ # scopes, since scope checking is disabled.
+ self.all_project_authorized_contexts = (self.all_project_contexts |
+ self.all_system_contexts)
+
+ # In the base/legacy case, any admin is an admin.
+ self.admin_authorized_contexts = set([self.project_admin_context,
+ self.system_admin_context,
+ self.legacy_admin_context])
@mock.patch('nova.objects.Flavor.save')
def test_create_flavor_extra_specs_policy(self, mock_save):
body = {'extra_specs': {'hw:numa_nodes': '1'}}
rule_name = policies.POLICY_ROOT % 'create'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.create,
- self.req, '1234',
- body=body)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ self.req, '1234',
+ body=body)
@mock.patch('nova.objects.Flavor._flavor_extra_specs_del')
@mock.patch('nova.objects.Flavor.save')
def test_delete_flavor_extra_specs_policy(self, mock_save, mock_delete):
rule_name = policies.POLICY_ROOT % 'delete'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, '1234', 'hw:cpu_policy')
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ self.req, '1234', 'hw:cpu_policy')
@mock.patch('nova.objects.Flavor.save')
def test_update_flavor_extra_specs_policy(self, mock_save):
body = {'hw:cpu_policy': 'shared'}
rule_name = policies.POLICY_ROOT % 'update'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.update,
- self.req, '1234', 'hw:cpu_policy',
- body=body)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller.update,
+ self.req, '1234', 'hw:cpu_policy',
+ body=body)
def test_show_flavor_extra_specs_policy(self):
rule_name = policies.POLICY_ROOT % 'show'
- self.common_policy_check(self.all_authorized_contexts,
- self.all_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, '1234',
- 'hw:cpu_policy')
+ self.common_policy_auth(self.all_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, '1234',
+ 'hw:cpu_policy')
def test_index_flavor_extra_specs_policy(self):
rule_name = policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.all_authorized_contexts,
- self.all_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req, '1234')
+ self.common_policy_auth(self.all_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req, '1234')
def test_flavor_detail_with_extra_specs_policy(self):
fakes.stub_out_flavor_get_all(self)
rule_name = policies.POLICY_ROOT % 'index'
req = fakes.HTTPRequest.blank('', version='2.61')
- authorize_res, unauthorize_res = self.common_policy_check(
- self.all_authorized_contexts, self.all_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.all_authorized_contexts,
rule_name, self.flavor_ctrl.detail, req,
fatal=False)
for resp in authorize_res:
@@ -181,8 +126,8 @@ class FlavorExtraSpecsPolicyTest(base.BasePolicyTest):
fakes.stub_out_flavor_get_by_flavor_id(self)
rule_name = policies.POLICY_ROOT % 'index'
req = fakes.HTTPRequest.blank('', version='2.61')
- authorize_res, unauthorize_res = self.common_policy_check(
- self.all_authorized_contexts, self.all_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.all_authorized_contexts,
rule_name, self.flavor_ctrl.show, req, '1',
fatal=False)
for resp in authorize_res:
@@ -221,9 +166,8 @@ class FlavorExtraSpecsPolicyTest(base.BasePolicyTest):
"disk": 1,
}
}
- authorize_res, unauthorize_res = self.common_policy_check(
- self.all_system_authorized_contexts,
- self.all_system_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.all_project_authorized_contexts,
rule_name, self.fm_ctrl._create, req, body=body,
fatal=False)
for resp in authorize_res:
@@ -242,9 +186,8 @@ class FlavorExtraSpecsPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.61')
- authorize_res, unauthorize_res = self.common_policy_check(
- self.all_system_authorized_contexts,
- self.all_system_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.all_project_authorized_contexts,
rule_name, self.fm_ctrl._update, req, '1',
body={'flavor': {'description': None}},
fatal=False)
@@ -253,88 +196,6 @@ class FlavorExtraSpecsPolicyTest(base.BasePolicyTest):
for resp in unauthorize_res:
self.assertNotIn('extra_specs', resp['flavor'])
- def test_server_detail_with_extra_specs_policy(self):
- rule = s_policies.SERVERS % 'detail'
- # server 'detail' policy is checked before flavor extra specs 'index'
- # policy so we have to allow it for everyone otherwise it will fail
- # first for unauthorized contexts.
- self.policy.set_rules({rule: "@"}, overwrite=False)
- req = fakes.HTTPRequest.blank('', version='2.47')
- rule_name = policies.POLICY_ROOT % 'index'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.all_authorized_contexts, self.all_unauthorized_contexts,
- rule_name, self.server_ctrl.detail, req,
- fatal=False)
- for resp in authorize_res:
- self.assertIn('extra_specs', resp['servers'][0]['flavor'])
- for resp in unauthorize_res:
- self.assertNotIn('extra_specs', resp['servers'][0]['flavor'])
-
- @mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
- @mock.patch('nova.compute.api.API.get_instance_host_status')
- def test_server_show_with_extra_specs_policy(self, mock_get, mock_block):
- rule = s_policies.SERVERS % 'show'
- # server 'show' policy is checked before flavor extra specs 'index'
- # policy so we have to allow it for everyone otherwise it will fail
- # first for unauthorized contexts.
- self.policy.set_rules({rule: "@"}, overwrite=False)
- req = fakes.HTTPRequest.blank('', version='2.47')
- rule_name = policies.POLICY_ROOT % 'index'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.all_authorized_contexts,
- self.all_unauthorized_contexts,
- rule_name, self.server_ctrl.show, req, 'fake',
- fatal=False)
- for resp in authorize_res:
- self.assertIn('extra_specs', resp['server']['flavor'])
- for resp in unauthorize_res:
- self.assertNotIn('extra_specs', resp['server']['flavor'])
-
- @mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
- @mock.patch('nova.compute.api.API.get_instance_host_status')
- @mock.patch('nova.compute.api.API.rebuild')
- def test_server_rebuild_with_extra_specs_policy(self, mock_rebuild,
- mock_get, mock_bdm):
- rule = s_policies.SERVERS % 'rebuild'
- # server 'rebuild' policy is checked before flavor extra specs 'index'
- # policy so we have to allow it for everyone otherwise it will fail
- # first for unauthorized contexts.
- self.policy.set_rules({rule: "@"}, overwrite=False)
- req = fakes.HTTPRequest.blank('', version='2.47')
- rule_name = policies.POLICY_ROOT % 'index'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.all_authorized_contexts,
- self.all_unauthorized_contexts,
- rule_name, self.server_ctrl._action_rebuild,
- req, self.instance.uuid,
- body={'rebuild': {"imageRef": uuids.fake_id}},
- fatal=False)
- for resp in authorize_res:
- self.assertIn('extra_specs', resp.obj['server']['flavor'])
- for resp in unauthorize_res:
- self.assertNotIn('extra_specs', resp.obj['server']['flavor'])
-
- @mock.patch('nova.compute.api.API.update_instance')
- def test_server_update_with_extra_specs_policy(self, mock_update):
- rule = s_policies.SERVERS % 'update'
- # server 'update' policy is checked before flavor extra specs 'index'
- # policy so we have to allow it for everyone otherwise it will fail
- # first for unauthorized contexts.
- self.policy.set_rules({rule: "@"}, overwrite=False)
- req = fakes.HTTPRequest.blank('', version='2.47')
- rule_name = policies.POLICY_ROOT % 'index'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.all_authorized_contexts,
- self.all_unauthorized_contexts,
- rule_name, self.server_ctrl.update,
- req, self.instance.uuid,
- body={'server': {'name': 'test'}},
- fatal=False)
- for resp in authorize_res:
- self.assertIn('extra_specs', resp['server']['flavor'])
- for resp in unauthorize_res:
- self.assertNotIn('extra_specs', resp['server']['flavor'])
-
class FlavorExtraSpecsScopeTypePolicyTest(FlavorExtraSpecsPolicyTest):
"""Test Flavor Extra Specs APIs policies with system scope enabled.
@@ -350,65 +211,53 @@ class FlavorExtraSpecsScopeTypePolicyTest(FlavorExtraSpecsPolicyTest):
super(FlavorExtraSpecsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that all system scoped are able to get flavor extra specs.
- self.all_system_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context
- ]
- self.all_system_unauthorized_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,
- self.other_project_reader_context
- ]
- # Check that system admin is able to create, update and delete flavor
- # extra specs.
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system admin is not able to create, update and
- # delete flavor extra specs.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
+ # Only project users are authorized
+ self.reduce_set('all_project_authorized', self.all_project_contexts)
+ self.reduce_set('all_authorized', self.all_project_contexts)
+
+ # Only admins can do admin things
+ self.admin_authorized_contexts = [self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class FlavorExtraSpecsNoLegacyNoScopeTest(FlavorExtraSpecsPolicyTest):
+ """Test Flavor Extra Specs API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(FlavorExtraSpecsNoLegacyNoScopeTest, self).setUp()
+
+ # Disabling legacy rules means that random roles no longer
+ # have power, but without scope checking there is no
+ # difference between project and system
+ everything_but_foo = (
+ self.all_project_contexts | self.all_system_contexts) - set([
+ self.system_foo_context,
+ self.project_foo_context,
+ ])
+ self.reduce_set('all_project_authorized', everything_but_foo)
+ self.reduce_set('all_authorized', everything_but_foo)
class FlavorExtraSpecsNoLegacyPolicyTest(FlavorExtraSpecsScopeTypePolicyTest):
"""Test Flavor Extra Specs APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
super(FlavorExtraSpecsNoLegacyPolicyTest, self).setUp()
- # Check that system or project reader are able to get flavor
- # extra specs.
- self.all_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.other_project_reader_context
- ]
- self.all_unauthorized_contexts = [
- self.project_foo_context, self.system_foo_context
- ]
- # Check that all system scoped reader are able to get flavor
- # extra specs.
- self.all_system_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context
- ]
- self.all_system_unauthorized_contexts = [
- self.legacy_admin_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
+ # Non-legacy rules do not imply random roles have any
+ # access. Same note as above, regarding other_project_*
+ # contexts. With scope checking enabled, project and system
+ # contexts stay separate.
+ self.reduce_set(
+ 'all_project_authorized',
+ self.all_project_contexts - set([self.project_foo_context]))
+ everything_but_foo_and_system = (
+ self.all_contexts - set([
+ self.project_foo_context,
+ ]) - self.all_system_contexts)
+ self.reduce_set('all_authorized', everything_but_foo_and_system)
diff --git a/nova/tests/unit/policies/test_flavor_manage.py b/nova/tests/unit/policies/test_flavor_manage.py
index 8a890a85af..0663a689cb 100644
--- a/nova/tests/unit/policies/test_flavor_manage.py
+++ b/nova/tests/unit/policies/test_flavor_manage.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import flavor_manage
@@ -31,18 +32,11 @@ class FlavorManagePolicyTest(base.BasePolicyTest):
super(FlavorManagePolicyTest, self).setUp()
self.controller = flavor_manage.FlavorManageController()
self.req = fakes.HTTPRequest.blank('')
- # Check that admin is able to manage the flavors.
+ # With legacy rule and no scope checks, all admin can manage
+ # the flavors.
self.admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to manage the flavors.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
def test_create_flavor_policy(self):
rule_name = fm_policies.POLICY_ROOT % 'create'
@@ -67,29 +61,34 @@ class FlavorManagePolicyTest(base.BasePolicyTest):
"disk": 1,
}
}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._create,
- self.req, body=body)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name, self.controller._create,
+ self.req, body=body)
@mock.patch('nova.objects.Flavor.get_by_flavor_id')
@mock.patch('nova.objects.Flavor.save')
def test_update_flavor_policy(self, mock_save, mock_get):
rule_name = fm_policies.POLICY_ROOT % 'update'
req = fakes.HTTPRequest.blank('', version='2.55')
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._update,
- req, uuids.fake_id,
- body={'flavor': {'description': None}})
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name, self.controller._update,
+ req, uuids.fake_id,
+ body={'flavor': {'description': None}})
@mock.patch('nova.objects.Flavor.destroy')
def test_delete_flavor_policy(self, mock_delete):
rule_name = fm_policies.POLICY_ROOT % 'delete'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._delete,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name, self.controller._delete,
+ self.req, uuids.fake_id)
+
+
+class FlavorManageNoLegacyNoScopeTest(FlavorManagePolicyTest):
+ """Test Flavor Access API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
class FlavorManageScopeTypePolicyTest(FlavorManagePolicyTest):
@@ -106,23 +105,16 @@ class FlavorManageScopeTypePolicyTest(FlavorManagePolicyTest):
super(FlavorManageScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to manage the flavors.
+ # With scope enabled, only project admin is able to manage
+ # the flavors.
self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system-admin is not able to manage the flavors.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
-
-class FlavorManageNoLegacyPolicyTest(FlavorManageScopeTypePolicyTest):
+ self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class FlavorManageScopeTypeNoLegacyPolicyTest(
+ FlavorManageScopeTypePolicyTest):
"""Test Flavor Manage APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
diff --git a/nova/tests/unit/policies/test_floating_ip_pools.py b/nova/tests/unit/policies/test_floating_ip_pools.py
index 08f36134d5..551f482bd4 100644
--- a/nova/tests/unit/policies/test_floating_ip_pools.py
+++ b/nova/tests/unit/policies/test_floating_ip_pools.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import floating_ip_pools
from nova.tests.unit.api.openstack import fakes
@@ -32,15 +32,15 @@ class FloatingIPPoolsPolicyTest(base.BasePolicyTest):
self.req = fakes.HTTPRequest.blank('')
# Check that everyone is able to list FIP pools.
- self.everyone_authorized_contexts = [
+ self.everyone_authorized_contexts = set([
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_reader_context,
self.other_project_member_context,
self.system_member_context, self.system_reader_context,
- self.system_foo_context]
- self.everyone_unauthorized_contexts = []
+ self.system_foo_context])
+ self.everyone_unauthorized_contexts = set([])
@mock.patch('nova.network.neutron.API.get_floating_ip_pools')
def test_floating_ip_pools_policy(self, mock_get):
@@ -66,6 +66,10 @@ class FloatingIPPoolsScopeTypePolicyTest(FloatingIPPoolsPolicyTest):
super(FloatingIPPoolsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ self.reduce_set('everyone_authorized', self.all_project_contexts)
+ self.everyone_unauthorized_contexts = (
+ self.all_contexts - self.everyone_authorized_contexts)
+
class FloatingIPPoolsNoLegacyPolicyTest(FloatingIPPoolsScopeTypePolicyTest):
"""Test Floating IP Pools APIs policies with system scope enabled,
diff --git a/nova/tests/unit/policies/test_floating_ips.py b/nova/tests/unit/policies/test_floating_ips.py
index 55453e7708..26c721e9e9 100644
--- a/nova/tests/unit/policies/test_floating_ips.py
+++ b/nova/tests/unit/policies/test_floating_ips.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -48,12 +49,13 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
id=1, uuid=uuid, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that everyone is able to perform crud operation on FIP.
+ # With legacy rule and scope disable, everyone is able to perform crud
+ # operation on FIP.
# NOTE: Nova cannot verify the FIP owner during nova policy
# enforcement so will be passing context's project_id as target to
# policy and always pass. If requester is not admin or owner
# of FIP then neutron will be returning the appropriate error.
- self.reader_authorized_contexts = [
+ self.member_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,
@@ -62,48 +64,45 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
- self.reader_unauthorized_contexts = []
- self.cd_authorized_contexts = self.reader_authorized_contexts
- self.cd_unauthorized_contexts = self.reader_unauthorized_contexts
- # Check that admin or owner is able to add/delete FIP to server.
- self.admin_or_owner_authorized_contexts = [
+ self.project_reader_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 and non-owner is not able to add/delete
- # FIP to server.
- self.admin_or_owner_unauthorized_contexts = [
+ self.project_reader_context, self.project_foo_context,
+ self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
+ self.other_project_member_context
]
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to add,
+ # delete FIP to server.
+ self.project_member_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]
@mock.patch('nova.network.neutron.API.get_floating_ip')
def test_show_floating_ip_policy(self, mock_get):
rule_name = "os_compute_api:os-floating-ips:show"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, uuids.fake_id)
@mock.patch('nova.network.neutron.API.get_floating_ips_by_project')
def test_index_floating_ip_policy(self, mock_get):
rule_name = "os_compute_api:os-floating-ips:list"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
@mock.patch('nova.network.neutron.API.get_floating_ip_by_address')
@mock.patch('nova.network.neutron.API.allocate_floating_ip')
def test_create_floating_ip_policy(self, mock_create, mock_get):
rule_name = "os_compute_api:os-floating-ips:create"
- self.common_policy_check(self.cd_authorized_contexts,
- self.cd_unauthorized_contexts,
- rule_name, self.controller.create,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.member_authorized_contexts,
+ rule_name, self.controller.create,
+ self.req, uuids.fake_id)
@mock.patch('nova.network.neutron.API.get_instance_id_by_floating_address')
@mock.patch('nova.network.neutron.API.get_floating_ip')
@@ -112,10 +111,9 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
def test_delete_floating_ip_policy(self, mock_delete, mock_get,
mock_instance):
rule_name = "os_compute_api:os-floating-ips:delete"
- self.common_policy_check(self.cd_authorized_contexts,
- self.cd_unauthorized_contexts,
- rule_name, self.controller.delete,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.member_authorized_contexts,
+ rule_name, self.controller.delete,
+ self.req, uuids.fake_id)
@mock.patch('nova.objects.Instance.get_network_info')
@mock.patch('nova.network.neutron.API.associate_floating_ip')
@@ -127,11 +125,10 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
mock_net.return_value = network_model.NetworkInfo.hydrate(ninfo)
body = {'addFloatingIp': {
'address': '1.2.3.4'}}
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.action_controller._add_floating_ip,
- self.req, self.instance.uuid, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.action_controller._add_floating_ip,
+ self.req, self.instance.uuid, body=body)
@mock.patch('nova.network.neutron.API.get_instance_id_by_floating_address')
@mock.patch('nova.network.neutron.API.get_floating_ip_by_address')
@@ -142,11 +139,53 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
mock_instance.return_value = self.instance.uuid
body = {'removeFloatingIp': {
'address': '1.2.3.4'}}
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.action_controller._remove_floating_ip,
- self.req, self.instance.uuid, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.action_controller._remove_floating_ip,
+ self.req, self.instance.uuid, body=body)
+
+
+class FloatingIPNoLegacyNoScopePolicyTest(FloatingIPPolicyTest):
+ """Test Floating IP APIs policies with system scope disabled,
+ and no more deprecated rules.
+ """
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ fip_policies.BASE_POLICY_NAME % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ fip_policies.BASE_POLICY_NAME % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ fip_policies.BASE_POLICY_NAME % 'create':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ fip_policies.BASE_POLICY_NAME % 'delete':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ fip_policies.BASE_POLICY_NAME % 'add':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ fip_policies.BASE_POLICY_NAME % 'remove':
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
+
+ def setUp(self):
+ super(FloatingIPNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to add/remove FIP to server.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+ # With no legacy, project other roles like foo will not be able
+ # to operate on FIP.
+ self.member_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ self.system_member_context,
+ self.other_project_member_context
+ ]
+ self.project_reader_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context,
+ self.other_project_reader_context,
+ self.system_member_context, self.system_reader_context,
+ self.other_project_member_context
+ ]
class FloatingIPScopeTypePolicyTest(FloatingIPPolicyTest):
@@ -163,63 +202,58 @@ class FloatingIPScopeTypePolicyTest(FloatingIPPolicyTest):
def setUp(self):
super(FloatingIPScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system users.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.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_reader_context,
+ self.other_project_member_context
+ ]
+ self.project_reader_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_reader_context,
+ self.other_project_member_context
+ ]
-class FloatingIPNoLegacyPolicyTest(FloatingIPScopeTypePolicyTest):
+class FloatingIPScopeTypeNoLegacyPolicyTest(FloatingIPScopeTypePolicyTest):
"""Test Floating IP APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
fip_policies.BASE_POLICY_NAME % 'list':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
fip_policies.BASE_POLICY_NAME % 'show':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
fip_policies.BASE_POLICY_NAME % 'create':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
fip_policies.BASE_POLICY_NAME % 'delete':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
fip_policies.BASE_POLICY_NAME % 'add':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
fip_policies.BASE_POLICY_NAME % 'remove':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
def setUp(self):
- super(FloatingIPNoLegacyPolicyTest, self).setUp()
+ super(FloatingIPScopeTypeNoLegacyPolicyTest, self).setUp()
# Check that system admin or owner is able to
# add/delete FIP to server.
- self.admin_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context,
- ]
- # Check that non-system and non-admin/owner is not able
- # to add/delete FIP to server.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+ # With no legacy and scope enabled, system users and project
+ # other roles like foo will not be able to operate FIP.
+ self.member_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context,
+ self.other_project_member_context
]
- self.reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context,
+ self.project_reader_authorized_contexts = [
+ self.legacy_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.other_project_reader_context,
- ]
- self.reader_unauthorized_contexts = [
- self.project_foo_context,
- self.system_foo_context
- ]
- self.cd_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.project_admin_context, self.project_member_context,
- self.legacy_admin_context, self.other_project_member_context
- ]
- self.cd_unauthorized_contexts = [
- self.system_reader_context,
- self.project_reader_context, self.project_foo_context,
- self.system_foo_context, self.other_project_reader_context
+ self.other_project_member_context
]
diff --git a/nova/tests/unit/policies/test_hosts.py b/nova/tests/unit/policies/test_hosts.py
index cdce7d2b1c..e07c907cf8 100644
--- a/nova/tests/unit/policies/test_hosts.py
+++ b/nova/tests/unit/policies/test_hosts.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import hosts
from nova.policies import base as base_policy
@@ -32,37 +32,19 @@ class HostsPolicyTest(base.BasePolicyTest):
self.controller = hosts.HostController()
self.req = fakes.HTTPRequest.blank('')
- # Check that admin is able to perform operations on hosts.
- self.system_admin_authorized_contexts = [
- self.system_admin_context, self.legacy_admin_context,
+ # With legacy rule and scope check disabled by default, system admin,
+ # legacy admin, and project admin will be able to perform hosts
+ # Operations.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to perform operations
- # on hosts.
- self.system_admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context, self.other_project_reader_context
- ]
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.legacy_admin_context,
- self.project_admin_context
- ]
- self.system_reader_unauthorized_contexts = [
- self.project_foo_context, self.system_foo_context,
- self.project_member_context, self.project_reader_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
@mock.patch('nova.compute.api.HostAPI.service_get_all')
def test_list_hosts_policy(self, mock_get):
rule_name = policies.POLICY_NAME % 'list'
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
@mock.patch('nova.context.set_target_cell')
@mock.patch('nova.objects.HostMapping.get_by_host')
@@ -71,41 +53,48 @@ class HostsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.compute.api.HostAPI.instance_get_all_by_host')
def test_show_host_policy(self, mock_get, mock_node, mock_map, mock_set):
rule_name = policies.POLICY_NAME % 'show'
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, 11111)
def test_update_host_policy(self):
rule_name = policies.POLICY_NAME % 'update'
- self.common_policy_check(self.system_admin_authorized_contexts,
- self.system_admin_unauthorized_contexts,
- rule_name, self.controller.update,
- self.req, 11111, body={})
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.update,
+ self.req, 11111, body={})
@mock.patch('nova.compute.api.HostAPI.host_power_action')
def test_reboot_host_policy(self, mock_action):
rule_name = policies.POLICY_NAME % 'reboot'
- self.common_policy_check(self.system_admin_authorized_contexts,
- self.system_admin_unauthorized_contexts,
- rule_name, self.controller.reboot,
- self.req, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.reboot,
+ self.req, 11111)
@mock.patch('nova.compute.api.HostAPI.host_power_action')
def test_shutdown_host_policy(self, mock_action):
rule_name = policies.POLICY_NAME % 'shutdown'
- self.common_policy_check(self.system_admin_authorized_contexts,
- self.system_admin_unauthorized_contexts,
- rule_name, self.controller.shutdown,
- self.req, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.shutdown,
+ self.req, 11111)
@mock.patch('nova.compute.api.HostAPI.host_power_action')
def test_startup_host_policy(self, mock_action):
rule_name = policies.POLICY_NAME % 'start'
- self.common_policy_check(self.system_admin_authorized_contexts,
- self.system_admin_unauthorized_contexts,
- rule_name, self.controller.startup,
- self.req, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.startup,
+ self.req, 11111)
+
+
+class HostsNoLegacyNoScopePolicyTest(HostsPolicyTest):
+ """Test Hosts APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only. In this case
+ system admin, legacy admin, and project admin will be able to perform
+ hosts Operations. Legacy admin will be allowed as policy is just admin
+ if no scope checks.
+
+ """
+
+ without_deprecated_rules = True
class HostsScopeTypePolicyTest(HostsPolicyTest):
@@ -122,72 +111,29 @@ class HostsScopeTypePolicyTest(HostsPolicyTest):
super(HostsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to perform operations on hosts.
- self.system_admin_authorized_contexts = [
- self.system_admin_context]
- # Check that system non-admin is not able to perform operations
- # on hosts.
- self.system_admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context, self.other_project_reader_context
- ]
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context
- ]
- self.system_reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_foo_context,
- self.system_foo_context, self.project_admin_context,
- self.project_member_context, self.project_reader_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
-
-
-class HostsNoLegacyPolicyTest(HostsScopeTypePolicyTest):
- """Test Hosts APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ # With scope checks enable, only system admin is able to perform
+ # hosts Operations.
+ self.project_admin_authorized_contexts = [self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class HostsScopeTypeNoLegacyPolicyTest(HostsScopeTypePolicyTest):
+ """Test Hosts APIs policies with with no legacy deprecated rules
+ and scope checks enabled which means scope + new defaults. So
+ only system admin is able to perform hosts Operations.
"""
+
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'list':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
policies.POLICY_NAME % 'show':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
policies.POLICY_NAME % 'update':
- base_policy.SYSTEM_ADMIN,
+ base_policy.ADMIN,
policies.POLICY_NAME % 'reboot':
- base_policy.SYSTEM_ADMIN,
+ base_policy.ADMIN,
policies.POLICY_NAME % 'shutdown':
- base_policy.SYSTEM_ADMIN,
+ base_policy.ADMIN,
policies.POLICY_NAME % 'startup':
- base_policy.SYSTEM_ADMIN}
-
- def setUp(self):
- super(HostsNoLegacyPolicyTest, self).setUp()
-
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context
- ]
- self.system_reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_foo_context,
- self.system_foo_context, self.project_admin_context,
- self.project_member_context, self.project_reader_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- self.system_admin_authorized_contexts = [
- self.system_admin_context
- ]
- self.system_admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.project_admin_context, self.project_member_context,
- self.legacy_admin_context, self.other_project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.system_foo_context, self.other_project_reader_context
- ]
+ base_policy.ADMIN}
diff --git a/nova/tests/unit/policies/test_hypervisors.py b/nova/tests/unit/policies/test_hypervisors.py
index 2b9eefcfd9..dd17ebe2fe 100644
--- a/nova/tests/unit/policies/test_hypervisors.py
+++ b/nova/tests/unit/policies/test_hypervisors.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import hypervisors
from nova.policies import base as base_policy
@@ -36,76 +36,67 @@ class HypervisorsPolicyTest(base.BasePolicyTest):
self.controller.host_api.service_get_by_compute_host = mock.MagicMock()
self.controller.host_api.compute_node_get = mock.MagicMock()
- # Check that system scoped admin, member and reader are able to
- # perform operations on hypervisors.
- # NOTE(gmann): Until old default rule which is admin_api is
- # deprecated and not removed, project admin and legacy admin
- # will be able to get hypervisors. This make sure that existing
- # tokens will keep working even we have changed this policy defaults
- # to reader role.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.legacy_admin_context,
+ # With legacy rule and scope check disabled by default, system admin,
+ # legacy admin, and project admin will be able to perform hypervisors
+ # Operations.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-system-reader are not able to perform operations
- # on hypervisors
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context,
- self.other_project_reader_context,
- ]
def test_list_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME % 'list'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
def test_list_details_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME % 'list-detail'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.detail,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.detail,
+ self.req)
def test_show_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME % 'show'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, 11111)
@mock.patch('nova.compute.api.HostAPI.get_host_uptime')
def test_uptime_hypervisors_policy(self, mock_uptime):
rule_name = hv_policies.BASE_POLICY_NAME % 'uptime'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.uptime,
- self.req, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.uptime,
+ self.req, 11111)
def test_search_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME % 'search'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.search,
- self.req, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.search,
+ self.req, 11111)
def test_servers_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME % 'servers'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.servers,
- self.req, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.servers,
+ self.req, 11111)
@mock.patch('nova.compute.api.HostAPI.compute_node_statistics')
def test_statistics_hypervisors_policy(self, mock_statistics):
rule_name = hv_policies.BASE_POLICY_NAME % 'statistics'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.statistics,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.statistics,
+ self.req)
+
+
+class HypervisorsNoLegacyNoScopePolicyTest(HypervisorsPolicyTest):
+ """Test Hypervisors APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only. In this case
+ system admin, legacy admin, and project admin will be able to perform
+ Hypervisors Operations. Legacy admin will be allowed as policy is just
+ admin if no scope checks.
+ """
+
+ without_deprecated_rules = True
class HypervisorsScopeTypePolicyTest(HypervisorsPolicyTest):
@@ -122,40 +113,33 @@ class HypervisorsScopeTypePolicyTest(HypervisorsPolicyTest):
super(HypervisorsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system reader is able to perform operations
- # on hypervisors.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system-reader is not able to perform operations
- # on hypervisors.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
-
-class HypervisorsNoLegacyPolicyTest(HypervisorsScopeTypePolicyTest):
- """Test Hypervisors APIs policies with system scope enabled,
- and no more deprecated rules.
+ # With scope checks enable, only system admin is able to perform
+ # hypervisors Operations.
+ self.project_admin_authorized_contexts = [self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class HypervisorsScopeTypeNoLegacyPolicyTest(HypervisorsScopeTypePolicyTest):
+ """Test Hypervisors APIs policies with no legacy deprecated rules
+ and scope checks enabled which means scope + new defaults so
+ only system admin is able to perform hypervisors Operations.
"""
+
without_deprecated_rules = True
+
rules_without_deprecation = {
hv_policies.BASE_POLICY_NAME % 'list':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
hv_policies.BASE_POLICY_NAME % 'list-detail':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
hv_policies.BASE_POLICY_NAME % 'show':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
hv_policies.BASE_POLICY_NAME % 'statistics':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
hv_policies.BASE_POLICY_NAME % 'uptime':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
hv_policies.BASE_POLICY_NAME % 'search':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
hv_policies.BASE_POLICY_NAME % 'servers':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
}
diff --git a/nova/tests/unit/policies/test_instance_actions.py b/nova/tests/unit/policies/test_instance_actions.py
index b3e43b3498..1ca9a66c14 100644
--- a/nova/tests/unit/policies/test_instance_actions.py
+++ b/nova/tests/unit/policies/test_instance_actions.py
@@ -11,8 +11,9 @@
# under the License.
import copy
+from unittest import mock
+
import fixtures
-import mock
from nova.api.openstack import api_version_request
from oslo_policy import policy as oslo_policy
@@ -62,33 +63,17 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that system reader are able to show the instance
- # actions events.
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.legacy_admin_context,
+ # With legacy rule and no scope checks, any role in project can
+ # get server action and all admin is able to get server action
+ # with event details.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-system-reader are not able to show the instance
- # actions events.
- self.system_reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context,
- self.other_project_reader_context,
- ]
-
- self.project_or_system_reader_authorized_contexts = [
+ # and project reader can get their server topology without host info.
+ self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_member_context, self.project_foo_context
- ]
-
- self.project_or_system_reader_unauthorized_contexts = [
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context, self.project_foo_context]
def _set_policy_rules(self, overwrite=True):
rules = {ia_policies.BASE_POLICY_NAME % 'show': '@'}
@@ -97,9 +82,8 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
def test_index_instance_action_policy(self):
rule_name = ia_policies.BASE_POLICY_NAME % "list"
- self.common_policy_check(
- self.project_or_system_reader_authorized_contexts,
- self.project_or_system_reader_unauthorized_contexts,
+ self.common_policy_auth(
+ self.project_reader_authorized_contexts,
rule_name, self.controller.index,
self.req, self.instance['uuid'])
@@ -108,9 +92,8 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
mock_action_get.return_value = fake_action
rule_name = ia_policies.BASE_POLICY_NAME % "show"
- self.common_policy_check(
- self.project_or_system_reader_authorized_contexts,
- self.project_or_system_reader_unauthorized_contexts,
+ self.common_policy_auth(
+ self.project_reader_authorized_contexts,
rule_name, self.controller.show,
self.req, self.instance['uuid'], fake_action['request_id'])
@@ -131,9 +114,8 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
self._set_policy_rules(overwrite=False)
rule_name = ia_policies.BASE_POLICY_NAME % "events"
- authorize_res, unauthorize_res = self.common_policy_check(
- self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.show,
self.req, self.instance['uuid'],
fake_action['request_id'], fatal=False)
@@ -149,6 +131,28 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
self.assertNotIn('events', action['instanceAction'])
+class InstanceActionsNoLegacyNoScopePolicyTest(InstanceActionsPolicyTest):
+ """Test os-instance-actions APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ ia_policies.BASE_POLICY_NAME % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ ia_policies.BASE_POLICY_NAME % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ ia_policies.BASE_POLICY_NAME % 'events':
+ base_policy.ADMIN,
+ }
+
+ def setUp(self):
+ super(InstanceActionsNoLegacyNoScopePolicyTest, self).setUp()
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
+
+
class InstanceActionsDeprecatedPolicyTest(base.BasePolicyTest):
"""Test os-instance-actions APIs Deprecated policies.
@@ -185,7 +189,7 @@ class InstanceActionsDeprecatedPolicyTest(base.BasePolicyTest):
@mock.patch('nova.api.openstack.common.get_instance')
def test_deprecated_policy_overridden_rule_is_checked(
self, mock_instance_get, mock_actions_get):
- # Test to verify if deprecatd overridden policy is working.
+ # Test to verify if deprecated overridden policy is working.
instance = fake_instance.fake_instance_obj(
self.admin_or_owner_req.environ['nova.context'])
@@ -193,7 +197,7 @@ class InstanceActionsDeprecatedPolicyTest(base.BasePolicyTest):
# Check for success as admin_or_owner role. Deprecated rule
# has been overridden with admin checks in policy.yaml
# If admin role pass it means overridden rule is enforced by
- # olso.policy because new default is system reader and the old
+ # oslo.policy because new default is system reader and the old
# default is admin.
self.controller.index(self.admin_or_owner_req, instance['uuid'])
@@ -221,6 +225,11 @@ class InstanceActionsScopeTypePolicyTest(InstanceActionsPolicyTest):
def setUp(self):
super(InstanceActionsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With Scope enable, system users no longer allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
@mock.patch('nova.objects.InstanceActionEventList.get_by_action')
@mock.patch('nova.objects.InstanceAction.get_by_request_id')
@@ -241,9 +250,8 @@ class InstanceActionsScopeTypePolicyTest(InstanceActionsPolicyTest):
self._set_policy_rules(overwrite=False)
rule_name = ia_policies.BASE_POLICY_NAME % "events:details"
- authorize_res, unauthorize_res = self.common_policy_check(
- self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.show,
self.req, self.instance['uuid'],
fake_action['request_id'], fatal=False)
@@ -267,54 +275,25 @@ class InstanceActionsScopeTypePolicyTest(InstanceActionsPolicyTest):
self.assertNotIn('details', event)
-class InstanceActionsNoLegacyPolicyTest(InstanceActionsPolicyTest):
+class InstanceActionsScopeTypeNoLegacyPolicyTest(
+ InstanceActionsScopeTypePolicyTest):
"""Test os-instance-actions APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
ia_policies.BASE_POLICY_NAME % 'list':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
ia_policies.BASE_POLICY_NAME % 'show':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
ia_policies.BASE_POLICY_NAME % 'events':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
}
def setUp(self):
- super(InstanceActionsNoLegacyPolicyTest, self).setUp()
- self.flags(enforce_scope=True, group="oslo_policy")
-
- # Check that system reader are able to get the
- # instance action events.
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_reader_context,
- self.system_member_context]
- # Check that non-system-reader are not able to
- # get the instance action events
- self.system_reader_unauthorized_contexts = [
- self.project_admin_context,
- self.system_foo_context, self.legacy_admin_context,
- self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context,
- self.other_project_reader_context,
- ]
-
- # Check that system or projct reader is able to
- # show the instance actions events.
- self.project_or_system_reader_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_member_context,
- ]
-
- # Check that non-system or non-project reader is not able to
- # show the instance actions events.
- self.project_or_system_reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ super(InstanceActionsScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With no legacy and scope enable, only project admin, member,
+ # and reader will be able to get server action and only admin
+ # with event details.
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_instance_usage_audit_log.py b/nova/tests/unit/policies/test_instance_usage_audit_log.py
index e320beacd2..71b0cdd2aa 100644
--- a/nova/tests/unit/policies/test_instance_usage_audit_log.py
+++ b/nova/tests/unit/policies/test_instance_usage_audit_log.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import instance_usage_audit_log as iual
from nova.policies import base as base_policy
@@ -35,37 +35,37 @@ class InstanceUsageAuditLogPolicyTest(base.BasePolicyTest):
self.controller.host_api.task_log_get_all = mock.MagicMock()
self.controller.host_api.service_get_all = mock.MagicMock()
- # Check that admin is able to get instance usage audit log.
- # NOTE(gmann): Until old default rule which is admin_api is
- # deprecated and not removed, project admin and legacy admin
- # will be able to get instance usage audit log. This make sure
- # that existing tokens will keep working even we have changed
- # this policy defaults to reader role.
- self.reader_authorized_contexts = [
+ # With legacy rule, all admin_api will be able to get instance usage
+ # audit log.
+ self.admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-admin is not able to get instance usage audit log.
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
+ self.project_admin_context]
def test_show_policy(self):
rule_name = iual_policies.BASE_POLICY_NAME % 'show'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, '2020-03-25 14:40:00')
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, '2020-03-25 14:40:00')
def test_index_policy(self):
rule_name = iual_policies.BASE_POLICY_NAME % 'list'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
+
+
+class InstanceUsageNoLegacyNoScopeTest(InstanceUsageAuditLogPolicyTest):
+ """Test Instance Usage API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ iual_policies.BASE_POLICY_NAME % 'list':
+ base_policy.ADMIN,
+ iual_policies.BASE_POLICY_NAME % 'show':
+ base_policy.ADMIN,
+ }
class InstanceUsageScopeTypePolicyTest(InstanceUsageAuditLogPolicyTest):
@@ -83,29 +83,21 @@ class InstanceUsageScopeTypePolicyTest(InstanceUsageAuditLogPolicyTest):
super(InstanceUsageScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system reader is able to get instance usage audit log.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system-admin is not able to get instance
- # usage audit log.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
-
-class InstanceUsageNoLegacyPolicyTest(InstanceUsageScopeTypePolicyTest):
+ # Scope checks remove project users power.
+ self.admin_authorized_contexts = [
+ self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class InstanceUsageScopeTypeNoLegacyPolicyTest(
+ InstanceUsageScopeTypePolicyTest):
"""Test Instance Usage Audit Log APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
iual_policies.BASE_POLICY_NAME % 'list':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
iual_policies.BASE_POLICY_NAME % 'show':
- base_policy.SYSTEM_READER,
+ base_policy.ADMIN,
}
diff --git a/nova/tests/unit/policies/test_keypairs.py b/nova/tests/unit/policies/test_keypairs.py
index 4faefea2ef..ee39133b7a 100644
--- a/nova/tests/unit/policies/test_keypairs.py
+++ b/nova/tests/unit/policies/test_keypairs.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from nova.policies import keypairs as policies
from nova.api.openstack.compute import keypairs
@@ -34,7 +35,7 @@ class KeypairsPolicyTest(base.BasePolicyTest):
# Check that everyone is able to create, delete and get
# their keypairs.
- self.everyone_authorized_contexts = [
+ self.everyone_authorized_contexts = set([
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.system_member_context, self.system_reader_context,
@@ -42,88 +43,58 @@ class KeypairsPolicyTest(base.BasePolicyTest):
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
- ]
- self.everyone_unauthorized_contexts = []
+ ])
# Check that admin is able to create, delete and get
# other users keypairs.
- self.admin_authorized_contexts = [
+ self.admin_authorized_contexts = set([
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context]
- # Check that non-admin is not able to create, delete and get
- # other users keypairs.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
-
- # Check that system reader is able to get
- # other users keypairs.
- self.system_reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to get
- # other users keypairs.
- self.system_reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_admin_context])
@mock.patch('nova.compute.api.KeypairAPI.get_key_pairs')
def test_index_keypairs_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req)
+ self.common_policy_auth(self.everyone_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req)
@mock.patch('nova.compute.api.KeypairAPI.get_key_pairs')
def test_index_others_keypairs_policy(self, mock_get):
req = fakes.HTTPRequest.blank('?user_id=user2', version='2.10')
rule_name = policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name,
- self.controller.index,
- req)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ req)
@mock.patch('nova.compute.api.KeypairAPI.get_key_pair')
def test_show_keypairs_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'show'
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, fakes.FAKE_UUID)
+ self.common_policy_auth(self.everyone_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, fakes.FAKE_UUID)
@mock.patch('nova.compute.api.KeypairAPI.get_key_pair')
def test_show_others_keypairs_policy(self, mock_get):
# Change the user_id in request context.
req = fakes.HTTPRequest.blank('?user_id=user2', version='2.10')
rule_name = policies.POLICY_ROOT % 'show'
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name,
- self.controller.show,
- req, fakes.FAKE_UUID)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ req, fakes.FAKE_UUID)
@mock.patch('nova.compute.api.KeypairAPI.create_key_pair')
def test_create_keypairs_policy(self, mock_create):
rule_name = policies.POLICY_ROOT % 'create'
mock_create.return_value = (test_keypair.fake_keypair, 'FAKE_KEY')
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name,
- self.controller.create,
- self.req,
- body={'keypair': {'name': 'create_test'}})
+ self.common_policy_auth(self.everyone_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ self.req,
+ body={'keypair': {'name': 'create_test'}})
@mock.patch('nova.compute.api.KeypairAPI.create_key_pair')
def test_create_others_keypairs_policy(self, mock_create):
@@ -132,31 +103,39 @@ class KeypairsPolicyTest(base.BasePolicyTest):
rule_name = policies.POLICY_ROOT % 'create'
mock_create.return_value = (test_keypair.fake_keypair, 'FAKE_KEY')
body = {'keypair': {'name': 'test2', 'user_id': 'user2'}}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.create,
- req, body=body)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ req, body=body)
@mock.patch('nova.compute.api.KeypairAPI.delete_key_pair')
def test_delete_keypairs_policy(self, mock_delete):
rule_name = policies.POLICY_ROOT % 'delete'
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, fakes.FAKE_UUID)
+ self.common_policy_auth(self.everyone_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ self.req, fakes.FAKE_UUID)
@mock.patch('nova.compute.api.KeypairAPI.delete_key_pair')
def test_delete_others_keypairs_policy(self, mock_delete):
# Change the user_id in request context.
req = fakes.HTTPRequest.blank('?user_id=user2', version='2.10')
rule_name = policies.POLICY_ROOT % 'delete'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- req, fakes.FAKE_UUID)
+ self.common_policy_auth(self.admin_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ req, fakes.FAKE_UUID)
+
+
+class KeypairsNoLegacyNoScopeTest(KeypairsPolicyTest):
+ """Test Keypairs API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(KeypairsNoLegacyNoScopeTest, self).setUp()
class KeypairsScopeTypePolicyTest(KeypairsPolicyTest):
@@ -173,6 +152,12 @@ class KeypairsScopeTypePolicyTest(KeypairsPolicyTest):
super(KeypairsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope checking, only project-scoped users are allowed
+ self.reduce_set('everyone_authorized', self.all_project_contexts)
+ self.admin_authorized_contexts = [
+ self.legacy_admin_context,
+ self.project_admin_context]
+
class KeypairsNoLegacyPolicyTest(KeypairsScopeTypePolicyTest):
"""Test Keypairs APIs policies with system scope enabled,
@@ -180,35 +165,3 @@ class KeypairsNoLegacyPolicyTest(KeypairsScopeTypePolicyTest):
access system APIs.
"""
without_deprecated_rules = True
-
- def setUp(self):
- super(KeypairsNoLegacyPolicyTest, self).setUp()
-
- # Check that system admin is able to create, delete and get
- # other users keypairs.
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that system non-admin is not able to create, delete and get
- # other users keypairs.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
- # Check that system reader is able to get
- # other users keypairs.
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to get
- # other users keypairs.
- self.system_reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
diff --git a/nova/tests/unit/policies/test_limits.py b/nova/tests/unit/policies/test_limits.py
index cab2b5f679..aba647caec 100644
--- a/nova/tests/unit/policies/test_limits.py
+++ b/nova/tests/unit/policies/test_limits.py
@@ -10,15 +10,19 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+import functools
+from unittest import mock
from nova.api.openstack.compute import limits
+import nova.conf
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
from nova.tests.unit.policies import base
+CONF = nova.conf.CONF
+
class LimitsPolicyTest(base.BasePolicyTest):
"""Test Limits APIs policies with all possible context.
@@ -55,48 +59,52 @@ class LimitsPolicyTest(base.BasePolicyTest):
mock_get_project_quotas.start()
# Check that everyone is able to get their limits
- self.everyone_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_member_context, self.other_project_member_context,
- self.project_foo_context, self.project_reader_context,
- self.other_project_reader_context,
- ]
- self.everyone_unauthorized_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 get limit. This make sure that existing
- # tokens will keep working even we have changed this policy defaults
- # to reader role.
- self.reader_authorized_contexts = [
+ self.everyone_authorized_contexts = self.all_contexts
+
+ # With legacy rule, any admin is able to get other projects limit.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_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.reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
+ self.project_admin_context]
def test_get_limits_policy(self):
rule_name = limits_policies.BASE_POLICY_NAME
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.everyone_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
def test_get_other_limits_policy(self):
+ rule = limits_policies.BASE_POLICY_NAME
+ self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('/?tenant_id=faketenant')
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)
+ if not CONF.oslo_policy.enforce_scope:
+ check_rule = rule_name
+ else:
+ check_rule = functools.partial(base.rule_if_system,
+ rule, rule_name)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ check_rule, self.controller.index,
+ req)
+
+
+class LimitsNoLegacyNoScopeTest(LimitsPolicyTest):
+ """Test Flavor Access API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME:
+ base_policy.ADMIN}
+
+ def setUp(self):
+ super(LimitsNoLegacyNoScopeTest, self).setUp()
+
+ # Even with no legacy rule, any admin can get other project
+ # limits.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context]
class LimitsScopeTypePolicyTest(LimitsPolicyTest):
@@ -114,22 +122,18 @@ class LimitsScopeTypePolicyTest(LimitsPolicyTest):
super(LimitsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # 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.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
+ # With Scope enable, system users no longer allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+ self.everyone_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context, self.project_reader_context,
self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
+ self.project_foo_context, self.other_project_reader_context
]
-class LimitsNoLegacyPolicyTest(LimitsScopeTypePolicyTest):
+class LimitsScopeTypeNoLegacyPolicyTest(LimitsScopeTypePolicyTest):
"""Test Limits APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@@ -137,4 +141,17 @@ class LimitsNoLegacyPolicyTest(LimitsScopeTypePolicyTest):
without_deprecated_rules = True
rules_without_deprecation = {
limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME:
- base_policy.SYSTEM_READER}
+ base_policy.ADMIN}
+
+ def setUp(self):
+ super(LimitsScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With no legacy and scope enable, only project level admin
+ # will get other projects limit.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+ self.everyone_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context, self.project_reader_context,
+ self.other_project_member_context,
+ self.project_foo_context, self.other_project_reader_context
+ ]
diff --git a/nova/tests/unit/policies/test_lock_server.py b/nova/tests/unit/policies/test_lock_server.py
index 883c71929e..31de5cff0c 100644
--- a/nova/tests/unit/policies/test_lock_server.py
+++ b/nova/tests/unit/policies/test_lock_server.py
@@ -10,13 +10,16 @@
# License for the specific language governing permissions and limitations
# under the License.
+import functools
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
from nova.api.openstack.compute import lock_server
from nova.compute import vm_states
+import nova.conf
from nova import exception
from nova.policies import base as base_policy
from nova.policies import lock_server as ls_policies
@@ -24,6 +27,8 @@ from nova.tests.unit.api.openstack import fakes
from nova.tests.unit import fake_instance
from nova.tests.unit.policies import base
+CONF = nova.conf.CONF
+
class LockServerPolicyTest(base.BasePolicyTest):
"""Test Lock server APIs policies with all possible context.
@@ -48,54 +53,39 @@ class LockServerPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or and server owner is able to lock/unlock
- # the server
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to lock,
+ # unlock the server.
+ self.project_action_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 lock/unlock
- # the server
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
- # Check that admin is able to unlock the server which is
- # locked by other
- self.admin_authorized_contexts = [
+
+ # By default, legacy rule are enable and scope check is disabled.
+ # system admin, legacy admin, and project admin is able to override
+ # unlock, regardless who locked the server.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to unlock the server
- # which is locked by other
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.compute.api.API.lock')
def test_lock_server_policy(self, mock_lock):
rule_name = ls_policies.POLICY_ROOT % 'lock'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._lock,
- self.req, self.instance.uuid,
- body={'lock': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._lock,
+ self.req, self.instance.uuid,
+ body={'lock': {}})
@mock.patch('nova.compute.api.API.unlock')
def test_unlock_server_policy(self, mock_unlock):
rule_name = ls_policies.POLICY_ROOT % 'unlock'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._unlock,
- self.req, self.instance.uuid,
- body={'unlock': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._unlock,
+ self.req, self.instance.uuid,
+ body={'unlock': {}})
@mock.patch('nova.compute.api.API.unlock')
@mock.patch('nova.compute.api.API.is_expected_locked_by')
@@ -104,12 +94,16 @@ class LockServerPolicyTest(base.BasePolicyTest):
rule = ls_policies.POLICY_ROOT % 'unlock'
self.policy.set_rules({rule: "@"}, overwrite=False)
rule_name = ls_policies.POLICY_ROOT % 'unlock:unlock_override'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller._unlock,
- self.req, self.instance.uuid,
- body={'unlock': {}})
+ if not CONF.oslo_policy.enforce_scope:
+ check_rule = rule_name
+ else:
+ check_rule = functools.partial(base.rule_if_system,
+ rule, rule_name)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ check_rule,
+ self.controller._unlock,
+ self.req, self.instance.uuid,
+ body={'unlock': {}})
def test_lock_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -125,7 +119,7 @@ class LockServerPolicyTest(base.BasePolicyTest):
exc.format_message())
@mock.patch('nova.compute.api.API.lock')
- def test_lock_sevrer_overridden_policy_pass_with_same_user(
+ def test_lock_server_overridden_policy_pass_with_same_user(
self, mock_lock):
rule_name = ls_policies.POLICY_ROOT % 'lock'
self.policy.set_rules({rule_name: "user_id:%(user_id)s"})
@@ -134,6 +128,22 @@ class LockServerPolicyTest(base.BasePolicyTest):
body={'lock': {}})
+class LockServerNoLegacyNoScopePolicyTest(LockServerPolicyTest):
+ """Test lock/unlock server APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(LockServerNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to lock/unlock the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+
+
class LockServerScopeTypePolicyTest(LockServerPolicyTest):
"""Test Lock Server APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -147,49 +157,28 @@ class LockServerScopeTypePolicyTest(LockServerPolicyTest):
def setUp(self):
super(LockServerScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin to lock/unlock the server.
+ self.project_action_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class LockServerNoLegacyPolicyTest(LockServerScopeTypePolicyTest):
+class LockServerScopeTypeNoLegacyPolicyTest(LockServerScopeTypePolicyTest):
"""Test Lock Server APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
- super(LockServerNoLegacyPolicyTest, self).setUp()
- # Check that system admin or and server owner is able to lock/unlock
- # the server
- 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 lock/unlock
- # the server
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context, self.project_reader_context,
- self.project_foo_context,
- self.other_project_reader_context,
- ]
-
- # Check that system admin is able to unlock the server which is
- # locked by other
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that system non-admin is not able to unlock the server
- # which is locked by other
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_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,
- self.other_project_reader_context,
- ]
+ super(LockServerScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enable and no legacy rule, only project admin/member
+ # will be able to lock/unlock the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
-class LockServerOverridePolicyTest(LockServerNoLegacyPolicyTest):
+class LockServerOverridePolicyTest(LockServerScopeTypeNoLegacyPolicyTest):
"""Test Lock Server APIs policies with system and project scoped
but default to system roles only are allowed for project roles
if override by operators. This test is with system scope enable
@@ -198,21 +187,11 @@ class LockServerOverridePolicyTest(LockServerNoLegacyPolicyTest):
def setUp(self):
super(LockServerOverridePolicyTest, self).setUp()
-
- # Check that system admin or project scoped role as override above
- # is able to unlock the server which is locked by other
- self.admin_authorized_contexts = [
- self.system_admin_context,
+ # We are overriding the 'unlock:unlock_override' policy
+ # to PROJECT_MEMBER so testing it with both admin as well
+ # as project member as allowed context.
+ self.project_admin_authorized_contexts = [
self.project_admin_context, self.project_member_context]
- # Check that non-system admin or project role is not able to
- # unlock the server which is locked by other
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context,
- self.project_foo_context, self.project_reader_context,
- self.other_project_reader_context,
- ]
def test_unlock_override_server_policy(self):
rule = ls_policies.POLICY_ROOT % 'unlock:unlock_override'
@@ -220,6 +199,6 @@ class LockServerOverridePolicyTest(LockServerNoLegacyPolicyTest):
# make unlock allowed for everyone so that we can check unlock
# override policy.
ls_policies.POLICY_ROOT % 'unlock': "@",
- rule: base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}, overwrite=False)
+ rule: base_policy.PROJECT_MEMBER}, overwrite=False)
super(LockServerOverridePolicyTest,
self).test_unlock_override_server_policy()
diff --git a/nova/tests/unit/policies/test_migrate_server.py b/nova/tests/unit/policies/test_migrate_server.py
index 0082b3d414..0f750770d9 100644
--- a/nova/tests/unit/policies/test_migrate_server.py
+++ b/nova/tests/unit/policies/test_migrate_server.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -47,28 +48,19 @@ class MigrateServerPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin is able to migrate the server.
- self.admin_authorized_contexts = [
+ # With legacy rule, any admin is able to migrate
+ # the server.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context
- ]
- # Check that non-admin is not able to migrate the server
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_admin_context]
@mock.patch('nova.compute.api.API.resize')
def test_migrate_server_policy(self, mock_resize):
rule_name = ms_policies.POLICY_ROOT % 'migrate'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._migrate,
- self.req, self.instance.uuid,
- body={'migrate': None})
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller._migrate,
+ self.req, self.instance.uuid,
+ body={'migrate': None})
@mock.patch('nova.compute.api.API.live_migrate')
def test_migrate_live_server_policy(self, mock_live_migrate):
@@ -78,11 +70,18 @@ class MigrateServerPolicyTest(base.BasePolicyTest):
'block_migration': "False",
'disk_over_commit': "False"}
}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._migrate_live,
- self.req, self.instance.uuid,
- body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller._migrate_live,
+ self.req, self.instance.uuid,
+ body=body)
+
+
+class MigrateServerNoLegacyNoScopeTest(MigrateServerPolicyTest):
+ """Test Server Migrations API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
class MigrateServerScopeTypePolicyTest(MigrateServerPolicyTest):
@@ -99,32 +98,21 @@ class MigrateServerScopeTypePolicyTest(MigrateServerPolicyTest):
def setUp(self):
super(MigrateServerScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope enabled, system admin is not allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class MigrateServerNoLegacyPolicyTest(MigrateServerScopeTypePolicyTest):
+class MigrateServerScopeTypeNoLegacyPolicyTest(
+ MigrateServerScopeTypePolicyTest):
"""Test Migrate Server APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
- def setUp(self):
- super(MigrateServerNoLegacyPolicyTest, self).setUp()
- # Check that system admin is able to migrate the server.
- self.admin_authorized_contexts = [
- self.system_admin_context
- ]
- # Check that non system admin is not able to migrate the server
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
-
-
-class MigrateServerOverridePolicyTest(MigrateServerNoLegacyPolicyTest):
+
+class MigrateServerOverridePolicyTest(
+ MigrateServerScopeTypeNoLegacyPolicyTest):
"""Test Migrate Server APIs policies with system and project scoped
but default to system roles only are allowed for project roles
if override by operators. This test is with system scope enable
@@ -136,23 +124,13 @@ class MigrateServerOverridePolicyTest(MigrateServerNoLegacyPolicyTest):
rule_migrate = ms_policies.POLICY_ROOT % 'migrate'
rule_live_migrate = ms_policies.POLICY_ROOT % 'migrate_live'
# NOTE(gmann): override the rule to project member and verify it
- # work as policy is system and projct scoped.
+ # work as policy is system and project scoped.
self.policy.set_rules({
- rule_migrate: base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
- rule_live_migrate: base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN},
+ rule_migrate: base_policy.PROJECT_MEMBER,
+ rule_live_migrate: base_policy.PROJECT_MEMBER},
overwrite=False)
- # Check that system admin or project scoped role as override above
+ # Check that project member role as override above
# is able to migrate the server
- self.admin_authorized_contexts = [
- self.system_admin_context,
+ self.project_admin_authorized_contexts = [
self.project_admin_context, self.project_member_context]
- # Check that non-system admin or project role is not able to
- # migrate the server
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
diff --git a/nova/tests/unit/policies/test_migrations.py b/nova/tests/unit/policies/test_migrations.py
index a124fa508b..25cd75a125 100644
--- a/nova/tests/unit/policies/test_migrations.py
+++ b/nova/tests/unit/policies/test_migrations.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import migrations
from nova.policies import migrations as migrations_policies
@@ -32,27 +32,25 @@ class MigrationsPolicyTest(base.BasePolicyTest):
self.controller = migrations.MigrationsController()
self.req = fakes.HTTPRequest.blank('')
- # Check that admin is able to list migrations.
- self.reader_authorized_contexts = [
+ # With legacy rule, any admin is able to list migrations.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context
- ]
- # Check that non-admin is not able to list migrations.
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_admin_context]
@mock.patch('nova.compute.api.API.get_migrations')
def test_list_migrations_policy(self, mock_migration):
rule_name = migrations_policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
+
+
+class MigrationsNoLegacyNoScopeTest(MigrationsPolicyTest):
+ """Test Migrations API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
class MigrationsScopeTypePolicyTest(MigrationsPolicyTest):
@@ -70,15 +68,14 @@ class MigrationsScopeTypePolicyTest(MigrationsPolicyTest):
super(MigrationsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system reader is able to list migrations.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non system reader is not able to list migrations.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ # With scope enabled, system admin is not allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+
+
+class MigrationsScopeTypeNoLegacyPolicyTest(
+ MigrationsScopeTypePolicyTest):
+ """Test Migrations APIs policies with system scope enabled,
+ and no more deprecated rules.
+ """
+ without_deprecated_rules = True
diff --git a/nova/tests/unit/policies/test_multinic.py b/nova/tests/unit/policies/test_multinic.py
index 21c14bfc57..852ff25965 100644
--- a/nova/tests/unit/policies/test_multinic.py
+++ b/nova/tests/unit/policies/test_multinic.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -45,40 +46,53 @@ class MultinicPolicyTest(base.BasePolicyTest):
id=1, uuid=uuid, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or owner is able to add/remove fixed ip.
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to
+ # add/remove fixed ip.
+ self.project_action_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 and non-owner is not able to add/remove
- # fixed ip.
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_reader_context, self.project_foo_context]
@mock.patch('nova.compute.api.API.add_fixed_ip')
def test_add_fixed_ip_policy(self, mock_add):
rule_name = "os_compute_api:os-multinic:add"
body = dict(addFixedIp=dict(networkId='test_net'))
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name, self.controller._add_fixed_ip,
- self.req, self.instance.uuid,
- body=body)
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name, self.controller._add_fixed_ip,
+ self.req, self.instance.uuid,
+ body=body)
@mock.patch('nova.compute.api.API.remove_fixed_ip')
def test_remove_fixed_ip_policy(self, mock_remove):
rule_name = "os_compute_api:os-multinic:remove"
body = dict(removeFixedIp=dict(address='1.2.3.4'))
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name, self.controller._remove_fixed_ip,
- self.req, self.instance.uuid,
- body=body)
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name, self.controller._remove_fixed_ip,
+ self.req, self.instance.uuid,
+ body=body)
+
+
+class MultinicNoLegacyNoScopePolicyTest(MultinicPolicyTest):
+ """Test Multinic APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.BASE_POLICY_NAME % 'add':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ policies.BASE_POLICY_NAME % 'remove':
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
+
+ def setUp(self):
+ super(MultinicNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to add/remove the fixed ip.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
class MultinicScopeTypePolicyTest(MultinicPolicyTest):
@@ -95,33 +109,26 @@ class MultinicScopeTypePolicyTest(MultinicPolicyTest):
def setUp(self):
super(MultinicScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin to add/remove
+ # the fixed ip.
+ self.project_action_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class MultinicNoLegacyPolicyTest(MultinicScopeTypePolicyTest):
+class MultinicScopeTypeNoLegacyPolicyTest(MultinicScopeTypePolicyTest):
"""Test Multinic APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.BASE_POLICY_NAME % 'add':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
policies.BASE_POLICY_NAME % 'remove':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
def setUp(self):
- super(MultinicNoLegacyPolicyTest, self).setUp()
- # Check that system admin or owner is able to
- # add/delete Fixed IP to server.
- self.admin_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context,
- ]
- # Check that non-system and non-admin/owner is not able
- # to add/delete Fixed IP to server.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
+ super(MultinicScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enable and no legacy rule, only project admin/member
+ # will be able to add/remove the fixed ip.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_networks.py b/nova/tests/unit/policies/test_networks.py
index 9ca018835c..9c3e0b735a 100644
--- a/nova/tests/unit/policies/test_networks.py
+++ b/nova/tests/unit/policies/test_networks.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import networks
@@ -38,7 +39,7 @@ class NetworksPolicyTest(base.BasePolicyTest):
# enforcement so will be passing context's project_id as target to
# policy and always pass. If requester is not admin or owner
# of networks then neutron will be returning the appropriate error.
- self.reader_authorized_contexts = [
+ self.project_reader_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,
@@ -47,23 +48,47 @@ class NetworksPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
- self.reader_unauthorized_contexts = []
@mock.patch('nova.network.neutron.API.get_all')
def test_list_networks_policy(self, mock_get):
rule_name = "os_compute_api:os-networks:list"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
@mock.patch('nova.network.neutron.API.get')
def test_show_network_policy(self, mock_get):
rule_name = "os_compute_api:os-networks:show"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, uuids.fake_id)
+
+
+class NetworksNoLegacyNoScopePolicyTest(NetworksPolicyTest):
+ """Test Networks APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.POLICY_ROOT % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ policies.POLICY_ROOT % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN}
+
+ def setUp(self):
+ super(NetworksNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy, project other roles like foo will not be able
+ # to get network.
+ self.project_reader_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context,
+ self.other_project_reader_context,
+ self.system_member_context, self.system_reader_context,
+ self.other_project_member_context
+ ]
class NetworksScopeTypePolicyTest(NetworksPolicyTest):
@@ -80,30 +105,30 @@ class NetworksScopeTypePolicyTest(NetworksPolicyTest):
def setUp(self):
super(NetworksScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ self.project_reader_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_reader_context,
+ self.other_project_member_context
+ ]
-class NetworksNoLegacyPolicyTest(NetworksScopeTypePolicyTest):
+class NetworksScopeTypeNoLegacyPolicyTest(NetworksScopeTypePolicyTest):
"""Test Networks APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_ROOT % 'list':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
policies.POLICY_ROOT % 'show':
- base_policy.PROJECT_READER_OR_SYSTEM_READER}
+ base_policy.PROJECT_READER_OR_ADMIN}
def setUp(self):
- super(NetworksNoLegacyPolicyTest, self).setUp()
- self.reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context,
+ super(NetworksScopeTypeNoLegacyPolicyTest, self).setUp()
+ self.project_reader_authorized_contexts = [
+ self.legacy_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.other_project_reader_context,
]
- self.reader_unauthorized_contexts = [
- self.project_foo_context,
- self.system_foo_context
- ]
diff --git a/nova/tests/unit/policies/test_pause_server.py b/nova/tests/unit/policies/test_pause_server.py
index 73e78bd55d..86a3e616dd 100644
--- a/nova/tests/unit/policies/test_pause_server.py
+++ b/nova/tests/unit/policies/test_pause_server.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -46,41 +47,32 @@ class PauseServerPolicyTest(base.BasePolicyTest):
user_id=user_id, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
-
- # Check that admin or and server owner is able to pause/unpause
- # the server
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to pause,
+ # unpause the server.
+ self.project_action_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 pause/unpause
- # the server
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.compute.api.API.pause')
def test_pause_server_policy(self, mock_pause):
rule_name = ps_policies.POLICY_ROOT % 'pause'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._pause,
- self.req, self.instance.uuid,
- body={'pause': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._pause,
+ self.req, self.instance.uuid,
+ body={'pause': {}})
@mock.patch('nova.compute.api.API.unpause')
def test_unpause_server_policy(self, mock_unpause):
rule_name = ps_policies.POLICY_ROOT % 'unpause'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._unpause,
- self.req, self.instance.uuid,
- body={'unpause': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._unpause,
+ self.req, self.instance.uuid,
+ body={'unpause': {}})
def test_pause_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -105,6 +97,22 @@ class PauseServerPolicyTest(base.BasePolicyTest):
body={'pause': {}})
+class PauseServerNoLegacyNoScopePolicyTest(PauseServerPolicyTest):
+ """Test Pause/unpause server APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(PauseServerNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to pause/unpause the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+
+
class PauseServerScopeTypePolicyTest(PauseServerPolicyTest):
"""Test Pause Server APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -118,28 +126,20 @@ class PauseServerScopeTypePolicyTest(PauseServerPolicyTest):
def setUp(self):
super(PauseServerScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin to pause/unpause the server.
+ self.project_action_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class PauseServerNoLegacyPolicyTest(PauseServerScopeTypePolicyTest):
+class PauseServerScopeTypeNoLegacyPolicyTest(PauseServerScopeTypePolicyTest):
"""Test Pause Server APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
- super(PauseServerNoLegacyPolicyTest, self).setUp()
- # Check that system admin or server owner is able to pause/unpause
- # the server
- 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 pause/unpause
- # the server
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context, self.project_reader_context,
- self.project_foo_context,
- self.other_project_reader_context,
- ]
+ super(PauseServerScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enable and no legacy rule, only project admin/member
+ # will be able to pause/unpause the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_quota_class_sets.py b/nova/tests/unit/policies/test_quota_class_sets.py
index 276c22fac4..09b90d5ebc 100644
--- a/nova/tests/unit/policies/test_quota_class_sets.py
+++ b/nova/tests/unit/policies/test_quota_class_sets.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import quota_classes
from nova.policies import quota_class_sets as policies
@@ -31,30 +31,12 @@ class QuotaClassSetsPolicyTest(base.BasePolicyTest):
self.controller = quota_classes.QuotaClassSetsController()
self.req = fakes.HTTPRequest.blank('')
- # Check that admin is able to update quota class
- self.admin_authorized_contexts = [
+ # With legacy rule and scope check disabled by default, system admin,
+ # legacy admin, and project admin will be able to get, update quota
+ # class.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to update quota class
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
- # Check that system reader is able to get quota class
- self.system_reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to get quota class
- self.system_reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.objects.Quotas.update_class')
def test_update_quota_class_sets_policy(self, mock_update):
@@ -64,21 +46,30 @@ class QuotaClassSetsPolicyTest(base.BasePolicyTest):
'ram': 51200, 'floating_ips': -1,
'fixed_ips': -1, 'instances': 10,
'injected_files': 5, 'cores': 20}}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.update,
- self.req, 'test_class',
- body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.update,
+ self.req, 'test_class',
+ body=body)
@mock.patch('nova.quota.QUOTAS.get_class_quotas')
def test_show_quota_class_sets_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'show'
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, 'test_class')
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, 'test_class')
+
+
+class QuotaClassSetsNoLegacyNoScopePolicyTest(QuotaClassSetsPolicyTest):
+ """Test QuotaClassSets APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only. In this case
+ system admin, legacy admin, and project admin will be able to get
+ update quota class. Legacy admin will be allowed as policy
+ is just admin if no scope checks.
+
+ """
+ without_deprecated_rules = True
class QuotaClassSetsScopeTypePolicyTest(QuotaClassSetsPolicyTest):
@@ -94,38 +85,17 @@ class QuotaClassSetsScopeTypePolicyTest(QuotaClassSetsPolicyTest):
def setUp(self):
super(QuotaClassSetsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to update and get quota class
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system/admin is not able to update and get quota class
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
- # Check that system reader is able to get quota class
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to get quota class
- self.system_reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
-
-
-class QuotaClassSetsNoLegacyPolicyTest(QuotaClassSetsScopeTypePolicyTest):
- """Test Quota Class Sets APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system APIs.
+
+ # With scope checks enable, only project admins are able to
+ # update and get quota class.
+ self.project_admin_authorized_contexts = [self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class QuotaClassScopeTypeNoLegacyPolicyTest(QuotaClassSetsScopeTypePolicyTest):
+ """Test QuotaClassSets APIs policies with no legacy deprecated rules
+ and scope checks enabled which means scope + new defaults so
+ only system admin is able to update and get quota class.
+
"""
without_deprecated_rules = True
-
- def setUp(self):
- super(QuotaClassSetsNoLegacyPolicyTest, self).setUp()
diff --git a/nova/tests/unit/policies/test_quota_sets.py b/nova/tests/unit/policies/test_quota_sets.py
index 0b8d15c384..3ff8cd1c02 100644
--- a/nova/tests/unit/policies/test_quota_sets.py
+++ b/nova/tests/unit/policies/test_quota_sets.py
@@ -10,9 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import quota_sets
+from nova import exception
from nova.policies import quota_sets as policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
@@ -33,55 +34,29 @@ class QuotaSetsPolicyTest(base.BasePolicyTest):
self.req = fakes.HTTPRequest.blank('')
self.project_id = self.req.environ['nova.context'].project_id
- # Check that admin is able to update or revert quota
- # to default.
- self.admin_authorized_contexts = [
+ # With legacy rule all admin is able to update or revert their quota
+ # to default or get other project quota.
+ self.project_admin_authorized_contexts = set([
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context]
- # Check that non-admin is not able to update or revert
- # quota to default.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that system reader is able to get another project's quota.
- self.system_reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to get another
- # project's quota.
- self.system_reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that everyone is able to get the default quota or
- # their own quota.
- self.everyone_authorized_contexts = [
+ self.project_admin_context])
+ # With legacy rule, everyone is able to get their own quota.
+ self.project_reader_authorized_contexts = set([
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
- self.other_project_reader_context
- ]
- self.everyone_unauthorized_contexts = []
- # Check that system reader or owner is able to get their own quota.
- self.system_reader_or_owner_authorized_contexts = [
+ self.other_project_reader_context])
+ # Everyone is able to get the default quota
+ self.everyone_authorized_contexts = set([
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
- self.other_project_reader_context
- ]
+ self.other_project_reader_context])
@mock.patch('nova.quota.QUOTAS.get_project_quotas')
@mock.patch('nova.quota.QUOTAS.get_settable_quotas')
@@ -91,41 +66,57 @@ class QuotaSetsPolicyTest(base.BasePolicyTest):
'instances': 50,
'cores': 50}
}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.update,
- self.req, self.project_id,
- body=body)
+ for cxtx in self.project_admin_authorized_contexts:
+ req = fakes.HTTPRequest.blank('')
+ req.environ['nova.context'] = cxtx
+ self.controller.update(req, cxtx.project_id, body=body)
+ for cxtx in (self.all_contexts -
+ set(self.project_admin_authorized_contexts)):
+ req = fakes.HTTPRequest.blank('')
+ req.environ['nova.context'] = cxtx
+ exc = self.assertRaises(
+ exception.PolicyNotAuthorized, self.controller.update,
+ req, cxtx.project_id, body=body)
+ self.assertEqual(
+ "Policy doesn't allow %s to be performed." % rule_name,
+ exc.format_message())
@mock.patch('nova.objects.Quotas.destroy_all_by_project')
def test_delete_quota_sets_policy(self, mock_delete):
rule_name = policies.POLICY_ROOT % 'delete'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, self.project_id)
+ for cxtx in self.project_admin_authorized_contexts:
+ req = fakes.HTTPRequest.blank('')
+ req.environ['nova.context'] = cxtx
+ self.controller.delete(req, cxtx.project_id)
+ for cxtx in (self.all_contexts -
+ set(self.project_admin_authorized_contexts)):
+ req = fakes.HTTPRequest.blank('')
+ req.environ['nova.context'] = cxtx
+ exc = self.assertRaises(
+ exception.PolicyNotAuthorized, self.controller.delete,
+ req, cxtx.project_id)
+ self.assertEqual(
+ "Policy doesn't allow %s to be performed." % rule_name,
+ exc.format_message())
@mock.patch('nova.quota.QUOTAS.get_defaults')
def test_default_quota_sets_policy(self, mock_default):
rule_name = policies.POLICY_ROOT % 'defaults'
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name,
- self.controller.defaults,
- self.req, self.project_id)
+ self.common_policy_auth(self.everyone_authorized_contexts,
+ rule_name,
+ self.controller.defaults,
+ self.req, self.project_id)
@mock.patch('nova.quota.QUOTAS.get_project_quotas')
def test_detail_quota_sets_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'detail'
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name,
- self.controller.detail,
- self.req, 'try-other-project')
- # Check if everyone (owner) is able to get their own quota
- for cxtx in self.system_reader_or_owner_authorized_contexts:
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.detail,
+ self.req, 'try-other-project')
+ # Check if project reader or higher roles are able to get
+ # their own quota
+ for cxtx in self.project_reader_authorized_contexts:
req = fakes.HTTPRequest.blank('')
req.environ['nova.context'] = cxtx
self.controller.detail(req, cxtx.project_id)
@@ -133,18 +124,44 @@ class QuotaSetsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.quota.QUOTAS.get_project_quotas')
def test_show_quota_sets_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'show'
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, 'try-other-project')
- # Check if everyone (owner) is able to get their own quota
- for cxtx in self.system_reader_or_owner_authorized_contexts:
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, 'try-other-project')
+ # Check if project reader or higher roles are able to get
+ # their own quota
+ for cxtx in self.project_reader_authorized_contexts:
req = fakes.HTTPRequest.blank('')
req.environ['nova.context'] = cxtx
self.controller.show(req, cxtx.project_id)
+class QuotaSetsNoLegacyNoScopePolicyTest(QuotaSetsPolicyTest):
+ """Test QuotaSets APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(QuotaSetsNoLegacyNoScopePolicyTest, self).setUp()
+ # Even with no legacy rule, because any admin requesting
+ # update/revert quota for their own project will be allowed.
+ # And any admin will be able to get other project quota.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context]
+ # With no legacy rule, other project and foo role will not be
+ # able to get the quota.
+ self.project_reader_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context,
+ self.system_member_context, self.system_reader_context,
+ self.project_member_context,
+ self.project_reader_context]
+
+
class QuotaSetsScopeTypePolicyTest(QuotaSetsPolicyTest):
"""Test Quota Sets APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -159,23 +176,16 @@ class QuotaSetsScopeTypePolicyTest(QuotaSetsPolicyTest):
super(QuotaSetsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to update or revert quota
- # to default.
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system admin is not able to update or revert
- # quota to default.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.project_admin_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
+ # With scope enabled, system users will be disallowed.
+ self.reduce_set('project_admin_authorized', set([
+ self.legacy_admin_context,
+ self.project_admin_context]))
+ self.reduce_set('project_reader_authorized',
+ self.all_project_contexts)
+ self.everyone_authorized_contexts = self.all_project_contexts
-class QuotaSetsNoLegacyPolicyTest(QuotaSetsScopeTypePolicyTest):
+class QuotaSetsScopeTypeNoLegacyPolicyTest(QuotaSetsScopeTypePolicyTest):
"""Test Quota Sets APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@@ -183,28 +193,9 @@ class QuotaSetsNoLegacyPolicyTest(QuotaSetsScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
- super(QuotaSetsNoLegacyPolicyTest, self).setUp()
-
- # Check that system reader is able to get another project's quota.
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to get anotherproject's
- # quota.
- self.system_reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that everyone is able to get their own quota.
- self.system_reader_or_owner_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.project_member_context,
- self.project_reader_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
+ super(QuotaSetsScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enabled and no legacy, system and
+ # non-reader/member users are disallowed.
+ self.reduce_set('project_reader_authorized',
+ self.all_project_contexts -
+ set([self.project_foo_context]))
diff --git a/nova/tests/unit/policies/test_remote_consoles.py b/nova/tests/unit/policies/test_remote_consoles.py
index 825f78a938..a441d1c550 100644
--- a/nova/tests/unit/policies/test_remote_consoles.py
+++ b/nova/tests/unit/policies/test_remote_consoles.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from nova.policies import remote_consoles as rc_policies
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -48,31 +49,38 @@ class RemoteConsolesPolicyTest(base.BasePolicyTest):
user_id=user_id, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
-
- # Check that admin or and server owner is able to get server
- # remote consoles.
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to get
+ # server remote consoles.
+ self.project_action_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 server
- # remote consoles.
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
def test_create_console_policy(self):
rule_name = rc_policies.BASE_POLICY_NAME
body = {'remote_console': {'protocol': 'vnc', 'type': 'novnc'}}
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.create,
- self.req, self.instance.uuid,
- body=body)
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ self.req, self.instance.uuid,
+ body=body)
+
+
+class RemoteConsolesNoLegacyNoScopePolicyTest(RemoteConsolesPolicyTest):
+ """Test Remote Consoles APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(RemoteConsolesNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able get server remote consoles.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
class RemoteConsolesScopeTypePolicyTest(RemoteConsolesPolicyTest):
@@ -88,9 +96,14 @@ class RemoteConsolesScopeTypePolicyTest(RemoteConsolesPolicyTest):
def setUp(self):
super(RemoteConsolesScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin to get server
+ # remote console.
+ self.project_action_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class RemoteConsolesNoLegacyPolicyTest(RemoteConsolesScopeTypePolicyTest):
+class RemoteConsolesScopeTypeNoLegacyPolicyTest(
+ RemoteConsolesScopeTypePolicyTest):
"""Test Remote Consoles APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@@ -98,18 +111,8 @@ class RemoteConsolesNoLegacyPolicyTest(RemoteConsolesScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
- super(RemoteConsolesNoLegacyPolicyTest, self).setUp()
- # Check that system admin or and server owner is able to get server
- # remote consoles.
- 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 get server
- # remote consoles.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context, self.project_reader_context,
- self.project_foo_context,
- self.other_project_reader_context,
- ]
+ super(RemoteConsolesScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enable and no legacy rule, only project admin/member
+ # will be able to get server remote console.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_rescue.py b/nova/tests/unit/policies/test_rescue.py
index f970425b40..120809877c 100644
--- a/nova/tests/unit/policies/test_rescue.py
+++ b/nova/tests/unit/policies/test_rescue.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from nova.policies import base as base_policy
from nova.policies import rescue as rs_policies
from oslo_utils.fixture import uuidsentinel as uuids
@@ -48,40 +49,32 @@ class RescueServerPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or and server owner is able to rescue/unrescue
- # the sevrer
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to rescue,
+ # unrescue the server.
+ self.project_action_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 rescue/unrescue
- # the server
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.compute.api.API.rescue')
def test_rescue_server_policy(self, mock_rescue):
rule_name = rs_policies.BASE_POLICY_NAME
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._rescue,
- self.req, self.instance.uuid,
- body={'rescue': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._rescue,
+ self.req, self.instance.uuid,
+ body={'rescue': {}})
@mock.patch('nova.compute.api.API.unrescue')
def test_unrescue_server_policy(self, mock_unrescue):
rule_name = rs_policies.UNRESCUE_POLICY_NAME
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._unrescue,
- self.req, self.instance.uuid,
- body={'unrescue': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._unrescue,
+ self.req, self.instance.uuid,
+ body={'unrescue': {}})
def test_rescue_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -97,7 +90,7 @@ class RescueServerPolicyTest(base.BasePolicyTest):
exc.format_message())
@mock.patch('nova.compute.api.API.rescue')
- def test_rescue_sevrer_overridden_policy_pass_with_same_user(
+ def test_rescue_server_overridden_policy_pass_with_same_user(
self, mock_rescue):
rule_name = rs_policies.BASE_POLICY_NAME
self.policy.set_rules({rule_name: "user_id:%(user_id)s"})
@@ -106,6 +99,27 @@ class RescueServerPolicyTest(base.BasePolicyTest):
body={'rescue': {}})
+class RescueServerNoLegacyNoScopePolicyTest(RescueServerPolicyTest):
+ """Test rescue/unrescue server APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ rs_policies.UNRESCUE_POLICY_NAME:
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ rs_policies.BASE_POLICY_NAME:
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
+
+ def setUp(self):
+ super(RescueServerNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to rescue/unrescue the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+
+
class RescueServerScopeTypePolicyTest(RescueServerPolicyTest):
"""Test Rescue Server APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -119,9 +133,13 @@ class RescueServerScopeTypePolicyTest(RescueServerPolicyTest):
def setUp(self):
super(RescueServerScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin to rescue/unrescue the
+ # server.
+ self.project_action_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class RescueServerNoLegacyPolicyTest(RescueServerScopeTypePolicyTest):
+class RescueServerScopeTypeNoLegacyPolicyTest(RescueServerScopeTypePolicyTest):
"""Test Rescue Server APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@@ -129,23 +147,13 @@ class RescueServerNoLegacyPolicyTest(RescueServerScopeTypePolicyTest):
without_deprecated_rules = True
rules_without_deprecation = {
rs_policies.UNRESCUE_POLICY_NAME:
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
rs_policies.BASE_POLICY_NAME:
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
def setUp(self):
- super(RescueServerNoLegacyPolicyTest, self).setUp()
- # Check that system admin or and server owner is able to
- # rescue/unrescue the sevrer
- 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 rescue/unrescue
- # the server
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context, self.project_reader_context,
- self.project_foo_context,
- self.other_project_reader_context,
- ]
+ super(RescueServerScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enable and no legacy rule, only project admin/member
+ # will be able to rescue/unrescue the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_security_groups.py b/nova/tests/unit/policies/test_security_groups.py
index 5fb35f83a0..a9d2f484ba 100644
--- a/nova/tests/unit/policies/test_security_groups.py
+++ b/nova/tests/unit/policies/test_security_groups.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -48,62 +49,75 @@ class ServerSecurityGroupsPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or and server owner is able to operate
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to operate
# server security groups.
- self.admin_or_owner_authorized_contexts = [
+ self.project_member_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 operate
- # server security groups.
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
-
- self.reader_authorized_contexts = [
+ # With legacy rule, any admin or project role is able to get their
+ # server SG.
+ self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_member_context, self.project_foo_context
- ]
-
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context, self.project_foo_context,
]
@mock.patch('nova.network.security_group_api.get_instance_security_groups')
def test_get_security_groups_policy(self, mock_get):
rule_name = policies.POLICY_NAME % 'list'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req, self.instance.uuid)
@mock.patch('nova.network.security_group_api.add_to_instance')
def test_add_security_groups_policy(self, mock_add):
rule_name = policies.POLICY_NAME % 'add'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.action_ctr._addSecurityGroup,
- self.req, self.instance.uuid,
- body={'addSecurityGroup':
- {'name': 'fake'}})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.action_ctr._addSecurityGroup,
+ self.req, self.instance.uuid,
+ body={'addSecurityGroup':
+ {'name': 'fake'}})
@mock.patch('nova.network.security_group_api.remove_from_instance')
def test_remove_security_groups_policy(self, mock_remove):
rule_name = policies.POLICY_NAME % 'remove'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.action_ctr._removeSecurityGroup,
- self.req, self.instance.uuid,
- body={'removeSecurityGroup':
- {'name': 'fake'}})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.action_ctr._removeSecurityGroup,
+ self.req, self.instance.uuid,
+ body={'removeSecurityGroup':
+ {'name': 'fake'}})
+
+
+class ServerSecurityGroupsNoLegacyNoScopePolicyTest(
+ ServerSecurityGroupsPolicyTest):
+ """Test Server Security Groups server APIs policies with no legacy
+ deprecated rules and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.POLICY_NAME % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ policies.POLICY_NAME % 'add':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ policies.POLICY_NAME % 'remove':
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
+
+ def setUp(self):
+ super(ServerSecurityGroupsNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to add/remove SG to server and reader to get SG.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
class SecurityGroupsPolicyTest(base.BasePolicyTest):
@@ -120,14 +134,23 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
self.rule_ctr = security_groups.SecurityGroupRulesController()
self.req = fakes.HTTPRequest.blank('')
- # Check that everyone is able to perform crud operation on.
- # security groups.
+ # With legacy and scope disabled, everyone is able to perform crud
+ # operation on security groups.
# NOTE(gmann): Nova cannot verify the security groups owner during
# nova policy enforcement so will be passing context's project_id
# as target to policy and always pass. If requester is not admin
# or owner of security groups then neutron will be returning the
# appropriate error.
- self.reader_authorized_contexts = [
+ self.project_member_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,
+ self.other_project_reader_context,
+ self.system_member_context, self.system_reader_context,
+ self.system_foo_context,
+ self.other_project_member_context
+ ]
+ self.project_reader_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,
@@ -136,29 +159,22 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
- self.reader_unauthorized_contexts = []
- self.sys_admin_or_owner_authorized_contexts = (
- self.reader_authorized_contexts)
- self.sys_admin_or_owner_unauthorized_contexts = (
- self.reader_unauthorized_contexts)
@mock.patch('nova.network.security_group_api.list')
def test_list_security_groups_policy(self, mock_get):
rule_name = policies.POLICY_NAME % 'get'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req)
@mock.patch('nova.network.security_group_api.get')
def test_show_security_groups_policy(self, mock_get):
rule_name = policies.POLICY_NAME % 'show'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, uuids.fake_id)
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.update_security_group')
@@ -167,11 +183,10 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
body = {'security_group': {
'name': 'test',
'description': 'test-desc'}}
- self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
- self.sys_admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.update,
- self.req, uuids.fake_id, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.update,
+ self.req, uuids.fake_id, body=body)
@mock.patch('nova.network.security_group_api.create_security_group')
def test_create_security_groups_policy(self, mock_create):
@@ -179,21 +194,19 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
body = {'security_group': {
'name': 'test',
'description': 'test-desc'}}
- self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
- self.sys_admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ self.req, body=body)
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.destroy')
def test_delete_security_groups_policy(self, mock_destroy, mock_get):
rule_name = policies.POLICY_NAME % 'delete'
- self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
- self.sys_admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ self.req, uuids.fake_id)
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.create_security_group_rule')
@@ -202,12 +215,11 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
body = {'security_group_rule': {
'ip_protocol': 'test', 'group_id': uuids.fake_id,
'parent_group_id': uuids.fake_id,
- 'from_port': 22, 'from_port': 22}}
- self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
- self.sys_admin_or_owner_unauthorized_contexts,
- rule_name,
- self.rule_ctr.create,
- self.req, body=body)
+ 'from_port': 22}}
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.rule_ctr.create,
+ self.req, body=body)
@mock.patch('nova.network.security_group_api.get_rule')
@mock.patch('nova.network.security_group_api.get')
@@ -215,11 +227,52 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
def test_delete_security_group_rules_policy(self, mock_remove, mock_get,
mock_rules):
rule_name = policies.POLICY_NAME % 'rule:delete'
- self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
- self.sys_admin_or_owner_unauthorized_contexts,
- rule_name,
- self.rule_ctr.delete,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.rule_ctr.delete,
+ self.req, uuids.fake_id)
+
+
+class SecurityGroupsNoLegacyNoScopePolicyTest(
+ SecurityGroupsPolicyTest):
+ """Test Security Groups APIs policies with system scope enabled,
+ and no more deprecated rules.
+ """
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.POLICY_NAME % 'get':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ policies.POLICY_NAME % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ policies.POLICY_NAME % 'create':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ policies.POLICY_NAME % 'update':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ policies.POLICY_NAME % 'delete':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ policies.POLICY_NAME % 'rule:create':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ policies.POLICY_NAME % 'rule:delete':
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
+
+ def setUp(self):
+ super(SecurityGroupsNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy, project other roles like foo will not be able
+ # to operate on SG.
+ 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.other_project_member_context
+ ]
+ self.project_reader_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context,
+ self.other_project_reader_context,
+ self.system_member_context, self.system_reader_context,
+ self.other_project_member_context
+ ]
class SecurityGroupsScopeTypePolicyTest(SecurityGroupsPolicyTest):
@@ -235,6 +288,20 @@ class SecurityGroupsScopeTypePolicyTest(SecurityGroupsPolicyTest):
def setUp(self):
super(SecurityGroupsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope enabled, system users will not be able to
+ # operate on SG.
+ 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_reader_context,
+ self.other_project_member_context
+ ]
+ self.project_reader_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_reader_context,
+ self.other_project_member_context
+ ]
class ServerSecurityGroupsScopeTypePolicyTest(ServerSecurityGroupsPolicyTest):
@@ -251,102 +318,71 @@ class ServerSecurityGroupsScopeTypePolicyTest(ServerSecurityGroupsPolicyTest):
def setUp(self):
super(ServerSecurityGroupsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system users.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class ServerSecurityGroupsNoLegacyPolicyTest(
+class ServerSecurityGroupsScopeTypeNoLegacyPolicyTest(
ServerSecurityGroupsScopeTypePolicyTest):
"""Test Security Groups APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'list':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
policies.POLICY_NAME % 'add':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
policies.POLICY_NAME % 'remove':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
def setUp(self):
- super(ServerSecurityGroupsNoLegacyPolicyTest, self).setUp()
-
- # Check that system or projct admin or owner is able to operate
- # server security groups.
- self.admin_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context]
- # Check that non-system and non-admin/owner is not able to operate
- # server security groups.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.project_reader_context,
- self.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context]
-
- # Check that system reader or projct is able to get
- # server security groups.
- self.reader_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_member_context,
- ]
-
- # Check that non-system reader nd non-admin/owner is not able to get
- # server security groups.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
+ super(ServerSecurityGroupsScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enable and no legacy rule, only project admin/member
+ # will be able to add/remove the SG to their server and reader
+ # will get SG of server.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
class SecurityGroupsNoLegacyPolicyTest(SecurityGroupsScopeTypePolicyTest):
"""Test Security Groups APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'get':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
policies.POLICY_NAME % 'show':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
policies.POLICY_NAME % 'create':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
policies.POLICY_NAME % 'update':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
policies.POLICY_NAME % 'delete':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
policies.POLICY_NAME % 'rule:create':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
policies.POLICY_NAME % 'rule:delete':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
def setUp(self):
super(SecurityGroupsNoLegacyPolicyTest, self).setUp()
-
- self.reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context,
+ # With no legacy and scope enabled, system users and project
+ # other roles like foo will not be able to operate SG.
+ self.project_member_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context,
+ self.other_project_member_context
+ ]
+ self.project_reader_authorized_contexts = [
+ self.legacy_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.other_project_reader_context,
- ]
- self.reader_unauthorized_contexts = [
- self.project_foo_context,
- self.system_foo_context
- ]
- self.sys_admin_or_owner_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.project_admin_context, self.project_member_context,
- self.legacy_admin_context, self.other_project_member_context
- ]
- self.sys_admin_or_owner_unauthorized_contexts = [
- self.system_reader_context,
- self.project_reader_context, self.project_foo_context,
- self.system_foo_context, self.other_project_reader_context
+ self.other_project_member_context
]
diff --git a/nova/tests/unit/policies/test_server_diagnostics.py b/nova/tests/unit/policies/test_server_diagnostics.py
index 04a099a7a3..4a4b192baa 100644
--- a/nova/tests/unit/policies/test_server_diagnostics.py
+++ b/nova/tests/unit/policies/test_server_diagnostics.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -46,26 +47,24 @@ class ServerDiagnosticsPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin is able to get server diagnostics.
- self.admin_authorized_contexts = [
+ # With legacy rule, any admin is able get server diagnostics.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context
- ]
- # Check that non-admin is not able to get server diagnostics.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_admin_context]
def test_server_diagnostics_policy(self):
rule_name = policies.BASE_POLICY_NAME
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req, self.instance.uuid)
+
+
+class ServerDiagnosticsNoLegacyNoScopeTest(ServerDiagnosticsPolicyTest):
+ """Test Server Diagnostics API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
class ServerDiagnosticsScopeTypePolicyTest(ServerDiagnosticsPolicyTest):
@@ -82,33 +81,21 @@ class ServerDiagnosticsScopeTypePolicyTest(ServerDiagnosticsPolicyTest):
def setUp(self):
super(ServerDiagnosticsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope enabled, system admin is not allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class ServerDiagnosticsNoLegacyPolicyTest(
+class ServerDiagnosticsScopeTypeNoLegacyPolicyTest(
ServerDiagnosticsScopeTypePolicyTest):
"""Test Server Diagnostics APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
- def setUp(self):
- super(ServerDiagnosticsNoLegacyPolicyTest, self).setUp()
- # Check that system admin is able to get server diagnostics.
- self.admin_authorized_contexts = [
- self.system_admin_context
- ]
- # Check that non system admin is not able to get server diagnostics.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
-
-
-class ServerDiagnosticsOverridePolicyTest(ServerDiagnosticsNoLegacyPolicyTest):
+
+class ServerDiagnosticsOverridePolicyTest(
+ ServerDiagnosticsScopeTypeNoLegacyPolicyTest):
"""Test Server Diagnostics APIs policies with system and project scoped
but default to system roles only are allowed for project roles
if override by operators. This test is with system scope enable
@@ -119,22 +106,12 @@ class ServerDiagnosticsOverridePolicyTest(ServerDiagnosticsNoLegacyPolicyTest):
super(ServerDiagnosticsOverridePolicyTest, self).setUp()
rule = policies.BASE_POLICY_NAME
# NOTE(gmann): override the rule to project member and verify it
- # work as policy is system and projct scoped.
+ # work as policy is project scoped.
self.policy.set_rules({
- rule: base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN},
+ rule: base_policy.PROJECT_MEMBER},
overwrite=False)
- # Check that system admin or project scoped role as override above
+ # Check that project member role as override above
# is able to get server diagnostics.
- self.admin_authorized_contexts = [
- self.system_admin_context,
+ self.project_admin_authorized_contexts = [
self.project_admin_context, self.project_member_context]
- # Check that non-system admin or project role is not able to
- # get server diagnostics.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context,
- self.project_foo_context, self.project_reader_context,
- self.other_project_reader_context,
- ]
diff --git a/nova/tests/unit/policies/test_server_external_events.py b/nova/tests/unit/policies/test_server_external_events.py
index f8f1bcd663..401b55325f 100644
--- a/nova/tests/unit/policies/test_server_external_events.py
+++ b/nova/tests/unit/policies/test_server_external_events.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import server_external_events as ev
@@ -33,20 +34,12 @@ class ServerExternalEventsPolicyTest(base.BasePolicyTest):
self.controller = ev.ServerExternalEventsController()
self.req = fakes.HTTPRequest.blank('')
- # Check that admin is able to create the server external events.
- self.admin_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin can
+ # create the server external events.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context
]
- # Check that non-admin is not able to create the server
- # external events.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.compute.api.API.external_instance_event')
@mock.patch('nova.objects.InstanceMappingList.get_by_instance_uuids')
@@ -58,10 +51,18 @@ class ServerExternalEventsPolicyTest(base.BasePolicyTest):
'server_uuid': uuids.fake_id,
'status': 'completed'}]
}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.create,
+ self.req, body=body)
+
+
+class ServerExternalEventsNoLegacyNoScopeTest(
+ ServerExternalEventsPolicyTest):
+ """Test Server External Events API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
class ServerExternalEventsScopeTypePolicyTest(ServerExternalEventsPolicyTest):
@@ -79,23 +80,12 @@ class ServerExternalEventsScopeTypePolicyTest(ServerExternalEventsPolicyTest):
super(ServerExternalEventsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that admin is able to create the server external events.
- self.admin_authorized_contexts = [
- self.system_admin_context,
- ]
- # Check that non-admin is not able to create the server
- # external events.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ # With scope checks, system admin is not allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class ServerExternalEventsNoLegacyPolicyTest(
+class ServerExternalEventsScopeTypeNoLegacyPolicyTest(
ServerExternalEventsScopeTypePolicyTest):
"""Test Server External Events APIs policies with system scope enabled,
and no more deprecated rules.
diff --git a/nova/tests/unit/policies/test_server_groups.py b/nova/tests/unit/policies/test_server_groups.py
index 0c8b3de0cd..b0df7ccb89 100644
--- a/nova/tests/unit/policies/test_server_groups.py
+++ b/nova/tests/unit/policies/test_server_groups.py
@@ -9,17 +9,22 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+import functools
+
+from unittest import mock
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import server_groups
+import nova.conf
from nova import objects
from nova.policies import server_groups as policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
+CONF = nova.conf.CONF
+
class ServerGroupPolicyTest(base.BasePolicyTest):
"""Test Server Groups APIs policies with all possible context.
@@ -45,98 +50,85 @@ 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 delete
- # the server group.
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or project any role(because legacy rule allow SG
+ # owner- having same project id and no role check) is able to
+ # delete and get SG.
+ self.project_member_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 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,
- self.other_project_reader_context,
+ self.project_reader_context, self.project_foo_context,
]
- # 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.project_reader_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,
- self.other_project_reader_context,
+ self.project_reader_context, self.project_foo_context,
]
- # Check that everyone is able to list
- # theie own server group. Due to old defaults everyone
- # is able to list their server groups.
+ # By default, legacy rule are enabled and scope check is disabled.
+ # system admin, legacy admin, and project admin is able to get
+ # all projects SG.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context]
+
+ # List SG can not check for project id so everyone is allowed.
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.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
self.other_project_reader_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_member_context, self.system_reader_context,
self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
+ self.other_project_member_context
]
- self.project_member_unauthorized_contexts = []
+
+ # With legacy rule, anyone can create SG.
+ self.project_create_authorized_contexts = (
+ self.everyone_authorized_contexts)
@mock.patch('nova.objects.InstanceGroupList.get_by_project_id')
def test_index_server_groups_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req)
+ self.common_policy_auth(self.everyone_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req)
@mock.patch('nova.objects.InstanceGroupList.get_all')
- def test_index_all_project_server_groups_policy(self, mock_get_all):
+ @mock.patch('nova.objects.InstanceGroupList.get_by_project_id')
+ def test_index_all_project_server_groups_policy(self, mock_get,
+ mock_get_all):
mock_get_all.return_value = objects.InstanceGroupList(objects=self.sg)
+ mock_get.return_value = objects.InstanceGroupList(
+ objects=[self.sg[0]])
# 'index' policy is checked before 'index:all_projects' so
# we have to allow it for everyone otherwise it will fail for
# unauthorized contexts here.
rule = policies.POLICY_ROOT % 'index'
self.policy.set_rules({rule: "@"}, overwrite=False)
- admin_req = fakes.HTTPRequest.blank(
- '/os-server-groups?all_projects=True',
- version='2.13', use_admin_context=True)
- # Check admin user get all projects server groups.
- resp = self.controller.index(admin_req)
- projs = [sg['project_id'] for sg in resp['server_groups']]
- self.assertEqual(2, len(projs))
- self.assertIn('proj2', projs)
- # Check non-admin user does not get all projects server groups.
- req = fakes.HTTPRequest.blank('/os-server-groups?all_projects=True',
- version='2.13')
- resp = self.controller.index(req)
- projs = [sg['project_id'] for sg in resp['server_groups']]
- self.assertNotIn('proj2', projs)
+ rule_name = policies.POLICY_ROOT % 'index:all_projects'
+ req = fakes.HTTPRequest.blank('?all_projects', version='2.13')
+ if not CONF.oslo_policy.enforce_scope:
+ check_rule = rule_name
+ else:
+ check_rule = functools.partial(base.rule_if_system,
+ rule, rule_name)
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
+ check_rule, self.controller.index,
+ req, fatal=False)
+ for resp in authorize_res:
+ projs = [sg['project_id'] for sg in resp['server_groups']]
+ self.assertEqual(2, len(projs))
+ self.assertIn('proj2', projs)
+ for resp in unauthorize_res:
+ projs = [sg['project_id'] for sg in resp['server_groups']]
+ self.assertNotIn('proj2', projs)
def test_show_server_groups_policy(self):
rule_name = policies.POLICY_ROOT % 'show'
- self.common_policy_check(
- self.system_reader_or_owner_authorized_contexts,
- self.system_reader_or_owner_unauthorized_contexts,
+ self.common_policy_auth(
+ self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, uuids.fake_id)
@@ -146,20 +138,54 @@ class ServerGroupPolicyTest(base.BasePolicyTest):
rule_name = policies.POLICY_ROOT % 'create'
body = {'server_group': {'name': 'fake',
'policies': ['affinity']}}
- self.common_policy_check(self.project_member_authorized_contexts,
- self.project_member_unauthorized_contexts,
- rule_name,
- self.controller.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_create_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ self.req, body=body)
@mock.patch('nova.objects.InstanceGroup.destroy')
def test_delete_server_groups_policy(self, mock_destroy):
rule_name = policies.POLICY_ROOT % 'delete'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, uuids.fake_id)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ self.req, uuids.fake_id)
+
+
+class ServerGroupNoLegacyNoScopePolicyTest(ServerGroupPolicyTest):
+ """Test Server Groups APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(ServerGroupNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy, only project admin, member will be able to delete
+ # the SG and also reader will be able to get the SG.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
+
+ # Even with no legacy rule, legacy admin is allowed to create SG
+ # use requesting context's project_id. Same for list SG.
+ self.project_create_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ self.system_member_context, self.other_project_member_context]
+
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_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.other_project_reader_context,
+ self.system_member_context, self.system_reader_context,
+ self.other_project_member_context
+ ]
class ServerGroupScopeTypePolicyTest(ServerGroupPolicyTest):
@@ -176,27 +202,31 @@ 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 = [
+ # With scope enable, it disallow system users.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+
+ self.project_create_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,
+ self.project_foo_context, self.other_project_reader_context,
+ self.other_project_member_context]
+
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+
+ self.everyone_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_reader_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):
- pass
-class ServerGroupNoLegacyPolicyTest(ServerGroupScopeTypePolicyTest):
+class ServerGroupScopeTypeNoLegacyPolicyTest(ServerGroupScopeTypePolicyTest):
"""Test Server Group APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@@ -204,58 +234,25 @@ class ServerGroupNoLegacyPolicyTest(ServerGroupScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
- super(ServerGroupNoLegacyPolicyTest, self).setUp()
+ super(ServerGroupScopeTypeNoLegacyPolicyTest, self).setUp()
+
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+
+ self.project_create_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context,
+ self.other_project_member_context]
+
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
+
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
- # 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,
- self.other_project_reader_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.other_project_reader_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.other_project_reader_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,
+ self.project_member_context, self.project_reader_context,
self.other_project_reader_context,
+ self.other_project_member_context
]
diff --git a/nova/tests/unit/policies/test_server_ips.py b/nova/tests/unit/policies/test_server_ips.py
index 29bd2d81c4..b837d2d0e2 100644
--- a/nova/tests/unit/policies/test_server_ips.py
+++ b/nova/tests/unit/policies/test_server_ips.py
@@ -49,37 +49,43 @@ class ServerIpsPolicyTest(base.BasePolicyTest):
self.mock_get_network.return_value = {'net1':
{'ips': '', 'floating_ips': ''}}
- # Check that admin or and server owner is able to get server
- # IP addresses.
- self.reader_or_owner_authorized_contexts = [
+ # With legacy rule, any admin or project role is able to get their
+ # server IP addresses.
+ self.project_reader_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,
- self.system_member_context, self.system_reader_context]
- # Check that non-admin/owner is not able to get the server IP
- # adderesses
- self.reader_or_owner_unauthorized_contexts = [
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
]
def test_index_ips_policy(self):
rule_name = ips_policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.reader_or_owner_authorized_contexts,
- self.reader_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req, self.instance.uuid)
def test_show_ips_policy(self):
rule_name = ips_policies.POLICY_ROOT % 'show'
- self.common_policy_check(self.reader_or_owner_authorized_contexts,
- self.reader_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, self.instance.uuid,
- 'net1')
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, self.instance.uuid,
+ 'net1')
+
+
+class ServerIpsNoLegacyNoScopePolicyTest(ServerIpsPolicyTest):
+ """Test Server Ips APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(ServerIpsNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy, only project admin, member, and reader will be able
+ # to get their server IP addresses.
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
class ServerIpsScopeTypePolicyTest(ServerIpsPolicyTest):
@@ -95,28 +101,21 @@ class ServerIpsScopeTypePolicyTest(ServerIpsPolicyTest):
def setUp(self):
super(ServerIpsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope enabled, system users will not be able
+ # to get the server IP addresses.
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class ServerIpsNoLegacyPolicyTest(ServerIpsScopeTypePolicyTest):
+class ServerIpsScopeTypeNoLegacyPolicyTest(ServerIpsScopeTypePolicyTest):
"""Test Server IPs APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
- super(ServerIpsNoLegacyPolicyTest, self).setUp()
-
- # Check that system reader or owner is able to
- # get the server IP adderesses.
- self.reader_or_owner_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.project_admin_context,
- self.project_member_context, self.project_reader_context]
- # Check that non-system and non-owner is not able to
- # get the server IP adderesses.
- self.reader_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ super(ServerIpsScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With no legacy and scope enable, only admin, member,
+ # and reader will be able to get their server IP addresses.
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_server_metadata.py b/nova/tests/unit/policies/test_server_metadata.py
index 89c6480adc..cf4fb19e7b 100644
--- a/nova/tests/unit/policies/test_server_metadata.py
+++ b/nova/tests/unit/policies/test_server_metadata.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import server_metadata
@@ -40,92 +41,88 @@ class ServerMetadataPolicyTest(base.BasePolicyTest):
id=1, uuid=uuids.fake_id, project_id=self.project_id)
self.mock_get.return_value = self.instance
- # Check that admin or and server owner is able to CRUD
- # the server metadata.
- 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 CRUD
- # the server metadata
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that admin or and server owner is able to get
- # the server metadata.
- self.reader_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to create,
+ # update, and delete the server metadata.
+ self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.system_member_context, self.system_reader_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
- # the server metadata.
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
+ # and they can get their own server metadata.
+ self.project_reader_authorized_contexts = (
+ self.project_member_authorized_contexts)
@mock.patch('nova.compute.api.API.get_instance_metadata')
def test_index_server_Metadata_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req, self.instance.uuid)
@mock.patch('nova.compute.api.API.get_instance_metadata')
def test_show_server_Metadata_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'show'
mock_get.return_value = {'key9': 'value'}
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, self.instance.uuid, 'key9')
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, self.instance.uuid, 'key9')
@mock.patch('nova.compute.api.API.update_instance_metadata')
def test_create_server_Metadata_policy(self, mock_quota):
rule_name = policies.POLICY_ROOT % 'create'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.create,
- self.req, self.instance.uuid,
- body={"metadata": {"key9": "value9"}})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ self.req, self.instance.uuid,
+ body={"metadata": {"key9": "value9"}})
@mock.patch('nova.compute.api.API.update_instance_metadata')
def test_update_server_Metadata_policy(self, mock_quota):
rule_name = policies.POLICY_ROOT % 'update'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.update,
- self.req, self.instance.uuid, 'key9',
- body={"meta": {"key9": "value9"}})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.update,
+ self.req, self.instance.uuid, 'key9',
+ body={"meta": {"key9": "value9"}})
@mock.patch('nova.compute.api.API.update_instance_metadata')
def test_update_all_server_Metadata_policy(self, mock_quota):
rule_name = policies.POLICY_ROOT % 'update_all'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.update_all,
- self.req, self.instance.uuid,
- body={"metadata": {"key9": "value9"}})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.update_all,
+ self.req, self.instance.uuid,
+ body={"metadata": {"key9": "value9"}})
@mock.patch('nova.compute.api.API.get_instance_metadata')
@mock.patch('nova.compute.api.API.delete_instance_metadata')
def test_delete_server_Metadata_policy(self, mock_delete, mock_get):
rule_name = policies.POLICY_ROOT % 'delete'
mock_get.return_value = {'key9': 'value'}
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, self.instance.uuid, 'key9')
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ self.req, self.instance.uuid, 'key9')
+
+
+class ServerMetadataNoLegacyNoScopePolicyTest(ServerMetadataPolicyTest):
+ """Test Server Metadata APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(ServerMetadataNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, legacy admin loose power.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
class ServerMetadataScopeTypePolicyTest(ServerMetadataPolicyTest):
@@ -141,9 +138,15 @@ class ServerMetadataScopeTypePolicyTest(ServerMetadataPolicyTest):
def setUp(self):
super(ServerMetadataScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With Scope enable, system users no longer allowed.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class ServerMetadataNoLegacyPolicyTest(ServerMetadataScopeTypePolicyTest):
+class ServerMetadataScopeTypeNoLegacyPolicyTest(
+ ServerMetadataScopeTypePolicyTest):
"""Test Server Metadata APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@@ -151,32 +154,10 @@ class ServerMetadataNoLegacyPolicyTest(ServerMetadataScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
- super(ServerMetadataNoLegacyPolicyTest, self).setUp()
- # Check that system admin or project member is able to create, update
- # and delete the server metadata.
- self.admin_or_owner_authorized_contexts = [
- self.system_admin_context, self.project_admin_context,
- self.project_member_context]
- # Check that non-system/admin/member is not able to create, update
- # and delete the server metadata.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_reader_context,
- self.system_foo_context, self.system_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that system admin or project member is able to
- # get the server metadata.
- self.reader_authorized_contexts = [
- self.system_admin_context,
- self.system_member_context, self.system_reader_context,
- self.project_admin_context, self.project_member_context,
- self.project_reader_context]
- # Check that non-system/admin/member is not able to
- # get the server metadata.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.system_foo_context,
- self.project_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
+ super(ServerMetadataScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With no legacy and scope enable, only project admin, member,
+ # and reader will be able to allowed operation on server metadata.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_server_migrations.py b/nova/tests/unit/policies/test_server_migrations.py
index b06d9ec167..b17d4ded1d 100644
--- a/nova/tests/unit/policies/test_server_migrations.py
+++ b/nova/tests/unit/policies/test_server_migrations.py
@@ -10,9 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import fixtures
-import mock
+from unittest import mock
+import fixtures
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import server_migrations
@@ -45,42 +45,18 @@ class ServerMigrationsPolicyTest(base.BasePolicyTest):
vm_state=vm_states.ACTIVE)
self.mock_get.return_value = self.instance
- # Check that admin is able to perform operations
+ # With legacy rule, any admin is able to perform operations
# for server migrations.
- self.admin_authorized_contexts = [
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to perform operations
- # for server migrations.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
- # Check that system-reader are able to perform operations
- # for server migrations.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.legacy_admin_context,
- self.project_admin_context]
- # Check that non-system-reader are not able to perform operations
- # for server migrations.
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.compute.api.API.get_migrations_in_progress_by_instance')
def test_list_server_migrations_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req, self.instance.uuid)
@mock.patch('nova.api.openstack.compute.server_migrations.output')
@mock.patch('nova.compute.api.API.get_migration_by_id_and_instance')
@@ -90,27 +66,32 @@ class ServerMigrationsPolicyTest(base.BasePolicyTest):
migration_type='live-migration',
status='running',
)
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, self.instance.uuid, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, self.instance.uuid, 11111)
@mock.patch('nova.compute.api.API.live_migrate_abort')
def test_delete_server_migrations_policy(self, mock_delete):
rule_name = policies.POLICY_ROOT % 'delete'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.delete,
- self.req, self.instance.uuid, 11111)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.delete,
+ self.req, self.instance.uuid, 11111)
@mock.patch('nova.compute.api.API.live_migrate_force_complete')
def test_force_delete_server_migrations_policy(self, mock_force):
rule_name = policies.POLICY_ROOT % 'force_complete'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller._force_complete,
- self.req, self.instance.uuid, 11111,
- body={"force_complete": None})
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller._force_complete,
+ self.req, self.instance.uuid, 11111,
+ body={"force_complete": None})
+
+
+class ServerMigrationsNoLegacyNoScopeTest(ServerMigrationsPolicyTest):
+ """Test Server Migrations API policies with deprecated rules
+ disabled, but scope checking still disabled.
+ """
+
+ without_deprecated_rules = True
class ServerMigrationsScopeTypePolicyTest(ServerMigrationsPolicyTest):
@@ -126,48 +107,21 @@ class ServerMigrationsScopeTypePolicyTest(ServerMigrationsPolicyTest):
def setUp(self):
super(ServerMigrationsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope enabled, system admin is not allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class ServerMigrationsNoLegacyPolicyTest(ServerMigrationsScopeTypePolicyTest):
+class ServerMigrationsScopeTypeNoLegacyPolicyTest(
+ ServerMigrationsScopeTypePolicyTest):
"""Test Server Migrations APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
- def setUp(self):
- super(ServerMigrationsNoLegacyPolicyTest, self).setUp()
- # Check that admin is able to perform operations
- # for server migrations.
- self.admin_authorized_contexts = [
- self.system_admin_context
- ]
- # Check that non-admin is not able to perform operations
- # for server migrations.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
- # Check that system reader is able to perform operations
- # for server migrations.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system-reader is not able to perform operations
- # for server migrations.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
-class ServerMigrationsOverridePolicyTest(ServerMigrationsNoLegacyPolicyTest):
+class ServerMigrationsOverridePolicyTest(
+ ServerMigrationsScopeTypeNoLegacyPolicyTest):
"""Test Server Migrations APIs policies with system and project scoped
but default to system roles only are allowed for project roles
if override by operators. This test is with system scope enable
@@ -181,38 +135,16 @@ class ServerMigrationsOverridePolicyTest(ServerMigrationsNoLegacyPolicyTest):
rule_force = policies.POLICY_ROOT % 'force_complete'
rule_delete = policies.POLICY_ROOT % 'delete'
# NOTE(gmann): override the rule to project member and verify it
- # work as policy is system and projct scoped.
+ # work as policy is project scoped.
self.policy.set_rules({
- rule_show: base_policy.PROJECT_READER_OR_SYSTEM_READER,
- rule_list: base_policy.PROJECT_READER_OR_SYSTEM_READER,
- rule_force: base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
- rule_delete: base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN},
+ rule_show: base_policy.PROJECT_READER,
+ rule_list: base_policy.PROJECT_READER,
+ rule_force: base_policy.PROJECT_READER,
+ rule_delete: base_policy.PROJECT_READER},
overwrite=False)
- # Check that system admin or project scoped role as override above
+ # Check that project reader as override above
# is able to migrate the server
- self.admin_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context]
- # Check that non-system admin or project role is not able to
- # migrate the server
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context,
- self.project_foo_context, self.project_reader_context,
- self.other_project_reader_context,
- ]
- # Check that system reader is able to perform operations
- # for server migrations.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.project_admin_context,
- self.project_member_context, self.project_reader_context]
- # Check that non-system-reader is not able to perform operations
- # for server migrations.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.system_foo_context,
- self.other_project_member_context, self.project_foo_context,
- self.other_project_reader_context,
- ]
+ self.project_admin_authorized_contexts = [
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context]
diff --git a/nova/tests/unit/policies/test_server_password.py b/nova/tests/unit/policies/test_server_password.py
index 1a28cf9f20..b163c6c562 100644
--- a/nova/tests/unit/policies/test_server_password.py
+++ b/nova/tests/unit/policies/test_server_password.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import server_password
@@ -41,51 +42,55 @@ class ServerPasswordPolicyTest(base.BasePolicyTest):
id=1, uuid=uuids.fake_id, project_id=self.project_id,
system_metadata={}, expected_attrs=['system_metadata'])
self.mock_get.return_value = self.instance
-
- # Check that admin or and server owner is able to
- # delete the server password.
- 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 delete
- # the server password.
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that admin or and server owner is able to get
- # the server password.
- self.reader_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to delete,
+ # the server Password.
+ self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.system_member_context, self.system_reader_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
- # the server password.
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
+ # and they can get their own server password.
+ self.project_reader_authorized_contexts = (
+ self.project_member_authorized_contexts)
@mock.patch('nova.api.metadata.password.extract_password')
def test_index_server_password_policy(self, mock_pass):
rule_name = policies.BASE_POLICY_NAME % 'show'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req, self.instance.uuid)
@mock.patch('nova.api.metadata.password.convert_password')
def test_clear_server_password_policy(self, mock_pass):
rule_name = policies.BASE_POLICY_NAME % 'clear'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.clear,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.clear,
+ self.req, self.instance.uuid)
+
+
+class ServerPasswordNoLegacyNoScopePolicyTest(ServerPasswordPolicyTest):
+ """Test Server Password APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.BASE_POLICY_NAME % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ policies.BASE_POLICY_NAME % 'clear':
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
+
+ def setUp(self):
+ super(ServerPasswordNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, legacy admin loose power.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
class ServerPasswordScopeTypePolicyTest(ServerPasswordPolicyTest):
@@ -101,50 +106,30 @@ class ServerPasswordScopeTypePolicyTest(ServerPasswordPolicyTest):
def setUp(self):
super(ServerPasswordScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With Scope enable, system users no longer allowed.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class ServerPasswordNoLegacyPolicyTest(ServerPasswordScopeTypePolicyTest):
+class ServerPasswordScopeTypeNoLegacyPolicyTest(
+ ServerPasswordScopeTypePolicyTest):
"""Test Server Password APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.BASE_POLICY_NAME % 'show':
- base_policy.PROJECT_READER_OR_SYSTEM_READER,
+ base_policy.PROJECT_READER_OR_ADMIN,
policies.BASE_POLICY_NAME % 'clear':
- base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
+ base_policy.PROJECT_MEMBER_OR_ADMIN}
def setUp(self):
- super(ServerPasswordNoLegacyPolicyTest, self).setUp()
-
- # Check that system or projct admin or owner is able to clear
- # server password.
- self.admin_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context]
- # Check that non-system and non-admin/owner is not able to clear
- # server password.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.project_reader_context,
- self.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context]
-
- # Check that system reader or projct owner is able to get
- # server password.
- self.reader_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_member_context,
- ]
-
- # Check that non-system reader nd non-admin/owner is not able to get
- # server password.
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
+ super(ServerPasswordScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With no legacy and scope enable, only project admin, member,
+ # and reader will be able to allowed operation on server password.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_server_tags.py b/nova/tests/unit/policies/test_server_tags.py
index b7efe86364..412177408c 100644
--- a/nova/tests/unit/policies/test_server_tags.py
+++ b/nova/tests/unit/policies/test_server_tags.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import server_tags
@@ -50,51 +51,32 @@ class ServerTagsPolicyTest(base.BasePolicyTest):
self.stub_out('nova.objects.InstanceMapping.get_by_instance_uuid',
lambda s, c, u: inst_map)
- # Check that admin or and server owner is able to perform
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to perform,
# operations on server tags.
- 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 perform operations
- # on server tags
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that reader or and server owner is able to perform operations
- # on server tags.
- self.reader_or_owner_authorized_contexts = [
+ self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.system_member_context, self.system_reader_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
- # Check that non-reader/owner is not able to perform operations
- # on server tags.
- self.reader_or_owner_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
+ self.project_reader_authorized_contexts = (
+ self.project_member_authorized_contexts)
@mock.patch('nova.objects.TagList.get_by_resource_id')
def test_index_server_tags_policy(self, mock_tag):
rule_name = policies.POLICY_ROOT % 'index'
- self.common_policy_check(self.reader_or_owner_authorized_contexts,
- self.reader_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req, self.instance.uuid)
@mock.patch('nova.objects.Tag.exists')
def test_show_server_tags_policy(self, mock_exists):
rule_name = policies.POLICY_ROOT % 'show'
- self.common_policy_check(self.reader_or_owner_authorized_contexts,
- self.reader_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, self.instance.uuid, uuids.fake_id)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, self.instance.uuid, uuids.fake_id)
@mock.patch('nova.notifications.base.send_instance_update_notification')
@mock.patch('nova.db.main.api.instance_tag_get_by_instance_uuid')
@@ -102,33 +84,30 @@ class ServerTagsPolicyTest(base.BasePolicyTest):
def test_update_server_tags_policy(self, mock_create, mock_tag,
mock_notf):
rule_name = policies.POLICY_ROOT % 'update'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.update,
- self.req, self.instance.uuid, uuids.fake_id,
- body=None)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.update,
+ self.req, self.instance.uuid, uuids.fake_id,
+ body=None)
@mock.patch('nova.notifications.base.send_instance_update_notification')
@mock.patch('nova.db.main.api.instance_tag_set')
def test_update_all_server_tags_policy(self, mock_set, mock_notf):
rule_name = policies.POLICY_ROOT % 'update_all'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.update_all,
- self.req, self.instance.uuid,
- body={'tags': ['tag1', 'tag2']})
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.update_all,
+ self.req, self.instance.uuid,
+ body={'tags': ['tag1', 'tag2']})
@mock.patch('nova.notifications.base.send_instance_update_notification')
@mock.patch('nova.objects.TagList.destroy')
def test_delete_all_server_tags_policy(self, mock_destroy, mock_notf):
rule_name = policies.POLICY_ROOT % 'delete_all'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.delete_all,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.delete_all,
+ self.req, self.instance.uuid)
@mock.patch('nova.notifications.base.send_instance_update_notification')
@mock.patch('nova.db.main.api.instance_tag_get_by_instance_uuid')
@@ -136,11 +115,27 @@ class ServerTagsPolicyTest(base.BasePolicyTest):
def test_delete_server_tags_policy(self, mock_destroy, mock_get,
mock_notf):
rule_name = policies.POLICY_ROOT % 'delete'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, self.instance.uuid, uuids.fake_id)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ self.req, self.instance.uuid, uuids.fake_id)
+
+
+class ServerTagsNoLegacyNoScopePolicyTest(ServerTagsPolicyTest):
+ """Test Server Tags APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(ServerTagsNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, legacy admin loose power.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
class ServerTagsScopeTypePolicyTest(ServerTagsPolicyTest):
@@ -156,9 +151,14 @@ class ServerTagsScopeTypePolicyTest(ServerTagsPolicyTest):
def setUp(self):
super(ServerTagsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With Scope enable, system users no longer allowed.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class ServerTagsNoLegacyPolicyTest(ServerTagsScopeTypePolicyTest):
+class ServerTagsScopeTypeNoLegacyPolicyTest(ServerTagsScopeTypePolicyTest):
"""Test Server Tags APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@@ -166,32 +166,10 @@ class ServerTagsNoLegacyPolicyTest(ServerTagsScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
- super(ServerTagsNoLegacyPolicyTest, self).setUp()
- # Check that system admin or project member is able to
- # perform operations on server tags.
- self.admin_or_owner_authorized_contexts = [
- self.system_admin_context, self.project_admin_context,
- self.project_member_context]
- # Check that non-system/admin/member is not able to
- # perform operations on server tags.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_reader_context,
- self.system_foo_context, self.system_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that system reader or owner is able to
- # perform operations on server tags.
- self.reader_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.system_member_context, self.system_reader_context,
- self.project_admin_context, self.project_member_context,
- self.project_reader_context]
- # Check that non-system/reader/owner is not able to
- # perform operations on server tags.
- self.reader_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_foo_context,
- self.project_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
+ super(ServerTagsScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With no legacy and scope enable, only project admin, member,
+ # and reader will be able to allowed operation on server tags.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_server_topology.py b/nova/tests/unit/policies/test_server_topology.py
index 51a3206a97..e2f81dfaad 100644
--- a/nova/tests/unit/policies/test_server_topology.py
+++ b/nova/tests/unit/policies/test_server_topology.py
@@ -51,40 +51,23 @@ class ServerTopologyPolicyTest(base.BasePolicyTest):
# Check that system reader or and server owner is able to get
# the server topology.
- self.system_reader_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin is able to get
+ # server topology wth host info.
+ self.project_admin_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,
- self.system_member_context, self.system_reader_context]
- # Check that non-stem reader/owner is not able to get
- # the server topology.
- self.system_reader_or_owner_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context,
- ]
- # Check that system reader is able to get the server topology
- # host information.
- self.system_reader_authorized_contexts = [
+ self.project_admin_context]
+ # and project reader can get their server topology without host info.
+ self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to get the server topology
- # host information.
- self.system_reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.project_foo_context, self.project_reader_context,
- self.other_project_reader_context
- ]
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context, self.project_foo_context]
def test_index_server_topology_policy(self):
rule_name = policies.BASE_POLICY_NAME % 'index'
- self.common_policy_check(
- self.system_reader_or_owner_authorized_contexts,
- self.system_reader_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req, self.instance.uuid)
def test_index_host_server_topology_policy(self):
rule_name = policies.BASE_POLICY_NAME % 'host:index'
@@ -93,9 +76,8 @@ class ServerTopologyPolicyTest(base.BasePolicyTest):
# fail first for unauthorized contexts.
rule = policies.BASE_POLICY_NAME % 'index'
self.policy.set_rules({rule: "@"}, overwrite=False)
- authorize_res, unauthorize_res = self.common_policy_check(
- self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.index, self.req, self.instance.uuid,
fatal=False)
for resp in authorize_res:
@@ -106,6 +88,20 @@ class ServerTopologyPolicyTest(base.BasePolicyTest):
self.assertNotIn('cpu_pinning', resp['nodes'][0])
+class ServerTopologyNoLegacyNoScopePolicyTest(ServerTopologyPolicyTest):
+ """Test Server Topology APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(ServerTopologyNoLegacyNoScopePolicyTest, self).setUp()
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
+
+
class ServerTopologyScopeTypePolicyTest(ServerTopologyPolicyTest):
"""Test Server Topology APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -119,24 +115,15 @@ class ServerTopologyScopeTypePolicyTest(ServerTopologyPolicyTest):
def setUp(self):
super(ServerTopologyScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
-
- # Check that system reader is able to get the server topology
- # host information.
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system/reader is not able to get the server topology
- # host information.
- self.system_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,
- self.other_project_reader_context,
- ]
+ # With Scope enable, system users no longer allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class ServerTopologyNoLegacyPolicyTest(ServerTopologyScopeTypePolicyTest):
+class ServerTopologyScopeTypeNoLegacyPolicyTest(
+ ServerTopologyScopeTypePolicyTest):
"""Test Server Topology APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@@ -144,18 +131,8 @@ class ServerTopologyNoLegacyPolicyTest(ServerTopologyScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
- super(ServerTopologyNoLegacyPolicyTest, self).setUp()
- # Check that system reader/owner is able to get
- # the server topology.
- self.system_reader_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context,
- self.system_member_context, self.system_reader_context,
- self.project_reader_context]
- # Check that non-system/reader/owner is not able to get
- # the server topology.
- 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.other_project_reader_context,
- ]
+ super(ServerTopologyScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With no legacy and scope enable, only project admin, member,
+ # and reader will be able to get server topology.
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_servers.py b/nova/tests/unit/policies/test_servers.py
index 33aadb948f..eee1e4ba51 100644
--- a/nova/tests/unit/policies/test_servers.py
+++ b/nova/tests/unit/policies/test_servers.py
@@ -10,9 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+import functools
+from unittest import mock
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -20,12 +21,14 @@ from nova.api.openstack.compute import migrate_server
from nova.api.openstack.compute import servers
from nova.compute import api as compute
from nova.compute import vm_states
+import nova.conf
from nova import exception
from nova.network import model
from nova.network import neutron
from nova import objects
from nova.objects import fields
from nova.objects.instance_group import InstanceGroup
+from nova.policies import base as base_policy
from nova.policies import extended_server_attributes as ea_policies
from nova.policies import servers as policies
from nova.tests.unit.api.openstack import fakes
@@ -33,6 +36,8 @@ from nova.tests.unit import fake_flavor
from nova.tests.unit import fake_instance
from nova.tests.unit.policies import base
+CONF = nova.conf.CONF
+
class ServersPolicyTest(base.BasePolicyTest):
"""Test Servers APIs policies with all possible context.
@@ -114,137 +119,41 @@ class ServersPolicyTest(base.BasePolicyTest):
'OS-EXT-SRV-ATTR:user_data'
]
- # Check that admin or and owner is able to update, delete
- # or perform server action.
- self.admin_or_owner_authorized_contexts = [
+ # Users that can take action on *our* project resources
+ self.project_action_authorized_contexts = set([
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 update, delete
- # or perform server action.
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
+ self.project_reader_context, self.project_foo_context,
+ ])
- # Check that system reader or owner is able to get
- # the server.
- 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,
- self.other_project_reader_context
- ]
+ # Users that can read *our* project resources
+ self.project_reader_authorized_contexts = (
+ self.project_action_authorized_contexts)
- # Check that everyone is able to list their own server.
- 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.project_foo_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context]
- self.everyone_unauthorized_contexts = [
- ]
- # Check that admin is able to create server with host request
- # and get server extended attributes or host status.
- self.admin_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context]
- # Check that non-admin is not able to create server with host request
- # and get server extended attributes or host status.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that sustem reader is able to list the server
- # for all projects.
- self.system_reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to list the server
- # for all projects.
- self.system_reader_unauthorized_contexts = [
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that project member is able to create serve
- self.project_member_authorized_contexts = [
+ # Users that _see_ project-scoped resources that they own
+ self.everyone_authorized_contexts = set(self.all_contexts)
+
+ # Users that can _do_ things to project-scoped resources they own
+ self.project_member_authorized_contexts = set(self.all_contexts)
+
+ # Users able to do admin things on project resources
+ self.project_admin_authorized_contexts = set([
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.project_member_context,
- self.system_member_context, self.system_reader_context,
- self.other_project_member_context, self.system_foo_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_reader_context]
- # Check that non-project member is not able to create server
- self.project_member_unauthorized_contexts = [
- ]
- # Check that project admin is able to create server with requested
- # destination.
- self.project_admin_authorized_contexts = [
+ self.project_admin_context])
+
+ # Admin (for APIs does not pass the project id as policy target
+ # for example, create server, list detail server) able to get
+ # all projects servers, create server on specific host etc.
+ # This is admin on any project because policy does not check
+ # the project id but they will be able to create server, get
+ # servers(unless all-tenant policy is allowed) of their own
+ # project only.
+ self.all_projects_admin_authorized_contexts = set([
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context]
- # Check that non-project admin is not able to create server with
- # requested destination
- self.project_admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that no one is able to resize cross cell.
+ self.project_admin_context])
+
+ # Users able to do cross-cell migrations
self.cross_cell_authorized_contexts = []
- self.cross_cell_unauthorized_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,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context]
- # Check that admin is able to access the zero disk flavor
- # and external network policies.
- self.zero_disk_external_net_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context]
- # Check that non-admin is not able to caccess the zero disk flavor
- # and external network policies.
- self.zero_disk_external_net_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that admin is able to get server extended attributes
- # or host status.
- self.server_attr_admin_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context]
- # Check that non-admin is not able to get server extended attributes
- # or host status.
- self.server_attr_admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
def test_index_server_policy(self):
@@ -261,9 +170,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.mock_get_all.side_effect = fake_get_all
rule_name = policies.SERVERS % 'index'
- self.common_policy_check(
+ self.common_policy_auth(
self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
rule_name,
self.controller.index,
self.req)
@@ -287,11 +195,16 @@ class ServersPolicyTest(base.BasePolicyTest):
self.mock_get_all.side_effect = fake_get_all
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name,
- self.controller.index,
- req)
+ if not CONF.oslo_policy.enforce_scope:
+ check_rule = rule_name
+ else:
+ check_rule = functools.partial(
+ base.rule_if_system, rule, rule_name)
+
+ self.common_policy_auth(self.all_projects_admin_authorized_contexts,
+ check_rule,
+ self.controller.index,
+ req)
@mock.patch('nova.compute.api.API.get_all')
def test_detail_list_server_policy(self, mock_get):
@@ -309,9 +222,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.mock_get_all.side_effect = fake_get_all
rule_name = policies.SERVERS % 'detail'
- self.common_policy_check(
+ self.common_policy_auth(
self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
rule_name,
self.controller.detail,
self.req)
@@ -335,11 +247,16 @@ class ServersPolicyTest(base.BasePolicyTest):
self.mock_get_all.side_effect = fake_get_all
- self.common_policy_check(self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
- rule_name,
- self.controller.detail,
- req)
+ if not CONF.oslo_policy.enforce_scope:
+ check_rule = rule_name
+ else:
+ check_rule = functools.partial(
+ base.rule_if_system, rule, rule_name)
+
+ self.common_policy_auth(self.all_projects_admin_authorized_contexts,
+ check_rule,
+ self.controller.detail,
+ req)
def test_index_server_allow_all_filters_policy(self):
# 'index' policy is checked before 'allow_all_filters' so
@@ -353,9 +270,9 @@ class ServersPolicyTest(base.BasePolicyTest):
expected_attrs=None, sort_keys=None, sort_dirs=None,
cell_down_support=False, all_tenants=False):
self.assertIsNotNone(search_opts)
- if context in self.system_reader_unauthorized_contexts:
+ if context not in self.all_projects_admin_authorized_contexts:
self.assertNotIn('host', search_opts)
- if context in self.system_reader_authorized_contexts:
+ if context in self.all_projects_admin_authorized_contexts:
self.assertIn('host', search_opts)
return objects.InstanceList(objects=self.servers)
@@ -363,9 +280,8 @@ class ServersPolicyTest(base.BasePolicyTest):
req = fakes.HTTPRequest.blank('/servers?host=1')
rule_name = policies.SERVERS % 'allow_all_filters'
- self.common_policy_check(
- self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
+ self.common_policy_auth(
+ self.all_projects_admin_authorized_contexts,
rule_name,
self.controller.index,
req, fatal=False)
@@ -382,18 +298,17 @@ class ServersPolicyTest(base.BasePolicyTest):
expected_attrs=None, sort_keys=None, sort_dirs=None,
cell_down_support=False, all_tenants=False):
self.assertIsNotNone(search_opts)
- if context in self.system_reader_unauthorized_contexts:
+ if context not in self.all_projects_admin_authorized_contexts:
self.assertNotIn('host', search_opts)
- if context in self.system_reader_authorized_contexts:
+ if context in self.all_projects_admin_authorized_contexts:
self.assertIn('host', search_opts)
return objects.InstanceList(objects=self.servers)
self.mock_get_all.side_effect = fake_get_all
req = fakes.HTTPRequest.blank('/servers?host=1')
rule_name = policies.SERVERS % 'allow_all_filters'
- self.common_policy_check(
- self.system_reader_authorized_contexts,
- self.system_reader_unauthorized_contexts,
+ self.common_policy_auth(
+ self.all_projects_admin_authorized_contexts,
rule_name,
self.controller.detail,
req, fatal=False)
@@ -401,22 +316,117 @@ class ServersPolicyTest(base.BasePolicyTest):
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
def test_show_server_policy(self, mock_bdm):
rule_name = policies.SERVERS % 'show'
- self.common_policy_check(
- self.system_reader_or_owner_authorized_contexts,
- self.system_reader_or_owner_unauthorized_contexts,
+ # Show includes readers
+ self.common_policy_auth(
+ self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, self.instance.uuid)
+ @mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
+ @mock.patch('nova.compute.api.API.get_instance_host_status')
+ def test_server_show_with_extra_specs_policy(self, mock_get, mock_block):
+ rule = policies.SERVERS % 'show'
+ # server 'show' policy is checked before flavor extra specs
+ # policy so we have to allow it for everyone otherwise it will fail
+ # first for unauthorized contexts.
+ self.policy.set_rules({rule: "@"}, overwrite=False)
+ req = fakes.HTTPRequest.blank('', version='2.47')
+ rule_name = policies.SERVERS % 'show:flavor-extra-specs'
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_reader_authorized_contexts,
+ rule_name, self.controller.show, req,
+ self.instance.uuid, fatal=False)
+ for resp in authorize_res:
+ self.assertIn('extra_specs', resp['server']['flavor'])
+ for resp in unauthorize_res:
+ self.assertNotIn('extra_specs', resp['server']['flavor'])
+
+ @mock.patch('nova.compute.api.API.get_all')
+ def test_server_detail_with_extra_specs_policy(self, mock_get):
+
+ def fake_get_all(context, search_opts=None,
+ limit=None, marker=None,
+ expected_attrs=None, sort_keys=None, sort_dirs=None,
+ cell_down_support=False, all_tenants=False):
+ self.assertIsNotNone(search_opts)
+ if 'project_id' in search_opts or 'user_id' in search_opts:
+ return objects.InstanceList(objects=self.servers)
+ else:
+ raise
+
+ self.mock_get_all.side_effect = fake_get_all
+ rule = policies.SERVERS % 'detail'
+ # server 'detail' policy is checked before flavor extra specs
+ # policy so we have to allow it for everyone otherwise it will fail
+ # first for unauthorized contexts.
+ self.policy.set_rules({rule: "@"}, overwrite=False)
+ req = fakes.HTTPRequest.blank('', version='2.47')
+ rule_name = policies.SERVERS % 'show:flavor-extra-specs'
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.everyone_authorized_contexts,
+ rule_name, self.controller.detail, req,
+ fatal=False)
+ for resp in authorize_res:
+ self.assertIn('extra_specs', resp['servers'][0]['flavor'])
+ for resp in unauthorize_res:
+ self.assertNotIn('extra_specs', resp['servers'][0]['flavor'])
+
+ @mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
+ @mock.patch('nova.compute.api.API.get_instance_host_status')
+ @mock.patch('nova.compute.api.API.rebuild')
+ def test_server_rebuild_with_extra_specs_policy(self, mock_rebuild,
+ mock_get, mock_bdm):
+ rule = policies.SERVERS % 'rebuild'
+ # server 'rebuild' policy is checked before flavor extra specs
+ # policy so we have to allow it for everyone otherwise it will fail
+ # first for unauthorized contexts.
+ self.policy.set_rules({rule: "@"}, overwrite=False)
+ req = fakes.HTTPRequest.blank('', version='2.47')
+ rule_name = policies.SERVERS % 'show:flavor-extra-specs'
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_reader_authorized_contexts,
+ rule_name, self.controller._action_rebuild,
+ req, self.instance.uuid,
+ body={'rebuild': {"imageRef": uuids.fake_id}},
+ fatal=False)
+ for resp in authorize_res:
+ self.assertIn('extra_specs', resp.obj['server']['flavor'])
+ for resp in unauthorize_res:
+ self.assertNotIn('extra_specs', resp.obj['server']['flavor'])
+
+ @mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
+ @mock.patch.object(InstanceGroup, 'get_by_instance_uuid')
+ @mock.patch('nova.compute.api.API.update_instance')
+ def test_server_update_with_extra_specs_policy(self,
+ mock_update, mock_group, mock_bdm):
+ mock_update.return_value = self.instance
+ rule = policies.SERVERS % 'update'
+ # server 'update' policy is checked before flavor extra specs
+ # policy so we have to allow it for everyone otherwise it will fail
+ # first for unauthorized contexts.
+ self.policy.set_rules({rule: "@"}, overwrite=False)
+ req = fakes.HTTPRequest.blank('', version='2.47')
+ rule_name = policies.SERVERS % 'show:flavor-extra-specs'
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_reader_authorized_contexts,
+ rule_name, self.controller.update,
+ req, self.instance.uuid,
+ body={'server': {'name': 'test'}},
+ fatal=False)
+ for resp in authorize_res:
+ self.assertIn('extra_specs', resp['server']['flavor'])
+ for resp in unauthorize_res:
+ self.assertNotIn('extra_specs', resp['server']['flavor'])
+
@mock.patch('nova.compute.api.API.create')
def test_create_server_policy(self, mock_create):
mock_create.return_value = ([self.instance], '')
rule_name = policies.SERVERS % 'create'
- self.common_policy_check(self.project_member_authorized_contexts,
- self.project_member_unauthorized_contexts,
- rule_name,
- self.controller.create,
- self.req, body=self.body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name,
+ self.controller.create,
+ self.req, body=self.body)
@mock.patch('nova.compute.api.API.create')
@mock.patch('nova.compute.api.API.parse_availability_zone')
@@ -431,11 +441,10 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
mock_create.return_value = ([self.instance], '')
mock_az.return_value = ('test', 'host', None)
- self.common_policy_check(self.project_admin_authorized_contexts,
- self.project_admin_unauthorized_contexts,
- self.rule_forced_host,
- self.controller.create,
- self.req, body=self.body)
+ self.common_policy_auth(self.all_projects_admin_authorized_contexts,
+ self.rule_forced_host,
+ self.controller.create,
+ self.req, body=self.body)
@mock.patch('nova.compute.api.API.create')
def test_create_attach_volume_server_policy(self, mock_create):
@@ -453,11 +462,10 @@ class ServersPolicyTest(base.BasePolicyTest):
'block_device_mapping': [{'device_name': 'foo'}],
},
}
- self.common_policy_check(self.project_member_authorized_contexts,
- self.project_member_unauthorized_contexts,
- self.rule_attach_volume,
- self.controller.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ self.rule_attach_volume,
+ self.controller.create,
+ self.req, body=body)
@mock.patch('nova.compute.api.API.create')
def test_create_attach_network_server_policy(self, mock_create):
@@ -477,11 +485,10 @@ class ServersPolicyTest(base.BasePolicyTest):
}],
},
}
- self.common_policy_check(self.project_member_authorized_contexts,
- self.project_member_unauthorized_contexts,
- self.rule_attach_network,
- self.controller.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ self.rule_attach_network,
+ self.controller.create,
+ self.req, body=body)
@mock.patch('nova.compute.api.API.create')
def test_create_trusted_certs_server_policy(self, mock_create):
@@ -504,20 +511,18 @@ class ServersPolicyTest(base.BasePolicyTest):
},
}
- self.common_policy_check(self.project_member_authorized_contexts,
- self.project_member_unauthorized_contexts,
- self.rule_trusted_certs,
- self.controller.create,
- req, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ self.rule_trusted_certs,
+ self.controller.create,
+ req, body=body)
@mock.patch('nova.compute.api.API.delete')
def test_delete_server_policy(self, mock_delete):
rule_name = policies.SERVERS % 'delete'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.delete,
- self.req, self.instance.uuid)
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller.delete,
+ self.req, self.instance.uuid)
def test_delete_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -547,11 +552,10 @@ class ServersPolicyTest(base.BasePolicyTest):
rule_name = policies.SERVERS % 'update'
body = {'server': {'name': 'test'}}
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.update,
- self.req, self.instance.uuid, body=body)
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller.update,
+ self.req, self.instance.uuid, body=body)
def test_update_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -582,44 +586,40 @@ class ServersPolicyTest(base.BasePolicyTest):
def test_confirm_resize_server_policy(self, mock_confirm_resize):
rule_name = policies.SERVERS % 'confirm_resize'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_confirm_resize,
- self.req, self.instance.uuid,
- body={'confirmResize': 'null'})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._action_confirm_resize,
+ self.req, self.instance.uuid,
+ body={'confirmResize': 'null'})
@mock.patch('nova.compute.api.API.revert_resize')
def test_revert_resize_server_policy(self, mock_revert_resize):
rule_name = policies.SERVERS % 'revert_resize'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_revert_resize,
- self.req, self.instance.uuid,
- body={'revertResize': 'null'})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._action_revert_resize,
+ self.req, self.instance.uuid,
+ body={'revertResize': 'null'})
@mock.patch('nova.compute.api.API.reboot')
def test_reboot_server_policy(self, mock_reboot):
rule_name = policies.SERVERS % 'reboot'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_reboot,
- self.req, self.instance.uuid,
- body={'reboot': {'type': 'soft'}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._action_reboot,
+ self.req, self.instance.uuid,
+ body={'reboot': {'type': 'soft'}})
@mock.patch('nova.compute.api.API.resize')
def test_resize_server_policy(self, mock_resize):
rule_name = policies.SERVERS % 'resize'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_resize,
- self.req, self.instance.uuid,
- body={'resize': {'flavorRef': 'f1'}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._action_resize,
+ self.req, self.instance.uuid,
+ body={'resize': {'flavorRef': 'f1'}})
def test_resize_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -650,23 +650,21 @@ class ServersPolicyTest(base.BasePolicyTest):
def test_start_server_policy(self, mock_start):
rule_name = policies.SERVERS % 'start'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._start_server,
- self.req, self.instance.uuid,
- body={'os-start': 'null'})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._start_server,
+ self.req, self.instance.uuid,
+ body={'os-start': 'null'})
@mock.patch('nova.compute.api.API.stop')
def test_stop_server_policy(self, mock_stop):
rule_name = policies.SERVERS % 'stop'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._stop_server,
- self.req, self.instance.uuid,
- body={'os-stop': 'null'})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._stop_server,
+ self.req, self.instance.uuid,
+ body={'os-stop': 'null'})
def test_stop_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -696,12 +694,11 @@ class ServersPolicyTest(base.BasePolicyTest):
@mock.patch('nova.compute.api.API.rebuild')
def test_rebuild_server_policy(self, mock_rebuild):
rule_name = policies.SERVERS % 'rebuild'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_rebuild,
- self.req, self.instance.uuid,
- body={'rebuild': {"imageRef": uuids.fake_id}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._action_rebuild,
+ self.req, self.instance.uuid,
+ body={'rebuild': {"imageRef": uuids.fake_id}})
def test_rebuild_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -743,11 +740,17 @@ class ServersPolicyTest(base.BasePolicyTest):
'trusted_image_certificates': [uuids.fake_id],
},
}
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_rebuild,
- req, self.instance.uuid, body=body)
+
+ if not CONF.oslo_policy.enforce_scope:
+ check_rule = rule_name
+ else:
+ check_rule = functools.partial(
+ base.rule_if_system, rule, rule_name)
+
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ check_rule,
+ self.controller._action_rebuild,
+ req, self.instance.uuid, body=body)
def test_rebuild_trusted_certs_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -796,12 +799,11 @@ class ServersPolicyTest(base.BasePolicyTest):
def test_create_image_server_policy(self, mock_snapshot, mock_image,
mock_bdm):
rule_name = policies.SERVERS % 'create_image'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_create_image,
- self.req, self.instance.uuid,
- body={'createImage': {"name": 'test'}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._action_create_image,
+ self.req, self.instance.uuid,
+ body={'createImage': {"name": 'test'}})
@mock.patch('nova.objects.BlockDeviceMappingList.get_by_instance_uuid')
@mock.patch('nova.image.glance.API.generate_image_url')
@@ -816,23 +818,26 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
rule_name = policies.SERVERS % 'create_image:allow_volume_backed'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_create_image,
- self.req, self.instance.uuid,
- body={'createImage': {"name": 'test'}})
+ if not CONF.oslo_policy.enforce_scope:
+ check_rule = rule_name
+ else:
+ check_rule = functools.partial(
+ base.rule_if_system, rule, rule_name)
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ check_rule,
+ self.controller._action_create_image,
+ self.req, self.instance.uuid,
+ body={'createImage': {"name": 'test'}})
@mock.patch('nova.compute.api.API.trigger_crash_dump')
def test_trigger_crash_dump_server_policy(self, mock_crash):
rule_name = policies.SERVERS % 'trigger_crash_dump'
req = fakes.HTTPRequest.blank('', version='2.17')
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._action_trigger_crash_dump,
- req, self.instance.uuid,
- body={'trigger_crash_dump': None})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._action_trigger_crash_dump,
+ req, self.instance.uuid,
+ body={'trigger_crash_dump': None})
def test_trigger_crash_dump_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -876,9 +881,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.3')
rule_name = ea_policies.BASE_POLICY_NAME
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.all_projects_admin_authorized_contexts,
rule_name, self.controller.detail, req,
fatal=False)
for attr in self.extended_attr:
@@ -897,9 +901,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.3')
rule_name = ea_policies.BASE_POLICY_NAME
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.show, req, 'fake',
fatal=False)
for attr in self.extended_attr:
@@ -920,9 +923,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = ea_policies.BASE_POLICY_NAME
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller._action_rebuild,
req, self.instance.uuid,
body={'rebuild': {"imageRef": uuids.fake_id}},
@@ -940,8 +942,11 @@ class ServersPolicyTest(base.BasePolicyTest):
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch.object(InstanceGroup, 'get_by_instance_uuid')
@mock.patch('nova.compute.api.API.update_instance')
+ @mock.patch('nova.compute.api.API.get_instance_host_status')
def test_server_update_with_extended_attr_policy(self,
- mock_update, mock_group, mock_bdm):
+ mock_status, mock_update, mock_group, mock_bdm):
+ mock_update.return_value = self.instance
+ mock_status.return_value = fields.HostStatus.UP
rule = policies.SERVERS % 'update'
# server 'update' policy is checked before extended attributes
# policy so we have to allow it for everyone otherwise it will fail
@@ -949,9 +954,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = ea_policies.BASE_POLICY_NAME
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.update,
req, self.instance.uuid,
body={'server': {'name': 'test'}},
@@ -977,9 +981,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.16')
rule_name = policies.SERVERS % 'show:host_status'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.all_projects_admin_authorized_contexts,
rule_name, self.controller.detail, req,
fatal=False)
for resp in authorize_res:
@@ -998,9 +1001,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.16')
rule_name = policies.SERVERS % 'show:host_status'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.show, req, 'fake',
fatal=False)
for resp in authorize_res:
@@ -1020,9 +1022,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = policies.SERVERS % 'show:host_status'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller._action_rebuild,
req, self.instance.uuid,
body={'rebuild': {"imageRef": uuids.fake_id}},
@@ -1035,8 +1036,11 @@ class ServersPolicyTest(base.BasePolicyTest):
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch.object(InstanceGroup, 'get_by_instance_uuid')
@mock.patch('nova.compute.api.API.update_instance')
+ @mock.patch('nova.compute.api.API.get_instance_host_status')
def test_server_update_with_host_status_policy(self,
- mock_update, mock_group, mock_bdm):
+ mock_status, mock_update, mock_group, mock_bdm):
+ mock_update.return_value = self.instance
+ mock_status.return_value = fields.HostStatus.UP
rule = policies.SERVERS % 'update'
# server 'update' policy is checked before host_status
# policy so we have to allow it for everyone otherwise it will fail
@@ -1044,9 +1048,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = policies.SERVERS % 'show:host_status'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.update,
req, self.instance.uuid,
body={'server': {'name': 'test'}},
@@ -1079,9 +1082,8 @@ class ServersPolicyTest(base.BasePolicyTest):
rule_host_status: "!"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.16')
rule_name = policies.SERVERS % 'show:host_status:unknown-only'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.all_projects_admin_authorized_contexts,
rule_name, self.controller.detail, req,
fatal=False)
for resp in authorize_res:
@@ -1107,9 +1109,8 @@ class ServersPolicyTest(base.BasePolicyTest):
rule_host_status: "!"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.16')
rule_name = policies.SERVERS % 'show:host_status:unknown-only'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.show, req, 'fake',
fatal=False)
for resp in authorize_res:
@@ -1136,9 +1137,8 @@ class ServersPolicyTest(base.BasePolicyTest):
rule_host_status: "!"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = policies.SERVERS % 'show:host_status:unknown-only'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller._action_rebuild,
req, self.instance.uuid,
body={'rebuild': {"imageRef": uuids.fake_id}},
@@ -1156,6 +1156,7 @@ class ServersPolicyTest(base.BasePolicyTest):
@mock.patch('nova.compute.api.API.update_instance')
def test_server_update_with_unknown_host_status_policy(self,
mock_update, mock_group, mock_status, mock_bdm):
+ mock_update.return_value = self.instance
mock_status.return_value = fields.HostStatus.UNKNOWN
rule = policies.SERVERS % 'update'
# server 'update' policy is checked before unknown host_status
@@ -1168,9 +1169,8 @@ class ServersPolicyTest(base.BasePolicyTest):
rule_host_status: "!"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = policies.SERVERS % 'show:host_status:unknown-only'
- authorize_res, unauthorize_res = self.common_policy_check(
- self.server_attr_admin_authorized_contexts,
- self.server_attr_admin_unauthorized_contexts,
+ authorize_res, unauthorize_res = self.common_policy_auth(
+ self.project_admin_authorized_contexts,
rule_name, self.controller.update,
req, self.instance.uuid,
body={'server': {'name': 'test'}},
@@ -1194,9 +1194,9 @@ class ServersPolicyTest(base.BasePolicyTest):
def fake_create(context, *args, **kwargs):
for attr in ['requested_host', 'requested_hypervisor_hostname']:
- if context in self.project_admin_authorized_contexts:
+ if context in self.all_projects_admin_authorized_contexts:
self.assertIn(attr, kwargs)
- if context in self.project_admin_unauthorized_contexts:
+ if context not in self.all_projects_admin_authorized_contexts:
self.assertNotIn(attr, kwargs)
return ([self.instance], '')
mock_create.side_effect = fake_create
@@ -1214,11 +1214,10 @@ class ServersPolicyTest(base.BasePolicyTest):
},
}
- self.common_policy_check(self.project_admin_authorized_contexts,
- self.project_admin_unauthorized_contexts,
- self.rule_requested_destination,
- self.controller.create,
- req, body=body)
+ self.common_policy_auth(self.all_projects_admin_authorized_contexts,
+ self.rule_requested_destination,
+ self.controller.create,
+ req, body=body)
@mock.patch(
'nova.servicegroup.api.API.service_is_up',
@@ -1230,10 +1229,9 @@ class ServersPolicyTest(base.BasePolicyTest):
@mock.patch('nova.compute.api.API._allow_resize_to_same_host')
@mock.patch('nova.objects.RequestSpec.get_by_instance_uuid')
@mock.patch('nova.objects.Instance.save')
- @mock.patch('nova.api.openstack.common.get_instance')
@mock.patch('nova.conductor.ComputeTaskAPI.resize_instance')
def test_cross_cell_resize_server_policy(
- self, mock_resize, mock_get, mock_save, mock_rs, mock_allow, m_net
+ self, mock_resize, mock_save, mock_rs, mock_allow, m_net
):
# 'migrate' policy is checked before 'resize:cross_cell' so
@@ -1263,13 +1261,13 @@ class ServersPolicyTest(base.BasePolicyTest):
)
return inst
- mock_get.side_effect = fake_get
+ self.mock_get.side_effect = fake_get
def fake_validate(context, instance,
host_name, allow_cross_cell_resize):
if context in self.cross_cell_authorized_contexts:
self.assertTrue(allow_cross_cell_resize)
- if context in self.cross_cell_unauthorized_contexts:
+ if context not in self.cross_cell_authorized_contexts:
self.assertFalse(allow_cross_cell_resize)
return objects.ComputeNode(host=1, hypervisor_hostname=2)
@@ -1277,23 +1275,24 @@ class ServersPolicyTest(base.BasePolicyTest):
'nova.compute.api.API._validate_host_for_cold_migrate',
fake_validate)
- self.common_policy_check(self.cross_cell_authorized_contexts,
- self.cross_cell_unauthorized_contexts,
- rule_name,
- self.m_controller._migrate,
- req, self.instance.uuid,
- body={'migrate': {'host': 'fake'}},
- fatal=False)
+ self.common_policy_auth(self.cross_cell_authorized_contexts,
+ rule_name,
+ self.m_controller._migrate,
+ req, self.instance.uuid,
+ body={'migrate': {'host': 'fake'}},
+ fatal=False)
def test_network_attach_external_network_policy(self):
# NOTE(gmann): Testing policy 'network:attach_external_network'
# which raise different error then PolicyNotAuthorized
# if not allowed.
neutron_api = neutron.API()
- for context in self.zero_disk_external_net_authorized_contexts:
+ for context in self.all_projects_admin_authorized_contexts:
neutron_api._check_external_network_attach(context,
[{'id': 1, 'router:external': 'ext'}])
- for context in self.zero_disk_external_net_unauthorized_contexts:
+ unauth = (set(self.all_contexts) -
+ set(self.all_projects_admin_authorized_contexts))
+ for context in unauth:
self.assertRaises(exception.ExternalNetworkAttachForbidden,
neutron_api._check_external_network_attach,
context, [{'id': 1, 'router:external': 'ext'}])
@@ -1306,16 +1305,63 @@ class ServersPolicyTest(base.BasePolicyTest):
flavor = objects.Flavor(
vcpus=1, memory_mb=512, root_gb=0, extra_specs={'hw:pmu': "true"})
compute_api = compute.API()
- for context in self.zero_disk_external_net_authorized_contexts:
+ for context in self.all_projects_admin_authorized_contexts:
compute_api._validate_flavor_image_nostatus(context,
image, flavor, None)
- for context in self.zero_disk_external_net_unauthorized_contexts:
+ unauth = (set(self.all_contexts) -
+ set(self.all_projects_admin_authorized_contexts))
+ for context in unauth:
self.assertRaises(
exception.BootFromVolumeRequiredForZeroDiskFlavor,
compute_api._validate_flavor_image_nostatus,
context, image, flavor, None)
+class ServersNoLegacyNoScopeTest(ServersPolicyTest):
+ """Test Servers API policies with deprecated rules disabled, but scope
+ checking still disabled.
+ """
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.SERVERS % 'show:flavor-extra-specs':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ }
+
+ def setUp(self):
+ super(ServersNoLegacyNoScopeTest, self).setUp()
+
+ # Disabling legacy rule support means that we no longer allow
+ # random roles on our project to take action on our
+ # resources. Legacy admin will have access.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+
+ # The only additional role that can read our resources is our
+ # own project_reader.
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
+
+ # Disabling legacy support means random roles lose power to
+ # see everything in their project.
+ self.reduce_set('everyone_authorized',
+ self.all_contexts - set([self.project_foo_context,
+ self.system_foo_context]))
+
+ # Disabling legacy support means readers and random roles lose
+ # power to create things on their own projects. Note that
+ # system_admin and system_member are still here because we are
+ # not rejecting them by scope, even though these operations
+ # with those tokens are likely to fail because they have no
+ # project.
+ self.reduce_set('project_member_authorized',
+ self.all_contexts - set([
+ self.system_reader_context,
+ self.system_foo_context,
+ self.project_reader_context,
+ self.project_foo_context,
+ self.other_project_reader_context]))
+
+
class ServersScopeTypePolicyTest(ServersPolicyTest):
"""Test Servers APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -1342,143 +1388,77 @@ class ServersScopeTypePolicyTest(ServersPolicyTest):
self.rule_requested_destination = None
self.rule_forced_host = None
- # Check that system admin is able to create server with host request
- # and get server extended attributes or host status.
- self.admin_authorized_contexts = [
- self.system_admin_context
- ]
- # Check that non-system/admin is not able to create server with
- # host request and get server extended attributes or host status.
- self.admin_unauthorized_contexts = [
- self.project_admin_context, self.legacy_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that system reader is able to list the server
- # for all projects.
- self.system_reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system reader is not able to list the server
- # for all projects.
- self.system_reader_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
-
- # Check if project member can create the server.
- self.project_member_authorized_contexts = [
- self.legacy_admin_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_reader_context
- ]
- # Check if non-project member cannot create the server.
- self.project_member_unauthorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context
- ]
-
- # Check that project admin is able to create server with requested
- # destination.
- self.project_admin_authorized_contexts = [
- self.legacy_admin_context, self.project_admin_context]
- # Check that non-project admin is not able to create server with
- # requested destination
- self.project_admin_unauthorized_contexts = [
- self.system_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
+ # With scope checking enabled, system admins no longer have
+ # admin-granted project resource access.
+ self.reduce_set('project_action_authorized',
+ set([self.legacy_admin_context,
+ self.project_admin_context,
+ self.project_member_context,
+ self.project_reader_context,
+ self.project_foo_context]))
+
+ # No change from the base behavior here, but we need to
+ # re-build this from project_action_authorized, since we
+ # changed it above.
+ self.project_reader_authorized_contexts = (
+ self.project_action_authorized_contexts)
+
+ # With scope checking enabled, system users no longer have
+ # project access, even to create their own resources.
+ self.reduce_set('project_member_authorized', self.all_project_contexts)
+
+ # With scope checking enabled, system admin is no longer an
+ # admin of project resources.
+ self.reduce_set('project_admin_authorized',
+ set([self.legacy_admin_context,
+ self.project_admin_context]))
+ self.reduce_set('all_projects_admin_authorized',
+ set([self.legacy_admin_context,
+ self.project_admin_context]))
+
+ # With scope checking enabled, system users also lose access to read
+ # project resources.
+ self.reduce_set('everyone_authorized',
+ self.all_contexts - self.all_system_contexts)
class ServersNoLegacyPolicyTest(ServersScopeTypePolicyTest):
"""Test Servers APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system_admin_or_owner APIs.
+ and no more deprecated rules.
"""
without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.SERVERS % 'show:flavor-extra-specs':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ }
def setUp(self):
super(ServersNoLegacyPolicyTest, self).setUp()
- # Check that system admin or owner is able to update, delete
- # or perform server action.
- self.admin_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.project_member_context,
- ]
- # Check that non-system and non-admin/owner is not able to update,
- # delete or perform server action.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context]
-
- # Check that system reader or projct owner is able to get
- # server.
- self.system_reader_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_member_context,
- ]
-
- # Check that non-system reader nd non-admin/owner is not able to get
- # server.
- self.system_reader_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.project_foo_context,
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_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.other_project_reader_context,
- ]
- self.everyone_unauthorized_contexts = [
- self.project_foo_context,
- self.system_foo_context
- ]
- # Check if project member can create the server.
- 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.
- self.project_member_unauthorized_contexts = [
- self.system_admin_context,
- self.system_member_context, self.project_reader_context,
- self.project_foo_context, self.other_project_reader_context,
- self.system_reader_context, self.system_foo_context
- ]
- # Check that system admin is able to get server extended attributes
- # or host status.
- self.server_attr_admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system admin is not able to get server extended
- # attributes or host status.
- self.server_attr_admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context
- ]
+ # Disabling legacy support means legacy_admin is no longer
+ # powerful on our project. Also, we drop the "any role on the
+ # project means you can do stuff" behavior, so project_reader
+ # and project_foo lose power.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+
+ # Only project_reader has additional read access to our
+ # project resources.
+ self.project_reader_authorized_contexts = (
+ self.project_action_authorized_contexts |
+ set([self.project_reader_context]))
+
+ # Disabling legacy support means random roles lose power to
+ # see everything in their project.
+ self.reduce_set(
+ 'everyone_authorized',
+ self.all_project_contexts - set([self.project_foo_context]))
+
+ # Disabling legacy support means readers and random roles lose
+ # power to create things on their own projects.
+ self.reduce_set('project_member_authorized',
+ self.all_project_contexts - set([
+ self.project_foo_context,
+ self.project_reader_context,
+ self.other_project_reader_context,
+ ]))
diff --git a/nova/tests/unit/policies/test_services.py b/nova/tests/unit/policies/test_services.py
index cdca5ebc7f..72465eb748 100644
--- a/nova/tests/unit/policies/test_services.py
+++ b/nova/tests/unit/policies/test_services.py
@@ -11,12 +11,9 @@
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import services as services_v21
-from nova import exception
-from nova.policies import base as base_policy
-from nova.tests import fixtures
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
@@ -34,64 +31,36 @@ class ServicesPolicyTest(base.BasePolicyTest):
super(ServicesPolicyTest, self).setUp()
self.controller = services_v21.ServiceController()
self.req = fakes.HTTPRequest.blank('/services')
- # Check that admin is able to change the service
- self.admin_authorized_contexts = [
+
+ # With legacy rule and scope check disabled by default, system admin,
+ # legacy admin, and project admin will be able to perform Services
+ # Operations.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to change the service
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
- # Check that system scoped admin, member and reader are able to
- # read the service data.
- # 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 service 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.system_admin_context, self.system_member_context,
- self.system_reader_context, self.legacy_admin_context,
- self.project_admin_context]
- # Check that non-system-reader are not able to read the service
- # data
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.project_foo_context, self.project_member_context,
- self.project_reader_context,
- self.other_project_reader_context,
- ]
def test_delete_service_policy(self):
rule_name = "os_compute_api:os-services:delete"
with mock.patch('nova.compute.api.HostAPI.service_get_by_id'):
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.delete,
- self.req, 1)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.delete,
+ self.req, 1)
def test_index_service_policy(self):
rule_name = "os_compute_api:os-services:list"
with mock.patch('nova.compute.api.HostAPI.service_get_all'):
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
def test_old_update_service_policy(self):
rule_name = "os_compute_api:os-services:update"
body = {'host': 'host1', 'binary': 'nova-compute'}
update = 'nova.compute.api.HostAPI.service_update_by_host_and_binary'
with mock.patch(update):
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.update,
- self.req, 'enable', body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.update,
+ self.req, 'enable', body=body)
def test_update_service_policy(self):
rule_name = "os_compute_api:os-services:update"
@@ -100,11 +69,25 @@ class ServicesPolicyTest(base.BasePolicyTest):
service = self.start_service(
'compute', 'fake-compute-host').service_ref
with mock.patch('nova.compute.api.HostAPI.service_update'):
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.update,
- req, service.uuid,
- body={'status': 'enabled'})
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.update,
+ req, service.uuid,
+ body={'status': 'enabled'})
+
+
+class ServicesNoLegacyNoScopePolicyTest(ServicesPolicyTest):
+ """Test Services APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only. In this case
+ system admin, legacy admin, and project admin will be able to
+ perform Service Operations. Legacy admin will be allowed as policy
+ is just admin if no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(ServicesNoLegacyNoScopePolicyTest, self).setUp()
class ServicesScopeTypePolicyTest(ServicesPolicyTest):
@@ -122,80 +105,16 @@ class ServicesScopeTypePolicyTest(ServicesPolicyTest):
super(ServicesScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to change the service
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system or non-admin is not able to change the service
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
- # Check that system admin, member and reader are able to read the
- # service data
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system or non-reader are not able to read the service
- # data
- self.reader_unauthorized_contexts = [
- self.system_foo_context, self.legacy_admin_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
-
-class ServicesDeprecatedPolicyTest(base.BasePolicyTest):
- """Test os-services APIs Deprecated policies.
-
- This class checks if deprecated policy rules are
- overridden by user on policy.yaml file then they
- still work because oslo.policy add deprecated rules
- in logical OR condition and enforce them for policy
- checks if overridden.
+ # With scope checks enable, only system admin is able to perform
+ # Service Operations.
+ self.project_admin_authorized_contexts = [self.legacy_admin_context,
+ self.project_admin_context]
+
+
+class ServicesScopeTypeNoLegacyPolicyTest(ServicesScopeTypePolicyTest):
+ """Test Services APIs policies with no legacy deprecated rules
+ and scope checks enabled which means scope + new defaults so
+ only system admin is able to perform Services Operations.
"""
- def setUp(self):
- super(ServicesDeprecatedPolicyTest, self).setUp()
- self.controller = services_v21.ServiceController()
- self.member_req = fakes.HTTPRequest.blank('')
- self.member_req.environ['nova.context'] = self.system_reader_context
- self.reader_req = fakes.HTTPRequest.blank('')
- self.reader_req.environ['nova.context'] = self.project_reader_context
- self.deprecated_policy = "os_compute_api:os-services"
- # Overridde rule with different checks than defaults so that we can
- # verify the rule overridden case.
- override_rules = {self.deprecated_policy: base_policy.SYSTEM_READER}
- # NOTE(gmann): Only override the deprecated rule in policy file so
- # that
- # we can verify if overridden checks are considered by oslo.policy.
- # Oslo.policy will consider the overridden rules if:
- # 1. overridden deprecated rule's checks are different than defaults
- # 2. new rules are not present in policy file
- self.policy = self.useFixture(fixtures.OverridePolicyFixture(
- rules_in_file=override_rules))
-
- def test_deprecated_policy_overridden_rule_is_checked(self):
- # Test to verify if deprecatd overridden policy is working.
-
- # check for success as member role. Deprecated rule
- # has been overridden with member checks in policy.yaml
- # If member role pass it means overridden rule is enforced by
- # olso.policy because new default is system admin and the old
- # default is admin.
- with mock.patch('nova.compute.api.HostAPI.service_get_by_id'):
- self.controller.index(self.member_req)
-
- # check for failure with reader context.
- exc = self.assertRaises(exception.PolicyNotAuthorized,
- self.controller.index, self.reader_req)
- self.assertEqual(
- "Policy doesn't allow os_compute_api:os-services:list to be"
- " performed.",
- exc.format_message())
+ without_deprecated_rules = True
diff --git a/nova/tests/unit/policies/test_shelve.py b/nova/tests/unit/policies/test_shelve.py
index c4cf3dedbb..052f844c3d 100644
--- a/nova/tests/unit/policies/test_shelve.py
+++ b/nova/tests/unit/policies/test_shelve.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import shelve
@@ -43,63 +44,48 @@ class ShelveServerPolicyTest(base.BasePolicyTest):
id=1, uuid=uuids.fake_id, project_id=self.project_id,
user_id=user_id, vm_state=vm_states.ACTIVE)
self.mock_get.return_value = self.instance
-
- # Check that admin or and server owner is able to shelve/unshelve
- # the server
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to shelve,
+ # unshelve the server.
+ self.project_action_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 shelve/unshelve
- # the server
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
- # Check that admin is able to shelve offload the server.
- self.admin_authorized_contexts = [
+
+ # By default, legacy rule are enable and scope check is disabled.
+ # system admin, legacy admin, and project admin is able to shelve
+ # offload the server.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
- # Check that non-admin is not able to shelve offload the server.
- self.admin_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.compute.api.API.shelve')
def test_shelve_server_policy(self, mock_shelve):
rule_name = policies.POLICY_ROOT % 'shelve'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._shelve,
- self.req, self.instance.uuid,
- body={'shelve': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._shelve,
+ self.req, self.instance.uuid,
+ body={'shelve': {}})
@mock.patch('nova.compute.api.API.unshelve')
def test_unshelve_server_policy(self, mock_unshelve):
rule_name = policies.POLICY_ROOT % 'unshelve'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._unshelve,
- self.req, self.instance.uuid,
- body={'unshelve': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._unshelve,
+ self.req, self.instance.uuid,
+ body={'unshelve': {}})
@mock.patch('nova.compute.api.API.shelve_offload')
def test_shelve_offload_server_policy(self, mock_offload):
rule_name = policies.POLICY_ROOT % 'shelve_offload'
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name,
- self.controller._shelve_offload,
- self.req, self.instance.uuid,
- body={'shelveOffload': {}})
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller._shelve_offload,
+ self.req, self.instance.uuid,
+ body={'shelveOffload': {}})
def test_shelve_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -115,7 +101,7 @@ class ShelveServerPolicyTest(base.BasePolicyTest):
exc.format_message())
@mock.patch('nova.compute.api.API.shelve')
- def test_shelve_sevrer_overridden_policy_pass_with_same_user(
+ def test_shelve_server_overridden_policy_pass_with_same_user(
self, mock_shelve):
rule_name = policies.POLICY_ROOT % 'shelve'
self.policy.set_rules({rule_name: "user_id:%(user_id)s"})
@@ -124,6 +110,22 @@ class ShelveServerPolicyTest(base.BasePolicyTest):
body={'shelve': {}})
+class ShelveServerNoLegacyNoScopePolicyTest(ShelveServerPolicyTest):
+ """Test shelve/unshelve server APIs policies with no legacy deprecated
+ rules and no scope checks which means new defaults only.
+
+ """
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(ShelveServerNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to shelve/unshelve the server and only project admin can
+ # shelve offload the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+
+
class ShelveServerScopeTypePolicyTest(ShelveServerPolicyTest):
"""Test Shelve Server APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -137,41 +139,23 @@ class ShelveServerScopeTypePolicyTest(ShelveServerPolicyTest):
def setUp(self):
super(ShelveServerScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin to shelve/unshelve the
+ # server.
+ self.project_action_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class ShelveServerNoLegacyPolicyTest(ShelveServerScopeTypePolicyTest):
+class ShelveServerScopeTypeNoLegacyPolicyTest(ShelveServerScopeTypePolicyTest):
"""Test Shelve Server APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
- super(ShelveServerNoLegacyPolicyTest, self).setUp()
-
- # Check that system admin or and owner is able to shelve/unshelve
- # the server.
- 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 shelve/unshelve
- # the server.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context, self.project_reader_context,
- self.project_foo_context,
- self.other_project_reader_context,
- ]
- # Check that system admin is able to shelve offload the server.
- self.admin_authorized_contexts = [
- self.system_admin_context
- ]
- # Check that non system admin is not able to shelve offload the server
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.project_admin_context,
- self.system_member_context, self.system_reader_context,
- self.system_foo_context, self.project_member_context,
- self.project_reader_context, self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ super(ShelveServerScopeTypeNoLegacyPolicyTest, self).setUp()
+ # With scope enable and no legacy rule, only project admin/member
+ # will be able to shelve/unshelve the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_simple_tenant_usage.py b/nova/tests/unit/policies/test_simple_tenant_usage.py
index 60eecdece8..d6aa7af901 100644
--- a/nova/tests/unit/policies/test_simple_tenant_usage.py
+++ b/nova/tests/unit/policies/test_simple_tenant_usage.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from nova.api.openstack.compute import simple_tenant_usage
from nova.policies import simple_tenant_usage as policies
@@ -32,47 +32,46 @@ class SimpleTenantUsagePolicyTest(base.BasePolicyTest):
self.req = fakes.HTTPRequest.blank('')
self.controller._get_instances_all_cells = mock.MagicMock()
- # Check that reader(legacy admin) or and owner is able to get
- # the tenant usage statistics for a specific tenant.
- self.reader_or_owner_authorized_contexts = [
+ # Currently any admin can list other project usage.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context]
+ # and project reader can get their usage statistics.
+ self.project_reader_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,
- self.system_member_context, self.system_reader_context]
- # Check that non-reader(legacy non-admin) or owner is not able to get
- # the tenant usage statistics for a specific tenant.
- self.reader_or_owner_unauthorized_contexts = [
- self.system_foo_context, self.other_project_member_context,
- self.other_project_reader_context
- ]
- # Check that reader is able to get the tenant usage statistics.
- self.reader_authorized_contexts = [
- self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-reader is not able to get the tenant usage statistics.
- 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,
- self.other_project_reader_context
]
def test_index_simple_tenant_usage_policy(self):
rule_name = policies.POLICY_ROOT % 'list'
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name,
- self.controller.index,
- self.req)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name,
+ self.controller.index,
+ self.req)
def test_show_simple_tenant_usage_policy(self):
rule_name = policies.POLICY_ROOT % 'show'
- self.common_policy_check(self.reader_or_owner_authorized_contexts,
- self.reader_or_owner_unauthorized_contexts,
- rule_name,
- self.controller.show,
- self.req, self.project_id)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name,
+ self.controller.show,
+ self.req, self.project_id)
+
+
+class SimpleTenantUsageNoLegacyNoScopePolicyTest(SimpleTenantUsagePolicyTest):
+ """Test Simple Tenant Usage APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(SimpleTenantUsageNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy, project other roles like foo will not be able
+ # to get tenant usage.
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
class SimpleTenantUsageScopeTypePolicyTest(SimpleTenantUsagePolicyTest):
@@ -88,23 +87,14 @@ class SimpleTenantUsageScopeTypePolicyTest(SimpleTenantUsagePolicyTest):
def setUp(self):
super(SimpleTenantUsageScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
-
- # Check that system reader is able to get the tenant usage statistics.
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context]
- # Check that non-system/reader is not able to get the tenant usage
- # statistics.
- 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,
- self.other_project_reader_context
- ]
+ # With Scope enable, system users no longer allowed.
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class SimpleTenantUsageNoLegacyPolicyTest(
+class SimpleTenantUsageScopeTypeNoLegacyPolicyTest(
SimpleTenantUsageScopeTypePolicyTest):
"""Test Simple Tenant Usage APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
@@ -113,17 +103,6 @@ class SimpleTenantUsageNoLegacyPolicyTest(
without_deprecated_rules = True
def setUp(self):
- super(SimpleTenantUsageNoLegacyPolicyTest, self).setUp()
- # Check that system reader or owner is able to get
- # the tenant usage statistics for a specific tenant.
- self.reader_or_owner_authorized_contexts = [
- self.system_admin_context, self.system_member_context,
- self.system_reader_context, self.project_admin_context,
- self.project_member_context, self.project_reader_context]
- # Check that non-system reader/owner is not able to get
- # the tenant usage statistics for a specific tenant.
- self.reader_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_foo_context,
- self.other_project_member_context,
- self.project_foo_context, self.other_project_reader_context
- ]
+ super(SimpleTenantUsageScopeTypeNoLegacyPolicyTest, self).setUp()
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_suspend_server.py b/nova/tests/unit/policies/test_suspend_server.py
index ecf0ebb9ab..7d3cde2799 100644
--- a/nova/tests/unit/policies/test_suspend_server.py
+++ b/nova/tests/unit/policies/test_suspend_server.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import suspend_server
@@ -44,40 +45,32 @@ class SuspendServerPolicyTest(base.BasePolicyTest):
user_id=user_id, vm_state=vm_states.ACTIVE)
self.mock_get.return_value = self.instance
- # Check that admin or and server owner is able to suspend/resume
- # the server
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow server
+ # owner- having same project id and no role check) is able to suspend
+ # resume the server.
+ self.project_action_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 suspend/resume
- # the server
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
@mock.patch('nova.compute.api.API.suspend')
def test_suspend_server_policy(self, mock_suspend):
rule_name = policies.POLICY_ROOT % 'suspend'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._suspend,
- self.req, self.instance.uuid,
- body={'suspend': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._suspend,
+ self.req, self.instance.uuid,
+ body={'suspend': {}})
@mock.patch('nova.compute.api.API.resume')
def test_resume_server_policy(self, mock_resume):
rule_name = policies.POLICY_ROOT % 'resume'
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name,
- self.controller._resume,
- self.req, self.instance.uuid,
- body={'resume': {}})
+ self.common_policy_auth(self.project_action_authorized_contexts,
+ rule_name,
+ self.controller._resume,
+ self.req, self.instance.uuid,
+ body={'resume': {}})
def test_suspend_server_policy_failed_with_other_user(self):
# Change the user_id in request context.
@@ -102,6 +95,22 @@ class SuspendServerPolicyTest(base.BasePolicyTest):
body={'suspend': {}})
+class SuspendServerNoLegacyNoScopePolicyTest(SuspendServerPolicyTest):
+ """Test suspend server APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(SuspendServerNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only project admin or member will be
+ # able to suspend/resume the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+
+
class SuspendServerScopeTypePolicyTest(SuspendServerPolicyTest):
"""Test Suspend Server APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@@ -115,28 +124,22 @@ class SuspendServerScopeTypePolicyTest(SuspendServerPolicyTest):
def setUp(self):
super(SuspendServerScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # Scope enable will not allow system admin to suspend/resume server.
+ self.project_action_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
-class SuspendServerNoLegacyPolicyTest(SuspendServerScopeTypePolicyTest):
- """Test Suspend Server APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to
- access system APIs.
+class SuspendServerScopeTypeNoLegacyTest(SuspendServerScopeTypePolicyTest):
+ """Test suspend/resume server APIs policies with system scope enabled,
+ and no more deprecated rules which means scope + new defaults so
+ only project admin and member is able to suspend/resume server.
"""
+
without_deprecated_rules = True
def setUp(self):
- super(SuspendServerNoLegacyPolicyTest, self).setUp()
- # Check that system admin or and server owner is able to
- # suspend/resume the server.
- 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 suspend/resume
- # the server.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.other_project_member_context, self.project_reader_context,
- self.project_foo_context,
- self.other_project_reader_context,
- ]
+ super(SuspendServerScopeTypeNoLegacyTest, self).setUp()
+ # With scope enable and no legacy rule only project admin/member
+ # will be able to suspend/resume the server.
+ self.project_action_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
diff --git a/nova/tests/unit/policies/test_tenant_networks.py b/nova/tests/unit/policies/test_tenant_networks.py
index 12e8731582..a5bc614902 100644
--- a/nova/tests/unit/policies/test_tenant_networks.py
+++ b/nova/tests/unit/policies/test_tenant_networks.py
@@ -10,10 +10,13 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import tenant_networks
+from nova.policies import base as base_policy
+from nova.policies import tenant_networks as policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
@@ -36,7 +39,7 @@ class TenantNetworksPolicyTest(base.BasePolicyTest):
# enforcement so will be passing context's project_id as target to
# policy and always pass. If requester is not admin or owner
# of networks then neutron will be returning the appropriate error.
- self.everyone_authorized_contexts = [
+ self.project_reader_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,
@@ -45,23 +48,46 @@ class TenantNetworksPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
- self.everyone_unauthorized_contexts = []
@mock.patch('nova.network.neutron.API.get_all')
def test_list_tenant_networks_policy(self, mock_get):
- rule_name = "os_compute_api:os-tenant-networks"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ rule_name = "os_compute_api:os-tenant-networks:list"
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
@mock.patch('nova.network.neutron.API.get')
def test_show_tenant_network_policy(self, mock_get):
- rule_name = "os_compute_api:os-tenant-networks"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, uuids.fake_id)
+ rule_name = "os_compute_api:os-tenant-networks:show"
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, uuids.fake_id)
+
+
+class TenantNetworksNoLegacyNoScopePolicyTest(TenantNetworksPolicyTest):
+ """Test Tenant Networks APIs policies with no legacy deprecated rules
+ and no scope checks.
+
+ """
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.POLICY_NAME % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ policies.POLICY_NAME % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN}
+
+ def setUp(self):
+ super(TenantNetworksNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy, project other roles like foo will not be able
+ # to get tenant network.
+ self.project_reader_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context,
+ self.other_project_reader_context,
+ self.system_member_context, self.system_reader_context,
+ self.other_project_member_context
+ ]
class TenantNetworksScopeTypePolicyTest(TenantNetworksPolicyTest):
@@ -78,3 +104,31 @@ class TenantNetworksScopeTypePolicyTest(TenantNetworksPolicyTest):
def setUp(self):
super(TenantNetworksScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ self.project_reader_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_reader_context,
+ self.other_project_member_context
+ ]
+
+
+class TenantNetworksScopeTypeNoLegacyPolicyTest(
+ TenantNetworksScopeTypePolicyTest):
+ """Test Tenant Networks APIs policies with system scope enabled,
+ and no more deprecated rules.
+ """
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ policies.POLICY_NAME % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ policies.POLICY_NAME % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN}
+
+ def setUp(self):
+ super(TenantNetworksScopeTypeNoLegacyPolicyTest, self).setUp()
+ self.project_reader_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context, self.project_reader_context,
+ self.other_project_member_context,
+ self.other_project_reader_context,
+ ]
diff --git a/nova/tests/unit/policies/test_volumes.py b/nova/tests/unit/policies/test_volumes.py
index 4ee33d0694..896881c03f 100644
--- a/nova/tests/unit/policies/test_volumes.py
+++ b/nova/tests/unit/policies/test_volumes.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
@@ -20,6 +21,8 @@ from nova.compute import vm_states
from nova import exception
from nova import objects
from nova.objects import block_device as block_device_obj
+from nova.policies import base as base_policy
+from nova.policies import volumes as v_policies
from nova.policies import volumes_attachments as va_policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit import fake_block_device
@@ -92,77 +95,50 @@ class VolumeAttachPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
- # Check that admin or owner is able to list/create/show/delete
- # the attached volume.
- self.admin_or_owner_authorized_contexts = [
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow
+ # resource owner- having same project id and no role check) is
+ # able create/delete/update the volume attachment.
+ self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.project_admin_context, self.project_foo_context,
- self.project_reader_context, self.project_member_context
- ]
-
- self.admin_or_owner_unauthorized_contexts = [
- self.system_member_context, self.system_reader_context,
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
-
- # Check that admin is able to update the attached volume
- self.admin_authorized_contexts = [
- self.legacy_admin_context,
- self.system_admin_context,
- self.project_admin_context
- ]
- # Check that non-admin is not able to update the attached
- # volume
- self.admin_unauthorized_contexts = [
- self.system_member_context,
- self.system_reader_context,
- self.system_foo_context,
- self.project_member_context,
- self.other_project_member_context,
- self.project_foo_context,
- self.project_reader_context,
- self.other_project_reader_context,
- ]
-
- self.reader_authorized_contexts = [
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context, self.project_foo_context]
+
+ # With legacy rule and no scope checks, all admin, project members
+ # project reader or other project role(because legacy rule allow
+ # resource owner- having same project id and no role check) is
+ # able get the volume attachment.
+ self.project_reader_authorized_contexts = (
+ self.project_member_authorized_contexts)
+
+ # By default, legacy rule are enable and scope check is disabled.
+ # system admin, legacy admin, and project admin is able to update
+ # volume attachment with a different volumeId.
+ self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
- self.system_reader_context, self.system_member_context,
- self.project_admin_context, self.project_reader_context,
- self.project_member_context, self.project_foo_context
- ]
-
- self.reader_unauthorized_contexts = [
- self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ self.project_admin_context]
@mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
def test_index_volume_attach_policy(self, mock_get_instance):
rule_name = self.policy_root % "index"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req, FAKE_UUID)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req, FAKE_UUID)
def test_show_volume_attach_policy(self):
rule_name = self.policy_root % "show"
- self.common_policy_check(self.reader_authorized_contexts,
- self.reader_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, FAKE_UUID, FAKE_UUID_A)
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, FAKE_UUID, FAKE_UUID_A)
@mock.patch('nova.compute.api.API.attach_volume')
def test_create_volume_attach_policy(self, mock_attach_volume):
rule_name = self.policy_root % "create"
body = {'volumeAttachment': {'volumeId': FAKE_UUID_B,
'device': '/dev/fake'}}
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name, self.controller.create,
- self.req, FAKE_UUID, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller.create,
+ self.req, FAKE_UUID, body=body)
@mock.patch.object(block_device_obj.BlockDeviceMapping, 'save')
def test_update_volume_attach_policy(self, mock_bdm_save):
@@ -171,28 +147,25 @@ class VolumeAttachPolicyTest(base.BasePolicyTest):
body = {'volumeAttachment': {
'volumeId': FAKE_UUID_A,
'delete_on_termination': True}}
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name, self.controller.update,
- req, FAKE_UUID,
- FAKE_UUID_A, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller.update,
+ req, FAKE_UUID,
+ FAKE_UUID_A, body=body)
@mock.patch('nova.compute.api.API.detach_volume')
def test_delete_volume_attach_policy(self, mock_detach_volume):
rule_name = self.policy_root % "delete"
- self.common_policy_check(self.admin_or_owner_authorized_contexts,
- self.admin_or_owner_unauthorized_contexts,
- rule_name, self.controller.delete,
- self.req, FAKE_UUID, FAKE_UUID_A)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller.delete,
+ self.req, FAKE_UUID, FAKE_UUID_A)
@mock.patch('nova.compute.api.API.swap_volume')
def test_swap_volume_attach_policy(self, mock_swap_volume):
rule_name = self.policy_root % "swap"
body = {'volumeAttachment': {'volumeId': FAKE_UUID_B}}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.update,
- self.req, FAKE_UUID, FAKE_UUID_A, body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.update,
+ self.req, FAKE_UUID, FAKE_UUID_A, body=body)
@mock.patch.object(block_device_obj.BlockDeviceMapping, 'save')
@mock.patch('nova.compute.api.API.swap_volume')
@@ -225,14 +198,31 @@ class VolumeAttachPolicyTest(base.BasePolicyTest):
req = fakes.HTTPRequest.blank('', version='2.85')
body = {'volumeAttachment': {'volumeId': FAKE_UUID_B,
'delete_on_termination': True}}
- self.common_policy_check(self.admin_authorized_contexts,
- self.admin_unauthorized_contexts,
- rule_name, self.controller.update,
- req, FAKE_UUID, FAKE_UUID_A, body=body)
+ self.common_policy_auth(self.project_admin_authorized_contexts,
+ rule_name, self.controller.update,
+ req, FAKE_UUID, FAKE_UUID_A, body=body)
mock_swap_volume.assert_called()
mock_bdm_save.assert_called()
+class VolumeAttachNoLegacyNoScopePolicyTest(VolumeAttachPolicyTest):
+ """Test volume attachment APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+
+ def setUp(self):
+ super(VolumeAttachNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy rule, only admin, member, or reader will be
+ # able to perform volume attachment operation on its own project.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_no_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_no_scope_no_legacy)
+
+
class VolumeAttachScopeTypePolicyTest(VolumeAttachPolicyTest):
"""Test os-volume-attachments APIs policies with system scope enabled.
@@ -248,77 +238,33 @@ class VolumeAttachScopeTypePolicyTest(VolumeAttachPolicyTest):
super(VolumeAttachScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
- # Check that system admin is able to update the attached volume
- self.admin_authorized_contexts = [
- self.system_admin_context]
- # Check that non-system or non-admin is not able to update
- # the attached volume.
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
+ # Scope enable will not allow system admin to perform the
+ # volume attachments.
+ self.project_member_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_m_r_or_admin_with_scope_and_legacy)
+ self.project_admin_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context]
-class VolumeAttachNoLegacyPolicyTest(VolumeAttachPolicyTest):
+
+class VolumeAttachScopeTypeNoLegacyPolicyTest(VolumeAttachScopeTypePolicyTest):
"""Test os-volume-attachments APIs policies with system scope enabled,
- and no more deprecated rules that allow the legacy admin API to access
- system_admin_or_owner APIs.
+ and no legacy deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
- super(VolumeAttachNoLegacyPolicyTest, self).setUp()
+ super(VolumeAttachScopeTypeNoLegacyPolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
-
- # Check that system or projct admin or owner is able to
- # list/create/show/delete the attached volume.
- self.admin_or_owner_authorized_contexts = [
- self.system_admin_context,
- self.project_admin_context,
- self.project_member_context
- ]
-
- # Check that non-system and non-admin/owner is not able to
- # list/create/show/delete the attached volume.
- self.admin_or_owner_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.project_reader_context,
- self.project_foo_context, self.system_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
-
- # Check that admin is able to update the attached volume
- self.admin_authorized_contexts = [
- self.system_admin_context
- ]
- # Check that non-admin is not able to update the attached
- # volume
- self.admin_unauthorized_contexts = [
- self.legacy_admin_context, self.system_member_context,
- self.system_reader_context, self.system_foo_context,
- self.project_admin_context, self.project_member_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- self.project_foo_context, self.project_reader_context
- ]
-
- self.reader_authorized_contexts = [
- self.system_admin_context, self.system_reader_context,
- self.system_member_context, self.project_admin_context,
- self.project_reader_context, self.project_member_context
- ]
-
- self.reader_unauthorized_contexts = [
- self.legacy_admin_context, self.system_foo_context,
- self.project_foo_context,
- self.other_project_member_context,
- self.other_project_reader_context,
- ]
+ # With scope enable and no legacy rule, it will not allow
+ # system users and project admin/member/reader will be able to
+ # perform volume attachment operation on its own project.
+ self.project_member_authorized_contexts = (
+ self.project_member_or_admin_with_scope_no_legacy)
+ self.project_reader_authorized_contexts = (
+ self.project_reader_or_admin_with_scope_no_legacy)
class VolumesPolicyTest(base.BasePolicyTest):
@@ -336,14 +282,23 @@ class VolumesPolicyTest(base.BasePolicyTest):
self.snapshot_ctlr = volumes_v21.SnapshotController()
self.req = fakes.HTTPRequest.blank('')
self.controller._translate_volume_summary_view = mock.MagicMock()
- # Check that everyone is able to perform crud operations
+ # Everyone will be able to perform crud operations
# on volume and volume snapshots.
# NOTE: Nova cannot verify the volume/snapshot owner during nova policy
# enforcement so will be passing context's project_id as target to
# policy and always pass. If requester is not admin or owner
# of volume/snapshot then cinder will be returning the appropriate
# error.
- self.everyone_authorized_contexts = [
+ self.project_member_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,
+ self.other_project_reader_context,
+ self.system_member_context, self.system_reader_context,
+ self.system_foo_context,
+ self.other_project_member_context
+ ]
+ self.project_reader_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,
@@ -352,94 +307,133 @@ class VolumesPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
- self.everyone_unauthorized_contexts = []
@mock.patch('nova.volume.cinder.API.get_all')
def test_list_volumes_policy(self, mock_get):
- rule_name = "os_compute_api:os-volumes"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.index,
- self.req)
+ rule_name = "os_compute_api:os-volumes:list"
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.index,
+ self.req)
@mock.patch('nova.volume.cinder.API.get_all')
def test_list_detail_volumes_policy(self, mock_get):
- rule_name = "os_compute_api:os-volumes"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.detail,
- self.req)
+ rule_name = "os_compute_api:os-volumes:detail"
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.detail,
+ self.req)
@mock.patch('nova.volume.cinder.API.get')
def test_show_volume_policy(self, mock_get):
- rule_name = "os_compute_api:os-volumes"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.show,
- self.req, uuids.fake_id)
+ rule_name = "os_compute_api:os-volumes:show"
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.controller.show,
+ self.req, uuids.fake_id)
@mock.patch('nova.api.openstack.compute.volumes.'
'_translate_volume_detail_view')
@mock.patch('nova.volume.cinder.API.create')
def test_create_volumes_policy(self, mock_create, mock_view):
- rule_name = "os_compute_api:os-volumes"
+ rule_name = "os_compute_api:os-volumes:create"
body = {"volume": {"size": 100,
"display_name": "Volume Test Name",
"display_description": "Volume Test Desc",
"availability_zone": "zone1:host1"}}
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller.create,
+ self.req, body=body)
@mock.patch('nova.volume.cinder.API.delete')
def test_delete_volume_policy(self, mock_delete):
- rule_name = "os_compute_api:os-volumes"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.controller.delete,
- self.req, uuids.fake_id)
+ rule_name = "os_compute_api:os-volumes:delete"
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.controller.delete,
+ self.req, uuids.fake_id)
@mock.patch('nova.volume.cinder.API.get_all_snapshots')
def test_list_snapshots_policy(self, mock_get):
- rule_name = "os_compute_api:os-volumes"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.snapshot_ctlr.index,
- self.req)
+ rule_name = "os_compute_api:os-volumes:snapshots:list"
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.snapshot_ctlr.index,
+ self.req)
@mock.patch('nova.volume.cinder.API.get_all_snapshots')
def test_list_detail_snapshots_policy(self, mock_get):
- rule_name = "os_compute_api:os-volumes"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.snapshot_ctlr.detail,
- self.req)
+ rule_name = "os_compute_api:os-volumes:snapshots:detail"
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.snapshot_ctlr.detail,
+ self.req)
@mock.patch('nova.volume.cinder.API.get_snapshot')
def test_show_snapshot_policy(self, mock_get):
- rule_name = "os_compute_api:os-volumes"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.snapshot_ctlr.show,
- self.req, uuids.fake_id)
+ rule_name = "os_compute_api:os-volumes:snapshots:show"
+ self.common_policy_auth(self.project_reader_authorized_contexts,
+ rule_name, self.snapshot_ctlr.show,
+ self.req, uuids.fake_id)
@mock.patch('nova.volume.cinder.API.create_snapshot')
def test_create_snapshot_policy(self, mock_create):
- rule_name = "os_compute_api:os-volumes"
+ rule_name = "os_compute_api:os-volumes:snapshots:create"
body = {"snapshot": {"volume_id": uuids.fake_id}}
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.snapshot_ctlr.create,
- self.req, body=body)
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.snapshot_ctlr.create,
+ self.req, body=body)
@mock.patch('nova.volume.cinder.API.delete_snapshot')
def test_delete_snapshot_policy(self, mock_delete):
- rule_name = "os_compute_api:os-volumes"
- self.common_policy_check(self.everyone_authorized_contexts,
- self.everyone_unauthorized_contexts,
- rule_name, self.snapshot_ctlr.delete,
- self.req, uuids.fake_id)
+ rule_name = "os_compute_api:os-volumes:snapshots:delete"
+ self.common_policy_auth(self.project_member_authorized_contexts,
+ rule_name, self.snapshot_ctlr.delete,
+ self.req, uuids.fake_id)
+
+
+class VolumesNoLegacyNoScopePolicyTest(VolumesPolicyTest):
+ """Test Volume APIs policies with no legacy deprecated rules
+ and no scope checks which means new defaults only.
+
+ """
+
+ without_deprecated_rules = True
+ rules_without_deprecation = {
+ v_policies.POLICY_NAME % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'detail':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'create':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'delete':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:detail':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:delete':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:create':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ }
+
+ def setUp(self):
+ super(VolumesNoLegacyNoScopePolicyTest, self).setUp()
+ # With no legacy, project other roles like foo will not be able
+ # to operate on volume and snapshot.
+ 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.other_project_member_context
+ ]
+ self.project_reader_authorized_contexts = [
+ self.legacy_admin_context, self.system_admin_context,
+ self.project_admin_context, self.project_member_context,
+ self.project_reader_context,
+ self.other_project_reader_context,
+ self.system_member_context, self.system_reader_context,
+ self.other_project_member_context
+ ]
class VolumesScopeTypePolicyTest(VolumesPolicyTest):
@@ -456,3 +450,65 @@ class VolumesScopeTypePolicyTest(VolumesPolicyTest):
def setUp(self):
super(VolumesScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
+ # With scope enabled, system users will not be able to
+ # operate on volume and snapshot.
+ 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_reader_context,
+ self.other_project_member_context
+ ]
+ self.project_reader_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_reader_context,
+ self.other_project_member_context
+ ]
+
+
+class VolumesScopeTypeNoLegacyPolicyTest(VolumesScopeTypePolicyTest):
+ """Test Volume APIs policies with system scope enabled,
+ and no legacy deprecated rules.
+ """
+ without_deprecated_rules = True
+
+ rules_without_deprecation = {
+ v_policies.POLICY_NAME % 'list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'detail':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'create':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'delete':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:list':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:detail':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:delete':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:create':
+ base_policy.PROJECT_MEMBER_OR_ADMIN,
+ v_policies.POLICY_NAME % 'snapshots:show':
+ base_policy.PROJECT_READER_OR_ADMIN,
+ }
+
+ def setUp(self):
+ super(VolumesScopeTypeNoLegacyPolicyTest, self).setUp()
+ self.flags(enforce_scope=True, group="oslo_policy")
+ # With no legacy and scope enabled, system users and project
+ # other roles like foo will not be able to operate on volume
+ # and snapshot.
+ self.project_member_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context,
+ self.other_project_member_context
+ ]
+ self.project_reader_authorized_contexts = [
+ self.legacy_admin_context, self.project_admin_context,
+ self.project_member_context, self.project_reader_context,
+ self.other_project_reader_context,
+ self.other_project_member_context
+ ]