From ab084d4d1dbaafe1568c19aef5101efebee1e373 Mon Sep 17 00:00:00 2001 From: Ghanshyam Mann Date: Sun, 13 Feb 2022 19:56:27 -0600 Subject: [PATCH] Modify remaining APIs as per RBAC new guidelines As per the RBAC new direction, we will allow project resources operation to be performed by the project scoped token only and system user will be allowed to perform system level operation only not project resources specific. Details about new direction can be found in community-wide goal - https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html This commit modify remaining APIs as per the new guidelines. Also, allow all project admin to list the other project limits. This is what we allowed in legacy policy and until we have domain admin or other way to list other project resources/info, we will keep that behaviour. Also modifying and adding tests for four cases: 1. enforce_scope=False + legacy rule (current default policies) 2. enforce_scope=False + No legacy rule 3. enforce_scope=True + legacy rule 4. enforce_scope=True + no legacy rule (end goal of new RBAC) Partial implement blueprint policy-defaults-refresh-2 Change-Id: I006d47aa2f4678a06c78057bcf407302abbe4907 --- .../compute/assisted_volume_snapshots.py | 10 ++ .../openstack/compute/console_auth_tokens.py | 2 +- nova/api/openstack/compute/limits.py | 3 +- nova/api/openstack/compute/migrations.py | 2 +- .../compute/server_external_events.py | 5 + nova/policies/assisted_volume_snapshots.py | 22 ++- nova/policies/console_auth_tokens.py | 4 +- nova/policies/console_output.py | 4 +- nova/policies/create_backup.py | 4 +- nova/policies/deferred_delete.py | 8 +- nova/policies/flavor_access.py | 10 +- nova/policies/flavor_manage.py | 6 +- nova/policies/instance_usage_audit_log.py | 4 +- nova/policies/keypairs.py | 8 +- nova/policies/limits.py | 6 +- nova/policies/migrate_server.py | 8 +- nova/policies/migrations.py | 4 +- nova/policies/server_diagnostics.py | 4 +- nova/policies/server_external_events.py | 12 +- nova/policies/servers_migrations.py | 16 +- .../unit/api/openstack/compute/test_limits.py | 3 +- .../test_assisted_volume_snapshots.py | 65 ++++---- .../unit/policies/test_console_auth_tokens.py | 59 +++---- .../unit/policies/test_console_output.py | 70 ++++---- .../tests/unit/policies/test_create_backup.py | 74 ++++----- .../unit/policies/test_deferred_delete.py | 92 ++++++----- .../tests/unit/policies/test_flavor_access.py | 155 ++++++------------ .../tests/unit/policies/test_flavor_manage.py | 60 +++---- .../policies/test_instance_usage_audit_log.py | 71 ++++---- nova/tests/unit/policies/test_keypairs.py | 142 +++++----------- nova/tests/unit/policies/test_limits.py | 110 +++++++------ .../unit/policies/test_migrate_server.py | 92 +++++------ nova/tests/unit/policies/test_migrations.py | 53 +++--- .../unit/policies/test_server_diagnostics.py | 79 ++++----- .../policies/test_server_external_events.py | 49 +++--- .../unit/policies/test_server_migrations.py | 149 ++++++----------- 36 files changed, 648 insertions(+), 817 deletions(-) diff --git a/nova/api/openstack/compute/assisted_volume_snapshots.py b/nova/api/openstack/compute/assisted_volume_snapshots.py index ea6ebc83597d..ae7213884b36 100644 --- a/nova/api/openstack/compute/assisted_volume_snapshots.py +++ b/nova/api/openstack/compute/assisted_volume_snapshots.py @@ -39,6 +39,11 @@ class AssistedVolumeSnapshotsController(wsgi.Controller): def create(self, req, body): """Creates a new snapshot.""" context = req.environ['nova.context'] + # NOTE(gmann) We pass empty target to policy enforcement. This API + # is called by cinder which does not have correct project_id. + # By passing the empty target, we make sure that we do not check + # the requester project_id and allow users with + # allowed role to create snapshot. context.can(avs_policies.POLICY_ROOT % 'create', target={}) snapshot = body['snapshot'] @@ -69,6 +74,11 @@ class AssistedVolumeSnapshotsController(wsgi.Controller): def delete(self, req, id): """Delete a snapshot.""" context = req.environ['nova.context'] + # NOTE(gmann) We pass empty target to policy enforcement. This API + # is called by cinder which does not have correct project_id. + # By passing the empty target, we make sure that we do not check + # the requester project_id and allow users with allowed role to + # delete snapshot. context.can(avs_policies.POLICY_ROOT % 'delete', target={}) delete_metadata = {} diff --git a/nova/api/openstack/compute/console_auth_tokens.py b/nova/api/openstack/compute/console_auth_tokens.py index ae838fe85793..810eb00ca3fd 100644 --- a/nova/api/openstack/compute/console_auth_tokens.py +++ b/nova/api/openstack/compute/console_auth_tokens.py @@ -30,7 +30,7 @@ class ConsoleAuthTokensController(wsgi.Controller): def _show(self, req, id, rdp_only): """Checks a console auth token and returns the related connect info.""" context = req.environ['nova.context'] - context.can(cat_policies.BASE_POLICY_NAME, target={}) + context.can(cat_policies.BASE_POLICY_NAME) token = id if not token: diff --git a/nova/api/openstack/compute/limits.py b/nova/api/openstack/compute/limits.py index e6f901e09dca..755a6c365654 100644 --- a/nova/api/openstack/compute/limits.py +++ b/nova/api/openstack/compute/limits.py @@ -78,8 +78,7 @@ class LimitsController(wsgi.Controller): project_id = context.project_id if 'tenant_id' in req.GET: project_id = req.GET.get('tenant_id') - context.can(limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME, - target={'project_id': project_id}) + context.can(limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME) quotas = QUOTAS.get_project_quotas(context, project_id, usages=True) diff --git a/nova/api/openstack/compute/migrations.py b/nova/api/openstack/compute/migrations.py index cb97a1498af5..31287b739333 100644 --- a/nova/api/openstack/compute/migrations.py +++ b/nova/api/openstack/compute/migrations.py @@ -89,7 +89,7 @@ class MigrationsController(wsgi.Controller): sort_dirs=None, sort_keys=None, limit=None, marker=None, allow_changes_since=False, allow_changes_before=False): context = req.environ['nova.context'] - context.can(migrations_policies.POLICY_ROOT % 'index', target={}) + context.can(migrations_policies.POLICY_ROOT % 'index') search_opts = {} search_opts.update(req.GET) if 'changes-since' in search_opts: diff --git a/nova/api/openstack/compute/server_external_events.py b/nova/api/openstack/compute/server_external_events.py index 162bd93697aa..55f17e354129 100644 --- a/nova/api/openstack/compute/server_external_events.py +++ b/nova/api/openstack/compute/server_external_events.py @@ -73,6 +73,11 @@ class ServerExternalEventsController(wsgi.Controller): def create(self, req, body): """Creates a new instance event.""" context = req.environ['nova.context'] + # NOTE(gmann) We pass empty target to policy enforcement. This API + # is called by neutron which does not have correct project_id where + # server belongs to. By passing the empty target, we make sure that + # we do not check the requester project_id and allow users with + # allowed role to create external event. context.can(see_policies.POLICY_ROOT % 'create', target={}) response_events = [] diff --git a/nova/policies/assisted_volume_snapshots.py b/nova/policies/assisted_volume_snapshots.py index ed919076b44b..0630ee7a50e6 100644 --- a/nova/policies/assisted_volume_snapshots.py +++ b/nova/policies/assisted_volume_snapshots.py @@ -24,7 +24,14 @@ POLICY_ROOT = 'os_compute_api:os-assisted-volume-snapshots:%s' assisted_volume_snapshots_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'create', - check_str=base.SYSTEM_ADMIN, + # TODO(gmann): This is internal API policy and called by + # cinder. Add 'service' role in this policy so that cinder + # can call it with user having 'service' role (not having + # correct project_id). That is for phase-2 of RBAC goal and until + # then, we keep it open for all admin in any project. We cannot + # default it to PROJECT_ADMIN which has the project_id in + # check_str and will fail if cinder call it with other project_id. + check_str=base.ADMIN, description="Create an assisted volume snapshot", operations=[ { @@ -32,10 +39,17 @@ assisted_volume_snapshots_policies = [ 'method': 'POST' } ], - scope_types=['system']), + scope_types=['project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete', - check_str=base.SYSTEM_ADMIN, + # TODO(gmann): This is internal API policy and called by + # cinder. Add 'service' role in this policy so that cinder + # can call it with user having 'service' role (not having + # correct project_id). That is for phase-2 of RBAC goal and until + # then, we keep it open for all admin in any project. We cannot + # default it to PROJECT_ADMIN which has the project_id in + # check_str and will fail if cinder call it with other project_id. + check_str=base.ADMIN, description="Delete an assisted volume snapshot", operations=[ { @@ -43,7 +57,7 @@ assisted_volume_snapshots_policies = [ 'method': 'DELETE' } ], - scope_types=['system']), + scope_types=['project']), ] diff --git a/nova/policies/console_auth_tokens.py b/nova/policies/console_auth_tokens.py index d6a00b735cc1..bad3130e780b 100644 --- a/nova/policies/console_auth_tokens.py +++ b/nova/policies/console_auth_tokens.py @@ -24,7 +24,7 @@ BASE_POLICY_NAME = 'os_compute_api:os-console-auth-tokens' console_auth_tokens_policies = [ policy.DocumentedRuleDefault( name=BASE_POLICY_NAME, - check_str=base.SYSTEM_READER, + check_str=base.PROJECT_ADMIN, description="Show console connection information for a given console " "authentication token", operations=[ @@ -33,7 +33,7 @@ console_auth_tokens_policies = [ 'path': '/os-console-auth-tokens/{console_token}' } ], - scope_types=['system']) + scope_types=['project']) ] diff --git a/nova/policies/console_output.py b/nova/policies/console_output.py index 461ef83a5492..4a5a21ef5521 100644 --- a/nova/policies/console_output.py +++ b/nova/policies/console_output.py @@ -24,7 +24,7 @@ BASE_POLICY_NAME = 'os_compute_api:os-console-output' console_output_policies = [ policy.DocumentedRuleDefault( name=BASE_POLICY_NAME, - check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, + check_str=base.PROJECT_MEMBER, description='Show console output for a server', operations=[ { @@ -32,7 +32,7 @@ console_output_policies = [ 'path': '/servers/{server_id}/action (os-getConsoleOutput)' } ], - scope_types=['system', 'project']) + scope_types=['project']) ] diff --git a/nova/policies/create_backup.py b/nova/policies/create_backup.py index b7acc36bd5fd..173ad3e36f5c 100644 --- a/nova/policies/create_backup.py +++ b/nova/policies/create_backup.py @@ -24,7 +24,7 @@ BASE_POLICY_NAME = 'os_compute_api:os-create-backup' create_backup_policies = [ policy.DocumentedRuleDefault( name=BASE_POLICY_NAME, - check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, + check_str=base.PROJECT_MEMBER, description='Create a back up of a server', operations=[ { @@ -32,7 +32,7 @@ create_backup_policies = [ 'path': '/servers/{server_id}/action (createBackup)' } ], - scope_types=['system', 'project']) + scope_types=['project']) ] diff --git a/nova/policies/deferred_delete.py b/nova/policies/deferred_delete.py index 32069790ed09..a912966897dd 100644 --- a/nova/policies/deferred_delete.py +++ b/nova/policies/deferred_delete.py @@ -36,7 +36,7 @@ DEPRECATED_POLICY = policy.DeprecatedRule( deferred_delete_policies = [ policy.DocumentedRuleDefault( name=BASE_POLICY_NAME % 'restore', - check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, + check_str=base.PROJECT_MEMBER, description="Restore a soft deleted server", operations=[ { @@ -44,11 +44,11 @@ deferred_delete_policies = [ 'path': '/servers/{server_id}/action (restore)' }, ], - scope_types=['system', 'project'], + scope_types=['project'], deprecated_rule=DEPRECATED_POLICY), policy.DocumentedRuleDefault( name=BASE_POLICY_NAME % 'force', - check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN, + check_str=base.PROJECT_MEMBER, description="Force delete a server before deferred cleanup", operations=[ { @@ -56,7 +56,7 @@ deferred_delete_policies = [ 'path': '/servers/{server_id}/action (forceDelete)' } ], - scope_types=['system', 'project'], + scope_types=['project'], deprecated_rule=DEPRECATED_POLICY) ] diff --git a/nova/policies/flavor_access.py b/nova/policies/flavor_access.py index b70ae71811b0..d86e472c2f66 100644 --- a/nova/policies/flavor_access.py +++ b/nova/policies/flavor_access.py @@ -25,8 +25,8 @@ POLICY_ROOT = 'os_compute_api:os-flavor-access:%s' # NOTE(gmann): Deprecating this policy explicitly as old defaults # admin or owner is not suitable for that which should be admin (Bug#1867840) # but changing that will break old deployment so let's keep supporting -# the old default also and new default can be SYSTEM_READER -# SYSTEM_READER rule in base class is defined with the deprecated rule of admin +# the old default also and new default can be System Admin. +# System Admin rule in base class is defined with the deprecated rule of admin # not admin or owner which is the main reason that we need to explicitly # deprecate this policy here. DEPRECATED_REASON = """ @@ -45,7 +45,7 @@ DEPRECATED_FLAVOR_ACCESS_POLICY = policy.DeprecatedRule( flavor_access_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'add_tenant_access', - check_str=base.SYSTEM_ADMIN, + check_str=base.ADMIN, description="Add flavor access to a tenant", operations=[ { @@ -56,7 +56,7 @@ flavor_access_policies = [ scope_types=['system']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'remove_tenant_access', - check_str=base.SYSTEM_ADMIN, + check_str=base.ADMIN, description="Remove flavor access from a tenant", operations=[ { @@ -67,7 +67,7 @@ flavor_access_policies = [ scope_types=['system']), policy.DocumentedRuleDefault( name=BASE_POLICY_NAME, - check_str=base.SYSTEM_READER, + check_str=base.ADMIN, description="""List flavor access information Allows access to the full list of tenants that have access diff --git a/nova/policies/flavor_manage.py b/nova/policies/flavor_manage.py index 07f33975cce1..b7876e8c9675 100644 --- a/nova/policies/flavor_manage.py +++ b/nova/policies/flavor_manage.py @@ -25,7 +25,7 @@ POLICY_ROOT = 'os_compute_api:os-flavor-manage:%s' flavor_manage_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'create', - check_str=base.SYSTEM_ADMIN, + check_str=base.ADMIN, description="Create a flavor", operations=[ { @@ -36,7 +36,7 @@ flavor_manage_policies = [ scope_types=['system']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'update', - check_str=base.SYSTEM_ADMIN, + check_str=base.ADMIN, description="Update a flavor", operations=[ { @@ -47,7 +47,7 @@ flavor_manage_policies = [ scope_types=['system']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete', - check_str=base.SYSTEM_ADMIN, + check_str=base.ADMIN, description="Delete a flavor", operations=[ { diff --git a/nova/policies/instance_usage_audit_log.py b/nova/policies/instance_usage_audit_log.py index 98ab12c52e03..f93ace08c195 100644 --- a/nova/policies/instance_usage_audit_log.py +++ b/nova/policies/instance_usage_audit_log.py @@ -36,7 +36,7 @@ DEPRECATED_POLICY = policy.DeprecatedRule( instance_usage_audit_log_policies = [ policy.DocumentedRuleDefault( name=BASE_POLICY_NAME % 'list', - check_str=base.SYSTEM_READER, + check_str=base.ADMIN, description="List all usage audits.", operations=[ { @@ -48,7 +48,7 @@ instance_usage_audit_log_policies = [ deprecated_rule=DEPRECATED_POLICY), policy.DocumentedRuleDefault( name=BASE_POLICY_NAME % 'show', - check_str=base.SYSTEM_READER, + check_str=base.ADMIN, description="List all usage audits occurred before " "a specified time for all servers on all compute hosts where " "usage auditing is configured", diff --git a/nova/policies/keypairs.py b/nova/policies/keypairs.py index 3feaa524bd33..b0ee4a8906de 100644 --- a/nova/policies/keypairs.py +++ b/nova/policies/keypairs.py @@ -23,7 +23,7 @@ POLICY_ROOT = 'os_compute_api:os-keypairs:%s' keypairs_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str='(' + base.SYSTEM_READER + ') or user_id:%(user_id)s', + check_str='(' + base.ADMIN + ') or user_id:%(user_id)s', description="List all keypairs", operations=[ { @@ -34,7 +34,7 @@ keypairs_policies = [ scope_types=['system', 'project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'create', - check_str='(' + base.SYSTEM_ADMIN + ') or user_id:%(user_id)s', + check_str='(' + base.ADMIN + ') or user_id:%(user_id)s', description="Create a keypair", operations=[ { @@ -45,7 +45,7 @@ keypairs_policies = [ scope_types=['system', 'project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete', - check_str='(' + base.SYSTEM_ADMIN + ') or user_id:%(user_id)s', + check_str='(' + base.ADMIN + ') or user_id:%(user_id)s', description="Delete a keypair", operations=[ { @@ -56,7 +56,7 @@ keypairs_policies = [ scope_types=['system', 'project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show', - check_str='(' + base.SYSTEM_READER + ') or user_id:%(user_id)s', + check_str='(' + base.ADMIN + ') or user_id:%(user_id)s', description="Show details of a keypair", operations=[ { diff --git a/nova/policies/limits.py b/nova/policies/limits.py index efe430c237ae..56bc0e830d21 100644 --- a/nova/policies/limits.py +++ b/nova/policies/limits.py @@ -46,10 +46,10 @@ limits_policies = [ 'path': '/limits' } ], - scope_types=['system', 'project']), + scope_types=['project']), policy.DocumentedRuleDefault( name=OTHER_PROJECT_LIMIT_POLICY_NAME, - check_str=base.SYSTEM_READER, + check_str=base.PROJECT_ADMIN, description="""Show rate and absolute limits of other project. This policy only checks if the user has access to the requested @@ -61,7 +61,7 @@ os_compute_api:limits passes""", 'path': '/limits' } ], - scope_types=['system'], + scope_types=['project'], deprecated_rule=DEPRECATED_POLICY), ] diff --git a/nova/policies/migrate_server.py b/nova/policies/migrate_server.py index fe1c5b55e00c..d00fd562d23a 100644 --- a/nova/policies/migrate_server.py +++ b/nova/policies/migrate_server.py @@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:os-migrate-server:%s' migrate_server_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'migrate', - check_str=base.SYSTEM_ADMIN, + check_str=base.PROJECT_ADMIN, description="Cold migrate a server to a host", operations=[ { @@ -32,10 +32,10 @@ migrate_server_policies = [ 'path': '/servers/{server_id}/action (migrate)' } ], - scope_types=['system', 'project']), + scope_types=['project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'migrate_live', - check_str=base.SYSTEM_ADMIN, + check_str=base.PROJECT_ADMIN, description="Live migrate a server to a new host without a reboot", operations=[ { @@ -43,7 +43,7 @@ migrate_server_policies = [ 'path': '/servers/{server_id}/action (os-migrateLive)' } ], - scope_types=['system', 'project']), + scope_types=['project']), ] diff --git a/nova/policies/migrations.py b/nova/policies/migrations.py index bb77d1f0bb63..4647d53496d8 100644 --- a/nova/policies/migrations.py +++ b/nova/policies/migrations.py @@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:os-migrations:%s' migrations_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str=base.SYSTEM_READER, + check_str=base.PROJECT_ADMIN, description="List migrations", operations=[ { @@ -32,7 +32,7 @@ migrations_policies = [ 'path': '/os-migrations' } ], - scope_types=['system']), + scope_types=['project']), ] diff --git a/nova/policies/server_diagnostics.py b/nova/policies/server_diagnostics.py index c788b3eb429d..ebafab43784a 100644 --- a/nova/policies/server_diagnostics.py +++ b/nova/policies/server_diagnostics.py @@ -24,7 +24,7 @@ BASE_POLICY_NAME = 'os_compute_api:os-server-diagnostics' server_diagnostics_policies = [ policy.DocumentedRuleDefault( name=BASE_POLICY_NAME, - check_str=base.SYSTEM_ADMIN, + check_str=base.PROJECT_ADMIN, description="Show the usage data for a server", operations=[ { @@ -32,7 +32,7 @@ server_diagnostics_policies = [ 'path': '/servers/{server_id}/diagnostics' } ], - scope_types=['system', 'project']), + scope_types=['project']), ] diff --git a/nova/policies/server_external_events.py b/nova/policies/server_external_events.py index bd9a21aea0a9..da832eb94de2 100644 --- a/nova/policies/server_external_events.py +++ b/nova/policies/server_external_events.py @@ -24,7 +24,15 @@ POLICY_ROOT = 'os_compute_api:os-server-external-events:%s' server_external_events_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'create', - check_str=base.SYSTEM_ADMIN, + # TODO(gmann): This is internal API policy and supposed to be called + # by neutron, cinder, ironic, and cyborg (may be other openstack + # services in future). Add 'service' role in this policy so that + # neutron can call it with user having 'service' role (not having + # server's project_id). That is for phase-2 of RBAC goal and until + # then, we keep it open for all admin in any project. We cannot + # default it to PROJECT_ADMIN which has the project_id in + # check_str and will fail if neutron call it with other project_id. + check_str=base.ADMIN, description="Create one or more external events", operations=[ { @@ -32,7 +40,7 @@ server_external_events_policies = [ 'path': '/os-server-external-events' } ], - scope_types=['system']), + scope_types=['project']), ] diff --git a/nova/policies/servers_migrations.py b/nova/policies/servers_migrations.py index a323ce5660d6..427da8bba25d 100644 --- a/nova/policies/servers_migrations.py +++ b/nova/policies/servers_migrations.py @@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:servers:migrations:%s' servers_migrations_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show', - check_str=base.SYSTEM_READER, + check_str=base.PROJECT_ADMIN, description="Show details for an in-progress live migration for a " "given server", operations=[ @@ -33,10 +33,10 @@ servers_migrations_policies = [ 'path': '/servers/{server_id}/migrations/{migration_id}' } ], - scope_types=['system', 'project']), + scope_types=['project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'force_complete', - check_str=base.SYSTEM_ADMIN, + check_str=base.PROJECT_ADMIN, description="Force an in-progress live migration for a given server " "to complete", operations=[ @@ -46,10 +46,10 @@ servers_migrations_policies = [ '/action (force_complete)' } ], - scope_types=['system', 'project']), + scope_types=['project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete', - check_str=base.SYSTEM_ADMIN, + check_str=base.PROJECT_ADMIN, description="Delete(Abort) an in-progress live migration", operations=[ { @@ -57,10 +57,10 @@ servers_migrations_policies = [ 'path': '/servers/{server_id}/migrations/{migration_id}' } ], - scope_types=['system', 'project']), + scope_types=['project']), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str=base.SYSTEM_READER, + check_str=base.PROJECT_ADMIN, description="Lists in-progress live migrations for a given server", operations=[ { @@ -68,7 +68,7 @@ servers_migrations_policies = [ 'path': '/servers/{server_id}/migrations' } ], - scope_types=['system', 'project']), + scope_types=['project']), ] diff --git a/nova/tests/unit/api/openstack/compute/test_limits.py b/nova/tests/unit/api/openstack/compute/test_limits.py index 31033e111d0c..6323be881d3c 100644 --- a/nova/tests/unit/api/openstack/compute/test_limits.py +++ b/nova/tests/unit/api/openstack/compute/test_limits.py @@ -212,8 +212,7 @@ class LimitsControllerTestV21(BaseLimitTestSuite): fake_req.get_response(self.controller) self.assertEqual(2, self.mock_can.call_count) self.mock_can.assert_called_with( - l_policies.OTHER_PROJECT_LIMIT_POLICY_NAME, - target={"project_id": tenant_id}) + l_policies.OTHER_PROJECT_LIMIT_POLICY_NAME) mock_get_quotas.assert_called_once_with(context, tenant_id, usages=True) diff --git a/nova/tests/unit/policies/test_assisted_volume_snapshots.py b/nova/tests/unit/policies/test_assisted_volume_snapshots.py index 3c9836e07bb0..5f7d6978e506 100644 --- a/nova/tests/unit/policies/test_assisted_volume_snapshots.py +++ b/nova/tests/unit/policies/test_assisted_volume_snapshots.py @@ -32,18 +32,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 +46,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 +57,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 +87,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_console_auth_tokens.py b/nova/tests/unit/policies/test_console_auth_tokens.py index 27dbd59540d2..ba70355d1738 100644 --- a/nova/tests/unit/policies/test_console_auth_tokens.py +++ b/nova/tests/unit/policies/test_console_auth_tokens.py @@ -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 3c16f5c1fade..406798754113 100644 --- a/nova/tests/unit/policies/test_console_output.py +++ b/nova/tests/unit/policies/test_console_output.py @@ -43,30 +43,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_admin_context, self.project_member_context] class ConsoleOutputScopeTypePolicyTest(ConsoleOutputPolicyTest): @@ -83,31 +90,24 @@ 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.legacy_admin_context, + self.project_admin_context, self.project_member_context, + self.project_reader_context, self.project_foo_context] -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 + # With scope enable and no legacy rule, only project admin/member can # get the server console. - self.admin_authorized_contexts = [ - self.system_admin_context, + self.project_member_authorized_contexts = [ self.project_admin_context, self.project_member_context] - # Check that non-system and non-admin/owner is not able to - # 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, - ] diff --git a/nova/tests/unit/policies/test_create_backup.py b/nova/tests/unit/policies/test_create_backup.py index 4985119201a5..a0eb696b896e 100644 --- a/nova/tests/unit/policies/test_create_backup.py +++ b/nova/tests/unit/policies/test_create_backup.py @@ -43,20 +43,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 +62,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_admin_context, self.project_member_context] class CreateBackupScopeTypePolicyTest(CreateBackupPolicyTest): @@ -89,31 +98,22 @@ 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.legacy_admin_context, + self.project_admin_context, self.project_member_context, + self.project_reader_context, self.project_foo_context] -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, + 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_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, - ] diff --git a/nova/tests/unit/policies/test_deferred_delete.py b/nova/tests/unit/policies/test_deferred_delete.py index ca2253df5492..1eb4f365c779 100644 --- a/nova/tests/unit/policies/test_deferred_delete.py +++ b/nova/tests/unit/policies/test_deferred_delete.py @@ -47,37 +47,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 +95,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, + dd_policies.BASE_POLICY_NAME % 'force': + base_policy.PROJECT_MEMBER} + + 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_admin_context, self.project_member_context] + + class DeferredDeleteScopeTypePolicyTest(DeferredDeletePolicyTest): """Test Deferred Delete APIs policies with system scope enabled. @@ -117,36 +130,29 @@ 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.legacy_admin_context, + self.project_admin_context, self.project_member_context, + self.project_reader_context, self.project_foo_context] -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, dd_policies.BASE_POLICY_NAME % 'force': - base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN} + base_policy.PROJECT_MEMBER} 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, + # 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_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, - ] diff --git a/nova/tests/unit/policies/test_flavor_access.py b/nova/tests/unit/policies/test_flavor_access.py index 46d9368c4b40..68c31c75f968 100644 --- a/nova/tests/unit/policies/test_flavor_access.py +++ b/nova/tests/unit/policies/test_flavor_access.py @@ -49,62 +49,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 +121,29 @@ 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 project 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, - ] + self.admin_index_authorized_contexts = [ + self.system_admin_context, self.system_member_context, + self.system_reader_context, self.system_foo_context] -class FlavorAccessNoLegacyPolicyTest(FlavorAccessPolicyTest): +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. - self.admin_authorized_contexts = [ + self.admin_index_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, - ] diff --git a/nova/tests/unit/policies/test_flavor_manage.py b/nova/tests/unit/policies/test_flavor_manage.py index 8a890a85aff3..32e25b547485 100644 --- a/nova/tests/unit/policies/test_flavor_manage.py +++ b/nova/tests/unit/policies/test_flavor_manage.py @@ -31,18 +31,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 +60,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 +104,15 @@ 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 enable, only system 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): +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_instance_usage_audit_log.py b/nova/tests/unit/policies/test_instance_usage_audit_log.py index e320beacd276..4a73d4328a77 100644 --- a/nova/tests/unit/policies/test_instance_usage_audit_log.py +++ b/nova/tests/unit/policies/test_instance_usage_audit_log.py @@ -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,20 @@ 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 - ] + # Scope checks remove project users power. + self.admin_authorized_contexts = [ + self.system_admin_context] -class InstanceUsageNoLegacyPolicyTest(InstanceUsageScopeTypePolicyTest): +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 4faefea2ef6a..d74e929ef289 100644 --- a/nova/tests/unit/policies/test_keypairs.py +++ b/nova/tests/unit/policies/test_keypairs.py @@ -43,87 +43,57 @@ class KeypairsPolicyTest(base.BasePolicyTest): 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.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, - ] @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 +102,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): @@ -180,35 +158,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 cab2b5f67970..e0e14fcfb226 100644 --- a/nova/tests/unit/policies/test_limits.py +++ b/nova/tests/unit/policies/test_limits.py @@ -10,15 +10,20 @@ # License for the specific language governing permissions and limitations # under the License. +import functools + 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 +60,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 = [] + self.everyone_authorized_contexts = self.all_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 = [ + # 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.PROJECT_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 +123,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 +142,17 @@ class LimitsNoLegacyPolicyTest(LimitsScopeTypePolicyTest): without_deprecated_rules = True rules_without_deprecation = { limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME: - base_policy.SYSTEM_READER} + base_policy.PROJECT_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_migrate_server.py b/nova/tests/unit/policies/test_migrate_server.py index 0082b3d414f3..0dc51174dd3d 100644 --- a/nova/tests/unit/policies/test_migrate_server.py +++ b/nova/tests/unit/policies/test_migrate_server.py @@ -47,28 +47,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 +69,23 @@ 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 + + def setUp(self): + super(MigrateServerNoLegacyNoScopeTest, self).setUp() + self.project_admin_authorized_contexts = [ + self.project_admin_context] class MigrateServerScopeTypePolicyTest(MigrateServerPolicyTest): @@ -99,32 +102,27 @@ 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, - ] + super(MigrateServerScopeTypeNoLegacyPolicyTest, self).setUp() + # with no legacy rule and scope enable., only project admin is able to + # migrate the server. + self.project_admin_authorized_contexts = [self.project_admin_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 @@ -138,21 +136,11 @@ class MigrateServerOverridePolicyTest(MigrateServerNoLegacyPolicyTest): # NOTE(gmann): override the rule to project member and verify it # work as policy is system and projct 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 a124fa508b95..61b5240a95ce 100644 --- a/nova/tests/unit/policies/test_migrations.py +++ b/nova/tests/unit/policies/test_migrations.py @@ -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_server_diagnostics.py b/nova/tests/unit/policies/test_server_diagnostics.py index 04a099a7a3ca..d421045abd31 100644 --- a/nova/tests/unit/policies/test_server_diagnostics.py +++ b/nova/tests/unit/policies/test_server_diagnostics.py @@ -46,26 +46,29 @@ 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 + + def setUp(self): + super(ServerDiagnosticsNoLegacyNoScopeTest, self).setUp() + self.project_admin_authorized_contexts = [ + self.project_admin_context] class ServerDiagnosticsScopeTypePolicyTest(ServerDiagnosticsPolicyTest): @@ -82,9 +85,12 @@ 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. @@ -92,23 +98,14 @@ class ServerDiagnosticsNoLegacyPolicyTest( 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, - ] + super(ServerDiagnosticsScopeTypeNoLegacyPolicyTest, self).setUp() + # with no legacy rule and scope enable., only project admin is able to + # get server diagnostics. + self.project_admin_authorized_contexts = [self.project_admin_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 +116,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 projct 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 f8f1bcd663cd..630b3e85316d 100644 --- a/nova/tests/unit/policies/test_server_external_events.py +++ b/nova/tests/unit/policies/test_server_external_events.py @@ -33,20 +33,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 +50,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 +79,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_migrations.py b/nova/tests/unit/policies/test_server_migrations.py index b06d9ec167f6..d6c249d166d7 100644 --- a/nova/tests/unit/policies/test_server_migrations.py +++ b/nova/tests/unit/policies/test_server_migrations.py @@ -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,37 @@ 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 + + def setUp(self): + super(ServerMigrationsNoLegacyNoScopeTest, self).setUp() + self.project_admin_authorized_contexts = [ + self.project_admin_context] class ServerMigrationsScopeTypePolicyTest(ServerMigrationsPolicyTest): @@ -126,48 +112,27 @@ 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() + super(ServerMigrationsScopeTypeNoLegacyPolicyTest, 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 - ] + self.project_admin_authorized_contexts = [self.project_admin_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 +146,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]