Browse Source

Merge "Add new default roles in os-hypervisors policies"

tags/21.0.0.0rc1
Zuul 3 months ago
committed by Gerrit Code Review
parent
commit
eb6b71d5db
6 changed files with 171 additions and 113 deletions
  1. +9
    -6
      nova/api/openstack/compute/hypervisors.py
  2. +80
    -14
      nova/policies/hypervisors.py
  3. +0
    -52
      nova/tests/unit/api/openstack/compute/test_hypervisors.py
  4. +7
    -0
      nova/tests/unit/fake_policy.py
  5. +68
    -40
      nova/tests/unit/policies/test_hypervisors.py
  6. +7
    -1
      nova/tests/unit/test_policy.py

+ 9
- 6
nova/api/openstack/compute/hypervisors.py View File

@@ -122,7 +122,6 @@ class HypervisorsController(wsgi.Controller):
:param links: If True, return links in the response for paging.
"""
context = req.environ['nova.context']
context.can(hv_policies.BASE_POLICY_NAME)

# The 2.53 microversion moves the search and servers routes into
# GET /os-hypervisors and GET /os-hypervisors/detail with query
@@ -221,6 +220,8 @@ class HypervisorsController(wsgi.Controller):
return self._index(req)

def _index(self, req, limit=None, marker=None, links=False):
context = req.environ['nova.context']
context.can(hv_policies.BASE_POLICY_NAME % 'list')
return self._get_hypervisors(req, detail=False, limit=limit,
marker=marker, links=links)

@@ -251,6 +252,8 @@ class HypervisorsController(wsgi.Controller):
return self._detail(req)

def _detail(self, req, limit=None, marker=None, links=False):
context = req.environ['nova.context']
context.can(hv_policies.BASE_POLICY_NAME % 'list-detail')
return self._get_hypervisors(req, detail=True, limit=limit,
marker=marker, links=links)

@@ -302,7 +305,7 @@ class HypervisorsController(wsgi.Controller):

def _show(self, req, id, with_servers=False):
context = req.environ['nova.context']
context.can(hv_policies.BASE_POLICY_NAME)
context.can(hv_policies.BASE_POLICY_NAME % 'show')

self._validate_id(req, id)

@@ -324,7 +327,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.expected_errors((400, 404, 501))
def uptime(self, req, id):
context = req.environ['nova.context']
context.can(hv_policies.BASE_POLICY_NAME)
context.can(hv_policies.BASE_POLICY_NAME % 'uptime')

self._validate_id(req, id)

@@ -362,7 +365,7 @@ class HypervisorsController(wsgi.Controller):
index and detail methods.
"""
context = req.environ['nova.context']
context.can(hv_policies.BASE_POLICY_NAME)
context.can(hv_policies.BASE_POLICY_NAME % 'search')
hypervisors = self._get_compute_nodes_by_name_pattern(context, id)
try:
return dict(hypervisors=[
@@ -386,7 +389,7 @@ class HypervisorsController(wsgi.Controller):
GET /os-hypervisors index and detail methods.
"""
context = req.environ['nova.context']
context.can(hv_policies.BASE_POLICY_NAME)
context.can(hv_policies.BASE_POLICY_NAME % 'servers')
compute_nodes = self._get_compute_nodes_by_name_pattern(context, id)
hypervisors = []
for compute_node in compute_nodes:
@@ -405,6 +408,6 @@ class HypervisorsController(wsgi.Controller):
@wsgi.expected_errors(())
def statistics(self, req):
context = req.environ['nova.context']
context.can(hv_policies.BASE_POLICY_NAME)
context.can(hv_policies.BASE_POLICY_NAME % 'statistics')
stats = self.host_api.compute_node_statistics(context)
return dict(hypervisor_statistics=stats)

+ 80
- 14
nova/policies/hypervisors.py View File

@@ -18,55 +18,121 @@ from oslo_policy import policy
from nova.policies import base


BASE_POLICY_NAME = 'os_compute_api:os-hypervisors'
BASE_POLICY_NAME = 'os_compute_api:os-hypervisors:%s'

DEPRECATED_POLICY = policy.DeprecatedRule(
'os_compute_api:os-hypervisors',
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.
"""

hypervisors_policies = [
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME,
check_str=base.RULE_ADMIN_API,
description="""Policy rule for hypervisor related APIs.

This rule will be checked for the following APIs:

List all hypervisors, list all hypervisors with details, show
summary statistics for all hypervisors over all compute nodes,
show details for a hypervisor, show the uptime of a hypervisor,
search hypervisor by hypervisor_hostname pattern and list all
servers on hypervisors that can match the provided
hypervisor_hostname pattern.""",
name=BASE_POLICY_NAME % 'list',
check_str=base.SYSTEM_READER,
description="List all hypervisors.",
operations=[
{
'path': '/os-hypervisors',
'method': 'GET'
},
],
scope_types=['system'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='21.0.0'),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'list-detail',
check_str=base.SYSTEM_READER,
description="List all hypervisors with details",
operations=[
{
'path': '/os-hypervisors/details',
'method': 'GET'
},
],
scope_types=['system'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='21.0.0'),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'statistics',
check_str=base.SYSTEM_READER,
description="Show summary statistics for all hypervisors "
"over all compute nodes.",
operations=[
{
'path': '/os-hypervisors/statistics',
'method': 'GET'
},
],
scope_types=['system'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='21.0.0'),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'show',
check_str=base.SYSTEM_READER,
description="Show details for a hypervisor.",
operations=[
{
'path': '/os-hypervisors/{hypervisor_id}',
'method': 'GET'
},
],
scope_types=['system'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='21.0.0'),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'uptime',
check_str=base.SYSTEM_READER,
description="Show the uptime of a hypervisor.",
operations=[
{
'path': '/os-hypervisors/{hypervisor_id}/uptime',
'method': 'GET'
},
],
scope_types=['system'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='21.0.0'),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'search',
check_str=base.SYSTEM_READER,
description="Search hypervisor by hypervisor_hostname pattern.",
operations=[
{
'path': '/os-hypervisors/{hypervisor_hostname_pattern}/search',
'method': 'GET'
},
],
scope_types=['system'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='21.0.0'),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'servers',
check_str=base.SYSTEM_READER,
description="List all servers on hypervisors that can match "
"the provided hypervisor_hostname pattern.",
operations=[
{
'path':
'/os-hypervisors/{hypervisor_hostname_pattern}/servers',
'method': 'GET'
}
],
scope_types=['system']
scope_types=['system'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='21.0.0',
),
]



+ 0
- 52
nova/tests/unit/api/openstack/compute/test_hypervisors.py View File

@@ -236,7 +236,6 @@ class HypervisorsTestV21(test.NoDBTestCase):
def setUp(self):
super(HypervisorsTestV21, self).setUp()
self._set_up_controller()
self.rule_hyp_show = "os_compute_api:os-hypervisors"

host_api = self.controller.host_api
host_api.compute_node_get_all = mock.MagicMock(
@@ -306,11 +305,6 @@ class HypervisorsTestV21(test.NoDBTestCase):

self.assertEqual(dict(hypervisors=self.INDEX_HYPER_DICTS), result)

def test_index_non_admin(self):
req = self._get_request(False)
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.index, req)

def test_index_compute_host_not_found(self):
"""Tests that if a service is deleted but the compute node is not we
don't fail when listing hypervisors.
@@ -387,11 +381,6 @@ class HypervisorsTestV21(test.NoDBTestCase):

self.assertEqual(dict(hypervisors=self.DETAIL_HYPERS_DICTS), result)

def test_detail_non_admin(self):
req = self._get_request(False)
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.detail, req)

def test_detail_compute_host_not_found(self):
"""Tests that if a service is deleted but the compute node is not we
don't fail when listing hypervisors.
@@ -514,12 +503,6 @@ class HypervisorsTestV21(test.NoDBTestCase):

self.assertEqual(dict(hypervisor=self.DETAIL_HYPERS_DICTS[0]), result)

def test_show_non_admin(self):
req = self._get_request(False)
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.show, req,
self._get_hyper_id())

def test_uptime_noid(self):
req = self._get_request(True)
hyper_id = uuids.hyper3 if self.expect_uuid_for_id else '3'
@@ -553,12 +536,6 @@ class HypervisorsTestV21(test.NoDBTestCase):
req = self._get_request(True)
self.assertRaises(exc.HTTPNotFound, self.controller.uptime, req, 'abc')

def test_uptime_non_admin(self):
req = self._get_request(False)
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.uptime, req,
self.TEST_HYPERS_OBJ[0].id)

def test_uptime_hypervisor_down(self):
with mock.patch.object(self.controller.host_api, 'get_host_uptime',
side_effect=exception.ComputeServiceUnavailable(host='dummy')
@@ -603,12 +580,6 @@ class HypervisorsTestV21(test.NoDBTestCase):

self.assertEqual(dict(hypervisors=self.INDEX_HYPER_DICTS), result)

def test_search_non_admin(self):
req = self._get_request(False)
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.search, req,
self.TEST_HYPERS_OBJ[0].id)

def test_search_non_exist(self):
with mock.patch.object(self.controller.host_api,
'compute_node_search_by_hypervisor',
@@ -673,12 +644,6 @@ class HypervisorsTestV21(test.NoDBTestCase):
req, '115')
self.assertEqual(1, mock_node_search.call_count)

def test_servers_non_admin(self):
req = self._get_request(False)
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.servers, req,
self.TEST_HYPERS_OBJ[0].id)

def test_servers_with_non_integer_hypervisor_id(self):
with mock.patch.object(self.controller.host_api,
'compute_node_search_by_hypervisor',
@@ -716,11 +681,6 @@ class HypervisorsTestV21(test.NoDBTestCase):
running_vms=4,
disk_available_least=200)), result)

def test_statistics_non_admin(self):
req = self._get_request(False)
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.statistics, req)


class HypervisorsTestV228(HypervisorsTestV21):
api_version = '2.28'
@@ -1080,12 +1040,6 @@ class HypervisorsTestV253(HypervisorsTestV252):
self.assertRaises(exc.HTTPNotFound, self.controller.index, req)
s.assert_called_once_with(req.environ['nova.context'], 'shenzhen')

def test_servers_non_admin(self):
"""There is no reason to test this for 2.53 since the
/os-hypervisors/servers route is deprecated.
"""
pass

def test_servers_non_id(self):
"""There is no reason to test this for 2.53 since the
/os-hypervisors/servers route is deprecated.
@@ -1164,12 +1118,6 @@ class HypervisorsTestV253(HypervisorsTestV252):
"""
pass

def test_search_non_admin(self):
"""There is no reason to test this for 2.53 since the
/os-hypervisors/search route is deprecated.
"""
pass

def test_search_unmapped(self):
"""This is already tested with test_index_compute_host_not_mapped."""
pass


+ 7
- 0
nova/tests/unit/fake_policy.py View File

@@ -58,6 +58,13 @@ policy_data = """
"os_compute_api:os-instance-actions:events:details": "",
"os_compute_api:os-instance-usage-audit-log:list": "",
"os_compute_api:os-instance-usage-audit-log:show": "",
"os_compute_api:os-hypervisors:list": "",
"os_compute_api:os-hypervisors:list-detail": "",
"os_compute_api:os-hypervisors:statistics": "",
"os_compute_api:os-hypervisors:show": "",
"os_compute_api:os-hypervisors:uptime": "",
"os_compute_api:os-hypervisors:search": "",
"os_compute_api:os-hypervisors:servers": "",

"os_compute_api:os-lock-server:lock": "",
"os_compute_api:os-lock-server:unlock": "",


+ 68
- 40
nova/tests/unit/policies/test_hypervisors.py View File

@@ -13,6 +13,7 @@
import mock

from nova.api.openstack.compute import hypervisors
from nova.policies import base as base_policy
from nova.policies import hypervisors as hv_policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
@@ -35,68 +36,72 @@ class HypervisorsPolicyTest(base.BasePolicyTest):
self.controller.host_api.service_get_by_compute_host = mock.MagicMock()
self.controller.host_api.compute_node_get = mock.MagicMock()

# Check that admin is able to perform operations
# on hypervisors.
self.admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
# Check that system scoped admin, member and reader are able to
# perform operations on hypervisors.
# NOTE(gmann): Until old default rule which is admin_api is
# deprecated and not removed, project admin and legacy admin
# will be able to read the agent data. This make sure that existing
# tokens will keep working even we have changed this policy defaults
# to reader role.
self.reader_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context, self.legacy_admin_context,
self.project_admin_context]
# Check that non-admin is not able to perform operations
# on hypervisors.
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
]
# Check that non-system-reader are not able to perform operations
# on hypervisors
self.reader_unauthorized_contexts = [
self.system_foo_context, self.other_project_member_context,
self.project_foo_context, self.project_member_context,
self.project_reader_context]

def test_list_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name = hv_policies.BASE_POLICY_NAME % 'list'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.index,
self.req)

def test_list_details_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name = hv_policies.BASE_POLICY_NAME % 'list-detail'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.detail,
self.req)

def test_show_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name = hv_policies.BASE_POLICY_NAME % 'show'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.show,
self.req, 11111)

@mock.patch('nova.compute.api.HostAPI.get_host_uptime')
def test_uptime_hypervisors_policy(self, mock_uptime):
rule_name = hv_policies.BASE_POLICY_NAME
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name = hv_policies.BASE_POLICY_NAME % 'uptime'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.uptime,
self.req, 11111)

def test_search_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name = hv_policies.BASE_POLICY_NAME % 'search'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.search,
self.req, 11111)

def test_servers_hypervisors_policy(self):
rule_name = hv_policies.BASE_POLICY_NAME
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name = hv_policies.BASE_POLICY_NAME % 'servers'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.servers,
self.req, 11111)

@mock.patch('nova.compute.api.HostAPI.compute_node_statistics')
def test_statistics_hypervisors_policy(self, mock_statistics):
rule_name = hv_policies.BASE_POLICY_NAME
self.common_policy_check(self.admin_authorized_contexts,
self.admin_unauthorized_contexts,
rule_name = hv_policies.BASE_POLICY_NAME % 'statistics'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.statistics,
self.req)

@@ -115,16 +120,39 @@ class HypervisorsScopeTypePolicyTest(HypervisorsPolicyTest):
super(HypervisorsScopeTypePolicyTest, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")

# Check that system admin is able to perform operations
# Check that system reader is able to perform operations
# on hypervisors.
self.admin_authorized_contexts = [
self.system_admin_context]
# Check that non-system-admin is not able to perform operations
self.reader_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context]
# Check that non-system-reader is not able to perform operations
# on hypervisors.
self.admin_unauthorized_contexts = [
self.legacy_admin_context, self.system_member_context,
self.system_reader_context, self.project_admin_context,
self.reader_unauthorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.system_foo_context, self.project_member_context,
self.other_project_member_context,
self.project_foo_context, self.project_reader_context
]


class HypervisorsNoLegacyPolicyTest(HypervisorsScopeTypePolicyTest):
"""Test Hypervisors APIs policies with system scope enabled,
and no more deprecated rules.
"""
without_deprecated_rules = True
rules_without_deprecation = {
hv_policies.BASE_POLICY_NAME % 'list':
base_policy.SYSTEM_READER,
hv_policies.BASE_POLICY_NAME % 'list-detail':
base_policy.SYSTEM_READER,
hv_policies.BASE_POLICY_NAME % 'show':
base_policy.SYSTEM_READER,
hv_policies.BASE_POLICY_NAME % 'statistics':
base_policy.SYSTEM_READER,
hv_policies.BASE_POLICY_NAME % 'uptime':
base_policy.SYSTEM_READER,
hv_policies.BASE_POLICY_NAME % 'search':
base_policy.SYSTEM_READER,
hv_policies.BASE_POLICY_NAME % 'servers':
base_policy.SYSTEM_READER,
}

+ 7
- 1
nova/tests/unit/test_policy.py View File

@@ -343,7 +343,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:os-flavor-manage:update",
"os_compute_api:os-flavor-manage:delete",
"os_compute_api:os-hosts",
"os_compute_api:os-hypervisors",
"os_compute_api:os-instance-actions:events",
"os_compute_api:os-lock-server:unlock:unlock_override",
"os_compute_api:os-migrate-server:migrate",
@@ -461,6 +460,13 @@ 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-hypervisors:list",
"os_compute_api:os-hypervisors:list-detail",
"os_compute_api:os-hypervisors:show",
"os_compute_api:os-hypervisors:statistics",
"os_compute_api:os-hypervisors:uptime",
"os_compute_api:os-hypervisors:search",
"os_compute_api:os-hypervisors:servers",
)

self.system_reader_or_owner_rules = (


Loading…
Cancel
Save