Fix server actions to be system and project scoped

This is follow up for review comment:
- https://review.opendev.org/#/c/716130/1/nova/policies/migrate_server.py@46

Let's keep server actions to be both scoped but default them
to SYSTEM-ADMIN/READER and pass the project_id as target. That
way if operator want to enable those policy for project role they
should be able to do.

Also update the defaults for rescue action which found during
audit.

Partial implement blueprint policy-defaults-refresh

Change-Id: If9864ed09d7f604edb8219693dd567638c746456
This commit is contained in:
Ghanshyam Mann
2020-04-14 17:37:21 -05:00
parent 07939afe3e
commit c7bfc323bc
9 changed files with 35 additions and 35 deletions

View File

@@ -40,8 +40,9 @@ class AdminActionsController(wsgi.Controller):
def _reset_network(self, req, id, body):
"""Permit admins to reset networking on a server."""
context = req.environ['nova.context']
context.can(aa_policies.POLICY_ROOT % 'reset_network', target={})
instance = common.get_instance(self.compute_api, context, id)
context.can(aa_policies.POLICY_ROOT % 'reset_network',
target={'project_id': instance.project_id})
try:
self.compute_api.reset_network(context, instance)
except exception.InstanceIsLocked as e:
@@ -53,8 +54,9 @@ class AdminActionsController(wsgi.Controller):
def _inject_network_info(self, req, id, body):
"""Permit admins to inject network info into a server."""
context = req.environ['nova.context']
context.can(aa_policies.POLICY_ROOT % 'inject_network_info', target={})
instance = common.get_instance(self.compute_api, context, id)
context.can(aa_policies.POLICY_ROOT % 'inject_network_info',
target={'project_id': instance.project_id})
try:
self.compute_api.inject_network_info(context, instance)
except exception.InstanceIsLocked as e:
@@ -67,12 +69,13 @@ class AdminActionsController(wsgi.Controller):
def _reset_state(self, req, id, body):
"""Permit admins to reset the state of a server."""
context = req.environ["nova.context"]
context.can(aa_policies.POLICY_ROOT % 'reset_state', target={})
instance = common.get_instance(self.compute_api, context, id)
context.can(aa_policies.POLICY_ROOT % 'reset_state',
target={'project_id': instance.project_id})
# Identify the desired state from the body
state = state_map[body["os-resetState"]["state"]]
instance = common.get_instance(self.compute_api, context, id)
instance.vm_state = state
instance.task_state = None
instance.save(admin_state_reset=True)

View File

@@ -32,7 +32,7 @@ admin_actions_policies = [
'path': '/servers/{server_id}/action (os-resetState)'
}
],
scope_types=['system']),
scope_types=['system', 'project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'inject_network_info',
check_str=base.SYSTEM_ADMIN,
@@ -43,7 +43,7 @@ admin_actions_policies = [
'path': '/servers/{server_id}/action (injectNetworkInfo)'
}
],
scope_types=['system']),
scope_types=['system', 'project']),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'reset_network',
check_str=base.SYSTEM_ADMIN,
@@ -54,7 +54,7 @@ admin_actions_policies = [
'path': '/servers/{server_id}/action (resetNetwork)'
}
],
scope_types=['system'])
scope_types=['system', 'project'])
]

View File

@@ -32,7 +32,7 @@ evacuate_policies = [
'method': 'POST'
}
],
scope_types=['system']),
scope_types=['system', 'project']),
]

View File

@@ -53,7 +53,7 @@ but in the other hand it might leak information about the deployment
'path': '/servers/{server_id}/os-instance-actions/{request_id}'
}
],
scope_types=['system']),
scope_types=['system', 'project']),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'events',
check_str=base.SYSTEM_READER,
@@ -70,7 +70,7 @@ passes, the name of the host.""",
'path': '/servers/{server_id}/os-instance-actions/{request_id}'
}
],
scope_types=['system']),
scope_types=['system', 'project']),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,

View File

@@ -35,7 +35,7 @@ for unrescue and keeping old policy for rescue.
rescue_policies = [
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME,
check_str=base.RULE_ADMIN_OR_OWNER,
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
description="Rescue a server",
operations=[
{
@@ -46,7 +46,7 @@ rescue_policies = [
scope_types=['system', 'project']),
policy.DocumentedRuleDefault(
name=UNRESCUE_POLICY_NAME,
check_str=base.RULE_ADMIN_OR_OWNER,
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
description="Unrescue a server",
operations=[
{

View File

@@ -44,6 +44,7 @@ class ResetStateTestsV21(test.NoDBTestCase):
instance.uuid = self.uuid
instance.vm_state = 'fake'
instance.task_state = 'fake'
instance.project_id = self.context.project_id
instance.obj_reset_changes()
return instance

View File

@@ -98,6 +98,15 @@ class AdminActionsScopeTypePolicyTest(AdminActionsPolicyTest):
super(AdminActionsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
class AdminActionsNoLegacyPolicyTest(AdminActionsScopeTypePolicyTest):
"""Test Admin Actions APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
def setUp(self):
super(AdminActionsScopeTypePolicyTest, self).setUp()
# Check that system admin is able to perform the system level actions
# on server.
self.admin_authorized_contexts = [

View File

@@ -130,7 +130,16 @@ class EvacuateScopeTypePolicyTest(EvacuatePolicyTest):
super(EvacuateScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
self.user_req.environ['nova.context'].system_scope = 'all'
class EvacuateNoLegacyPolicyTest(EvacuateScopeTypePolicyTest):
"""Test Evacuate APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
"""
without_deprecated_rules = True
def setUp(self):
super(EvacuateNoLegacyPolicyTest, self).setUp()
# Check that system admin is able to evacuate server.
self.admin_authorized_contexts = [
@@ -144,11 +153,3 @@ class EvacuateScopeTypePolicyTest(EvacuatePolicyTest):
self.other_project_member_context,
self.project_foo_context, self.project_reader_context
]
class EvacuateNoLegacyPolicyTest(EvacuateScopeTypePolicyTest):
"""Test Evacuate APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system APIs.
"""
without_deprecated_rules = True

View File

@@ -219,20 +219,6 @@ class InstanceActionsScopeTypePolicyTest(InstanceActionsPolicyTest):
super(InstanceActionsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
# Check that system reader is able to get the
# instance action events
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 instance action events
self.system_reader_unauthorized_contexts = [
self.system_foo_context, self.legacy_admin_context,
self.project_admin_context, self.project_member_context,
self.other_project_member_context,
self.project_foo_context, self.project_reader_context
]
@mock.patch('nova.objects.InstanceActionEventList.get_by_action')
@mock.patch('nova.objects.InstanceAction.get_by_request_id')
def test_show_instance_action_policy_with_show_details(