Make more project level APIs scoped to project only

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 more projects level APIs to be scoped
to project only.

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: I6731aa6edd0c6bed5edb9eaaaa98b5e43aaeeb74
This commit is contained in:
Ghanshyam Mann 2022-02-09 23:35:16 -06:00
parent 60c9e3edad
commit d7be635fb4
35 changed files with 1528 additions and 1395 deletions

View File

@ -167,7 +167,7 @@ class ServerGroupController(wsgi.Controller):
# new defaults completly then we can remove the above check.
# Until then, let's keep the old behaviour.
context.can(sg_policies.POLICY_ROOT % 'index:all_projects',
target={})
target={'project_id': project_id})
sgs = objects.InstanceGroupList.get_all(context)
else:
sgs = objects.InstanceGroupList.get_by_project_id(

View File

@ -35,7 +35,8 @@ class ServerTopologyController(wsgi.Controller):
target={'project_id': instance.project_id})
host_policy = (st_policies.BASE_POLICY_NAME % 'host:index')
show_host_info = context.can(host_policy, fatal=False)
show_host_info = context.can(host_policy,
target={'project_id': instance.project_id}, fatal=False)
return self._get_numa_topology(context, instance, show_host_info)

View File

@ -506,6 +506,11 @@ class VolumeAttachmentController(wsgi.Controller):
# different from the 'id' in the url path, or only swap is allowed by
# the microversion, we should check the swap volume policy.
# otherwise, check the volume update policy.
# NOTE(gmann) We pass empty target to policy enforcement. This API
# is called by cinder 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 perform the swap volume.
if only_swap or id != volume_id:
context.can(va_policies.POLICY_ROOT % 'swap', target={})
else:

View File

@ -37,7 +37,7 @@ DEPRECATED_INTERFACES_POLICY = policy.DeprecatedRule(
attach_interfaces_policies = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List port interfaces attached to a server",
operations=[
{
@ -45,11 +45,11 @@ attach_interfaces_policies = [
'path': '/servers/{server_id}/os-interface'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_INTERFACES_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show details of a port interface attached to a server",
operations=[
{
@ -57,11 +57,11 @@ attach_interfaces_policies = [
'path': '/servers/{server_id}/os-interface/{port_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_INTERFACES_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Attach an interface to a server",
operations=[
{
@ -69,11 +69,11 @@ attach_interfaces_policies = [
'path': '/servers/{server_id}/os-interface'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_INTERFACES_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Detach an interface from a server",
operations=[
{
@ -81,7 +81,7 @@ attach_interfaces_policies = [
'path': '/servers/{server_id}/os-interface/{port_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_INTERFACES_POLICY)
]

View File

@ -38,7 +38,7 @@ DEPRECATED_FIP_POLICY = policy.DeprecatedRule(
floating_ips_policies = [
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'add',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Associate floating IPs to server. "
" This API is deprecated.",
operations=[
@ -47,11 +47,11 @@ floating_ips_policies = [
'path': '/servers/{server_id}/action (addFloatingIp)'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_FIP_POLICY),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'remove',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Disassociate floating IPs to server. "
" This API is deprecated.",
operations=[
@ -60,11 +60,11 @@ floating_ips_policies = [
'path': '/servers/{server_id}/action (removeFloatingIp)'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_FIP_POLICY),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List floating IPs. This API is deprecated.",
operations=[
{
@ -72,11 +72,11 @@ floating_ips_policies = [
'path': '/os-floating-ips'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_FIP_POLICY),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Create floating IPs. This API is deprecated.",
operations=[
{
@ -84,11 +84,11 @@ floating_ips_policies = [
'path': '/os-floating-ips'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_FIP_POLICY),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show floating IPs. This API is deprecated.",
operations=[
{
@ -96,11 +96,11 @@ floating_ips_policies = [
'path': '/os-floating-ips/{floating_ip_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_FIP_POLICY),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Delete floating IPs. This API is deprecated.",
operations=[
{
@ -108,7 +108,7 @@ floating_ips_policies = [
'path': '/os-floating-ips/{floating_ip_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_FIP_POLICY),
]

View File

@ -38,7 +38,7 @@ DEPRECATED_INSTANCE_ACTION_POLICY = policy.DeprecatedRule(
instance_actions_policies = [
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'events:details',
check_str=base.SYSTEM_READER,
check_str=base.PROJECT_ADMIN,
description="""Add "details" key in action events for a server.
This check is performed only after the check
@ -56,10 +56,10 @@ but in the other hand it might leak information about the deployment
'path': '/servers/{server_id}/os-instance-actions/{request_id}'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'events',
check_str=base.SYSTEM_READER,
check_str=base.PROJECT_ADMIN,
description="""Add events details in action details for a server.
This check is performed only after the check
os_compute_api:os-instance-actions:show passes. Beginning with Microversion
@ -73,10 +73,10 @@ passes, the name of the host.""",
'path': '/servers/{server_id}/os-instance-actions/{request_id}'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""List actions for a server.""",
operations=[
{
@ -84,11 +84,11 @@ passes, the name of the host.""",
'path': '/servers/{server_id}/os-instance-actions'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_INSTANCE_ACTION_POLICY),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""Show action details for a server.""",
operations=[
{
@ -96,7 +96,7 @@ passes, the name of the host.""",
'path': '/servers/{server_id}/os-instance-actions/{request_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_INSTANCE_ACTION_POLICY),
]

View File

@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:ips:%s'
ips_policies = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show IP addresses details for a network label of a "
" server",
operations=[
@ -33,10 +33,10 @@ ips_policies = [
'path': '/servers/{server_id}/ips/{network_label}'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'index',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List IP addresses that are assigned to a server",
operations=[
{
@ -44,7 +44,7 @@ ips_policies = [
'path': '/servers/{server_id}/ips'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
]

View File

@ -38,7 +38,7 @@ DEPRECATED_POLICY = policy.DeprecatedRule(
networks_policies = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""List networks for the project.
This API is proxy calls to the Network service. This is deprecated.""",
@ -48,11 +48,11 @@ This API is proxy calls to the Network service. This is deprecated.""",
'path': '/os-networks'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""Show network details.
This API is proxy calls to the Network service. This is deprecated.""",
@ -62,7 +62,7 @@ This API is proxy calls to the Network service. This is deprecated.""",
'path': '/os-networks/{network_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
]

View File

@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:os-quota-sets:%s'
quota_sets_policies = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'update',
check_str=base.SYSTEM_ADMIN,
check_str=base.PROJECT_ADMIN,
description="Update the quotas",
operations=[
{
@ -32,7 +32,7 @@ quota_sets_policies = [
'path': '/os-quota-sets/{tenant_id}'
}
],
scope_types=['system']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'defaults',
check_str=base.RULE_ANY,
@ -46,7 +46,13 @@ quota_sets_policies = [
scope_types=['system', 'project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
# TODO(gmann): Until we have domain admin or so to get other project's
# data, allow admin role(with scope check it will be project admin) to
# get other project quota. We cannot use PROJECT_ADMIN here as
# project_id passed in request url is used as policy targets which
# would not match with context's project_id fetched for rule
# PROJECT_ADMIN check.
check_str='(' + base.PROJECT_READER + ') or role:admin',
description="Show a quota",
operations=[
{
@ -54,10 +60,10 @@ quota_sets_policies = [
'path': '/os-quota-sets/{tenant_id}'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str=base.SYSTEM_ADMIN,
check_str=base.PROJECT_ADMIN,
description="Revert quotas to defaults",
operations=[
{
@ -65,10 +71,13 @@ quota_sets_policies = [
'path': '/os-quota-sets/{tenant_id}'
}
],
scope_types=['system']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'detail',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
# TODO(gmann): Until we have domain admin or so to get other project's
# data, allow admin role(with scope check it will be project admin) to
# get other project quota.
check_str='(' + base.PROJECT_READER + ') or role:admin',
description="Show the detail of quota",
operations=[
{
@ -76,7 +85,7 @@ quota_sets_policies = [
'path': '/os-quota-sets/{tenant_id}/detail'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
]

View File

@ -38,7 +38,7 @@ DEPRECATED_POLICY = policy.DeprecatedRule(
security_groups_policies = [
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'get',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List security groups. This API is deprecated.",
operations=[
{
@ -46,11 +46,11 @@ security_groups_policies = [
'path': '/os-security-groups'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show security group. This API is deprecated.",
operations=[
{
@ -58,11 +58,11 @@ security_groups_policies = [
'path': '/os-security-groups/{security_group_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Create security group. This API is deprecated.",
operations=[
{
@ -70,11 +70,11 @@ security_groups_policies = [
'path': '/os-security-groups'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'update',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Update security group. This API is deprecated.",
operations=[
{
@ -82,11 +82,11 @@ security_groups_policies = [
'path': '/os-security-groups/{security_group_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Delete security group. This API is deprecated.",
operations=[
{
@ -94,11 +94,11 @@ security_groups_policies = [
'path': '/os-security-groups/{security_group_id}'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'rule:create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Create security group Rule. This API is deprecated.",
operations=[
{
@ -106,11 +106,11 @@ security_groups_policies = [
'path': '/os-security-group-rules'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'rule:delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Delete security group Rule. This API is deprecated.",
operations=[
{
@ -118,11 +118,11 @@ security_groups_policies = [
'path': '/os-security-group-rules/{security_group_id}'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List security groups of server.",
operations=[
{
@ -130,11 +130,11 @@ security_groups_policies = [
'path': '/servers/{server_id}/os-security-groups'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'add',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Add security groups to server.",
operations=[
{
@ -142,11 +142,11 @@ security_groups_policies = [
'path': '/servers/{server_id}/action (addSecurityGroup)'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'remove',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Remove security groups from server.",
operations=[
{
@ -154,7 +154,7 @@ security_groups_policies = [
'path': '/servers/{server_id}/action (removeSecurityGroup)'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
]

View File

@ -32,20 +32,11 @@ server_groups_policies = [
'method': 'POST'
}
],
# (NOTE)gmann: Reason for 'project' only scope:
# POST SG need project_id to create the serve groups
# system scope members do not have project id for which
# SG needs to be created.
# If we allow system scope role also then created SG will have
# project_id of system role, not the one he/she wants to create the SG
# for (nobody can create the SG for other projects because API does
# not take project id in request ). So keeping this scoped to project
# only as these roles are the only ones who will be creating SG.
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Delete a server group",
operations=[
{
@ -53,11 +44,11 @@ server_groups_policies = [
'method': 'DELETE'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'index',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List all server groups",
operations=[
{
@ -65,11 +56,11 @@ server_groups_policies = [
'method': 'GET'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'index:all_projects',
check_str=base.SYSTEM_READER,
check_str=base.PROJECT_ADMIN,
description="List all server groups for all projects",
operations=[
{
@ -77,11 +68,11 @@ server_groups_policies = [
'method': 'GET'
}
],
scope_types=['system']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show details of a server group",
operations=[
{
@ -89,7 +80,7 @@ server_groups_policies = [
'method': 'GET'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
]

View File

@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:server-metadata:%s'
server_metadata_policies = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'index',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List all metadata of a server",
operations=[
{
@ -32,11 +32,11 @@ server_metadata_policies = [
'method': 'GET'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show metadata for a server",
operations=[
{
@ -44,11 +44,11 @@ server_metadata_policies = [
'method': 'GET'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Create metadata for a server",
operations=[
{
@ -56,11 +56,11 @@ server_metadata_policies = [
'method': 'POST'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'update_all',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Replace metadata for a server",
operations=[
{
@ -68,11 +68,11 @@ server_metadata_policies = [
'method': 'PUT'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'update',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Update metadata from a server",
operations=[
{
@ -80,11 +80,11 @@ server_metadata_policies = [
'method': 'PUT'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Delete metadata from a server",
operations=[
{
@ -92,7 +92,7 @@ server_metadata_policies = [
'method': 'DELETE'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
]

View File

@ -37,7 +37,7 @@ DEPRECATED_POLICY = policy.DeprecatedRule(
server_password_policies = [
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show the encrypted administrative "
"password of a server",
operations=[
@ -46,11 +46,11 @@ server_password_policies = [
'path': '/servers/{server_id}/os-server-password'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'clear',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Clear the encrypted administrative "
"password of a server",
operations=[
@ -59,7 +59,7 @@ server_password_policies = [
'path': '/servers/{server_id}/os-server-password'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
]

View File

@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:os-server-tags:%s'
server_tags_policies = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete_all',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Delete all the server tags",
operations=[
{
@ -32,10 +32,10 @@ server_tags_policies = [
'path': '/servers/{server_id}/tags'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'index',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List all tags for given server",
operations=[
{
@ -43,10 +43,10 @@ server_tags_policies = [
'path': '/servers/{server_id}/tags'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'update_all',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Replace all tags on specified server with the new set "
"of tags.",
operations=[
@ -56,10 +56,10 @@ server_tags_policies = [
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Delete a single tag from the specified server",
operations=[
{
@ -67,11 +67,11 @@ server_tags_policies = [
'path': '/servers/{server_id}/tags/{tag}'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'update',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Add a single tag to the server if server has no "
"specified tag",
operations=[
@ -80,11 +80,11 @@ server_tags_policies = [
'path': '/servers/{server_id}/tags/{tag}'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Check tag existence on the server.",
operations=[
{
@ -92,7 +92,7 @@ server_tags_policies = [
'path': '/servers/{server_id}/tags/{tag}'
}
],
scope_types=['system', 'project']
scope_types=['project']
),
]

View File

@ -21,7 +21,7 @@ BASE_POLICY_NAME = 'compute:server:topology:%s'
server_topology_policies = [
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'index',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show the NUMA topology data for a server",
operations=[
{
@ -29,11 +29,11 @@ server_topology_policies = [
'path': '/servers/{server_id}/topology'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
# Control host NUMA node and cpu pinning information
name=BASE_POLICY_NAME % 'host:index',
check_str=base.SYSTEM_READER,
check_str=base.PROJECT_ADMIN,
description="Show the NUMA topology data for a server with host "
"NUMA ID and CPU pinning information",
operations=[
@ -42,7 +42,7 @@ server_topology_policies = [
'path': '/servers/{server_id}/topology'
}
],
scope_types=['system']),
scope_types=['project']),
]

View File

@ -24,7 +24,7 @@ POLICY_ROOT = 'os_compute_api:os-simple-tenant-usage:%s'
simple_tenant_usage_policies = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show usage statistics for a specific tenant",
operations=[
{
@ -32,10 +32,10 @@ simple_tenant_usage_policies = [
'path': '/os-simple-tenant-usage/{tenant_id}'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'list',
check_str=base.SYSTEM_READER,
check_str=base.PROJECT_ADMIN,
description="List per tenant usage statistics for all tenants",
operations=[
{
@ -43,7 +43,7 @@ simple_tenant_usage_policies = [
'path': '/os-simple-tenant-usage'
}
],
scope_types=['system']),
scope_types=['project']),
]

View File

@ -38,7 +38,7 @@ DEPRECATED_POLICY = policy.DeprecatedRule(
tenant_networks_policies = [
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""List project networks.
This API is proxy calls to the Network service. This is deprecated.""",
@ -48,11 +48,11 @@ This API is proxy calls to the Network service. This is deprecated.""",
'path': '/os-tenant-networks'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""Show project network details.
This API is proxy calls to the Network service. This is deprecated.""",
@ -62,7 +62,7 @@ This API is proxy calls to the Network service. This is deprecated.""",
'path': '/os-tenant-networks/{network_id}'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
]

View File

@ -38,7 +38,7 @@ DEPRECATED_POLICY = policy.DeprecatedRule(
volumes_policies = [
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""List volumes.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -48,11 +48,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-volumes'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="""Create volume.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -62,11 +62,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-volumes'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'detail',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""List volumes detail.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -76,11 +76,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-volumes/detail'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""Show volume.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -90,11 +90,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-volumes/{volume_id}'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="""Delete volume.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -104,11 +104,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-volumes/{volume_id}'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'snapshots:list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""List snapshots.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -118,11 +118,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-snapshots'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'snapshots:create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="""Create snapshots.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -132,11 +132,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-snapshots'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'snapshots:detail',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""List snapshots details.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -146,11 +146,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-snapshots/detail'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'snapshots:show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="""Show snapshot.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -160,11 +160,11 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-snapshots/{snapshot_id}'
},
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'snapshots:delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="""Delete snapshot.
This API is a proxy call to the Volume service. It is deprecated.""",
@ -174,7 +174,7 @@ This API is a proxy call to the Volume service. It is deprecated.""",
'path': '/os-snapshots/{snapshot_id}'
}
],
scope_types=['system', 'project'],
scope_types=['project'],
deprecated_rule=DEPRECATED_POLICY),
]

View File

@ -24,17 +24,17 @@ POLICY_ROOT = 'os_compute_api:os-volumes-attachments:%s'
volumes_attachments_policies = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'index',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="List volume attachments for an instance",
operations=[
{'method': 'GET',
'path': '/servers/{server_id}/os-volume_attachments'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Attach a volume to an instance",
operations=[
{
@ -42,10 +42,10 @@ volumes_attachments_policies = [
'path': '/servers/{server_id}/os-volume_attachments'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
check_str=base.PROJECT_READER,
description="Show details of a volume attachment",
operations=[
{
@ -54,10 +54,10 @@ volumes_attachments_policies = [
'/servers/{server_id}/os-volume_attachments/{volume_id}'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'update',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="""Update a volume attachment.
New 'update' policy about 'swap + update' request (which is possible
only >2.85) only <swap policy> is checked. We expect <swap policy> to be
@ -70,10 +70,17 @@ always superset of this policy permission.
'/servers/{server_id}/os-volume_attachments/{volume_id}'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'swap',
check_str=base.SYSTEM_ADMIN,
# TODO(gmann): This is internal API policy and supposed to be called
# only by cinder. Add 'service' role in this policy so that cinder
# 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 cinder call it with other project_id.
check_str=base.ADMIN,
description="Update a volume attachment with a different volumeId",
operations=[
{
@ -82,10 +89,10 @@ always superset of this policy permission.
'/servers/{server_id}/os-volume_attachments/{volume_id}'
}
],
scope_types=['system']),
scope_types=['project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
check_str=base.PROJECT_MEMBER,
description="Detach a volume from an instance",
operations=[
{
@ -94,7 +101,7 @@ always superset of this policy permission.
'/servers/{server_id}/os-volume_attachments/{volume_id}'
}
],
scope_types=['system', 'project']),
scope_types=['project']),
]

View File

@ -129,7 +129,7 @@ class TestPolicyCheck(test.NoDBTestCase):
def test_filter_rules_non_admin(self):
context = nova_context.RequestContext()
rule_conditions = [base_policies.PROJECT_READER_OR_SYSTEM_READER]
rule_conditions = [base_policies.PROJECT_READER]
expected_rules = [r.name for r in ia_policies.list_rules() if
r.check_str in rule_conditions]
self._check_filter_rules(context, expected_rules=expected_rules)
@ -156,7 +156,7 @@ class TestPolicyCheck(test.NoDBTestCase):
db_context = nova_context.RequestContext(user_id='fake-user',
project_id='fake-project')
instance = fake_instance.fake_instance_obj(db_context)
rule_conditions = [base_policies.PROJECT_READER_OR_SYSTEM_READER]
rule_conditions = [base_policies.PROJECT_READER]
expected_rules = [r.name for r in ia_policies.list_rules() if
r.check_str in rule_conditions]
self._check_filter_rules(db_context, instance, expected_rules)

View File

@ -47,40 +47,25 @@ class AttachInterfacesPolicyTest(base.BasePolicyTest):
vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
self.admin_authorized_contexts = [
# With legacy rule and no scope checks, all admin, project members
# project reader or other project role(because legacy rule allow server
# owner- having same project id and no role check) is able to attach,
# detach an interface from a server.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_foo_context,
self.project_reader_context, self.project_member_context
]
self.admin_unauthorized_contexts = [
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_member_context, self.project_foo_context
]
self.reader_unauthorized_contexts = [
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
# and they can get their own server attached interfaces.
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
@mock.patch('nova.compute.api.API.get')
@mock.patch('nova.network.neutron.API.list_ports')
def test_index_interfaces_policy(self, mock_port, mock_get):
rule_name = "os_compute_api:os-attach-interfaces:list"
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.index,
self.req, uuids.fake_id)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.index,
self.req, uuids.fake_id)
@mock.patch('nova.compute.api.API.get')
@mock.patch('nova.network.neutron.API.show_port')
@ -97,11 +82,10 @@ class AttachInterfacesPolicyTest(base.BasePolicyTest):
"fixed_ips": ["10.0.2.2"],
"device_id": server_id,
}}
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.show,
self.req, server_id, port_id)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, server_id, port_id)
@mock.patch('nova.compute.api.API.get')
@mock.patch('nova.api.openstack.compute.attach_interfaces'
@ -110,19 +94,44 @@ class AttachInterfacesPolicyTest(base.BasePolicyTest):
def test_attach_interface(self, mock_interface, mock_port, mock_get):
rule_name = "os_compute_api:os-attach-interfaces:create"
body = {'interfaceAttachment': {'net_id': uuids.fake_id}}
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name, self.controller.create,
self.req, uuids.fake_id, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.controller.create,
self.req, uuids.fake_id, body=body)
@mock.patch('nova.compute.api.API.get')
@mock.patch('nova.compute.api.API.detach_interface')
def test_delete_interface(self, mock_detach, mock_get):
rule_name = "os_compute_api:os-attach-interfaces:delete"
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name, self.controller.delete,
self.req, uuids.fake_id, uuids.fake_id)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.controller.delete,
self.req, uuids.fake_id, uuids.fake_id)
class AttachInterfacesNoLegacyNoScopePolicyTest(AttachInterfacesPolicyTest):
"""Test Attach Interfaces APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
rules_without_deprecation = {
ai_policies.POLICY_ROOT % 'list':
base_policy.PROJECT_READER,
ai_policies.POLICY_ROOT % 'show':
base_policy.PROJECT_READER,
ai_policies.POLICY_ROOT % 'create':
base_policy.PROJECT_MEMBER,
ai_policies.POLICY_ROOT % 'delete':
base_policy.PROJECT_MEMBER}
def setUp(self):
super(AttachInterfacesNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, legacy admin loose power.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
class AttachInterfacesScopeTypePolicyTest(AttachInterfacesPolicyTest):
@ -138,6 +147,13 @@ class AttachInterfacesScopeTypePolicyTest(AttachInterfacesPolicyTest):
def setUp(self):
super(AttachInterfacesScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With Scope enable, system users no longer allowed.
self.project_member_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
class AttachInterfacesDeprecatedPolicyTest(base.BasePolicyTest):
@ -192,55 +208,28 @@ class AttachInterfacesDeprecatedPolicyTest(base.BasePolicyTest):
exc.format_message())
class AttachInterfacesNoLegacyPolicyTest(AttachInterfacesPolicyTest):
class AttachInterfacesScopeTypeNoLegacyPolicyTest(
AttachInterfacesScopeTypePolicyTest):
"""Test Attach Interfaces APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system_admin_or_owner APIs.
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
ai_policies.POLICY_ROOT % 'list':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
ai_policies.POLICY_ROOT % 'show':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
ai_policies.POLICY_ROOT % 'create':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
ai_policies.POLICY_ROOT % 'delete':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
base_policy.PROJECT_MEMBER}
def setUp(self):
super(AttachInterfacesNoLegacyPolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check that system or projct admin or owner is able to
# create or delete interfaces.
self.admin_authorized_contexts = [
self.system_admin_context,
super(AttachInterfacesScopeTypeNoLegacyPolicyTest, self).setUp()
# With no legacy and scope enable, only project admin, member,
# and reader will be able to allowed operation on server interface.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
# Check that non-system and non-admin/owner is not able to
# create or delete interfaces.
self.admin_unauthorized_contexts = [
self.legacy_admin_context, self.project_reader_context,
self.project_foo_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
# Check that system reader or projct is able to
# create or delete interfaces.
self.reader_authorized_contexts = [
self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_member_context
]
# Check that non-system reader nd non-admin/owner is not able to
# create or delete interfaces.
self.reader_unauthorized_contexts = [
self.legacy_admin_context, self.project_foo_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context,
]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]

View File

@ -48,12 +48,13 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
id=1, uuid=uuid, vm_state=vm_states.ACTIVE,
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
# Check that everyone is able to perform crud operation on FIP.
# With legacy rule and scope disable, everyone is able to perform crud
# operation on FIP.
# NOTE: Nova cannot verify the FIP owner during nova policy
# enforcement so will be passing context's project_id as target to
# policy and always pass. If requester is not admin or owner
# of FIP then neutron will be returning the appropriate error.
self.reader_authorized_contexts = [
self.member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
@ -62,48 +63,45 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
self.reader_unauthorized_contexts = []
self.cd_authorized_contexts = self.reader_authorized_contexts
self.cd_unauthorized_contexts = self.reader_unauthorized_contexts
# Check that admin or owner is able to add/delete FIP to server.
self.admin_or_owner_authorized_contexts = [
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context
]
# Check that non-admin and non-owner is not able to add/delete
# FIP to server.
self.admin_or_owner_unauthorized_contexts = [
self.project_reader_context, self.project_foo_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context
self.other_project_member_context
]
# With legacy rule and no scope checks, all admin, project members
# project reader or other project role(because legacy rule allow server
# owner- having same project id and no role check) is able to add,
# delete FIP to server.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
@mock.patch('nova.network.neutron.API.get_floating_ip')
def test_show_floating_ip_policy(self, mock_get):
rule_name = "os_compute_api:os-floating-ips:show"
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
@mock.patch('nova.network.neutron.API.get_floating_ips_by_project')
def test_index_floating_ip_policy(self, mock_get):
rule_name = "os_compute_api:os-floating-ips:list"
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.index,
self.req)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.index,
self.req)
@mock.patch('nova.network.neutron.API.get_floating_ip_by_address')
@mock.patch('nova.network.neutron.API.allocate_floating_ip')
def test_create_floating_ip_policy(self, mock_create, mock_get):
rule_name = "os_compute_api:os-floating-ips:create"
self.common_policy_check(self.cd_authorized_contexts,
self.cd_unauthorized_contexts,
rule_name, self.controller.create,
self.req, uuids.fake_id)
self.common_policy_auth(self.member_authorized_contexts,
rule_name, self.controller.create,
self.req, uuids.fake_id)
@mock.patch('nova.network.neutron.API.get_instance_id_by_floating_address')
@mock.patch('nova.network.neutron.API.get_floating_ip')
@ -112,10 +110,9 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
def test_delete_floating_ip_policy(self, mock_delete, mock_get,
mock_instance):
rule_name = "os_compute_api:os-floating-ips:delete"
self.common_policy_check(self.cd_authorized_contexts,
self.cd_unauthorized_contexts,
rule_name, self.controller.delete,
self.req, uuids.fake_id)
self.common_policy_auth(self.member_authorized_contexts,
rule_name, self.controller.delete,
self.req, uuids.fake_id)
@mock.patch('nova.objects.Instance.get_network_info')
@mock.patch('nova.network.neutron.API.associate_floating_ip')
@ -127,11 +124,10 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
mock_net.return_value = network_model.NetworkInfo.hydrate(ninfo)
body = {'addFloatingIp': {
'address': '1.2.3.4'}}
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.action_controller._add_floating_ip,
self.req, self.instance.uuid, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.action_controller._add_floating_ip,
self.req, self.instance.uuid, body=body)
@mock.patch('nova.network.neutron.API.get_instance_id_by_floating_address')
@mock.patch('nova.network.neutron.API.get_floating_ip_by_address')
@ -142,11 +138,53 @@ class FloatingIPPolicyTest(base.BasePolicyTest):
mock_instance.return_value = self.instance.uuid
body = {'removeFloatingIp': {
'address': '1.2.3.4'}}
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.action_controller._remove_floating_ip,
self.req, self.instance.uuid, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.action_controller._remove_floating_ip,
self.req, self.instance.uuid, body=body)
class FloatingIPNoLegacyNoScopePolicyTest(FloatingIPPolicyTest):
"""Test Floating IP APIs policies with system scope disabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
fip_policies.BASE_POLICY_NAME % 'list':
base_policy.PROJECT_READER,
fip_policies.BASE_POLICY_NAME % 'show':
base_policy.PROJECT_READER,
fip_policies.BASE_POLICY_NAME % 'create':
base_policy.PROJECT_MEMBER,
fip_policies.BASE_POLICY_NAME % 'delete':
base_policy.PROJECT_MEMBER,
fip_policies.BASE_POLICY_NAME % 'add':
base_policy.PROJECT_MEMBER,
fip_policies.BASE_POLICY_NAME % 'remove':
base_policy.PROJECT_MEMBER}
def setUp(self):
super(FloatingIPNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, only project admin or member will be
# able to add/remove FIP to server.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
# With no legacy, project other roles like foo will not be able
# to operate on FIP.
self.member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.system_member_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context
]
class FloatingIPScopeTypePolicyTest(FloatingIPPolicyTest):
@ -163,63 +201,60 @@ class FloatingIPScopeTypePolicyTest(FloatingIPPolicyTest):
def setUp(self):
super(FloatingIPScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Scope enable will not allow system users.
self.project_member_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
self.member_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context
]
class FloatingIPNoLegacyPolicyTest(FloatingIPScopeTypePolicyTest):
class FloatingIPScopeTypeNoLegacyPolicyTest(FloatingIPScopeTypePolicyTest):
"""Test Floating IP APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
fip_policies.BASE_POLICY_NAME % 'list':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
fip_policies.BASE_POLICY_NAME % 'show':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
fip_policies.BASE_POLICY_NAME % 'create':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
fip_policies.BASE_POLICY_NAME % 'delete':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
fip_policies.BASE_POLICY_NAME % 'add':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
fip_policies.BASE_POLICY_NAME % 'remove':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
base_policy.PROJECT_MEMBER}
def setUp(self):
super(FloatingIPNoLegacyPolicyTest, self).setUp()
super(FloatingIPScopeTypeNoLegacyPolicyTest, self).setUp()
# Check that system admin or owner is able to
# add/delete FIP to server.
self.admin_or_owner_authorized_contexts = [
self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
# With no legacy and scope enabled, system users and project
# other roles like foo will not be able to operate FIP.
self.member_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context,
self.other_project_member_context
]
# Check that non-system and non-admin/owner is not able
# to add/delete FIP to server.
self.admin_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_foo_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.reader_unauthorized_contexts = [
self.project_foo_context,
self.system_foo_context
]
self.cd_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.project_admin_context, self.project_member_context,
self.legacy_admin_context, self.other_project_member_context
]
self.cd_unauthorized_contexts = [
self.system_reader_context,
self.project_reader_context, self.project_foo_context,
self.system_foo_context, self.other_project_reader_context
self.other_project_member_context
]

View File

@ -62,33 +62,17 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
# Check that system reader are able to show the instance
# actions events.
self.system_reader_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context, self.legacy_admin_context,
self.project_admin_context]
# Check that non-system-reader are not able to show the instance
# actions events.
self.system_reader_unauthorized_contexts = [
self.system_foo_context, self.other_project_member_context,
self.project_foo_context, self.project_member_context,
self.project_reader_context,
self.other_project_reader_context,
]
self.project_or_system_reader_authorized_contexts = [
# With legacy rule and no scope checks, any role in project can
# get server action and all admin is able to get server action
# with event details.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_member_context, self.project_foo_context
]
self.project_or_system_reader_unauthorized_contexts = [
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.project_admin_context]
# and project reader can get their server topology without host info.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
def _set_policy_rules(self, overwrite=True):
rules = {ia_policies.BASE_POLICY_NAME % 'show': '@'}
@ -97,9 +81,8 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
def test_index_instance_action_policy(self):
rule_name = ia_policies.BASE_POLICY_NAME % "list"
self.common_policy_check(
self.project_or_system_reader_authorized_contexts,
self.project_or_system_reader_unauthorized_contexts,
self.common_policy_auth(
self.project_reader_authorized_contexts,
rule_name, self.controller.index,
self.req, self.instance['uuid'])
@ -108,9 +91,8 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
mock_action_get.return_value = fake_action
rule_name = ia_policies.BASE_POLICY_NAME % "show"
self.common_policy_check(
self.project_or_system_reader_authorized_contexts,
self.project_or_system_reader_unauthorized_contexts,
self.common_policy_auth(
self.project_reader_authorized_contexts,
rule_name, self.controller.show,
self.req, self.instance['uuid'], fake_action['request_id'])
@ -131,9 +113,8 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
self._set_policy_rules(overwrite=False)
rule_name = ia_policies.BASE_POLICY_NAME % "events"
authorize_res, unauthorize_res = self.common_policy_check(
self.system_reader_authorized_contexts,
self.system_reader_unauthorized_contexts,
authorize_res, unauthorize_res = self.common_policy_auth(
self.project_admin_authorized_contexts,
rule_name, self.controller.show,
self.req, self.instance['uuid'],
fake_action['request_id'], fatal=False)
@ -149,6 +130,31 @@ class InstanceActionsPolicyTest(base.BasePolicyTest):
self.assertNotIn('events', action['instanceAction'])
class InstanceActionsNoLegacyNoScopePolicyTest(InstanceActionsPolicyTest):
"""Test os-instance-actions APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
rules_without_deprecation = {
ia_policies.BASE_POLICY_NAME % 'list':
base_policy.PROJECT_READER,
ia_policies.BASE_POLICY_NAME % 'show':
base_policy.PROJECT_READER,
ia_policies.BASE_POLICY_NAME % 'events':
base_policy.PROJECT_ADMIN,
}
def setUp(self):
super(InstanceActionsNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, legacy admin loose power.
self.project_admin_authorized_contexts = [self.project_admin_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
class InstanceActionsDeprecatedPolicyTest(base.BasePolicyTest):
"""Test os-instance-actions APIs Deprecated policies.
@ -221,6 +227,13 @@ class InstanceActionsScopeTypePolicyTest(InstanceActionsPolicyTest):
def setUp(self):
super(InstanceActionsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With Scope enable, system users no longer allowed.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context]
self.project_reader_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
@mock.patch('nova.objects.InstanceActionEventList.get_by_action')
@mock.patch('nova.objects.InstanceAction.get_by_request_id')
@ -241,9 +254,8 @@ class InstanceActionsScopeTypePolicyTest(InstanceActionsPolicyTest):
self._set_policy_rules(overwrite=False)
rule_name = ia_policies.BASE_POLICY_NAME % "events:details"
authorize_res, unauthorize_res = self.common_policy_check(
self.system_reader_authorized_contexts,
self.system_reader_unauthorized_contexts,
authorize_res, unauthorize_res = self.common_policy_auth(
self.project_admin_authorized_contexts,
rule_name, self.controller.show,
self.req, self.instance['uuid'],
fake_action['request_id'], fatal=False)
@ -267,54 +279,27 @@ class InstanceActionsScopeTypePolicyTest(InstanceActionsPolicyTest):
self.assertNotIn('details', event)
class InstanceActionsNoLegacyPolicyTest(InstanceActionsPolicyTest):
class InstanceActionsScopeTypeNoLegacyPolicyTest(InstanceActionsPolicyTest):
"""Test os-instance-actions APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system_admin_or_owner APIs.
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
ia_policies.BASE_POLICY_NAME % 'list':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
ia_policies.BASE_POLICY_NAME % 'show':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
ia_policies.BASE_POLICY_NAME % 'events':
base_policy.SYSTEM_READER,
base_policy.PROJECT_ADMIN,
}
def setUp(self):
super(InstanceActionsNoLegacyPolicyTest, self).setUp()
super(InstanceActionsScopeTypeNoLegacyPolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check that system reader are able to get the
# instance action events.
self.system_reader_authorized_contexts = [
self.system_admin_context, self.system_reader_context,
self.system_member_context]
# Check that non-system-reader are not able to
# get the instance action events
self.system_reader_unauthorized_contexts = [
self.project_admin_context,
self.system_foo_context, self.legacy_admin_context,
self.other_project_member_context,
self.project_foo_context, self.project_member_context,
self.project_reader_context,
self.other_project_reader_context,
]
# Check that system or projct reader is able to
# show the instance actions events.
self.project_or_system_reader_authorized_contexts = [
self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_member_context,
]
# Check that non-system or non-project reader is not able to
# show the instance actions events.
self.project_or_system_reader_unauthorized_contexts = [
self.legacy_admin_context, self.project_foo_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context,
]
# With no legacy and scope enable, only project admin, member,
# and reader will be able to get server action and only admin
# with event details.
self.project_admin_authorized_contexts = [self.project_admin_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]

View File

@ -38,7 +38,7 @@ class NetworksPolicyTest(base.BasePolicyTest):
# enforcement so will be passing context's project_id as target to
# policy and always pass. If requester is not admin or owner
# of networks then neutron will be returning the appropriate error.
self.reader_authorized_contexts = [
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
@ -47,23 +47,47 @@ class NetworksPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
self.reader_unauthorized_contexts = []
@mock.patch('nova.network.neutron.API.get_all')
def test_list_networks_policy(self, mock_get):
rule_name = "os_compute_api:os-networks:list"
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.index,
self.req)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.index,
self.req)
@mock.patch('nova.network.neutron.API.get')
def test_show_network_policy(self, mock_get):
rule_name = "os_compute_api:os-networks:show"
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
class NetworksNoLegacyNoScopePolicyTest(NetworksPolicyTest):
"""Test Networks APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_ROOT % 'list':
base_policy.PROJECT_READER,
policies.POLICY_ROOT % 'show':
base_policy.PROJECT_READER}
def setUp(self):
super(NetworksNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy, project other roles like foo will not be able
# to get network.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context
]
class NetworksScopeTypePolicyTest(NetworksPolicyTest):
@ -80,30 +104,30 @@ class NetworksScopeTypePolicyTest(NetworksPolicyTest):
def setUp(self):
super(NetworksScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context
]
class NetworksNoLegacyPolicyTest(NetworksScopeTypePolicyTest):
class NetworksScopeTypeNoLegacyPolicyTest(NetworksScopeTypePolicyTest):
"""Test Networks APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_ROOT % 'list':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
policies.POLICY_ROOT % 'show':
base_policy.PROJECT_READER_OR_SYSTEM_READER}
base_policy.PROJECT_READER}
def setUp(self):
super(NetworksNoLegacyPolicyTest, self).setUp()
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
super(NetworksScopeTypeNoLegacyPolicyTest, self).setUp()
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.reader_unauthorized_contexts = [
self.project_foo_context,
self.system_foo_context
]

View File

@ -13,6 +13,7 @@
import mock
from nova.api.openstack.compute import quota_sets
from nova import exception
from nova.policies import quota_sets as policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
@ -33,35 +34,21 @@ class QuotaSetsPolicyTest(base.BasePolicyTest):
self.req = fakes.HTTPRequest.blank('')
self.project_id = self.req.environ['nova.context'].project_id
# Check that admin is able to update or revert quota
# to default.
self.admin_authorized_contexts = [
# With legacy rule all admin is able to update or revert their quota
# to default or get other project quota.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
# Check that non-admin is not able to update or revert
# quota to default.
self.admin_unauthorized_contexts = [
# With legacy rule, everyone is able to get their own quota.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context
]
# Check that system reader is able to get another project's quota.
self.system_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context]
# Check that non-system reader is not able to get another
# project's quota.
self.system_reader_unauthorized_contexts = [
self.system_foo_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context
]
# Check that everyone is able to get the default quota or
# their own quota.
self.other_project_reader_context]
# Everyone is able to get the default quota
self.everyone_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
@ -69,19 +56,7 @@ class QuotaSetsPolicyTest(base.BasePolicyTest):
self.system_foo_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context
]
self.everyone_unauthorized_contexts = []
# Check that system reader or owner is able to get their own quota.
self.system_reader_or_owner_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context
]
self.other_project_reader_context]
@mock.patch('nova.quota.QUOTAS.get_project_quotas')
@mock.patch('nova.quota.QUOTAS.get_settable_quotas')
@ -91,41 +66,57 @@ class QuotaSetsPolicyTest(base.BasePolicyTest):
'instances': 50,
'cores': 50}
}
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name,
self.controller.update,
self.req, self.project_id,
body=body)
for cxtx in self.project_admin_authorized_contexts:
req = fakes.HTTPRequest.blank('')
req.environ['nova.context'] = cxtx
self.controller.update(req, cxtx.project_id, body=body)
for cxtx in (self.all_contexts -
set(self.project_admin_authorized_contexts)):
req = fakes.HTTPRequest.blank('')
req.environ['nova.context'] = cxtx
exc = self.assertRaises(
exception.PolicyNotAuthorized, self.controller.update,
req, cxtx.project_id, body=body)
self.assertEqual(
"Policy doesn't allow %s to be performed." % rule_name,
exc.format_message())
@mock.patch('nova.objects.Quotas.destroy_all_by_project')
def test_delete_quota_sets_policy(self, mock_delete):
rule_name = policies.POLICY_ROOT % 'delete'
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name,
self.controller.delete,
self.req, self.project_id)
for cxtx in self.project_admin_authorized_contexts:
req = fakes.HTTPRequest.blank('')
req.environ['nova.context'] = cxtx
self.controller.delete(req, cxtx.project_id)
for cxtx in (self.all_contexts -
set(self.project_admin_authorized_contexts)):
req = fakes.HTTPRequest.blank('')
req.environ['nova.context'] = cxtx
exc = self.assertRaises(
exception.PolicyNotAuthorized, self.controller.delete,
req, cxtx.project_id)
self.assertEqual(
"Policy doesn't allow %s to be performed." % rule_name,
exc.format_message())
@mock.patch('nova.quota.QUOTAS.get_defaults')
def test_default_quota_sets_policy(self, mock_default):
rule_name = policies.POLICY_ROOT % 'defaults'
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name,
self.controller.defaults,
self.req, self.project_id)
self.common_policy_auth(self.everyone_authorized_contexts,
rule_name,
self.controller.defaults,
self.req, self.project_id)
@mock.patch('nova.quota.QUOTAS.get_project_quotas')
def test_detail_quota_sets_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'detail'
self.common_policy_check(self.system_reader_authorized_contexts,
self.system_reader_unauthorized_contexts,
rule_name,
self.controller.detail,
self.req, 'try-other-project')
# Check if everyone (owner) is able to get their own quota
for cxtx in self.system_reader_or_owner_authorized_contexts:
self.common_policy_auth(self.project_admin_authorized_contexts,
rule_name,
self.controller.detail,
self.req, 'try-other-project')
# Check if project reader or higher roles are able to get
# their own quota
for cxtx in self.project_reader_authorized_contexts:
req = fakes.HTTPRequest.blank('')
req.environ['nova.context'] = cxtx
self.controller.detail(req, cxtx.project_id)
@ -133,18 +124,44 @@ class QuotaSetsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.quota.QUOTAS.get_project_quotas')
def test_show_quota_sets_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'show'
self.common_policy_check(self.system_reader_authorized_contexts,
self.system_reader_unauthorized_contexts,
rule_name,
self.controller.show,
self.req, 'try-other-project')
# Check if everyone (owner) is able to get their own quota
for cxtx in self.system_reader_or_owner_authorized_contexts:
self.common_policy_auth(self.project_admin_authorized_contexts,
rule_name,
self.controller.show,
self.req, 'try-other-project')
# Check if project reader or higher roles are able to get
# their own quota
for cxtx in self.project_reader_authorized_contexts:
req = fakes.HTTPRequest.blank('')
req.environ['nova.context'] = cxtx
self.controller.show(req, cxtx.project_id)
class QuotaSetsNoLegacyNoScopePolicyTest(QuotaSetsPolicyTest):
"""Test QuotaSets APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
def setUp(self):
super(QuotaSetsNoLegacyNoScopePolicyTest, self).setUp()
# Even with no legacy rule, because any admin requesting
# update/revert quota for their own project will be allowed.
# And any admin will be able to get other project quota.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
# With no legacy rule, other project and foo role will not be
# able to get the quota.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.system_member_context, self.system_reader_context,
self.project_member_context,
self.project_reader_context]
class QuotaSetsScopeTypePolicyTest(QuotaSetsPolicyTest):
"""Test Quota Sets APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@ -159,23 +176,19 @@ class QuotaSetsScopeTypePolicyTest(QuotaSetsPolicyTest):
super(QuotaSetsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check that system admin is able to update or revert quota
# to default.
self.admin_authorized_contexts = [
self.system_admin_context]
# Check that non-system admin is not able to update or revert
# quota to default.
self.admin_unauthorized_contexts = [
self.legacy_admin_context, self.system_member_context,
self.project_admin_context, self.system_reader_context,
self.system_foo_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
# With scope enable, system users will be disallowed.
self.project_admin_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context
]
self.other_project_reader_context]
class QuotaSetsNoLegacyPolicyTest(QuotaSetsScopeTypePolicyTest):
class QuotaSetsScopeTypeNoLegacyPolicyTest(QuotaSetsScopeTypePolicyTest):
"""Test Quota Sets APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@ -183,28 +196,7 @@ class QuotaSetsNoLegacyPolicyTest(QuotaSetsScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
super(QuotaSetsNoLegacyPolicyTest, self).setUp()
# Check that system reader is able to get another project's quota.
self.system_reader_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context]
# Check that non-system reader is not able to get anotherproject's
# quota.
self.system_reader_unauthorized_contexts = [
super(QuotaSetsScopeTypeNoLegacyPolicyTest, self).setUp()
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.system_foo_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context
]
# Check that everyone is able to get their own quota.
self.system_reader_or_owner_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.system_member_context, self.system_reader_context,
self.project_member_context,
self.project_reader_context,
self.other_project_member_context,
self.other_project_reader_context
]
self.project_member_context, self.project_reader_context]

View File

@ -48,62 +48,77 @@ class ServerSecurityGroupsPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
# Check that admin or and server owner is able to operate
# With legacy rule and no scope checks, all admin, project members
# project reader or other project role(because legacy rule allow server
# owner- having same project id and no role check) is able to operate
# server security groups.
self.admin_or_owner_authorized_contexts = [
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
# Check that non-admin/owner is not able to operate
# server security groups.
self.admin_or_owner_unauthorized_contexts = [
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
self.reader_authorized_contexts = [
# With legacy rule, any admin or project role is able to get their
# server SG.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_member_context, self.project_foo_context
]
self.reader_unauthorized_contexts = [
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
]
@mock.patch('nova.network.security_group_api.get_instance_security_groups')
def test_get_security_groups_policy(self, mock_get):
rule_name = policies.POLICY_NAME % 'list'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
@mock.patch('nova.network.security_group_api.add_to_instance')
def test_add_security_groups_policy(self, mock_add):
rule_name = policies.POLICY_NAME % 'add'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.action_ctr._addSecurityGroup,
self.req, self.instance.uuid,
body={'addSecurityGroup':
{'name': 'fake'}})
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.action_ctr._addSecurityGroup,
self.req, self.instance.uuid,
body={'addSecurityGroup':
{'name': 'fake'}})
@mock.patch('nova.network.security_group_api.remove_from_instance')
def test_remove_security_groups_policy(self, mock_remove):
rule_name = policies.POLICY_NAME % 'remove'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.action_ctr._removeSecurityGroup,
self.req, self.instance.uuid,
body={'removeSecurityGroup':
{'name': 'fake'}})
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.action_ctr._removeSecurityGroup,
self.req, self.instance.uuid,
body={'removeSecurityGroup':
{'name': 'fake'}})
class ServerSecurityGroupsNoLegacyNoScopePolicyTest(
ServerSecurityGroupsPolicyTest):
"""Test Server Security Groups server APIs policies with no legacy
deprecated rules and no scope checks.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'list':
base_policy.PROJECT_READER,
policies.POLICY_NAME % 'add':
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'remove':
base_policy.PROJECT_MEMBER}
def setUp(self):
super(ServerSecurityGroupsNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, only project admin or member will be
# able to add/remove SG to server and reader to get SG.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context,
]
class SecurityGroupsPolicyTest(base.BasePolicyTest):
@ -120,14 +135,23 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
self.rule_ctr = security_groups.SecurityGroupRulesController()
self.req = fakes.HTTPRequest.blank('')
# Check that everyone is able to perform crud operation on.
# security groups.
# With legacy and scope disabled, everyone is able to perform crud
# operation on security groups.
# NOTE(gmann): Nova cannot verify the security groups owner during
# nova policy enforcement so will be passing context's project_id
# as target to policy and always pass. If requester is not admin
# or owner of security groups then neutron will be returning the
# appropriate error.
self.reader_authorized_contexts = [
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
@ -136,29 +160,22 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
self.reader_unauthorized_contexts = []
self.sys_admin_or_owner_authorized_contexts = (
self.reader_authorized_contexts)
self.sys_admin_or_owner_unauthorized_contexts = (
self.reader_unauthorized_contexts)
@mock.patch('nova.network.security_group_api.list')
def test_list_security_groups_policy(self, mock_get):
rule_name = policies.POLICY_NAME % 'get'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.index,
self.req)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.index,
self.req)
@mock.patch('nova.network.security_group_api.get')
def test_show_security_groups_policy(self, mock_get):
rule_name = policies.POLICY_NAME % 'show'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.show,
self.req, uuids.fake_id)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, uuids.fake_id)
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.update_security_group')
@ -167,11 +184,10 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
body = {'security_group': {
'name': 'test',
'description': 'test-desc'}}
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.update,
self.req, uuids.fake_id, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.update,
self.req, uuids.fake_id, body=body)
@mock.patch('nova.network.security_group_api.create_security_group')
def test_create_security_groups_policy(self, mock_create):
@ -179,21 +195,19 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
body = {'security_group': {
'name': 'test',
'description': 'test-desc'}}
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.create,
self.req, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.create,
self.req, body=body)
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.destroy')
def test_delete_security_groups_policy(self, mock_destroy, mock_get):
rule_name = policies.POLICY_NAME % 'delete'
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.delete,
self.req, uuids.fake_id)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.delete,
self.req, uuids.fake_id)
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.create_security_group_rule')
@ -203,11 +217,10 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
'ip_protocol': 'test', 'group_id': uuids.fake_id,
'parent_group_id': uuids.fake_id,
'from_port': 22, 'from_port': 22}}
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.rule_ctr.create,
self.req, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.rule_ctr.create,
self.req, body=body)
@mock.patch('nova.network.security_group_api.get_rule')
@mock.patch('nova.network.security_group_api.get')
@ -215,11 +228,52 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
def test_delete_security_group_rules_policy(self, mock_remove, mock_get,
mock_rules):
rule_name = policies.POLICY_NAME % 'rule:delete'
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.rule_ctr.delete,
self.req, uuids.fake_id)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.rule_ctr.delete,
self.req, uuids.fake_id)
class SecurityGroupsNoLegacyNoScopePolicyTest(
SecurityGroupsPolicyTest):
"""Test Security Groups APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'get':
base_policy.PROJECT_READER,
policies.POLICY_NAME % 'show':
base_policy.PROJECT_READER,
policies.POLICY_NAME % 'create':
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'update':
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'delete':
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'rule:create':
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'rule:delete':
base_policy.PROJECT_MEMBER}
def setUp(self):
super(SecurityGroupsNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy, project other roles like foo will not be able
# to operate on SG.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.system_member_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context
]
class SecurityGroupsScopeTypePolicyTest(SecurityGroupsPolicyTest):
@ -235,6 +289,20 @@ class SecurityGroupsScopeTypePolicyTest(SecurityGroupsPolicyTest):
def setUp(self):
super(SecurityGroupsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With scope enabled, system users will not be able to
# operate on SG.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context
]
class ServerSecurityGroupsScopeTypePolicyTest(ServerSecurityGroupsPolicyTest):
@ -251,102 +319,78 @@ class ServerSecurityGroupsScopeTypePolicyTest(ServerSecurityGroupsPolicyTest):
def setUp(self):
super(ServerSecurityGroupsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Scope enable will not allow system users.
self.project_member_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context
]
class ServerSecurityGroupsNoLegacyPolicyTest(
class ServerSecurityGroupsScopeTypeNoLegacyPolicyTest(
ServerSecurityGroupsScopeTypePolicyTest):
"""Test Security Groups APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system_admin_or_owner APIs.
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'list':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
policies.POLICY_NAME % 'add':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'remove':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
base_policy.PROJECT_MEMBER}
def setUp(self):
super(ServerSecurityGroupsNoLegacyPolicyTest, self).setUp()
# Check that system or projct admin or owner is able to operate
# server security groups.
self.admin_or_owner_authorized_contexts = [
self.system_admin_context,
super(ServerSecurityGroupsScopeTypeNoLegacyPolicyTest, self).setUp()
# With scope enable and no legacy rule, only project admin/member
# will be able to add/remove the SG to their server and reader
# will get SG of server.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
# Check that non-system and non-admin/owner is not able to operate
# server security groups.
self.admin_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.project_reader_context,
self.project_foo_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context]
# Check that system reader or projct is able to get
# server security groups.
self.reader_authorized_contexts = [
self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_member_context,
]
# Check that non-system reader nd non-admin/owner is not able to get
# server security groups.
self.reader_unauthorized_contexts = [
self.legacy_admin_context, self.project_foo_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context
]
class SecurityGroupsNoLegacyPolicyTest(SecurityGroupsScopeTypePolicyTest):
"""Test Security Groups APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system_admin_or_owner APIs.
and no more deprecated.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'get':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
policies.POLICY_NAME % 'show':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
policies.POLICY_NAME % 'create':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'update':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'delete':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'rule:create':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
base_policy.PROJECT_MEMBER,
policies.POLICY_NAME % 'rule:delete':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
base_policy.PROJECT_MEMBER}
def setUp(self):
super(SecurityGroupsNoLegacyPolicyTest, self).setUp()
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
# With no legacy and scope enabled, system users and project
# other roles like foo will not be able to operate SG.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.reader_unauthorized_contexts = [
self.project_foo_context,
self.system_foo_context
]
self.sys_admin_or_owner_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.project_admin_context, self.project_member_context,
self.legacy_admin_context, self.other_project_member_context
]
self.sys_admin_or_owner_unauthorized_contexts = [
self.system_reader_context,
self.project_reader_context, self.project_foo_context,
self.system_foo_context, self.other_project_reader_context
self.other_project_member_context
]

View File

@ -9,17 +9,21 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import functools
import fixtures
import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import server_groups
import nova.conf
from nova import objects
from nova.policies import server_groups as policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
CONF = nova.conf.CONF
class ServerGroupPolicyTest(base.BasePolicyTest):
"""Test Server Groups APIs policies with all possible context.
@ -45,98 +49,85 @@ class ServerGroupPolicyTest(base.BasePolicyTest):
user_id='u2', policies=[], members=[])]
self.mock_get.return_value = self.sg[0]
# Check that admin or and owner is able to delete
# the server group.
self.admin_or_owner_authorized_contexts = [
# With legacy rule and no scope checks, all admin, project members
# project reader or project any role(because legacy rule allow SG
# owner- having same project id and no role check) is able to
# delete and get SG.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
# Check that non-admin/owner is not able to delete
# the server group.
self.admin_or_owner_unauthorized_contexts = [
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
self.project_reader_context, self.project_foo_context,
]
# Check that system reader or owner is able to get
# the server group. Due to old default everyone
# is allowed to perform this operation.
self.system_reader_or_owner_authorized_contexts = [
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.system_member_context,
self.system_reader_context, self.project_foo_context
self.project_reader_context, self.project_foo_context,
]
self.system_reader_or_owner_unauthorized_contexts = [
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
# Check that everyone is able to list
# theie own server group. Due to old defaults everyone
# is able to list their server groups.
# By default, legacy rule are enabled and scope check is disabled.
# system admin, legacy admin, and project admin is able to get
# all projects SG.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
# List SG can not check for project id so everyone is allowed.
self.everyone_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
self.other_project_member_context
]
self.everyone_unauthorized_contexts = [
]
# Check that project member is able to create server group.
# Due to old defaults everyone is able to list their server groups.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.system_member_context, self.project_reader_context,
self.project_foo_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.project_member_unauthorized_contexts = []
# With legacy rule, anyone can create SG.
self.project_create_authorized_contexts = (
self.everyone_authorized_contexts)
@mock.patch('nova.objects.InstanceGroupList.get_by_project_id')
def test_index_server_groups_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'index'
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name,
self.controller.index,
self.req)
self.common_policy_auth(self.everyone_authorized_contexts,
rule_name,
self.controller.index,
self.req)
@mock.patch('nova.objects.InstanceGroupList.get_all')
def test_index_all_project_server_groups_policy(self, mock_get_all):
@mock.patch('nova.objects.InstanceGroupList.get_by_project_id')
def test_index_all_project_server_groups_policy(self, mock_get,
mock_get_all):
mock_get_all.return_value = objects.InstanceGroupList(objects=self.sg)
mock_get.return_value = objects.InstanceGroupList(
objects=[self.sg[0]])
# 'index' policy is checked before 'index:all_projects' so
# we have to allow it for everyone otherwise it will fail for
# unauthorized contexts here.
rule = policies.POLICY_ROOT % 'index'
self.policy.set_rules({rule: "@"}, overwrite=False)
admin_req = fakes.HTTPRequest.blank(
'/os-server-groups?all_projects=True',
version='2.13', use_admin_context=True)
# Check admin user get all projects server groups.
resp = self.controller.index(admin_req)
projs = [sg['project_id'] for sg in resp['server_groups']]
self.assertEqual(2, len(projs))
self.assertIn('proj2', projs)
# Check non-admin user does not get all projects server groups.
req = fakes.HTTPRequest.blank('/os-server-groups?all_projects=True',
version='2.13')
resp = self.controller.index(req)
projs = [sg['project_id'] for sg in resp['server_groups']]
self.assertNotIn('proj2', projs)
rule_name = policies.POLICY_ROOT % 'index:all_projects'
req = fakes.HTTPRequest.blank('?all_projects', version='2.13')
if not CONF.oslo_policy.enforce_scope:
check_rule = rule_name
else:
check_rule = functools.partial(base.rule_if_system,
rule, rule_name)
authorize_res, unauthorize_res = self.common_policy_auth(
self.project_admin_authorized_contexts,
check_rule, self.controller.index,
req, fatal=False)
for resp in authorize_res:
projs = [sg['project_id'] for sg in resp['server_groups']]
self.assertEqual(2, len(projs))
self.assertIn('proj2', projs)
for resp in unauthorize_res:
projs = [sg['project_id'] for sg in resp['server_groups']]
self.assertNotIn('proj2', projs)
def test_show_server_groups_policy(self):
rule_name = policies.POLICY_ROOT % 'show'
self.common_policy_check(
self.system_reader_or_owner_authorized_contexts,
self.system_reader_or_owner_unauthorized_contexts,
self.common_policy_auth(
self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, uuids.fake_id)
@ -146,20 +137,56 @@ class ServerGroupPolicyTest(base.BasePolicyTest):
rule_name = policies.POLICY_ROOT % 'create'
body = {'server_group': {'name': 'fake',
'policies': ['affinity']}}
self.common_policy_check(self.project_member_authorized_contexts,
self.project_member_unauthorized_contexts,
rule_name,
self.controller.create,
self.req, body=body)
self.common_policy_auth(self.project_create_authorized_contexts,
rule_name,
self.controller.create,
self.req, body=body)
@mock.patch('nova.objects.InstanceGroup.destroy')
def test_delete_server_groups_policy(self, mock_destroy):
rule_name = policies.POLICY_ROOT % 'delete'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.delete,
self.req, uuids.fake_id)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.delete,
self.req, uuids.fake_id)
class ServerGroupNoLegacyNoScopePolicyTest(ServerGroupPolicyTest):
"""Test Server Groups APIs policies with no legacy deprecated rules
and no scope checks which means new defaults only.
"""
without_deprecated_rules = True
def setUp(self):
super(ServerGroupNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy, only project admin, member will be able to delete
# the SG and also reader will be able to get the SG.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
# Even with no legacy rule, legacy admin is allowed to create SG
# use requesting context's project_id. Same for list SG.
self.project_create_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.system_member_context, self.other_project_member_context]
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
self.everyone_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context
]
class ServerGroupScopeTypePolicyTest(ServerGroupPolicyTest):
@ -176,27 +203,37 @@ class ServerGroupScopeTypePolicyTest(ServerGroupPolicyTest):
super(ServerGroupScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check if project scoped can create the server group.
# With scope enable, it disallow system users.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context,
self.other_project_member_context,
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context,
]
self.project_create_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context]
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context]
self.everyone_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_reader_context,
]
# Check if non-project scoped cannot create the server group.
self.project_member_unauthorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context, self.system_foo_context
self.other_project_member_context
]
# TODO(gmann): Test this with system scope once we remove
# the hardcoded admin check
def test_index_all_project_server_groups_policy(self):
pass
class ServerGroupNoLegacyPolicyTest(ServerGroupScopeTypePolicyTest):
class ServerGroupScopeTypeNoLegacyPolicyTest(ServerGroupScopeTypePolicyTest):
"""Test Server Group APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@ -204,58 +241,26 @@ class ServerGroupNoLegacyPolicyTest(ServerGroupScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
super(ServerGroupNoLegacyPolicyTest, self).setUp()
super(ServerGroupScopeTypeNoLegacyPolicyTest, self).setUp()
# Check that system admin or and owner is able to delete
# the server group.
self.admin_or_owner_authorized_contexts = [
self.system_admin_context,
self.project_admin_context, self.project_member_context,
]
# Check that non-system admin/owner is not able to delete
# the server group.
self.admin_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_member_context,
self.system_reader_context, self.system_foo_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
# Check that system reader or owner is able to get
# the server group.
self.system_reader_or_owner_authorized_contexts = [
self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.system_member_context,
self.system_reader_context
]
self.system_reader_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_foo_context,
self.other_project_member_context, self.project_foo_context,
self.other_project_reader_context,
]
self.everyone_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.everyone_unauthorized_contexts = [
self.project_foo_context,
self.system_foo_context
]
# Check if project member can create the server group.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_create_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.other_project_member_context
]
# Check if non-project member cannot create the server group.
self.project_member_unauthorized_contexts = [
self.system_admin_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.project_reader_context,
self.project_foo_context,
self.project_member_context,
self.other_project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context]
self.everyone_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.other_project_reader_context,
self.other_project_member_context
]

View File

@ -49,37 +49,45 @@ class ServerIpsPolicyTest(base.BasePolicyTest):
self.mock_get_network.return_value = {'net1':
{'ips': '', 'floating_ips': ''}}
# Check that admin or and server owner is able to get server
# IP addresses.
self.reader_or_owner_authorized_contexts = [
# With legacy rule, any admin or project role is able to get their
# server IP addresses.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.system_member_context, self.system_reader_context]
# Check that non-admin/owner is not able to get the server IP
# adderesses
self.reader_or_owner_unauthorized_contexts = [
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
def test_index_ips_policy(self):
rule_name = ips_policies.POLICY_ROOT % 'index'
self.common_policy_check(self.reader_or_owner_authorized_contexts,
self.reader_or_owner_unauthorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
def test_show_ips_policy(self):
rule_name = ips_policies.POLICY_ROOT % 'show'
self.common_policy_check(self.reader_or_owner_authorized_contexts,
self.reader_or_owner_unauthorized_contexts,
rule_name,
self.controller.show,
self.req, self.instance.uuid,
'net1')
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, self.instance.uuid,
'net1')
class ServerIpsNoLegacyNoScopePolicyTest(ServerIpsPolicyTest):
"""Test Server Ips APIs policies with no legacy deprecated rules
and no scope checks which means new defaults only.
"""
without_deprecated_rules = True
def setUp(self):
super(ServerIpsNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy, only project admin, member, and reader will be able
# to get their server IP adderesses.
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context,
]
class ServerIpsScopeTypePolicyTest(ServerIpsPolicyTest):
@ -95,28 +103,26 @@ class ServerIpsScopeTypePolicyTest(ServerIpsPolicyTest):
def setUp(self):
super(ServerIpsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With scope enabled, system users will not be able
# to get the server IP adderesses.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context
]
class ServerIpsNoLegacyPolicyTest(ServerIpsScopeTypePolicyTest):
class ServerIpsScopeTypeNoLegacyPolicyTest(ServerIpsScopeTypePolicyTest):
"""Test Server IPs APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system_admin_or_owner APIs.
and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
super(ServerIpsNoLegacyPolicyTest, self).setUp()
# Check that system reader or owner is able to
# get the server IP adderesses.
self.reader_or_owner_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context, self.project_admin_context,
self.project_member_context, self.project_reader_context]
# Check that non-system and non-owner is not able to
# get the server IP adderesses.
self.reader_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.project_foo_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context,
super(ServerIpsScopeTypeNoLegacyPolicyTest, self).setUp()
# With no legacy and scope enable, only project admin, member,
# and reader will be able to get their server IP adderesses.
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context
]

View File

@ -40,92 +40,89 @@ class ServerMetadataPolicyTest(base.BasePolicyTest):
id=1, uuid=uuids.fake_id, project_id=self.project_id)
self.mock_get.return_value = self.instance
# Check that admin or and server owner is able to CRUD
# the server metadata.
self.admin_or_owner_authorized_contexts = [
# With legacy rule and no scope checks, all admin, project members
# project reader or other project role(because legacy rule allow server
# owner- having same project id and no role check) is able to create,
# update, and delete the server metadata.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
# Check that non-admin/owner is not able to CRUD
# the server metadata
self.admin_or_owner_unauthorized_contexts = [
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
# Check that admin or and server owner is able to get
# the server metadata.
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.system_member_context, self.system_reader_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
# Check that non-admin/owner is not able to get
# the server metadata.
self.reader_unauthorized_contexts = [
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
# and they can get their own server metadata.
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
@mock.patch('nova.compute.api.API.get_instance_metadata')
def test_index_server_Metadata_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'index'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
@mock.patch('nova.compute.api.API.get_instance_metadata')
def test_show_server_Metadata_policy(self, mock_get):
rule_name = policies.POLICY_ROOT % 'show'
mock_get.return_value = {'key9': 'value'}
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.show,
self.req, self.instance.uuid, 'key9')
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, self.instance.uuid, 'key9')
@mock.patch('nova.compute.api.API.update_instance_metadata')
def test_create_server_Metadata_policy(self, mock_quota):
rule_name = policies.POLICY_ROOT % 'create'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.create,
self.req, self.instance.uuid,
body={"metadata": {"key9": "value9"}})
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.create,
self.req, self.instance.uuid,
body={"metadata": {"key9": "value9"}})
@mock.patch('nova.compute.api.API.update_instance_metadata')
def test_update_server_Metadata_policy(self, mock_quota):
rule_name = policies.POLICY_ROOT % 'update'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.update,
self.req, self.instance.uuid, 'key9',
body={"meta": {"key9": "value9"}})
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.update,
self.req, self.instance.uuid, 'key9',
body={"meta": {"key9": "value9"}})
@mock.patch('nova.compute.api.API.update_instance_metadata')
def test_update_all_server_Metadata_policy(self, mock_quota):
rule_name = policies.POLICY_ROOT % 'update_all'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.update_all,
self.req, self.instance.uuid,
body={"metadata": {"key9": "value9"}})
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.update_all,
self.req, self.instance.uuid,
body={"metadata": {"key9": "value9"}})
@mock.patch('nova.compute.api.API.get_instance_metadata')
@mock.patch('nova.compute.api.API.delete_instance_metadata')
def test_delete_server_Metadata_policy(self, mock_delete, mock_get):
rule_name = policies.POLICY_ROOT % 'delete'
mock_get.return_value = {'key9': 'value'}
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.delete,
self.req, self.instance.uuid, 'key9')
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.delete,
self.req, self.instance.uuid, 'key9')
class ServerMetadataNoLegacyNoScopePolicyTest(ServerMetadataPolicyTest):
"""Test Server Metadata APIs policies with no legacy deprecated rules
and no scope checks which means new defaults only.
"""
without_deprecated_rules = True
def setUp(self):
super(ServerMetadataNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, legacy admin loose power.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
class ServerMetadataScopeTypePolicyTest(ServerMetadataPolicyTest):
@ -141,9 +138,17 @@ class ServerMetadataScopeTypePolicyTest(ServerMetadataPolicyTest):
def setUp(self):
super(ServerMetadataScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With Scope enable, system users no longer allowed.
self.project_member_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
class ServerMetadataNoLegacyPolicyTest(ServerMetadataScopeTypePolicyTest):
class ServerMetadataScopeTypeNoLegacyPolicyTest(
ServerMetadataScopeTypePolicyTest):
"""Test Server Metadata APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@ -151,32 +156,11 @@ class ServerMetadataNoLegacyPolicyTest(ServerMetadataScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
super(ServerMetadataNoLegacyPolicyTest, self).setUp()
# Check that system admin or project member is able to create, update
# and delete the server metadata.
self.admin_or_owner_authorized_contexts = [
self.system_admin_context, self.project_admin_context,
self.project_member_context]
# Check that non-system/admin/member is not able to create, update
# and delete the server metadata.
self.admin_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_reader_context,
self.system_foo_context, self.system_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context
]
# Check that system admin or project member is able to
# get the server metadata.
self.reader_authorized_contexts = [
self.system_admin_context,
self.system_member_context, self.system_reader_context,
super(ServerMetadataScopeTypeNoLegacyPolicyTest, self).setUp()
# With no legacy and scope enable, only project admin, member,
# and reader will be able to allowed operation on server metadata.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
# Check that non-system/admin/member is not able to
# get the server metadata.
self.reader_unauthorized_contexts = [
self.legacy_admin_context, self.system_foo_context,
self.project_foo_context, self.other_project_member_context,
self.other_project_reader_context
]

View File

@ -41,51 +41,56 @@ class ServerPasswordPolicyTest(base.BasePolicyTest):
id=1, uuid=uuids.fake_id, project_id=self.project_id,
system_metadata={}, expected_attrs=['system_metadata'])
self.mock_get.return_value = self.instance
# Check that admin or and server owner is able to
# delete the server password.
self.admin_or_owner_authorized_contexts = [
# With legacy rule and no scope checks, all admin, project members
# project reader or other project role(because legacy rule allow server
# owner- having same project id and no role check) is able to delete,
# the server Password.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
# Check that non-admin/owner is not able to delete
# the server password.
self.admin_or_owner_unauthorized_contexts = [
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
# Check that admin or and server owner is able to get
# the server password.
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.system_member_context, self.system_reader_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
# Check that non-admin/owner is not able to get
# the server password.
self.reader_unauthorized_contexts = [
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
# and they can get their own server password.
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
@mock.patch('nova.api.metadata.password.extract_password')
def test_index_server_password_policy(self, mock_pass):
rule_name = policies.BASE_POLICY_NAME % 'show'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
@mock.patch('nova.api.metadata.password.convert_password')
def test_clear_server_password_policy(self, mock_pass):
rule_name = policies.BASE_POLICY_NAME % 'clear'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.clear,
self.req, self.instance.uuid)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.clear,
self.req, self.instance.uuid)
class ServerPasswordNoLegacyNoScopePolicyTest(ServerPasswordPolicyTest):
"""Test Server Password APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.BASE_POLICY_NAME % 'show':
base_policy.PROJECT_READER,
policies.BASE_POLICY_NAME % 'clear':
base_policy.PROJECT_MEMBER}
def setUp(self):
super(ServerPasswordNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, legacy admin loose power.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
class ServerPasswordScopeTypePolicyTest(ServerPasswordPolicyTest):
@ -101,50 +106,33 @@ class ServerPasswordScopeTypePolicyTest(ServerPasswordPolicyTest):
def setUp(self):
super(ServerPasswordScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With Scope enable, system users no longer allowed.
self.project_member_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
class ServerPasswordNoLegacyPolicyTest(ServerPasswordScopeTypePolicyTest):
class ServerPasswordScopeTypeNoLegacyPolicyTest(
ServerPasswordScopeTypePolicyTest):
"""Test Server Password APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system_admin_or_owner APIs.
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.BASE_POLICY_NAME % 'show':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
base_policy.PROJECT_READER,
policies.BASE_POLICY_NAME % 'clear':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
base_policy.PROJECT_MEMBER}
def setUp(self):
super(ServerPasswordNoLegacyPolicyTest, self).setUp()
# Check that system or projct admin or owner is able to clear
# server password.
self.admin_or_owner_authorized_contexts = [
self.system_admin_context,
super(ServerPasswordScopeTypeNoLegacyPolicyTest, self).setUp()
# With no legacy and scope enable, only project admin, member,
# and reader will be able to allowed operation on server password.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
# Check that non-system and non-admin/owner is not able to clear
# server password.
self.admin_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.project_reader_context,
self.project_foo_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context]
# Check that system reader or projct owner is able to get
# server password.
self.reader_authorized_contexts = [
self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_member_context,
]
# Check that non-system reader nd non-admin/owner is not able to get
# server password.
self.reader_unauthorized_contexts = [
self.legacy_admin_context, self.project_foo_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]

View File

@ -50,51 +50,32 @@ class ServerTagsPolicyTest(base.BasePolicyTest):
self.stub_out('nova.objects.InstanceMapping.get_by_instance_uuid',
lambda s, c, u: inst_map)
# Check that admin or and server owner is able to perform
# With legacy rule and no scope checks, all admin, project members
# project reader or other project role(because legacy rule allow server
# owner- having same project id and no role check) is able to perform,
# operations on server tags.
self.admin_or_owner_authorized_contexts = [
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context
]
# Check that non-admin/owner is not able to perform operations
# on server tags
self.admin_or_owner_unauthorized_contexts = [
self.system_member_context, self.system_reader_context,
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
# Check that reader or and server owner is able to perform operations
# on server tags.
self.reader_or_owner_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.system_member_context, self.system_reader_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
# Check that non-reader/owner is not able to perform operations
# on server tags.
self.reader_or_owner_unauthorized_contexts = [
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
@mock.patch('nova.objects.TagList.get_by_resource_id')
def test_index_server_tags_policy(self, mock_tag):
rule_name = policies.POLICY_ROOT % 'index'
self.common_policy_check(self.reader_or_owner_authorized_contexts,
self.reader_or_owner_unauthorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
@mock.patch('nova.objects.Tag.exists')
def test_show_server_tags_policy(self, mock_exists):
rule_name = policies.POLICY_ROOT % 'show'
self.common_policy_check(self.reader_or_owner_authorized_contexts,
self.reader_or_owner_unauthorized_contexts,
rule_name,
self.controller.show,
self.req, self.instance.uuid, uuids.fake_id)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, self.instance.uuid, uuids.fake_id)
@mock.patch('nova.notifications.base.send_instance_update_notification')
@mock.patch('nova.db.main.api.instance_tag_get_by_instance_uuid')
@ -102,33 +83,30 @@ class ServerTagsPolicyTest(base.BasePolicyTest):
def test_update_server_tags_policy(self, mock_create, mock_tag,
mock_notf):
rule_name = policies.POLICY_ROOT % 'update'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.update,
self.req, self.instance.uuid, uuids.fake_id,
body=None)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.update,
self.req, self.instance.uuid, uuids.fake_id,
body=None)
@mock.patch('nova.notifications.base.send_instance_update_notification')
@mock.patch('nova.db.main.api.instance_tag_set')
def test_update_all_server_tags_policy(self, mock_set, mock_notf):
rule_name = policies.POLICY_ROOT % 'update_all'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.update_all,
self.req, self.instance.uuid,
body={'tags': ['tag1', 'tag2']})
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.update_all,
self.req, self.instance.uuid,
body={'tags': ['tag1', 'tag2']})
@mock.patch('nova.notifications.base.send_instance_update_notification')
@mock.patch('nova.objects.TagList.destroy')
def test_delete_all_server_tags_policy(self, mock_destroy, mock_notf):
rule_name = policies.POLICY_ROOT % 'delete_all'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.delete_all,
self.req, self.instance.uuid)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.delete_all,
self.req, self.instance.uuid)
@mock.patch('nova.notifications.base.send_instance_update_notification')
@mock.patch('nova.db.main.api.instance_tag_get_by_instance_uuid')
@ -136,11 +114,28 @@ class ServerTagsPolicyTest(base.BasePolicyTest):
def test_delete_server_tags_policy(self, mock_destroy, mock_get,
mock_notf):
rule_name = policies.POLICY_ROOT % 'delete'
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.delete,
self.req, self.instance.uuid, uuids.fake_id)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name,
self.controller.delete,
self.req, self.instance.uuid, uuids.fake_id)
class ServerTagsNoLegacyNoScopePolicyTest(ServerTagsPolicyTest):
"""Test Server Tags APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
def setUp(self):
super(ServerTagsNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, legacy admin loose power.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
class ServerTagsScopeTypePolicyTest(ServerTagsPolicyTest):
@ -156,9 +151,16 @@ class ServerTagsScopeTypePolicyTest(ServerTagsPolicyTest):
def setUp(self):
super(ServerTagsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With Scope enable, system users no longer allowed.
self.project_member_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
class ServerTagsNoLegacyPolicyTest(ServerTagsScopeTypePolicyTest):
class ServerTagsScopeTypeNoLegacyPolicyTest(ServerTagsScopeTypePolicyTest):
"""Test Server Tags APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@ -166,32 +168,11 @@ class ServerTagsNoLegacyPolicyTest(ServerTagsScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
super(ServerTagsNoLegacyPolicyTest, self).setUp()
# Check that system admin or project member is able to
# perform operations on server tags.
self.admin_or_owner_authorized_contexts = [
self.system_admin_context, self.project_admin_context,
self.project_member_context]
# Check that non-system/admin/member is not able to
# perform operations on server tags.
self.admin_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_reader_context,
self.system_foo_context, self.system_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context
]
# Check that system reader or owner is able to
# perform operations on server tags.
self.reader_or_owner_authorized_contexts = [
self.system_admin_context,
self.system_member_context, self.system_reader_context,
super(ServerTagsScopeTypeNoLegacyPolicyTest, self).setUp()
# With no legacy and scope enable, only project admin, member,
# and reader will be able to allowed operation on server tags.
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
# Check that non-system/reader/owner is not able to
# perform operations on server tags.
self.reader_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_foo_context,
self.project_foo_context, self.other_project_member_context,
self.other_project_reader_context
]

View File

@ -51,40 +51,23 @@ class ServerTopologyPolicyTest(base.BasePolicyTest):
# Check that system reader or and server owner is able to get
# the server topology.
self.system_reader_or_owner_authorized_contexts = [
# With legacy rule and no scope checks, all admin is able to get
# server topology wth host info.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
# and project reader can get their server topology without host info.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.system_member_context, self.system_reader_context]
# Check that non-stem reader/owner is not able to get
# the server topology.
self.system_reader_or_owner_unauthorized_contexts = [
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context,
]
# Check that system reader is able to get the server topology
# host information.
self.system_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context]
# Check that non-system reader is not able to get the server topology
# host information.
self.system_reader_unauthorized_contexts = [
self.system_foo_context, self.project_member_context,
self.other_project_member_context,
self.project_foo_context, self.project_reader_context,
self.other_project_reader_context
]
self.project_reader_context, self.project_foo_context]
def test_index_server_topology_policy(self):
rule_name = policies.BASE_POLICY_NAME % 'index'
self.common_policy_check(
self.system_reader_or_owner_authorized_contexts,
self.system_reader_or_owner_unauthorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.index,
self.req, self.instance.uuid)
def test_index_host_server_topology_policy(self):
rule_name = policies.BASE_POLICY_NAME % 'host:index'
@ -93,9 +76,8 @@ class ServerTopologyPolicyTest(base.BasePolicyTest):
# fail first for unauthorized contexts.
rule = policies.BASE_POLICY_NAME % 'index'
self.policy.set_rules({rule: "@"}, overwrite=False)
authorize_res, unauthorize_res = self.common_policy_check(
self.system_reader_authorized_contexts,
self.system_reader_unauthorized_contexts,
authorize_res, unauthorize_res = self.common_policy_auth(
self.project_admin_authorized_contexts,
rule_name, self.controller.index, self.req, self.instance.uuid,
fatal=False)
for resp in authorize_res:
@ -106,6 +88,23 @@ class ServerTopologyPolicyTest(base.BasePolicyTest):
self.assertNotIn('cpu_pinning', resp['nodes'][0])
class ServerTopologyNoLegacyNoScopePolicyTest(ServerTopologyPolicyTest):
"""Test Server Topology APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
def setUp(self):
super(ServerTopologyNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, legacy admin loose power.
self.project_admin_authorized_contexts = [self.project_admin_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
class ServerTopologyScopeTypePolicyTest(ServerTopologyPolicyTest):
"""Test Server Topology APIs policies with system scope enabled.
This class set the nova.conf [oslo_policy] enforce_scope to True
@ -119,24 +118,17 @@ class ServerTopologyScopeTypePolicyTest(ServerTopologyPolicyTest):
def setUp(self):
super(ServerTopologyScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check that system reader is able to get the server topology
# host information.
self.system_reader_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context]
# Check that non-system/reader is not able to get the server topology
# host information.
self.system_reader_unauthorized_contexts = [
self.legacy_admin_context, self.system_foo_context,
# With Scope enable, system users no longer allowed.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context]
self.project_reader_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.other_project_member_context,
self.project_foo_context, self.project_reader_context,
self.other_project_reader_context,
]
self.project_reader_context, self.project_foo_context]
class ServerTopologyNoLegacyPolicyTest(ServerTopologyScopeTypePolicyTest):
class ServerTopologyScopeTypeNoLegacyPolicyTest(
ServerTopologyScopeTypePolicyTest):
"""Test Server Topology APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
@ -144,18 +136,11 @@ class ServerTopologyNoLegacyPolicyTest(ServerTopologyScopeTypePolicyTest):
without_deprecated_rules = True
def setUp(self):
super(ServerTopologyNoLegacyPolicyTest, self).setUp()
# Check that system reader/owner is able to get
# the server topology.
self.system_reader_or_owner_authorized_contexts = [
self.system_admin_context,
super(ServerTopologyScopeTypeNoLegacyPolicyTest, self).setUp()
# With no legacy and scope enable, only project admin, member,
# and reader will be able to get server topology and only admin
# with host info.
self.project_admin_authorized_contexts = [self.project_admin_context]
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.system_member_context, self.system_reader_context,
self.project_reader_context]
# Check that non-system/reader/owner is not able to get
# the server topology.
self.system_reader_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_foo_context,
self.other_project_member_context, self.project_foo_context,
self.other_project_reader_context,
]

View File

@ -32,47 +32,48 @@ class SimpleTenantUsagePolicyTest(base.BasePolicyTest):
self.req = fakes.HTTPRequest.blank('')
self.controller._get_instances_all_cells = mock.MagicMock()
# Check that reader(legacy admin) or and owner is able to get
# the tenant usage statistics for a specific tenant.
self.reader_or_owner_authorized_contexts = [
# Currently any admin can list other project usage.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
# and project reader can get their usage statistics.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.system_member_context, self.system_reader_context]
# Check that non-reader(legacy non-admin) or owner is not able to get
# the tenant usage statistics for a specific tenant.
self.reader_or_owner_unauthorized_contexts = [
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
# Check that reader is able to get the tenant usage statistics.
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.system_member_context,
self.system_reader_context]
# Check that non-reader is not able to get the tenant usage statistics.
self.reader_unauthorized_contexts = [
self.system_foo_context, self.project_member_context,
self.other_project_member_context,
self.project_foo_context, self.project_reader_context,
self.other_project_reader_context
]
def test_index_simple_tenant_usage_policy(self):
rule_name = policies.POLICY_ROOT % 'list'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.index,
self.req)
self.common_policy_auth(self.project_admin_authorized_contexts,
rule_name,
self.controller.index,
self.req)
def test_show_simple_tenant_usage_policy(self):
rule_name = policies.POLICY_ROOT % 'show'
self.common_policy_check(self.reader_or_owner_authorized_contexts,
self.reader_or_owner_unauthorized_contexts,
rule_name,
self.controller.show,
self.req, self.project_id)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name,
self.controller.show,
self.req, self.project_id)
class SimpleTenantUsageNoLegacyNoScopePolicyTest(SimpleTenantUsagePolicyTest):
"""Test Simple Tenant Usage APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
def setUp(self):
super(SimpleTenantUsageNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy, project other roles like foo will not be able
# to get tenant usage.
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context,
]
class SimpleTenantUsageScopeTypePolicyTest(SimpleTenantUsagePolicyTest):
@ -88,23 +89,17 @@ class SimpleTenantUsageScopeTypePolicyTest(SimpleTenantUsagePolicyTest):
def setUp(self):
super(SimpleTenantUsageScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check that system reader is able to get the tenant usage statistics.
self.reader_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context]
# Check that non-system/reader is not able to get the tenant usage
# statistics.
self.reader_unauthorized_contexts = [
self.legacy_admin_context, self.system_foo_context,
self.project_admin_context, self.project_member_context,
self.other_project_member_context,
self.project_foo_context, self.project_reader_context,
self.other_project_reader_context
# With Scope enable, system users no longer allowed.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context,
]
class SimpleTenantUsageNoLegacyPolicyTest(
class SimpleTenantUsageScopeTypeNoLegacyPolicyTest(
SimpleTenantUsageScopeTypePolicyTest):
"""Test Simple Tenant Usage APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
@ -113,17 +108,8 @@ class SimpleTenantUsageNoLegacyPolicyTest(
without_deprecated_rules = True
def setUp(self):
super(SimpleTenantUsageNoLegacyPolicyTest, self).setUp()
# Check that system reader or owner is able to get
# the tenant usage statistics for a specific tenant.
self.reader_or_owner_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context, self.project_admin_context,
self.project_member_context, self.project_reader_context]
# Check that non-system reader/owner is not able to get
# the tenant usage statistics for a specific tenant.
self.reader_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_foo_context,
self.other_project_member_context,
self.project_foo_context, self.other_project_reader_context
super(SimpleTenantUsageScopeTypeNoLegacyPolicyTest, self).setUp()
self.project_reader_authorized_contexts = [
self.project_admin_context,
self.project_member_context, self.project_reader_context,
]

View File

@ -14,6 +14,8 @@ import mock
from oslo_utils.fixture import uuidsentinel as uuids
from nova.api.openstack.compute import tenant_networks
from nova.policies import base as base_policy
from nova.policies import tenant_networks as policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
@ -36,7 +38,7 @@ class TenantNetworksPolicyTest(base.BasePolicyTest):
# enforcement so will be passing context's project_id as target to
# policy and always pass. If requester is not admin or owner
# of networks then neutron will be returning the appropriate error.
self.everyone_authorized_contexts = [
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
@ -45,23 +47,46 @@ class TenantNetworksPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
self.everyone_unauthorized_contexts = []
@mock.patch('nova.network.neutron.API.get_all')
def test_list_tenant_networks_policy(self, mock_get):
rule_name = "os_compute_api:os-tenant-networks"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.controller.index,
self.req)
rule_name = "os_compute_api:os-tenant-networks:list"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.index,
self.req)
@mock.patch('nova.network.neutron.API.get')
def test_show_tenant_network_policy(self, mock_get):
rule_name = "os_compute_api:os-tenant-networks"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
rule_name = "os_compute_api:os-tenant-networks:show"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
class TenantNetworksNoLegacyNoScopePolicyTest(TenantNetworksPolicyTest):
"""Test Tenant Networks APIs policies with no legacy deprecated rules
and no scope checks.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'list':
base_policy.PROJECT_READER,
policies.POLICY_NAME % 'show':
base_policy.PROJECT_READER}
def setUp(self):
super(TenantNetworksNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy, project other roles like foo will not be able
# to get tenant network.
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context
]
class TenantNetworksScopeTypePolicyTest(TenantNetworksPolicyTest):
@ -78,3 +103,31 @@ class TenantNetworksScopeTypePolicyTest(TenantNetworksPolicyTest):
def setUp(self):
super(TenantNetworksScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context
]
class TenantNetworksScopeTypeNoLegacyPolicyTest(
TenantNetworksScopeTypePolicyTest):
"""Test Tenant Networks APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'list':
base_policy.PROJECT_READER,
policies.POLICY_NAME % 'show':
base_policy.PROJECT_READER}
def setUp(self):
super(TenantNetworksScopeTypeNoLegacyPolicyTest, self).setUp()
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.other_project_member_context,
self.other_project_reader_context,
]

View File

@ -20,6 +20,8 @@ from nova.compute import vm_states
from nova import exception
from nova import objects
from nova.objects import block_device as block_device_obj
from nova.policies import base as base_policy
from nova.policies import volumes as v_policies
from nova.policies import volumes_attachments as va_policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit import fake_block_device
@ -92,77 +94,50 @@ class VolumeAttachPolicyTest(base.BasePolicyTest):
task_state=None, launched_at=timeutils.utcnow())
self.mock_get.return_value = self.instance
# Check that admin or owner is able to list/create/show/delete
# the attached volume.
self.admin_or_owner_authorized_contexts = [
# With legacy rule and no scope checks, all admin, project members
# project reader or other project role(because legacy rule allow
# resource owner- having same project id and no role check) is
# able create/delete/update the volume attachment.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_foo_context,
self.project_reader_context, self.project_member_context
]
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
self.admin_or_owner_unauthorized_contexts = [
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
# With legacy rule and no scope checks, all admin, project members
# project reader or other project role(because legacy rule allow
# resource owner- having same project id and no role check) is
# able get the volume attachment.
self.project_reader_authorized_contexts = (
self.project_member_authorized_contexts)
# Check that admin is able to update the attached volume
self.admin_authorized_contexts = [
self.legacy_admin_context,
self.system_admin_context,
self.project_admin_context
]
# Check that non-admin is not able to update the attached
# volume
self.admin_unauthorized_contexts = [
self.system_member_context,
self.system_reader_context,
self.system_foo_context,
self.project_member_context,
self.other_project_member_context,
self.project_foo_context,
self.project_reader_context,
self.other_project_reader_context,
]
self.reader_authorized_contexts = [
# By default, legacy rule are enable and scope check is disabled.
# system admin, legacy admin, and project admin is able to update
# volume attachment with a different volumeId.
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.system_reader_context, self.system_member_context,
self.project_admin_context, self.project_reader_context,
self.project_member_context, self.project_foo_context
]
self.reader_unauthorized_contexts = [
self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.project_admin_context]
@mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
def test_index_volume_attach_policy(self, mock_get_instance):
rule_name = self.policy_root % "index"
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.index,
self.req, FAKE_UUID)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.index,
self.req, FAKE_UUID)
def test_show_volume_attach_policy(self):
rule_name = self.policy_root % "show"
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.show,
self.req, FAKE_UUID, FAKE_UUID_A)
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.show,
self.req, FAKE_UUID, FAKE_UUID_A)
@mock.patch('nova.compute.api.API.attach_volume')
def test_create_volume_attach_policy(self, mock_attach_volume):
rule_name = self.policy_root % "create"
body = {'volumeAttachment': {'volumeId': FAKE_UUID_B,
'device': '/dev/fake'}}
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name, self.controller.create,
self.req, FAKE_UUID, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.controller.create,
self.req, FAKE_UUID, body=body)
@mock.patch.object(block_device_obj.BlockDeviceMapping, 'save')
def test_update_volume_attach_policy(self, mock_bdm_save):
@ -171,28 +146,25 @@ class VolumeAttachPolicyTest(base.BasePolicyTest):
body = {'volumeAttachment': {
'volumeId': FAKE_UUID_A,
'delete_on_termination': True}}
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name, self.controller.update,
req, FAKE_UUID,
FAKE_UUID_A, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.controller.update,
req, FAKE_UUID,
FAKE_UUID_A, body=body)
@mock.patch('nova.compute.api.API.detach_volume')
def test_delete_volume_attach_policy(self, mock_detach_volume):
rule_name = self.policy_root % "delete"
self.common_policy_check(self.admin_or_owner_authorized_contexts,
self.admin_or_owner_unauthorized_contexts,
rule_name, self.controller.delete,
self.req, FAKE_UUID, FAKE_UUID_A)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.controller.delete,
self.req, FAKE_UUID, FAKE_UUID_A)
@mock.patch('nova.compute.api.API.swap_volume')
def test_swap_volume_attach_policy(self, mock_swap_volume):
rule_name = self.policy_root % "swap"
body = {'volumeAttachment': {'volumeId': FAKE_UUID_B}}
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name, self.controller.update,
self.req, FAKE_UUID, FAKE_UUID_A, body=body)
self.common_policy_auth(self.project_admin_authorized_contexts,
rule_name, self.controller.update,
self.req, FAKE_UUID, FAKE_UUID_A, body=body)
@mock.patch.object(block_device_obj.BlockDeviceMapping, 'save')
@mock.patch('nova.compute.api.API.swap_volume')
@ -225,14 +197,33 @@ class VolumeAttachPolicyTest(base.BasePolicyTest):
req = fakes.HTTPRequest.blank('', version='2.85')
body = {'volumeAttachment': {'volumeId': FAKE_UUID_B,
'delete_on_termination': True}}
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name, self.controller.update,
req, FAKE_UUID, FAKE_UUID_A, body=body)
self.common_policy_auth(self.project_admin_authorized_contexts,
rule_name, self.controller.update,
req, FAKE_UUID, FAKE_UUID_A, body=body)
mock_swap_volume.assert_called()
mock_bdm_save.assert_called()
class VolumeAttachNoLegacyNoScopePolicyTest(VolumeAttachPolicyTest):
"""Test volume attachment APIs policies with no legacy deprecated rules
and no scope checks which means new defaults only.
"""
without_deprecated_rules = True
def setUp(self):
super(VolumeAttachNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy rule, only project admin, member, or reader will be
# able to perform volume attachment operation on its own project.
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.project_reader_context]
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
class VolumeAttachScopeTypePolicyTest(VolumeAttachPolicyTest):
"""Test os-volume-attachments APIs policies with system scope enabled.
@ -248,77 +239,39 @@ class VolumeAttachScopeTypePolicyTest(VolumeAttachPolicyTest):
super(VolumeAttachScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check that system admin is able to update the attached volume
self.admin_authorized_contexts = [
self.system_admin_context]
# Check that non-system or non-admin is not able to update
# the attached volume.
self.admin_unauthorized_contexts = [
self.legacy_admin_context, self.system_member_context,
self.system_reader_context, self.system_foo_context,
# Scope enable will not allow system admin to perform the
# volume attachments.
self.project_member_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.other_project_member_context,
self.other_project_reader_context,
self.project_foo_context, self.project_reader_context
]
self.project_reader_context, self.project_foo_context]
self.project_reader_authorized_contexts = [
self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context]
self.project_admin_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context]
class VolumeAttachNoLegacyPolicyTest(VolumeAttachPolicyTest):
class VolumeAttachScopeTypeNoLegacyPolicyTest(VolumeAttachScopeTypePolicyTest):
"""Test os-volume-attachments APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to access
system_admin_or_owner APIs.
and no legacy deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
super(VolumeAttachNoLegacyPolicyTest, self).setUp()
super(VolumeAttachScopeTypeNoLegacyPolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check that system or projct admin or owner is able to
# list/create/show/delete the attached volume.
self.admin_or_owner_authorized_contexts = [
self.system_admin_context,
self.project_admin_context,
self.project_member_context
]
# Check that non-system and non-admin/owner is not able to
# list/create/show/delete the attached volume.
self.admin_or_owner_unauthorized_contexts = [
self.legacy_admin_context, self.system_member_context,
self.system_reader_context, self.project_reader_context,
self.project_foo_context, self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
# Check that admin is able to update the attached volume
self.admin_authorized_contexts = [
self.system_admin_context
]
# Check that non-admin is not able to update the attached
# volume
self.admin_unauthorized_contexts = [
self.legacy_admin_context, self.system_member_context,
self.system_reader_context, self.system_foo_context,
# With scope enable and no legacy rule, it will not allow
# system users and project admin/member/reader will be able to
# perform volume attachment operation on its own project.
self.project_reader_authorized_contexts = [
self.project_admin_context, self.project_member_context,
self.other_project_member_context,
self.other_project_reader_context,
self.project_foo_context, self.project_reader_context
]
self.reader_authorized_contexts = [
self.system_admin_context, self.system_reader_context,
self.system_member_context, self.project_admin_context,
self.project_reader_context, self.project_member_context
]
self.reader_unauthorized_contexts = [
self.legacy_admin_context, self.system_foo_context,
self.project_foo_context,
self.other_project_member_context,
self.other_project_reader_context,
]
self.project_reader_context]
self.project_member_authorized_contexts = [
self.project_admin_context, self.project_member_context]
class VolumesPolicyTest(base.BasePolicyTest):
@ -336,14 +289,23 @@ class VolumesPolicyTest(base.BasePolicyTest):
self.snapshot_ctlr = volumes_v21.SnapshotController()
self.req = fakes.HTTPRequest.blank('')
self.controller._translate_volume_summary_view = mock.MagicMock()
# Check that everyone is able to perform crud operations
# Everyone will be able to perform crud operations
# on volume and volume snapshots.
# NOTE: Nova cannot verify the volume/snapshot owner during nova policy
# enforcement so will be passing context's project_id as target to
# policy and always pass. If requester is not admin or owner
# of volume/snapshot then cinder will be returning the appropriate
# error.
self.everyone_authorized_contexts = [
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.system_foo_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
@ -352,94 +314,133 @@ class VolumesPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
self.everyone_unauthorized_contexts = []
@mock.patch('nova.volume.cinder.API.get_all')
def test_list_volumes_policy(self, mock_get):
rule_name = "os_compute_api:os-volumes"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.controller.index,
self.req)
rule_name = "os_compute_api:os-volumes:list"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.index,
self.req)
@mock.patch('nova.volume.cinder.API.get_all')
def test_list_detail_volumes_policy(self, mock_get):
rule_name = "os_compute_api:os-volumes"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.controller.detail,
self.req)
rule_name = "os_compute_api:os-volumes:detail"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.detail,
self.req)
@mock.patch('nova.volume.cinder.API.get')
def test_show_volume_policy(self, mock_get):
rule_name = "os_compute_api:os-volumes"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
rule_name = "os_compute_api:os-volumes:show"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
@mock.patch('nova.api.openstack.compute.volumes.'
'_translate_volume_detail_view')
@mock.patch('nova.volume.cinder.API.create')
def test_create_volumes_policy(self, mock_create, mock_view):
rule_name = "os_compute_api:os-volumes"
rule_name = "os_compute_api:os-volumes:create"
body = {"volume": {"size": 100,
"display_name": "Volume Test Name",
"display_description": "Volume Test Desc",
"availability_zone": "zone1:host1"}}
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.controller.create,
self.req, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.controller.create,
self.req, body=body)
@mock.patch('nova.volume.cinder.API.delete')
def test_delete_volume_policy(self, mock_delete):
rule_name = "os_compute_api:os-volumes"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.controller.delete,
self.req, uuids.fake_id)
rule_name = "os_compute_api:os-volumes:delete"
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.controller.delete,
self.req, uuids.fake_id)
@mock.patch('nova.volume.cinder.API.get_all_snapshots')
def test_list_snapshots_policy(self, mock_get):
rule_name = "os_compute_api:os-volumes"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.snapshot_ctlr.index,
self.req)
rule_name = "os_compute_api:os-volumes:snapshots:list"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.snapshot_ctlr.index,
self.req)
@mock.patch('nova.volume.cinder.API.get_all_snapshots')
def test_list_detail_snapshots_policy(self, mock_get):
rule_name = "os_compute_api:os-volumes"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.snapshot_ctlr.detail,
self.req)
rule_name = "os_compute_api:os-volumes:snapshots:detail"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.snapshot_ctlr.detail,
self.req)
@mock.patch('nova.volume.cinder.API.get_snapshot')
def test_show_snapshot_policy(self, mock_get):
rule_name = "os_compute_api:os-volumes"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.snapshot_ctlr.show,
self.req, uuids.fake_id)
rule_name = "os_compute_api:os-volumes:snapshots:show"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.snapshot_ctlr.show,
self.req, uuids.fake_id)
@mock.patch('nova.volume.cinder.API.create_snapshot')
def test_create_snapshot_policy(self, mock_create):
rule_name = "os_compute_api:os-volumes"
rule_name = "os_compute_api:os-volumes:snapshots:create"
body = {"snapshot": {"volume_id": uuids.fake_id}}
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.snapshot_ctlr.create,
self.req, body=body)
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.snapshot_ctlr.create,
self.req, body=body)
@mock.patch('nova.volume.cinder.API.delete_snapshot')
def test_delete_snapshot_policy(self, mock_delete):
rule_name = "os_compute_api:os-volumes"
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name, self.snapshot_ctlr.delete,
self.req, uuids.fake_id)
rule_name = "os_compute_api:os-volumes:snapshots:delete"
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.snapshot_ctlr.delete,
self.req, uuids.fake_id)
class VolumesNoLegacyNoScopePolicyTest(VolumesPolicyTest):
"""Test Volume APIs policies with no legacy deprecated rules
and no scope checks which means new defaults only.
"""
without_deprecated_rules = True
rules_without_deprecation = {
v_policies.POLICY_NAME % 'list':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'detail':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'show':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'create':
base_policy.PROJECT_MEMBER,
v_policies.POLICY_NAME % 'delete':
base_policy.PROJECT_MEMBER,
v_policies.POLICY_NAME % 'snapshots:list':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'snapshots:detail':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'snapshots:delete':
base_policy.PROJECT_MEMBER,
v_policies.POLICY_NAME % 'snapshots:create':
base_policy.PROJECT_MEMBER,
v_policies.POLICY_NAME % 'snapshots:show':
base_policy.PROJECT_READER,
}
def setUp(self):
super(VolumesNoLegacyNoScopePolicyTest, self).setUp()
# With no legacy, project other roles like foo will not be able
# to operate on volume and snapshot.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.system_member_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context,
self.other_project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context
]
class VolumesScopeTypePolicyTest(VolumesPolicyTest):
@ -456,3 +457,65 @@ class VolumesScopeTypePolicyTest(VolumesPolicyTest):
def setUp(self):
super(VolumesScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With scope enabled, system users will not be able to
# operate on volume and snapshot.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_reader_context,
self.other_project_member_context
]
class VolumesScopeTypeNoLegacyPolicyTest(VolumesScopeTypePolicyTest):
"""Test Volume APIs policies with system scope enabled,
and no legacy deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
v_policies.POLICY_NAME % 'list':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'detail':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'show':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'create':
base_policy.PROJECT_MEMBER,
v_policies.POLICY_NAME % 'delete':
base_policy.PROJECT_MEMBER,
v_policies.POLICY_NAME % 'snapshots:list':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'snapshots:detail':
base_policy.PROJECT_READER,
v_policies.POLICY_NAME % 'snapshots:delete':
base_policy.PROJECT_MEMBER,
v_policies.POLICY_NAME % 'snapshots:create':
base_policy.PROJECT_MEMBER,
v_policies.POLICY_NAME % 'snapshots:show':
base_policy.PROJECT_READER,
}
def setUp(self):
super(VolumesScopeTypeNoLegacyPolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# With no legacy and scope enabled, system users and project
# other roles like foo will not be able to operate on volume
# and snapshot.
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context,
self.other_project_member_context
]
self.project_reader_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.other_project_reader_context,
self.other_project_member_context
]