tripleo-common/tripleo_common/tests/image/test_base.py
gengchc2 e58f0dd180 Replaces yaml.load() with yaml.safe_load()
Yaml.load() return Python object may be dangerous if you receive
a YAML document from an untrusted source such as the Internet.
The function yaml.safe_load() limits this ability to simple Python
objects like integers or lists.

Reference:
https://security.openstack.org/guidelines/dg_avoid-dangerous-input-parsing-libraries.html

Change-Id: Ib825121510cc83384f738fb9eabd9821db57d28a
2017-03-10 01:16:49 +00:00

168 lines
6.3 KiB
Python

# Copyright 2015 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
import mock
from tripleo_common.image.base import BaseImageManager
from tripleo_common.image.exception import ImageSpecificationException
from tripleo_common.tests import base as testbase
from tripleo_common.tests.image import fakes
class TestBaseImageManager(testbase.TestCase):
def setUp(self):
super(TestBaseImageManager, self).setUp()
@mock.patch('yaml.safe_load', autospec=True)
@mock.patch('os.path.isfile', autospec=True)
def test_load_config_files(self, mock_os_path_isfile, mock_yaml_load):
mock_yaml_load.return_value = fakes.create_disk_images()
mock_os_path_isfile.return_value = True
mock_open_context = mock.mock_open()
mock_open_context().read.return_value = "YAML"
with mock.patch('six.moves.builtins.open', mock_open_context):
base_manager = BaseImageManager(['yamlfile'])
disk_images = base_manager.load_config_files('disk_images')
mock_yaml_load.assert_called_once_with("YAML")
self.assertEqual([{
'arch': 'amd64',
'distro': 'some_awesome_os',
'imagename': 'overcloud',
'type': 'qcow2',
'elements': ['image_element']
}], disk_images)
def test_load_config_files_not_found(self):
base_manager = BaseImageManager(['file/does/not/exist'])
self.assertRaises(IOError, base_manager.load_config_files,
'disk_images')
@mock.patch('tripleo_common.image.base.BaseImageManager.APPEND_ATTRIBUTES',
['elements', 'options', 'packages', 'environment'])
@mock.patch('yaml.safe_load', autospec=True)
@mock.patch('os.path.isfile', autospec=True)
def test_load_config_files_multiple_files(self, mock_os_path_isfile,
mock_yaml_load):
mock_yaml_load.side_effect = [{
'disk_images': [{
'arch': 'amd64',
'imagename': 'overcloud',
'distro': 'some_awesome_distro',
'type': 'qcow2',
'elements': ['image_element'],
'environment': {'test_env': '1'},
}]},
{
'disk_images': [{
'imagename': 'overcloud',
'elements': ['another_image_element'],
'packages': ['a_package'],
'otherkey': 'some_other_key',
'environment': {'test_env2': '0'},
}]}]
mock_os_path_isfile.return_value = True
mock_open_context = mock.mock_open()
mock_open_context().read.return_value = "YAML"
with mock.patch('six.moves.builtins.open', mock_open_context):
base_manager = BaseImageManager(['yamlfile1', 'yamlfile2'])
disk_images = base_manager.load_config_files('disk_images')
self.assertEqual(2, mock_yaml_load.call_count)
self.assertEqual([{
'arch': 'amd64',
'distro': 'some_awesome_distro',
'imagename': 'overcloud',
'type': 'qcow2',
'elements': ['image_element', 'another_image_element'],
'packages': ['a_package'],
'otherkey': 'some_other_key',
'environment': {'test_env': '1', 'test_env2': '0'},
}], disk_images)
@mock.patch('yaml.safe_load', autospec=True)
@mock.patch('os.path.isfile', autospec=True)
def test_load_config_files_missing_image_name(self, mock_os_path_isfile,
mock_yaml_load):
mock_yaml_load.return_value = {
'disk_images': [{
'arch': 'amd64',
'imagename': 'overcloud',
'type': 'qcow2',
'elements': ['image_element']
}, {
'arch': 'amd64',
'type': 'qcow2',
}]
}
mock_os_path_isfile.return_value = True
mock_open_context = mock.mock_open()
mock_open_context().read.return_value = "YAML"
with mock.patch('six.moves.builtins.open', mock_open_context):
base_manager = BaseImageManager(['yamlfile'])
self.assertRaises(ImageSpecificationException,
base_manager.load_config_files, 'disk_images')
@mock.patch('yaml.safe_load', autospec=True)
@mock.patch('os.path.isfile', autospec=True)
def test_load_config_files_single_image(self, mock_os_path_isfile,
mock_yaml_load):
mock_yaml_load.side_effect = [{
'disk_images': [
{
'arch': 'amd64',
'imagename': 'overcloud',
'distro': 'some_awesome_distro',
'type': 'qcow2',
'elements': ['image_element']
},
{
'arch': 'amd64',
'imagename': 'not-overcloud',
'distro': 'some_other_distro',
'type': 'qcow2',
'elements': ['other_element']
}
]}]
mock_os_path_isfile.return_value = True
mock_open_context = mock.mock_open()
mock_open_context().read.return_value = "YAML"
with mock.patch('six.moves.builtins.open', mock_open_context):
base_manager = BaseImageManager(['yamlfile1'],
images=['not-overcloud'])
disk_images = base_manager.load_config_files('disk_images')
self.assertEqual(1, mock_yaml_load.call_count)
self.assertEqual([{
'arch': 'amd64',
'distro': 'some_other_distro',
'imagename': 'not-overcloud',
'type': 'qcow2',
'elements': ['other_element'],
}], disk_images)