Blame tests/unittests/test_handler/test_handler_ca_certs.py

Packit Service a04d08
# This file is part of cloud-init. See LICENSE file for license information.
Packit Service a04d08
Packit Service a04d08
from cloudinit import cloud
Packit Service 751c4a
from cloudinit import distros
Packit Service a04d08
from cloudinit.config import cc_ca_certs
Packit Service a04d08
from cloudinit import helpers
Packit Service 751c4a
from cloudinit import subp
Packit Service a04d08
from cloudinit import util
Packit Service a04d08
Packit Service a04d08
from cloudinit.tests.helpers import TestCase
Packit Service a04d08
Packit Service a04d08
import logging
Packit Service a04d08
import shutil
Packit Service a04d08
import tempfile
Packit Service a04d08
import unittest
Packit Service 751c4a
from contextlib import ExitStack
Packit Service 751c4a
from unittest import mock
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestNoConfig(unittest.TestCase):
Packit Service a04d08
    def setUp(self):
Packit Service a04d08
        super(TestNoConfig, self).setUp()
Packit Service a04d08
        self.name = "ca-certs"
Packit Service a04d08
        self.cloud_init = None
Packit Service a04d08
        self.log = logging.getLogger("TestNoConfig")
Packit Service a04d08
        self.args = []
Packit Service a04d08
Packit Service a04d08
    def test_no_config(self):
Packit Service a04d08
        """
Packit Service a04d08
        Test that nothing is done if no ca-certs configuration is provided.
Packit Service a04d08
        """
Packit Service a04d08
        config = util.get_builtin_cfg()
Packit Service a04d08
        with ExitStack() as mocks:
Packit Service a04d08
            util_mock = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'write_file'))
Packit Service a04d08
            certs_mock = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(cc_ca_certs, 'update_ca_certs'))
Packit Service a04d08
Packit Service a04d08
            cc_ca_certs.handle(self.name, config, self.cloud_init, self.log,
Packit Service a04d08
                               self.args)
Packit Service a04d08
Packit Service a04d08
            self.assertEqual(util_mock.call_count, 0)
Packit Service a04d08
            self.assertEqual(certs_mock.call_count, 0)
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestConfig(TestCase):
Packit Service a04d08
    def setUp(self):
Packit Service a04d08
        super(TestConfig, self).setUp()
Packit Service a04d08
        self.name = "ca-certs"
Packit Service 751c4a
        distro = self._fetch_distro('ubuntu')
Packit Service a04d08
        self.paths = None
Packit Service 751c4a
        self.cloud = cloud.Cloud(None, self.paths, None, distro, None)
Packit Service a04d08
        self.log = logging.getLogger("TestNoConfig")
Packit Service a04d08
        self.args = []
Packit Service a04d08
Packit Service a04d08
        self.mocks = ExitStack()
Packit Service a04d08
        self.addCleanup(self.mocks.close)
Packit Service a04d08
Packit Service a04d08
        # Mock out the functions that actually modify the system
Packit Service a04d08
        self.mock_add = self.mocks.enter_context(
Packit Service a04d08
            mock.patch.object(cc_ca_certs, 'add_ca_certs'))
Packit Service a04d08
        self.mock_update = self.mocks.enter_context(
Packit Service a04d08
            mock.patch.object(cc_ca_certs, 'update_ca_certs'))
Packit Service a04d08
        self.mock_remove = self.mocks.enter_context(
Packit Service a04d08
            mock.patch.object(cc_ca_certs, 'remove_default_ca_certs'))
Packit Service a04d08
Packit Service 751c4a
    def _fetch_distro(self, kind):
Packit Service 751c4a
        cls = distros.fetch(kind)
Packit Service 751c4a
        paths = helpers.Paths({})
Packit Service 751c4a
        return cls(kind, {}, paths)
Packit Service 751c4a
Packit Service a04d08
    def test_no_trusted_list(self):
Packit Service a04d08
        """
Packit Service a04d08
        Test that no certificates are written if the 'trusted' key is not
Packit Service a04d08
        present.
Packit Service a04d08
        """
Packit Service a04d08
        config = {"ca-certs": {}}
Packit Service a04d08
Packit Service a04d08
        cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
Packit Service a04d08
Packit Service a04d08
        self.assertEqual(self.mock_add.call_count, 0)
Packit Service a04d08
        self.assertEqual(self.mock_update.call_count, 1)
Packit Service a04d08
        self.assertEqual(self.mock_remove.call_count, 0)
Packit Service a04d08
Packit Service a04d08
    def test_empty_trusted_list(self):
Packit Service a04d08
        """Test that no certificate are written if 'trusted' list is empty."""
Packit Service a04d08
        config = {"ca-certs": {"trusted": []}}
Packit Service a04d08
Packit Service a04d08
        cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
Packit Service a04d08
Packit Service a04d08
        self.assertEqual(self.mock_add.call_count, 0)
Packit Service a04d08
        self.assertEqual(self.mock_update.call_count, 1)
Packit Service a04d08
        self.assertEqual(self.mock_remove.call_count, 0)
Packit Service a04d08
Packit Service a04d08
    def test_single_trusted(self):
Packit Service a04d08
        """Test that a single cert gets passed to add_ca_certs."""
Packit Service a04d08
        config = {"ca-certs": {"trusted": ["CERT1"]}}
Packit Service a04d08
Packit Service a04d08
        cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
Packit Service a04d08
Packit Service a04d08
        self.mock_add.assert_called_once_with(['CERT1'])
Packit Service a04d08
        self.assertEqual(self.mock_update.call_count, 1)
Packit Service a04d08
        self.assertEqual(self.mock_remove.call_count, 0)
Packit Service a04d08
Packit Service a04d08
    def test_multiple_trusted(self):
Packit Service a04d08
        """Test that multiple certs get passed to add_ca_certs."""
Packit Service a04d08
        config = {"ca-certs": {"trusted": ["CERT1", "CERT2"]}}
Packit Service a04d08
Packit Service a04d08
        cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
Packit Service a04d08
Packit Service a04d08
        self.mock_add.assert_called_once_with(['CERT1', 'CERT2'])
Packit Service a04d08
        self.assertEqual(self.mock_update.call_count, 1)
Packit Service a04d08
        self.assertEqual(self.mock_remove.call_count, 0)
Packit Service a04d08
Packit Service a04d08
    def test_remove_default_ca_certs(self):
Packit Service a04d08
        """Test remove_defaults works as expected."""
Packit Service a04d08
        config = {"ca-certs": {"remove-defaults": True}}
Packit Service a04d08
Packit Service a04d08
        cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
Packit Service a04d08
Packit Service a04d08
        self.assertEqual(self.mock_add.call_count, 0)
Packit Service a04d08
        self.assertEqual(self.mock_update.call_count, 1)
Packit Service a04d08
        self.assertEqual(self.mock_remove.call_count, 1)
Packit Service a04d08
Packit Service a04d08
    def test_no_remove_defaults_if_false(self):
Packit Service a04d08
        """Test remove_defaults is not called when config value is False."""
Packit Service a04d08
        config = {"ca-certs": {"remove-defaults": False}}
Packit Service a04d08
Packit Service a04d08
        cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
Packit Service a04d08
Packit Service a04d08
        self.assertEqual(self.mock_add.call_count, 0)
Packit Service a04d08
        self.assertEqual(self.mock_update.call_count, 1)
Packit Service a04d08
        self.assertEqual(self.mock_remove.call_count, 0)
Packit Service a04d08
Packit Service a04d08
    def test_correct_order_for_remove_then_add(self):
Packit Service a04d08
        """Test remove_defaults is not called when config value is False."""
Packit Service a04d08
        config = {"ca-certs": {"remove-defaults": True, "trusted": ["CERT1"]}}
Packit Service a04d08
Packit Service a04d08
        cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
Packit Service a04d08
Packit Service a04d08
        self.mock_add.assert_called_once_with(['CERT1'])
Packit Service a04d08
        self.assertEqual(self.mock_update.call_count, 1)
Packit Service a04d08
        self.assertEqual(self.mock_remove.call_count, 1)
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestAddCaCerts(TestCase):
Packit Service a04d08
Packit Service a04d08
    def setUp(self):
Packit Service a04d08
        super(TestAddCaCerts, self).setUp()
Packit Service a04d08
        tmpdir = tempfile.mkdtemp()
Packit Service a04d08
        self.addCleanup(shutil.rmtree, tmpdir)
Packit Service a04d08
        self.paths = helpers.Paths({
Packit Service a04d08
            'cloud_dir': tmpdir,
Packit Service a04d08
        })
Packit Service a04d08
Packit Service a04d08
    def test_no_certs_in_list(self):
Packit Service a04d08
        """Test that no certificate are written if not provided."""
Packit Service a04d08
        with mock.patch.object(util, 'write_file') as mockobj:
Packit Service a04d08
            cc_ca_certs.add_ca_certs([])
Packit Service a04d08
        self.assertEqual(mockobj.call_count, 0)
Packit Service a04d08
Packit Service a04d08
    def test_single_cert_trailing_cr(self):
Packit Service a04d08
        """Test adding a single certificate to the trusted CAs
Packit Service a04d08
        when existing ca-certificates has trailing newline"""
Packit Service a04d08
        cert = "CERT1\nLINE2\nLINE3"
Packit Service a04d08
Packit Service a04d08
        ca_certs_content = "line1\nline2\ncloud-init-ca-certs.crt\nline3\n"
Packit Service a04d08
        expected = "line1\nline2\nline3\ncloud-init-ca-certs.crt\n"
Packit Service a04d08
Packit Service a04d08
        with ExitStack() as mocks:
Packit Service a04d08
            mock_write = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'write_file'))
Packit Service a04d08
            mock_load = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'load_file',
Packit Service a04d08
                                  return_value=ca_certs_content))
Packit Service a04d08
Packit Service a04d08
            cc_ca_certs.add_ca_certs([cert])
Packit Service a04d08
Packit Service a04d08
            mock_write.assert_has_calls([
Packit Service a04d08
                mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
Packit Service a04d08
                          cert, mode=0o644),
Packit Service a04d08
                mock.call("/etc/ca-certificates.conf", expected, omode="wb")])
Packit Service a04d08
            mock_load.assert_called_once_with("/etc/ca-certificates.conf")
Packit Service a04d08
Packit Service a04d08
    def test_single_cert_no_trailing_cr(self):
Packit Service a04d08
        """Test adding a single certificate to the trusted CAs
Packit Service a04d08
        when existing ca-certificates has no trailing newline"""
Packit Service a04d08
        cert = "CERT1\nLINE2\nLINE3"
Packit Service a04d08
Packit Service a04d08
        ca_certs_content = "line1\nline2\nline3"
Packit Service a04d08
Packit Service a04d08
        with ExitStack() as mocks:
Packit Service a04d08
            mock_write = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'write_file'))
Packit Service a04d08
            mock_load = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'load_file',
Packit Service a04d08
                                  return_value=ca_certs_content))
Packit Service a04d08
Packit Service a04d08
            cc_ca_certs.add_ca_certs([cert])
Packit Service a04d08
Packit Service a04d08
            mock_write.assert_has_calls([
Packit Service a04d08
                mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
Packit Service a04d08
                          cert, mode=0o644),
Packit Service a04d08
                mock.call("/etc/ca-certificates.conf",
Packit Service a04d08
                          "%s\n%s\n" % (ca_certs_content,
Packit Service a04d08
                                        "cloud-init-ca-certs.crt"),
Packit Service a04d08
                          omode="wb")])
Packit Service a04d08
Packit Service a04d08
            mock_load.assert_called_once_with("/etc/ca-certificates.conf")
Packit Service a04d08
Packit Service 751c4a
    def test_single_cert_to_empty_existing_ca_file(self):
Packit Service 751c4a
        """Test adding a single certificate to the trusted CAs
Packit Service 751c4a
        when existing ca-certificates.conf is empty"""
Packit Service 751c4a
        cert = "CERT1\nLINE2\nLINE3"
Packit Service 751c4a
Packit Service 751c4a
        expected = "cloud-init-ca-certs.crt\n"
Packit Service 751c4a
Packit Service 751c4a
        with ExitStack() as mocks:
Packit Service 751c4a
            mock_write = mocks.enter_context(
Packit Service 751c4a
                mock.patch.object(util, 'write_file', autospec=True))
Packit Service 751c4a
            mock_stat = mocks.enter_context(
Packit Service 751c4a
                mock.patch("cloudinit.config.cc_ca_certs.os.stat")
Packit Service 751c4a
            )
Packit Service 751c4a
            mock_stat.return_value.st_size = 0
Packit Service 751c4a
Packit Service 751c4a
            cc_ca_certs.add_ca_certs([cert])
Packit Service 751c4a
Packit Service 751c4a
            mock_write.assert_has_calls([
Packit Service 751c4a
                mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
Packit Service 751c4a
                          cert, mode=0o644),
Packit Service 751c4a
                mock.call("/etc/ca-certificates.conf", expected, omode="wb")])
Packit Service 751c4a
Packit Service a04d08
    def test_multiple_certs(self):
Packit Service a04d08
        """Test adding multiple certificates to the trusted CAs."""
Packit Service a04d08
        certs = ["CERT1\nLINE2\nLINE3", "CERT2\nLINE2\nLINE3"]
Packit Service a04d08
        expected_cert_file = "\n".join(certs)
Packit Service a04d08
        ca_certs_content = "line1\nline2\nline3"
Packit Service a04d08
Packit Service a04d08
        with ExitStack() as mocks:
Packit Service a04d08
            mock_write = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'write_file'))
Packit Service a04d08
            mock_load = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'load_file',
Packit Service a04d08
                                  return_value=ca_certs_content))
Packit Service a04d08
Packit Service a04d08
            cc_ca_certs.add_ca_certs(certs)
Packit Service a04d08
Packit Service a04d08
            mock_write.assert_has_calls([
Packit Service a04d08
                mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
Packit Service a04d08
                          expected_cert_file, mode=0o644),
Packit Service a04d08
                mock.call("/etc/ca-certificates.conf",
Packit Service a04d08
                          "%s\n%s\n" % (ca_certs_content,
Packit Service a04d08
                                        "cloud-init-ca-certs.crt"),
Packit Service a04d08
                          omode='wb')])
Packit Service a04d08
Packit Service a04d08
            mock_load.assert_called_once_with("/etc/ca-certificates.conf")
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestUpdateCaCerts(unittest.TestCase):
Packit Service a04d08
    def test_commands(self):
Packit Service 751c4a
        with mock.patch.object(subp, 'subp') as mockobj:
Packit Service a04d08
            cc_ca_certs.update_ca_certs()
Packit Service a04d08
            mockobj.assert_called_once_with(
Packit Service a04d08
                ["update-ca-certificates"], capture=False)
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestRemoveDefaultCaCerts(TestCase):
Packit Service a04d08
Packit Service a04d08
    def setUp(self):
Packit Service a04d08
        super(TestRemoveDefaultCaCerts, self).setUp()
Packit Service a04d08
        tmpdir = tempfile.mkdtemp()
Packit Service a04d08
        self.addCleanup(shutil.rmtree, tmpdir)
Packit Service a04d08
        self.paths = helpers.Paths({
Packit Service a04d08
            'cloud_dir': tmpdir,
Packit Service a04d08
        })
Packit Service a04d08
Packit Service a04d08
    def test_commands(self):
Packit Service a04d08
        with ExitStack() as mocks:
Packit Service a04d08
            mock_delete = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'delete_dir_contents'))
Packit Service a04d08
            mock_write = mocks.enter_context(
Packit Service a04d08
                mock.patch.object(util, 'write_file'))
Packit Service 751c4a
            mock_subp = mocks.enter_context(mock.patch.object(subp, 'subp'))
Packit Service a04d08
Packit Service 751c4a
            cc_ca_certs.remove_default_ca_certs('ubuntu')
Packit Service a04d08
Packit Service a04d08
            mock_delete.assert_has_calls([
Packit Service a04d08
                mock.call("/usr/share/ca-certificates/"),
Packit Service a04d08
                mock.call("/etc/ssl/certs/")])
Packit Service a04d08
Packit Service a04d08
            mock_write.assert_called_once_with(
Packit Service a04d08
                "/etc/ca-certificates.conf", "", mode=0o644)
Packit Service a04d08
Packit Service a04d08
            mock_subp.assert_called_once_with(
Packit Service a04d08
                ('debconf-set-selections', '-'),
Packit Service a04d08
                "ca-certificates ca-certificates/trust_new_crts select no")
Packit Service a04d08
Packit Service a04d08
# vi: ts=4 expandtab