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:
@@ -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)
|
||||
|
||||
@@ -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'])
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ evacuate_policies = [
|
||||
'method': 'POST'
|
||||
}
|
||||
],
|
||||
scope_types=['system']),
|
||||
scope_types=['system', 'project']),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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=[
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user