Merge "Add test coverage of existing server attributes policies"

This commit is contained in:
Zuul
2020-04-16 17:10:54 +00:00
committed by Gerrit Code Review
+351 -1
View File
@@ -19,6 +19,9 @@ from nova.api.openstack.compute import servers
from nova.compute import vm_states
from nova import exception
from nova import objects
from nova.objects import fields
from nova.objects.instance_group import InstanceGroup
from nova.policies import extended_server_attributes as ea_policies
from nova.policies import servers as policies
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit import fake_flavor
@@ -53,7 +56,8 @@ class ServersPolicyTest(base.BasePolicyTest):
self.instance = fake_instance.fake_instance_obj(
self.project_member_context,
id=1, uuid=uuids.fake_id, project_id=self.project_id,
user_id=user_id, vm_state=vm_states.ACTIVE)
user_id=user_id, vm_state=vm_states.ACTIVE,
system_metadata={}, expected_attrs=['system_metadata'])
self.mock_flavor = self.useFixture(
fixtures.MockPatch('nova.compute.flavors.get_flavor_by_flavor_id'
@@ -86,6 +90,17 @@ class ServersPolicyTest(base.BasePolicyTest):
'flavorRef': uuids.fake_id,
},
}
self.extended_attr = ['OS-EXT-SRV-ATTR:host',
'OS-EXT-SRV-ATTR:hypervisor_hostname',
'OS-EXT-SRV-ATTR:instance_name',
'OS-EXT-SRV-ATTR:hostname',
'OS-EXT-SRV-ATTR:kernel_id',
'OS-EXT-SRV-ATTR:launch_index',
'OS-EXT-SRV-ATTR:ramdisk_id',
'OS-EXT-SRV-ATTR:reservation_id',
'OS-EXT-SRV-ATTR:root_device_name',
'OS-EXT-SRV-ATTR:user_data'
]
# Check that admin or and owner is able to update, delete
# or perform server action.
@@ -164,6 +179,20 @@ class ServersPolicyTest(base.BasePolicyTest):
# Check that non-project member is not able to create server
self.project_member_unauthorized_contexts = [
]
# Check that admin is able to get server extended attributes
# or host status.
self.server_attr_admin_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context]
# Check that non-admin is not able to get server extended attributes
# or host status.
self.server_attr_admin_unauthorized_contexts = [
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
]
def test_index_server_policy(self):
@@ -784,6 +813,327 @@ class ServersPolicyTest(base.BasePolicyTest):
self.controller._action_trigger_crash_dump(req,
self.instance.uuid, body=body)
def test_server_detail_with_extended_attr_policy(self):
def fake_get_all(context, search_opts=None,
limit=None, marker=None,
expected_attrs=None, sort_keys=None, sort_dirs=None,
cell_down_support=False, all_tenants=False):
return objects.InstanceList(objects=self.servers)
self.mock_get_all.side_effect = fake_get_all
rule = policies.SERVERS % 'detail'
# server 'detail' policy is checked before extended attributes
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts.
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.3')
rule_name = ea_policies.BASE_POLICY_NAME
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.detail, req,
fatal=False)
for attr in self.extended_attr:
for resp in authorize_res:
self.assertIn(attr, resp['servers'][0])
for resp in unauthorize_res:
self.assertNotIn(attr, resp['servers'][0])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch('nova.compute.api.API.get_instance_host_status')
def test_server_show_with_extended_attr_policy(self, mock_get, mock_block):
rule = policies.SERVERS % 'show'
# server 'show' policy is checked before extended attributes
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts.
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.3')
rule_name = ea_policies.BASE_POLICY_NAME
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.show, req, 'fake',
fatal=False)
for attr in self.extended_attr:
for resp in authorize_res:
self.assertIn(attr, resp['server'])
for resp in unauthorize_res:
self.assertNotIn(attr, resp['server'])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch('nova.compute.api.API.get_instance_host_status')
@mock.patch('nova.compute.api.API.rebuild')
def test_server_rebuild_with_extended_attr_policy(self, mock_rebuild,
mock_get, mock_bdm):
rule = policies.SERVERS % 'rebuild'
# server 'rebuild' policy is checked before extended attributes
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts.
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = ea_policies.BASE_POLICY_NAME
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller._action_rebuild,
req, self.instance.uuid,
body={'rebuild': {"imageRef": uuids.fake_id}},
fatal=False)
for attr in self.extended_attr:
# NOTE(gmann): user_data attribute is always present in
# rebuild response since 2.47.
if attr == 'OS-EXT-SRV-ATTR:user_data':
continue
for resp in authorize_res:
self.assertIn(attr, resp.obj['server'])
for resp in unauthorize_res:
self.assertNotIn(attr, resp.obj['server'])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch.object(InstanceGroup, 'get_by_instance_uuid')
@mock.patch('nova.compute.api.API.update_instance')
def test_server_update_with_extended_attr_policy(self,
mock_update, mock_group, mock_bdm):
rule = policies.SERVERS % 'update'
# server 'update' policy is checked before extended attributes
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts.
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = ea_policies.BASE_POLICY_NAME
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.update,
req, self.instance.uuid,
body={'server': {'name': 'test'}},
fatal=False)
for attr in self.extended_attr:
for resp in authorize_res:
self.assertIn(attr, resp['server'])
for resp in unauthorize_res:
self.assertNotIn(attr, resp['server'])
def test_server_detail_with_host_status_policy(self):
def fake_get_all(context, search_opts=None,
limit=None, marker=None,
expected_attrs=None, sort_keys=None, sort_dirs=None,
cell_down_support=False, all_tenants=False):
return objects.InstanceList(objects=self.servers)
self.mock_get_all.side_effect = fake_get_all
rule = policies.SERVERS % 'detail'
# server 'detail' policy is checked before host_status
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts.
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.16')
rule_name = policies.SERVERS % 'show:host_status'
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.detail, req,
fatal=False)
for resp in authorize_res:
self.assertIn('host_status', resp['servers'][0])
for resp in unauthorize_res:
self.assertNotIn('host_status', resp['servers'][0])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch('nova.compute.api.API.get_instance_host_status')
def test_server_show_with_host_status_policy(self,
mock_status, mock_block):
rule = policies.SERVERS % 'show'
# server 'show' policy is checked before host_status
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts.
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.16')
rule_name = policies.SERVERS % 'show:host_status'
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.show, req, 'fake',
fatal=False)
for resp in authorize_res:
self.assertIn('host_status', resp['server'])
for resp in unauthorize_res:
self.assertNotIn('host_status', resp['server'])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch('nova.compute.api.API.get_instance_host_status')
@mock.patch('nova.compute.api.API.rebuild')
def test_server_rebuild_with_host_status_policy(self, mock_rebuild,
mock_status, mock_bdm):
rule = policies.SERVERS % 'rebuild'
# server 'rebuild' policy is checked before host_status
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts.
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = policies.SERVERS % 'show:host_status'
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller._action_rebuild,
req, self.instance.uuid,
body={'rebuild': {"imageRef": uuids.fake_id}},
fatal=False)
for resp in authorize_res:
self.assertIn('host_status', resp.obj['server'])
for resp in unauthorize_res:
self.assertNotIn('host_status', resp.obj['server'])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch.object(InstanceGroup, 'get_by_instance_uuid')
@mock.patch('nova.compute.api.API.update_instance')
def test_server_update_with_host_status_policy(self,
mock_update, mock_group, mock_bdm):
rule = policies.SERVERS % 'update'
# server 'update' policy is checked before host_status
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts.
self.policy.set_rules({rule: "@"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = policies.SERVERS % 'show:host_status'
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.update,
req, self.instance.uuid,
body={'server': {'name': 'test'}},
fatal=False)
for resp in authorize_res:
self.assertIn('host_status', resp['server'])
for resp in unauthorize_res:
self.assertNotIn('host_status', resp['server'])
@mock.patch('nova.compute.api.API.get_instances_host_statuses')
def test_server_detail_with_unknown_host_status_policy(self, mock_status):
def fake_get_all(context, search_opts=None,
limit=None, marker=None,
expected_attrs=None, sort_keys=None, sort_dirs=None,
cell_down_support=False, all_tenants=False):
return objects.InstanceList(objects=self.servers)
self.mock_get_all.side_effect = fake_get_all
host_statuses = {}
for server in self.servers:
host_statuses.update({server.uuid: fields.HostStatus.UNKNOWN})
mock_status.return_value = host_statuses
rule = policies.SERVERS % 'detail'
# server 'detail' policy is checked before unknown host_status
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts. To verify the unknown host_status
# policy we need to disallow host_status policy for everyone.
rule_host_status = policies.SERVERS % 'show:host_status'
self.policy.set_rules({
rule: "@",
rule_host_status: "!"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.16')
rule_name = policies.SERVERS % 'show:host_status:unknown-only'
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.detail, req,
fatal=False)
for resp in authorize_res:
self.assertIn('host_status', resp['servers'][0])
self.assertEqual(fields.HostStatus.UNKNOWN,
resp['servers'][0]['host_status'])
for resp in unauthorize_res:
self.assertNotIn('host_status', resp['servers'][0])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch('nova.compute.api.API.get_instance_host_status')
def test_server_show_with_unknown_host_status_policy(self,
mock_status, mock_block):
mock_status.return_value = fields.HostStatus.UNKNOWN
rule = policies.SERVERS % 'show'
# server 'show' policy is checked before unknown host_status
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts. To verify the unknown host_status
# policy we need to disallow host_status policy for everyone.
rule_host_status = policies.SERVERS % 'show:host_status'
self.policy.set_rules({
rule: "@",
rule_host_status: "!"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.16')
rule_name = policies.SERVERS % 'show:host_status:unknown-only'
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.show, req, 'fake',
fatal=False)
for resp in authorize_res:
self.assertIn('host_status', resp['server'])
self.assertEqual(
fields.HostStatus.UNKNOWN, resp['server']['host_status'])
for resp in unauthorize_res:
self.assertNotIn('host_status', resp['server'])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch('nova.compute.api.API.get_instance_host_status')
@mock.patch('nova.compute.api.API.rebuild')
def test_server_rebuild_with_unknown_host_status_policy(self, mock_rebuild,
mock_status, mock_bdm):
mock_status.return_value = fields.HostStatus.UNKNOWN
rule = policies.SERVERS % 'rebuild'
# server 'rebuild' policy is checked before unknown host_status
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts. To verify the unknown host_status
# policy we need to disallow host_status policy for everyone.
rule_host_status = policies.SERVERS % 'show:host_status'
self.policy.set_rules({
rule: "@",
rule_host_status: "!"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = policies.SERVERS % 'show:host_status:unknown-only'
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller._action_rebuild,
req, self.instance.uuid,
body={'rebuild': {"imageRef": uuids.fake_id}},
fatal=False)
for resp in authorize_res:
self.assertIn('host_status', resp.obj['server'])
self.assertEqual(
fields.HostStatus.UNKNOWN, resp.obj['server']['host_status'])
for resp in unauthorize_res:
self.assertNotIn('host_status', resp.obj['server'])
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
@mock.patch('nova.compute.api.API.get_instance_host_status')
@mock.patch.object(InstanceGroup, 'get_by_instance_uuid')
@mock.patch('nova.compute.api.API.update_instance')
def test_server_update_with_unknown_host_status_policy(self,
mock_update, mock_group, mock_status, mock_bdm):
mock_status.return_value = fields.HostStatus.UNKNOWN
rule = policies.SERVERS % 'update'
# server 'update' policy is checked before unknown host_status
# policy so we have to allow it for everyone otherwise it will fail
# first for unauthorized contexts. To verify the unknown host_status
# policy we need to disallow host_status policy for everyone.
rule_host_status = policies.SERVERS % 'show:host_status'
self.policy.set_rules({
rule: "@",
rule_host_status: "!"}, overwrite=False)
req = fakes.HTTPRequest.blank('', version='2.75')
rule_name = policies.SERVERS % 'show:host_status:unknown-only'
authorize_res, unauthorize_res = self.common_policy_check(
self.server_attr_admin_authorized_contexts,
self.server_attr_admin_unauthorized_contexts,
rule_name, self.controller.update,
req, self.instance.uuid,
body={'server': {'name': 'test'}},
fatal=False)
for resp in authorize_res:
self.assertIn('host_status', resp['server'])
self.assertEqual(
fields.HostStatus.UNKNOWN, resp['server']['host_status'])
for resp in unauthorize_res:
self.assertNotIn('host_status', resp['server'])
class ServersScopeTypePolicyTest(ServersPolicyTest):
"""Test Servers APIs policies with system scope enabled.