Merge "Add new default roles in hosts policies"
This commit is contained in:
commit
09ed4c21db
|
@ -71,7 +71,8 @@ class HostController(wsgi.Controller):
|
|||
|
||||
"""
|
||||
context = req.environ['nova.context']
|
||||
context.can(hosts_policies.BASE_POLICY_NAME)
|
||||
context.can(hosts_policies.POLICY_NAME % 'list',
|
||||
target={})
|
||||
filters = {'disabled': False}
|
||||
zone = req.GET.get('zone', None)
|
||||
if zone:
|
||||
|
@ -108,7 +109,8 @@ class HostController(wsgi.Controller):
|
|||
return val == "enable"
|
||||
|
||||
context = req.environ['nova.context']
|
||||
context.can(hosts_policies.BASE_POLICY_NAME)
|
||||
context.can(hosts_policies.POLICY_NAME % 'update',
|
||||
target={})
|
||||
# See what the user wants to 'update'
|
||||
status = body.get('status')
|
||||
maint_mode = body.get('maintenance_mode')
|
||||
|
@ -168,7 +170,6 @@ class HostController(wsgi.Controller):
|
|||
def _host_power_action(self, req, host_name, action):
|
||||
"""Reboots, shuts down or powers up the host."""
|
||||
context = req.environ['nova.context']
|
||||
context.can(hosts_policies.BASE_POLICY_NAME)
|
||||
try:
|
||||
result = self.api.host_power_action(context, host_name, action)
|
||||
except NotImplementedError:
|
||||
|
@ -182,16 +183,25 @@ class HostController(wsgi.Controller):
|
|||
@wsgi.Controller.api_version("2.1", "2.42")
|
||||
@wsgi.expected_errors((400, 404, 501))
|
||||
def startup(self, req, id):
|
||||
context = req.environ['nova.context']
|
||||
context.can(hosts_policies.POLICY_NAME % 'start',
|
||||
target={})
|
||||
return self._host_power_action(req, host_name=id, action="startup")
|
||||
|
||||
@wsgi.Controller.api_version("2.1", "2.42")
|
||||
@wsgi.expected_errors((400, 404, 501))
|
||||
def shutdown(self, req, id):
|
||||
context = req.environ['nova.context']
|
||||
context.can(hosts_policies.POLICY_NAME % 'shutdown',
|
||||
target={})
|
||||
return self._host_power_action(req, host_name=id, action="shutdown")
|
||||
|
||||
@wsgi.Controller.api_version("2.1", "2.42")
|
||||
@wsgi.expected_errors((400, 404, 501))
|
||||
def reboot(self, req, id):
|
||||
context = req.environ['nova.context']
|
||||
context.can(hosts_policies.POLICY_NAME % 'reboot',
|
||||
target={})
|
||||
return self._host_power_action(req, host_name=id, action="reboot")
|
||||
|
||||
@staticmethod
|
||||
|
@ -257,7 +267,8 @@ class HostController(wsgi.Controller):
|
|||
'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}
|
||||
"""
|
||||
context = req.environ['nova.context']
|
||||
context.can(hosts_policies.BASE_POLICY_NAME)
|
||||
context.can(hosts_policies.POLICY_NAME % 'show',
|
||||
target={})
|
||||
host_name = id
|
||||
try:
|
||||
mapping = objects.HostMapping.get_by_host(context, host_name)
|
||||
|
|
|
@ -20,41 +20,116 @@ from nova.policies import base
|
|||
|
||||
BASE_POLICY_NAME = 'os_compute_api:os-hosts'
|
||||
|
||||
POLICY_NAME = 'os_compute_api:os-hosts:%s'
|
||||
|
||||
DEPRECATED_POLICY = policy.DeprecatedRule(
|
||||
BASE_POLICY_NAME,
|
||||
base.RULE_ADMIN_API,
|
||||
)
|
||||
|
||||
DEPRECATED_REASON = """
|
||||
Nova API policies are introducing new default roles with scope_type
|
||||
capabilities. Old policies are deprecated and silently going to be ignored
|
||||
in nova 23.0.0 release.
|
||||
"""
|
||||
|
||||
hosts_policies = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=BASE_POLICY_NAME,
|
||||
check_str=base.RULE_ADMIN_API,
|
||||
description="""List, show and manage physical hosts.
|
||||
name=POLICY_NAME % 'list',
|
||||
check_str=base.SYSTEM_READER,
|
||||
description="""List physical hosts.
|
||||
|
||||
These APIs are all deprecated in favor of os-hypervisors and os-services.""",
|
||||
This API is deprecated in favor of os-hypervisors and os-services.""",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/os-hosts'
|
||||
},
|
||||
],
|
||||
scope_types=['system'],
|
||||
deprecated_rule=DEPRECATED_POLICY,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since='22.0.0'),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_NAME % 'show',
|
||||
check_str=base.SYSTEM_READER,
|
||||
description="""Show physical host.
|
||||
|
||||
This API is deprecated in favor of os-hypervisors and os-services.""",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/os-hosts/{host_name}'
|
||||
},
|
||||
}
|
||||
],
|
||||
scope_types=['system'],
|
||||
deprecated_rule=DEPRECATED_POLICY,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since='22.0.0'),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_NAME % 'update',
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
description="""Update physical host.
|
||||
|
||||
This API is deprecated in favor of os-hypervisors and os-services.""",
|
||||
operations=[
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/os-hosts/{host_name}'
|
||||
},
|
||||
],
|
||||
scope_types=['system'],
|
||||
deprecated_rule=DEPRECATED_POLICY,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since='22.0.0'),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_NAME % 'reboot',
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
description="""Reboot physical host.
|
||||
|
||||
This API is deprecated in favor of os-hypervisors and os-services.""",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/os-hosts/{host_name}/reboot'
|
||||
},
|
||||
],
|
||||
scope_types=['system'],
|
||||
deprecated_rule=DEPRECATED_POLICY,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since='22.0.0'),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_NAME % 'shutdown',
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
description="""Shutdown physical host.
|
||||
|
||||
This API is deprecated in favor of os-hypervisors and os-services.""",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/os-hosts/{host_name}/shutdown'
|
||||
},
|
||||
],
|
||||
scope_types=['system'],
|
||||
deprecated_rule=DEPRECATED_POLICY,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since='22.0.0'),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_NAME % 'start',
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
description="""Start physical host.
|
||||
|
||||
This API is deprecated in favor of os-hypervisors and os-services.""",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/os-hosts/{host_name}/startup'
|
||||
}
|
||||
],
|
||||
scope_types=['system']),
|
||||
scope_types=['system'],
|
||||
deprecated_rule=DEPRECATED_POLICY,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since='22.0.0'),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -105,6 +105,12 @@ policy_data = """
|
|||
"os_compute_api:os-keypairs:create": "",
|
||||
"os_compute_api:os-keypairs:show": "",
|
||||
"os_compute_api:os-keypairs:delete": "",
|
||||
"os_compute_api:os-hosts:list": "",
|
||||
"os_compute_api:os-hosts:show": "",
|
||||
"os_compute_api:os-hosts:update": "",
|
||||
"os_compute_api:os-hosts:reboot": "",
|
||||
"os_compute_api:os-hosts:shutdown": "",
|
||||
"os_compute_api:os-hosts:start": "",
|
||||
"os_compute_api:os-hypervisors:list": "",
|
||||
"os_compute_api:os-hypervisors:list-detail": "",
|
||||
"os_compute_api:os-hypervisors:statistics": "",
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
import mock
|
||||
|
||||
from nova.api.openstack.compute import hosts
|
||||
from nova.policies import base as base_policy
|
||||
from nova.policies import hosts as policies
|
||||
from nova.tests.unit.api.openstack import fakes
|
||||
from nova.tests.unit.policies import base
|
||||
|
@ -32,22 +33,34 @@ class HostsPolicyTest(base.BasePolicyTest):
|
|||
self.req = fakes.HTTPRequest.blank('')
|
||||
|
||||
# Check that admin is able to perform operations on hosts.
|
||||
self.admin_authorized_contexts = [
|
||||
self.system_admin_authorized_contexts = [
|
||||
self.system_admin_context, self.legacy_admin_context,
|
||||
self.project_admin_context]
|
||||
# Check that non-admin is not able to perform operations
|
||||
# on hosts.
|
||||
self.admin_unauthorized_contexts = [
|
||||
self.system_admin_unauthorized_contexts = [
|
||||
self.system_member_context, self.system_reader_context,
|
||||
self.system_foo_context, self.other_project_member_context,
|
||||
self.project_foo_context, self.project_member_context,
|
||||
self.project_reader_context, self.other_project_reader_context]
|
||||
self.project_reader_context, self.other_project_reader_context
|
||||
]
|
||||
self.system_reader_authorized_contexts = [
|
||||
self.system_admin_context, self.system_member_context,
|
||||
self.system_reader_context, self.legacy_admin_context,
|
||||
self.project_admin_context
|
||||
]
|
||||
self.system_reader_unauthorized_contexts = [
|
||||
self.project_foo_context, self.system_foo_context,
|
||||
self.project_member_context, self.project_reader_context,
|
||||
self.other_project_member_context,
|
||||
self.other_project_reader_context
|
||||
]
|
||||
|
||||
@mock.patch('nova.compute.api.HostAPI.service_get_all')
|
||||
def test_list_hosts_policy(self, mock_get):
|
||||
rule_name = policies.BASE_POLICY_NAME
|
||||
self.common_policy_check(self.admin_authorized_contexts,
|
||||
self.admin_unauthorized_contexts,
|
||||
rule_name = policies.POLICY_NAME % 'list'
|
||||
self.common_policy_check(self.system_reader_authorized_contexts,
|
||||
self.system_reader_unauthorized_contexts,
|
||||
rule_name, self.controller.index,
|
||||
self.req)
|
||||
|
||||
|
@ -57,40 +70,40 @@ class HostsPolicyTest(base.BasePolicyTest):
|
|||
'get_first_node_by_host_for_old_compat')
|
||||
@mock.patch('nova.compute.api.HostAPI.instance_get_all_by_host')
|
||||
def test_show_host_policy(self, mock_get, mock_node, mock_map, mock_set):
|
||||
rule_name = policies.BASE_POLICY_NAME
|
||||
self.common_policy_check(self.admin_authorized_contexts,
|
||||
self.admin_unauthorized_contexts,
|
||||
rule_name = policies.POLICY_NAME % 'show'
|
||||
self.common_policy_check(self.system_reader_authorized_contexts,
|
||||
self.system_reader_unauthorized_contexts,
|
||||
rule_name, self.controller.show,
|
||||
self.req, 11111)
|
||||
|
||||
def test_update_host_policy(self):
|
||||
rule_name = policies.BASE_POLICY_NAME
|
||||
self.common_policy_check(self.admin_authorized_contexts,
|
||||
self.admin_unauthorized_contexts,
|
||||
rule_name = policies.POLICY_NAME % 'update'
|
||||
self.common_policy_check(self.system_admin_authorized_contexts,
|
||||
self.system_admin_unauthorized_contexts,
|
||||
rule_name, self.controller.update,
|
||||
self.req, 11111, body={})
|
||||
|
||||
@mock.patch('nova.compute.api.HostAPI.host_power_action')
|
||||
def test_reboot_host_policy(self, mock_action):
|
||||
rule_name = policies.BASE_POLICY_NAME
|
||||
self.common_policy_check(self.admin_authorized_contexts,
|
||||
self.admin_unauthorized_contexts,
|
||||
rule_name = policies.POLICY_NAME % 'reboot'
|
||||
self.common_policy_check(self.system_admin_authorized_contexts,
|
||||
self.system_admin_unauthorized_contexts,
|
||||
rule_name, self.controller.reboot,
|
||||
self.req, 11111)
|
||||
|
||||
@mock.patch('nova.compute.api.HostAPI.host_power_action')
|
||||
def test_shutdown_host_policy(self, mock_action):
|
||||
rule_name = policies.BASE_POLICY_NAME
|
||||
self.common_policy_check(self.admin_authorized_contexts,
|
||||
self.admin_unauthorized_contexts,
|
||||
rule_name = policies.POLICY_NAME % 'shutdown'
|
||||
self.common_policy_check(self.system_admin_authorized_contexts,
|
||||
self.system_admin_unauthorized_contexts,
|
||||
rule_name, self.controller.shutdown,
|
||||
self.req, 11111)
|
||||
|
||||
@mock.patch('nova.compute.api.HostAPI.host_power_action')
|
||||
def test_startup_host_policy(self, mock_action):
|
||||
rule_name = policies.BASE_POLICY_NAME
|
||||
self.common_policy_check(self.admin_authorized_contexts,
|
||||
self.admin_unauthorized_contexts,
|
||||
rule_name = policies.POLICY_NAME % 'start'
|
||||
self.common_policy_check(self.system_admin_authorized_contexts,
|
||||
self.system_admin_unauthorized_contexts,
|
||||
rule_name, self.controller.startup,
|
||||
self.req, 11111)
|
||||
|
||||
|
@ -110,13 +123,71 @@ class HostsScopeTypePolicyTest(HostsPolicyTest):
|
|||
self.flags(enforce_scope=True, group="oslo_policy")
|
||||
|
||||
# Check that system admin is able to perform operations on hosts.
|
||||
self.admin_authorized_contexts = [
|
||||
self.system_admin_authorized_contexts = [
|
||||
self.system_admin_context]
|
||||
# Check that system non-admin is not able to perform operations
|
||||
# on hosts.
|
||||
self.admin_unauthorized_contexts = [
|
||||
self.system_admin_unauthorized_contexts = [
|
||||
self.legacy_admin_context, self.project_admin_context,
|
||||
self.system_member_context, self.system_reader_context,
|
||||
self.system_foo_context, self.other_project_member_context,
|
||||
self.project_foo_context, self.project_member_context,
|
||||
self.project_reader_context, self.other_project_reader_context]
|
||||
self.project_reader_context, self.other_project_reader_context
|
||||
]
|
||||
self.system_reader_authorized_contexts = [
|
||||
self.system_admin_context, self.system_member_context,
|
||||
self.system_reader_context
|
||||
]
|
||||
self.system_reader_unauthorized_contexts = [
|
||||
self.legacy_admin_context, self.project_foo_context,
|
||||
self.system_foo_context, self.project_admin_context,
|
||||
self.project_member_context, self.project_reader_context,
|
||||
self.other_project_member_context,
|
||||
self.other_project_reader_context
|
||||
]
|
||||
|
||||
|
||||
class HostsNoLegacyPolicyTest(HostsScopeTypePolicyTest):
|
||||
"""Test Hosts APIs policies with system scope enabled,
|
||||
and no more deprecated rules that allow the legacy admin API to
|
||||
access system_admin_or_owner APIs.
|
||||
"""
|
||||
without_deprecated_rules = True
|
||||
rules_without_deprecation = {
|
||||
policies.POLICY_NAME % 'list':
|
||||
base_policy.SYSTEM_READER,
|
||||
policies.POLICY_NAME % 'show':
|
||||
base_policy.SYSTEM_READER,
|
||||
policies.POLICY_NAME % 'update':
|
||||
base_policy.SYSTEM_ADMIN,
|
||||
policies.POLICY_NAME % 'reboot':
|
||||
base_policy.SYSTEM_ADMIN,
|
||||
policies.POLICY_NAME % 'shutdown':
|
||||
base_policy.SYSTEM_ADMIN,
|
||||
policies.POLICY_NAME % 'startup':
|
||||
base_policy.SYSTEM_ADMIN}
|
||||
|
||||
def setUp(self):
|
||||
super(HostsNoLegacyPolicyTest, self).setUp()
|
||||
|
||||
self.system_reader_authorized_contexts = [
|
||||
self.system_admin_context, self.system_member_context,
|
||||
self.system_reader_context
|
||||
]
|
||||
self.system_reader_unauthorized_contexts = [
|
||||
self.legacy_admin_context, self.project_foo_context,
|
||||
self.system_foo_context, self.project_admin_context,
|
||||
self.project_member_context, self.project_reader_context,
|
||||
self.other_project_member_context,
|
||||
self.other_project_reader_context
|
||||
]
|
||||
self.system_admin_authorized_contexts = [
|
||||
self.system_admin_context
|
||||
]
|
||||
self.system_admin_unauthorized_contexts = [
|
||||
self.system_member_context, self.system_reader_context,
|
||||
self.project_admin_context, self.project_member_context,
|
||||
self.legacy_admin_context, self.other_project_member_context,
|
||||
self.project_reader_context, self.project_foo_context,
|
||||
self.system_foo_context, self.other_project_reader_context
|
||||
]
|
||||
|
|
|
@ -348,7 +348,10 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
|
|||
"os_compute_api:os-flavor-manage:create",
|
||||
"os_compute_api:os-flavor-manage:update",
|
||||
"os_compute_api:os-flavor-manage:delete",
|
||||
"os_compute_api:os-hosts",
|
||||
"os_compute_api:os-hosts:update",
|
||||
"os_compute_api:os-hosts:reboot",
|
||||
"os_compute_api:os-hosts:shutdown",
|
||||
"os_compute_api:os-hosts:start",
|
||||
"os_compute_api:os-instance-actions:events",
|
||||
"os_compute_api:os-lock-server:unlock:unlock_override",
|
||||
"os_compute_api:os-migrate-server:migrate",
|
||||
|
@ -475,6 +478,8 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
|
|||
"os_compute_api:os-instance-usage-audit-log:list",
|
||||
"os_compute_api:os-instance-usage-audit-log:show",
|
||||
"os_compute_api:os-agents:list",
|
||||
"os_compute_api:os-hosts:list",
|
||||
"os_compute_api:os-hosts:show",
|
||||
"os_compute_api:os-hypervisors:list",
|
||||
"os_compute_api:os-hypervisors:list-detail",
|
||||
"os_compute_api:os-hypervisors:show",
|
||||
|
|
Loading…
Reference in New Issue