diff --git a/doc/source/commands/system_build.rst b/doc/source/commands/system_build.rst index 668d64c0..8652ac63 100644 --- a/doc/source/commands/system_build.rst +++ b/doc/source/commands/system_build.rst @@ -18,6 +18,7 @@ SYNOPSIS [--obs-repo-internal] [--add-package=...] [--delete-package=...] + [--signing-key=...] kiwi system build help DESCRIPTION @@ -61,6 +62,14 @@ OPTIONS is shared between multiple image builds on that host for performance reasons. +--signing-key= + + set the key file to be trusted and imported into the package + manager database before performing any opertaion. This is useful + if an image build should take and validate repository and package + signatures during build time. This option can be specified multiple + times + --delete-package= specify package to delete. The option can be specified diff --git a/doc/source/commands/system_create.rst b/doc/source/commands/system_create.rst index 6013e4d2..2a06e114 100644 --- a/doc/source/commands/system_create.rst +++ b/doc/source/commands/system_create.rst @@ -10,6 +10,7 @@ SYNOPSIS kiwi system create -h | --help kiwi system create --root= --target-dir= + [--signing-key=...] kiwi system create help DESCRIPTION @@ -33,3 +34,12 @@ OPTIONS --target-dir= Path to store the build results. + +--signing-key= + + set the key file to be trusted and imported into the package + manager database before performing any opertaion. This is useful + if an image build should take and validate repository and package + signatures during build time. In create step this option only + affects the boot image. This option can be specified multiple + times diff --git a/doc/source/commands/system_prepare.rst b/doc/source/commands/system_prepare.rst index 5c7ffe25..92bde9ed 100644 --- a/doc/source/commands/system_prepare.rst +++ b/doc/source/commands/system_prepare.rst @@ -18,6 +18,7 @@ SYNOPSIS [--obs-repo-internal] [--add-package=...] [--delete-package=...] + [--signing-key=...] kiwi system prepare help DESCRIPTION @@ -59,6 +60,14 @@ OPTIONS is shared between multiple image builds on that host for performance reasons. +--signing-key= + + set the key file to be trusted and imported into the package + manager database before performing any opertaion. This is useful + if an image build should take and validate repository and package + signatures during build time. This option can be specified multiple + times + --delete-package= specify package to delete. The option can be specified diff --git a/kiwi/boot/image/__init__.py b/kiwi/boot/image/__init__.py index a6fae6f1..22f257b6 100644 --- a/kiwi/boot/image/__init__.py +++ b/kiwi/boot/image/__init__.py @@ -28,12 +28,14 @@ class BootImage(object): """ BootImge factory """ - def __new__(self, xml_state, target_dir, root_dir=None): + def __new__(self, xml_state, target_dir, root_dir=None, signing_keys=None): initrd_system = xml_state.build_type.get_initrd_system() if not initrd_system: initrd_system = 'kiwi' if initrd_system == 'kiwi': - return BootImageKiwi(xml_state, target_dir) + return BootImageKiwi( + xml_state, target_dir, signing_keys=signing_keys + ) elif initrd_system == 'dracut': return BootImageDracut(xml_state, target_dir, root_dir) else: diff --git a/kiwi/boot/image/base.py b/kiwi/boot/image/base.py index 824852f9..6384f0e4 100644 --- a/kiwi/boot/image/base.py +++ b/kiwi/boot/image/base.py @@ -56,7 +56,9 @@ class BootImageBase(object): Instance of XMLState of the boot image description """ - def __init__(self, xml_state, target_dir, root_dir=None): + def __init__( + self, xml_state, target_dir, root_dir=None, signing_keys=None + ): self.xml_state = xml_state self.target_dir = target_dir self.initrd_filename = None @@ -64,6 +66,7 @@ class BootImageBase(object): self.setup = None self.temp_directories = [] self.call_destructor = True + self.signing_keys = signing_keys self.boot_root_directory = root_dir if not self.boot_root_directory: diff --git a/kiwi/boot/image/builtin_kiwi.py b/kiwi/boot/image/builtin_kiwi.py index f4ce0a9b..9872f173 100644 --- a/kiwi/boot/image/builtin_kiwi.py +++ b/kiwi/boot/image/builtin_kiwi.py @@ -52,7 +52,7 @@ class BootImageKiwi(BootImageBase): root_dir=self.boot_root_directory, allow_existing=True ) - manager = system.setup_repositories() + manager = system.setup_repositories(signing_keys=self.signing_keys) system.install_bootstrap( manager ) diff --git a/kiwi/builder/__init__.py b/kiwi/builder/__init__.py index 9155893e..cb842e12 100644 --- a/kiwi/builder/__init__.py +++ b/kiwi/builder/__init__.py @@ -33,7 +33,7 @@ class ImageBuilder(object): """ image builder factory """ - def __new__(self, xml_state, target_dir, root_dir): + def __new__(self, xml_state, target_dir, root_dir, custom_args=None): requested_image_type = xml_state.get_build_type_name() if requested_image_type in Defaults.get_filesystem_image_types(): return FileSystemBuilder( @@ -41,15 +41,15 @@ class ImageBuilder(object): ) elif requested_image_type in Defaults.get_disk_image_types(): return DiskBuilder( - xml_state, target_dir, root_dir + xml_state, target_dir, root_dir, custom_args ) elif requested_image_type in Defaults.get_live_image_types(): return LiveImageBuilder( - xml_state, target_dir, root_dir + xml_state, target_dir, root_dir, custom_args ) elif requested_image_type in Defaults.get_network_image_types(): return PxeBuilder( - xml_state, target_dir, root_dir + xml_state, target_dir, root_dir, custom_args ) elif requested_image_type in Defaults.get_archive_image_types(): return ArchiveBuilder( diff --git a/kiwi/builder/disk.py b/kiwi/builder/disk.py index 052b78e7..8d2192e8 100644 --- a/kiwi/builder/disk.py +++ b/kiwi/builder/disk.py @@ -171,7 +171,7 @@ class DiskBuilder(object): * :attr:`result` Instance of Result """ - def __init__(self, xml_state, target_dir, root_dir): + def __init__(self, xml_state, target_dir, root_dir, custom_args=None): self.arch = platform.machine() if self.arch == 'i686' or self.arch == 'i586': self.arch = 'ix86' @@ -206,8 +206,15 @@ class DiskBuilder(object): self.disk_setup = DiskSetup( xml_state, root_dir ) + self.custom_args = custom_args + + self.signing_keys = None + if custom_args and 'signing_keys' in custom_args: + self.signing_keys = custom_args['signing_keys'] + self.boot_image = BootImage( - xml_state, target_dir, root_dir + xml_state, target_dir, root_dir, + signing_keys=self.signing_keys ) self.firmware = FirmWare( xml_state @@ -256,7 +263,7 @@ class DiskBuilder(object): * image="vmx" """ disk = DiskBuilder( - self.xml_state, self.target_dir, self.root_dir + self.xml_state, self.target_dir, self.root_dir, self.custom_args ) result = disk.create_disk() @@ -480,7 +487,8 @@ class DiskBuilder(object): self.xml_state.build_type.get_initrd_system() self.boot_image = BootImageKiwi( - self.xml_state, self.target_dir + self.xml_state, self.target_dir, + signing_keys=self.signing_keys ) self.boot_image.prepare() diff --git a/kiwi/builder/live.py b/kiwi/builder/live.py index 154c7e3b..acca3fdf 100644 --- a/kiwi/builder/live.py +++ b/kiwi/builder/live.py @@ -100,7 +100,7 @@ class LiveImageBuilder(object): * :attr:`result` Instance of Result """ - def __init__(self, xml_state, target_dir, root_dir): + def __init__(self, xml_state, target_dir, root_dir, custom_args=None): self.media_dir = None self.arch = platform.machine() if self.arch == 'i686' or self.arch == 'i586': @@ -122,8 +122,12 @@ class LiveImageBuilder(object): if not self.live_type: self.live_type = Defaults.get_default_live_iso_type() + boot_signing_keys = None + if custom_args and 'signing_keys' in custom_args: + boot_signing_keys = custom_args['signing_keys'] + self.boot_image_task = BootImage( - xml_state, target_dir + xml_state, target_dir, signing_keys=boot_signing_keys ) self.firmware = FirmWare( xml_state diff --git a/kiwi/builder/pxe.py b/kiwi/builder/pxe.py index e4178e94..dd9d1eb7 100644 --- a/kiwi/builder/pxe.py +++ b/kiwi/builder/pxe.py @@ -73,7 +73,7 @@ class PxeBuilder(object): * :attr:`result` Instance of Result """ - def __init__(self, xml_state, target_dir, root_dir): + def __init__(self, xml_state, target_dir, root_dir, custom_args=None): self.target_dir = target_dir self.compressed = xml_state.build_type.get_compressed() self.machine = xml_state.get_build_type_machine_section() @@ -84,8 +84,13 @@ class PxeBuilder(object): self.system_setup = SystemSetup( xml_state=xml_state, root_dir=root_dir ) + + boot_signing_keys = None + if custom_args and 'signing_keys' in custom_args: + boot_signing_keys = custom_args['signing_keys'] + self.boot_image_task = BootImage( - xml_state, target_dir + xml_state, target_dir, signing_keys=boot_signing_keys ) self.image_name = ''.join( [ diff --git a/kiwi/package_manager/apt.py b/kiwi/package_manager/apt.py index 17afa1a8..1e87ab58 100644 --- a/kiwi/package_manager/apt.py +++ b/kiwi/package_manager/apt.py @@ -132,6 +132,13 @@ class PackageManagerApt(PackageManagerBase): device='/dev', mountpoint=self.root_dir + '/dev' ) dev_mount.umount() + if self.repository.unauthenticated == 'false': + log.warning( + 'KIWI does not support signature checks for apt-get ' + 'package manager during the bootstrap procedure, any ' + 'provided key will only be used inside the chroot ' + 'environment' + ) Command.run( [ 'debootstrap', '--no-check-gpg', self.distribution, @@ -144,6 +151,10 @@ class PackageManagerApt(PackageManagerBase): data.sync_data( options=['-a', '-H', '-X', '-A'] ) + for key in self.repository.signing_keys: + Command.run([ + 'chroot', self.root_dir, 'apt-key', 'add', key + ], self.command_env) except Exception as e: raise KiwiDebootstrapError( '%s: %s' % (type(e).__name__, format(e)) diff --git a/kiwi/repository/apt.py b/kiwi/repository/apt.py index 9853853d..4ec12d0e 100644 --- a/kiwi/repository/apt.py +++ b/kiwi/repository/apt.py @@ -56,6 +56,7 @@ class RepositoryApt(RepositoryBase): """ self.custom_args = custom_args self.exclude_docs = False + self.signing_keys = [] if not custom_args: self.custom_args = [] @@ -167,6 +168,16 @@ class RepositoryApt(RepositoryBase): 'deb %s %s %s\n' % (uri, dist, components) ) + def import_trusted_keys(self, signing_keys): + """ + Keeps trusted keys so that later on they can be imported into + the image by the PackageManager instance. + + :param list signing_keys: list of the key files to import + """ + for key in signing_keys: + self.signing_keys.append(key) + def delete_repo(self, name): """ Delete apt-get repository diff --git a/kiwi/repository/base.py b/kiwi/repository/base.py index 9213187e..725667dc 100644 --- a/kiwi/repository/base.py +++ b/kiwi/repository/base.py @@ -86,6 +86,16 @@ class RepositoryBase(object): """ raise NotImplementedError + def import_trusted_keys(self, signing_keys): + """ + Imports trusted keys into the image + + Implementation in specialized repository class + + :param list signing_keys: list of the key files to import + """ + raise NotImplementedError + def cleanup_unused_repos(self): """ Cleanup/Delete unused repositories diff --git a/kiwi/repository/dnf.py b/kiwi/repository/dnf.py index f851094a..b6908c4f 100644 --- a/kiwi/repository/dnf.py +++ b/kiwi/repository/dnf.py @@ -23,6 +23,7 @@ from tempfile import NamedTemporaryFile # project from kiwi.repository.base import RepositoryBase from kiwi.path import Path +from kiwi.command import Command class RepositoryDnf(RepositoryBase): @@ -160,6 +161,15 @@ class RepositoryDnf(RepositoryBase): with open(repo_file, 'w') as repo: repo_config.write(repo) + def import_trusted_keys(self, signing_keys): + """ + Imports trusted keys into the image + + :param list signing_keys: list of the key files to import + """ + for key in signing_keys: + Command.run(['rpm', '--root', self.root_dir, '--import', key]) + def delete_repo(self, name): """ Delete dnf repository @@ -253,9 +263,9 @@ class RepositoryDnf(RepositoryBase): self.runtime_dnf_config.set( 'main', 'gpgcheck', self.gpg_check ) - self.runtime_dnf_config.set( - 'main', 'repo_gpgcheck', self.gpg_check - ) + # We are not setting repo_gpgcheck, which forces repository + # signatures checks, because current Fedora 25 releases do not + # provide signed repositories, only signed packages if self.exclude_docs: self.runtime_dnf_config.set( 'main', 'tsflags', 'nodocs' diff --git a/kiwi/repository/yum.py b/kiwi/repository/yum.py index 8f3194f7..fe435433 100644 --- a/kiwi/repository/yum.py +++ b/kiwi/repository/yum.py @@ -21,6 +21,7 @@ from tempfile import NamedTemporaryFile # project from kiwi.logger import log +from kiwi.command import Command from kiwi.repository.base import RepositoryBase from kiwi.path import Path @@ -159,6 +160,15 @@ class RepositoryYum(RepositoryBase): with open(repo_file, 'w') as repo: repo_config.write(repo) + def import_trusted_keys(self, signing_keys): + """ + Imports trusted keys into the image + + :param list signing_keys: list of the key files to import + """ + for key in signing_keys: + Command.run(['rpm', '--root', self.root_dir, '--import', key]) + def delete_repo(self, name): """ Delete yum repository @@ -248,9 +258,9 @@ class RepositoryYum(RepositoryBase): self.runtime_yum_config.set( 'main', 'gpgcheck', self.gpg_check ) - self.runtime_yum_config.set( - 'main', 'repo_gpgcheck', self.gpg_check - ) + # We are not setting repo_gpgcheck, which forces repository + # signature checks. Because, at the time of writing this comment, + # yum v3.4.3 was not capable to perform a repository key validation self.runtime_yum_config.set( 'main', 'metadata_expire', '1800' ) diff --git a/kiwi/repository/zypper.py b/kiwi/repository/zypper.py index 96286888..70580b95 100644 --- a/kiwi/repository/zypper.py +++ b/kiwi/repository/zypper.py @@ -243,6 +243,15 @@ class RepositoryZypper(RepositoryBase): ) self._restore_package_cache() + def import_trusted_keys(self, signing_keys): + """ + Imports trusted keys into the image + + :param list signing_keys: list of the key files to import + """ + for key in signing_keys: + Command.run(['rpm', '--root', self.root_dir, '--import', key]) + def delete_repo(self, name): """ Delete zypper repository diff --git a/kiwi/system/prepare.py b/kiwi/system/prepare.py index a547068d..d077437f 100644 --- a/kiwi/system/prepare.py +++ b/kiwi/system/prepare.py @@ -90,7 +90,7 @@ class SystemPrepare(object): # for System operations self.uri_list = [] - def setup_repositories(self, clear_cache=False): + def setup_repositories(self, clear_cache=False, signing_keys=None): """ Set up repositories for software installation and return a package manager for performing software installation tasks @@ -108,6 +108,8 @@ class SystemPrepare(object): repo = Repository( self.root_bind, package_manager, repository_options ) + if signing_keys: + repo.import_trusted_keys(signing_keys) for xml_repo in repository_sections: repo_type = xml_repo.get_type() repo_source = xml_repo.get_source().get_path() diff --git a/kiwi/tasks/system_build.py b/kiwi/tasks/system_build.py index 4e6170e9..aa13c607 100644 --- a/kiwi/tasks/system_build.py +++ b/kiwi/tasks/system_build.py @@ -28,6 +28,7 @@ usage: kiwi system build -h | --help [--delete-package=...] [--set-container-derived-from=] [--set-container-tag=] + [--signing-key=...] kiwi system build help commands: @@ -75,6 +76,8 @@ options: repository in the XML description --target-dir= the target directory to store the system image file(s) + --signing-key= + includes the key-file as a trusted key for package manager validations """ import os @@ -190,7 +193,8 @@ class SystemBuildTask(CliTask): self.command_args['--allow-existing-root'] ) manager = system.setup_repositories( - self.command_args['--clear-cache'] + self.command_args['--clear-cache'], + self.command_args['--signing-key'] ) system.install_bootstrap(manager) system.install_system( @@ -248,7 +252,8 @@ class SystemBuildTask(CliTask): image_builder = ImageBuilder( self.xml_state, abs_target_dir_path, - image_root + image_root, + {'signing_keys': self.command_args['--signing-key']} ) result = image_builder.create() result.print_results() diff --git a/kiwi/tasks/system_create.py b/kiwi/tasks/system_create.py index 4646b228..9dd24925 100644 --- a/kiwi/tasks/system_create.py +++ b/kiwi/tasks/system_create.py @@ -18,6 +18,7 @@ """ usage: kiwi system create -h | --help kiwi system create --root= --target-dir= + [--signing-key=...] kiwi system create help commands: @@ -34,6 +35,8 @@ options: a former system prepare call --target-dir= the target directory to store the system image file(s) + --signing-key= + includes the key-file as a trusted key for package manager validations """ import os @@ -93,7 +96,8 @@ class SystemCreateTask(CliTask): image_builder = ImageBuilder( self.xml_state, abs_target_dir_path, - abs_root_path + abs_root_path, + custom_args={'signing_keys': self.command_args['--signing-key']} ) result = image_builder.create() result.print_results() diff --git a/kiwi/tasks/system_prepare.py b/kiwi/tasks/system_prepare.py index 071092d0..a9008f43 100644 --- a/kiwi/tasks/system_prepare.py +++ b/kiwi/tasks/system_prepare.py @@ -28,6 +28,7 @@ usage: kiwi system prepare -h | --help [--delete-package=...] [--set-container-derived-from=] [--set-container-tag=] + [--signing-key=...] kiwi system prepare help commands: @@ -73,6 +74,8 @@ options: --set-repo= overwrite the repo source, type, alias or priority for the first repository in the XML description + --signing-key= + includes the key-file as a trusted key for package manager validations """ import os @@ -174,7 +177,8 @@ class SystemPrepareTask(CliTask): self.command_args['--allow-existing-root'] ) manager = system.setup_repositories( - self.command_args['--clear-cache'] + self.command_args['--clear-cache'], + self.command_args['--signing-key'] ) system.install_bootstrap(manager) system.install_system( diff --git a/test/unit/boot_image_builtin_kiwi_test.py b/test/unit/boot_image_builtin_kiwi_test.py index aa9e18c1..167b468e 100644 --- a/test/unit/boot_image_builtin_kiwi_test.py +++ b/test/unit/boot_image_builtin_kiwi_test.py @@ -50,7 +50,9 @@ class TestBootImageKiwi(object): def test_prepare(self, mock_boot_path): mock_boot_path.return_value = '../data' self.boot_image.prepare() - self.system_prepare.setup_repositories.assert_called_once_with() + self.system_prepare.setup_repositories.assert_called_once_with( + signing_keys=None + ) self.system_prepare.install_bootstrap.assert_called_once_with( self.manager ) diff --git a/test/unit/boot_image_test.py b/test/unit/boot_image_test.py index 8d87a152..55703b2b 100644 --- a/test/unit/boot_image_test.py +++ b/test/unit/boot_image_test.py @@ -23,7 +23,7 @@ class TestBootImage(object): self.xml_state.build_type.get_initrd_system.return_value = None BootImage(self.xml_state, 'target_dir') mock_kiwi.assert_called_once_with( - self.xml_state, 'target_dir' + self.xml_state, 'target_dir', signing_keys=None ) @patch('kiwi.boot.image.BootImageKiwi') @@ -31,13 +31,13 @@ class TestBootImage(object): self.xml_state.build_type.get_initrd_system.return_value = 'kiwi' BootImage(self.xml_state, 'target_dir') mock_kiwi.assert_called_once_with( - self.xml_state, 'target_dir' + self.xml_state, 'target_dir', signing_keys=None ) @patch('kiwi.boot.image.BootImageDracut') def test_boot_image_task_dracut(self, mock_dracut): self.xml_state.build_type.get_initrd_system.return_value = 'dracut' - BootImage(self.xml_state, 'target_dir') + BootImage(self.xml_state, 'target_dir', 'root_dir') mock_dracut.assert_called_once_with( - self.xml_state, 'target_dir', None + self.xml_state, 'target_dir', 'root_dir' ) diff --git a/test/unit/builder_disk_test.py b/test/unit/builder_disk_test.py index de6ec578..277f87d2 100644 --- a/test/unit/builder_disk_test.py +++ b/test/unit/builder_disk_test.py @@ -163,7 +163,8 @@ class TestDiskBuilder(object): return_value=self.luks_root ) self.disk_builder = DiskBuilder( - XMLState(description.load()), 'target_dir', 'root_dir' + XMLState(description.load()), 'target_dir', 'root_dir', + custom_args={'signing_keys': ['key_file_a', 'key_file_b']} ) self.disk_builder.root_filesystem_is_overlay = False self.disk_builder.build_type_name = 'oem' diff --git a/test/unit/builder_live_test.py b/test/unit/builder_live_test.py index 654e2f84..3dd3dfaf 100644 --- a/test/unit/builder_live_test.py +++ b/test/unit/builder_live_test.py @@ -67,7 +67,8 @@ class TestLiveImageBuilder(object): return_value='custom_cmdline' ) self.live_image = LiveImageBuilder( - self.xml_state, 'target_dir', 'root_dir' + self.xml_state, 'target_dir', 'root_dir', + custom_args={'signing_keys': ['key_file_a', 'key_file_b']} ) self.live_image.machine = mock.Mock() self.live_image.machine.get_domain = mock.Mock( diff --git a/test/unit/builder_pxe_test.py b/test/unit/builder_pxe_test.py index b210952c..aca05d9c 100644 --- a/test/unit/builder_pxe_test.py +++ b/test/unit/builder_pxe_test.py @@ -50,7 +50,8 @@ class TestPxeBuilder(object): return_value=self.kernel ) self.pxe = PxeBuilder( - self.xml_state, 'target_dir', 'root_dir' + self.xml_state, 'target_dir', 'root_dir', + custom_args={'signing_keys': ['key_file_a', 'key_file_b']} ) self.machine = mock.Mock() self.machine.get_domain = mock.Mock( diff --git a/test/unit/builder_test.py b/test/unit/builder_test.py index 6e947e80..e1f482b0 100644 --- a/test/unit/builder_test.py +++ b/test/unit/builder_test.py @@ -29,7 +29,7 @@ class TestImageBuilder(object): ) ImageBuilder(xml_state, 'target_dir', 'root_dir') mock_builder.assert_called_once_with( - xml_state, 'target_dir', 'root_dir' + xml_state, 'target_dir', 'root_dir', None ) @patch('kiwi.builder.LiveImageBuilder') @@ -40,7 +40,7 @@ class TestImageBuilder(object): ) ImageBuilder(xml_state, 'target_dir', 'root_dir') mock_builder.assert_called_once_with( - xml_state, 'target_dir', 'root_dir' + xml_state, 'target_dir', 'root_dir', None ) @patch('kiwi.builder.PxeBuilder') @@ -51,7 +51,7 @@ class TestImageBuilder(object): ) ImageBuilder(xml_state, 'target_dir', 'root_dir') mock_builder.assert_called_once_with( - xml_state, 'target_dir', 'root_dir' + xml_state, 'target_dir', 'root_dir', None ) @patch('kiwi.builder.ArchiveBuilder') diff --git a/test/unit/cli_test.py b/test/unit/cli_test.py index 74f2ef6a..ed2711eb 100644 --- a/test/unit/cli_test.py +++ b/test/unit/cli_test.py @@ -46,6 +46,7 @@ class TestCli(object): '--delete-package': [], '--set-container-derived-from': None, '--set-container-tag': None, + '--signing-key': [], '-h': False, 'help': False, 'prepare': True, diff --git a/test/unit/package_manager_apt_test.py b/test/unit/package_manager_apt_test.py index 01119e1e..14e9b5a5 100644 --- a/test/unit/package_manager_apt_test.py +++ b/test/unit/package_manager_apt_test.py @@ -12,6 +12,8 @@ class TestPackageManagerApt(object): def setup(self): repository = mock.Mock() repository.root_dir = 'root-dir' + repository.signing_keys = ['key-file.asc'] + repository.unauthenticated = 'false' root_bind = mock.Mock() root_bind.move_to_root = mock.Mock( @@ -76,12 +78,13 @@ class TestPackageManagerApt(object): mock_exists.return_value = True self.manager.process_install_requests_bootstrap() + @patch('kiwi.logger.log.warning') @patch('kiwi.command.Command.call') @patch('kiwi.command.Command.run') @patch('os.path.exists') @patch('kiwi.package_manager.apt.DataSync') def test_process_install_requests_bootstrap( - self, mock_sync, mock_exists, mock_run, mock_call + self, mock_sync, mock_exists, mock_run, mock_call, mock_warn ): self.manager.request_package('apt-get') self.manager.request_package('vim') @@ -101,6 +104,9 @@ class TestPackageManagerApt(object): 'debootstrap', '--no-check-gpg', 'xenial', 'root-dir.debootstrap', 'xenial_path'], ['env']), + call([ + 'chroot', 'root-dir', 'apt-key', 'add', 'key-file.asc' + ], ['env']), call(['rm', '-r', '-f', 'root-dir.debootstrap']), call([ 'chroot', 'root-dir', 'apt-get', @@ -112,6 +118,7 @@ class TestPackageManagerApt(object): 'root-moved-arguments', 'install', 'vim'], ['env'] ) + assert mock_warn.called @patch('kiwi.command.Command.call') @patch('kiwi.command.Command.run') diff --git a/test/unit/repository_apt_test.py b/test/unit/repository_apt_test.py index 525cee7a..83e9bf11 100644 --- a/test/unit/repository_apt_test.py +++ b/test/unit/repository_apt_test.py @@ -128,6 +128,10 @@ class TestRepositoryApt(object): '/shared-dir/apt-get/sources.list.d/foo.list', 'w' ) + def test_import_trusted_keys(self): + self.repo.import_trusted_keys(['key-file-a.asc', 'key-file-b.asc']) + assert self.repo.signing_keys == ['key-file-a.asc', 'key-file-b.asc'] + @patch('kiwi.path.Path.wipe') def test_delete_repo(self, mock_wipe): self.repo.delete_repo('foo') diff --git a/test/unit/repository_base_test.py b/test/unit/repository_base_test.py index 27b22b7d..5a9e4b45 100644 --- a/test/unit/repository_base_test.py +++ b/test/unit/repository_base_test.py @@ -27,6 +27,10 @@ class TestRepositoryBase(object): 'user', 'secret', 'credentials-file' ) + @raises(NotImplementedError) + def test_import_trusted_keys(self): + self.repo.import_trusted_keys(['key-file.asc']) + @raises(NotImplementedError) def test_delete_repo(self): self.repo.delete_repo('name') diff --git a/test/unit/repository_dnf_test.py b/test/unit/repository_dnf_test.py index b828b103..800d41ad 100644 --- a/test/unit/repository_dnf_test.py +++ b/test/unit/repository_dnf_test.py @@ -41,7 +41,6 @@ class TestRepositoryDnf(object): call('main', 'obsoletes', '1'), call('main', 'plugins', '1'), call('main', 'gpgcheck', '0'), - call('main', 'repo_gpgcheck', '0'), call('main', 'tsflags', 'nodocs'), call('main', 'enabled', '1') ] @@ -81,7 +80,6 @@ class TestRepositoryDnf(object): call('main', 'obsoletes', '1'), call('main', 'plugins', '1'), call('main', 'gpgcheck', '0'), - call('main', 'repo_gpgcheck', '0'), call('main', 'tsflags', 'nodocs'), call('main', 'enabled', '1') ] @@ -112,6 +110,14 @@ class TestRepositoryDnf(object): '/shared-dir/dnf/repos/foo.repo', 'w' ) + @patch('kiwi.command.Command.run') + def test_import_trusted_keys(self, mock_run): + self.repo.import_trusted_keys(['key-file-a.asc', 'key-file-b.asc']) + assert mock_run.call_args_list == [ + call(['rpm', '--root', '../data', '--import', 'key-file-a.asc']), + call(['rpm', '--root', '../data', '--import', 'key-file-b.asc']) + ] + @patch('kiwi.path.Path.wipe') def test_delete_repo(self, mock_wipe): self.repo.delete_repo('foo') diff --git a/test/unit/repository_yum_test.py b/test/unit/repository_yum_test.py index ff7e3819..073f7a42 100644 --- a/test/unit/repository_yum_test.py +++ b/test/unit/repository_yum_test.py @@ -40,7 +40,6 @@ class TestRepositoryYum(object): call('main', 'obsoletes', '1'), call('main', 'plugins', '1'), call('main', 'gpgcheck', '0'), - call('main', 'repo_gpgcheck', '0'), call('main', 'metadata_expire', '1800'), call('main', 'group_command', 'compat'), call('main', 'enabled', '1') @@ -84,7 +83,6 @@ class TestRepositoryYum(object): call('main', 'obsoletes', '1'), call('main', 'plugins', '1'), call('main', 'gpgcheck', '0'), - call('main', 'repo_gpgcheck', '0'), call('main', 'metadata_expire', '1800'), call('main', 'group_command', 'compat'), call('main', 'enabled', '1') @@ -116,6 +114,14 @@ class TestRepositoryYum(object): '/shared-dir/yum/repos/foo.repo', 'w' ) + @patch('kiwi.command.Command.run') + def test_import_trusted_keys(self, mock_run): + self.repo.import_trusted_keys(['key-file-a.asc', 'key-file-b.asc']) + assert mock_run.call_args_list == [ + call(['rpm', '--root', '../data', '--import', 'key-file-a.asc']), + call(['rpm', '--root', '../data', '--import', 'key-file-b.asc']) + ] + @patch('kiwi.path.Path.wipe') def test_delete_repo(self, mock_wipe): self.repo.delete_repo('foo') diff --git a/test/unit/repository_zypper_test.py b/test/unit/repository_zypper_test.py index f131f869..c5a2f127 100644 --- a/test/unit/repository_zypper_test.py +++ b/test/unit/repository_zypper_test.py @@ -126,6 +126,14 @@ class TestRepositoryZypper(object): ]) ] + @patch('kiwi.command.Command.run') + def test_import_trusted_keys(self, mock_run): + self.repo.import_trusted_keys(['key-file-a.asc', 'key-file-b.asc']) + assert mock_run.call_args_list == [ + call(['rpm', '--root', '../data', '--import', 'key-file-a.asc']), + call(['rpm', '--root', '../data', '--import', 'key-file-b.asc']) + ] + @patch('kiwi.command.Command.run') @patch('kiwi.repository.zypper.Path.wipe') @patch('os.path.exists') diff --git a/test/unit/system_prepare_test.py b/test/unit/system_prepare_test.py index 17d449b9..9ca3876d 100644 --- a/test/unit/system_prepare_test.py +++ b/test/unit/system_prepare_test.py @@ -181,7 +181,10 @@ class TestSystemPrepare(object): repo = mock.Mock() mock_repo.return_value = repo - self.system.setup_repositories(clear_cache=True) + self.system.setup_repositories( + clear_cache=True, + signing_keys=['key-file-a.asc', 'key-file-b.asc'] + ) mock_repo.assert_called_once_with( self.system.root_bind, 'package-manager-name', @@ -211,6 +214,9 @@ class TestSystemPrepare(object): call('uri-alias'), call('uri-alias') ] + repo.import_trusted_keys.assert_called_once_with( + ['key-file-a.asc', 'key-file-b.asc'] + ) @patch('kiwi.system.prepare.Repository') @patch('kiwi.system.prepare.Uri') diff --git a/test/unit/tasks_system_build_test.py b/test/unit/tasks_system_build_test.py index acfdcb61..b702f033 100644 --- a/test/unit/tasks_system_build_test.py +++ b/test/unit/tasks_system_build_test.py @@ -82,6 +82,7 @@ class TestSystemBuildTask(object): self.task.command_args['--set-container-derived-from'] = None self.task.command_args['--set-container-tag'] = None self.task.command_args['--clear-cache'] = False + self.task.command_args['--signing-key'] = None @patch('kiwi.logger.Logger.set_logfile') def test_process_system_build(self, mock_log): @@ -92,7 +93,7 @@ class TestSystemBuildTask(object): self.runtime_checker.check_image_include_repos_http_resolvable.assert_called_once_with() self.runtime_checker.check_target_directory_not_in_shared_cache.assert_called_once_with(self.abs_target_dir) self.runtime_checker.check_repositories_configured.assert_called_once_with() - self.system_prepare.setup_repositories.assert_called_once_with(False) + self.system_prepare.setup_repositories.assert_called_once_with(False, None) self.system_prepare.install_bootstrap.assert_called_once_with( self.manager ) @@ -127,7 +128,7 @@ class TestSystemBuildTask(object): self._init_command_args() self.task.command_args['--add-package'] = ['vim'] self.task.process() - self.system_prepare.setup_repositories.assert_called_once_with(False) + self.system_prepare.setup_repositories.assert_called_once_with(False, None) self.system_prepare.install_packages.assert_called_once_with( self.manager, ['vim'] ) @@ -137,7 +138,7 @@ class TestSystemBuildTask(object): self._init_command_args() self.task.command_args['--delete-package'] = ['vim'] self.task.process() - self.system_prepare.setup_repositories.assert_called_once_with(False) + self.system_prepare.setup_repositories.assert_called_once_with(False, None) self.system_prepare.delete_packages.assert_called_once_with( self.manager, ['vim'] ) diff --git a/test/unit/tasks_system_create_test.py b/test/unit/tasks_system_create_test.py index 105a4172..f084c104 100644 --- a/test/unit/tasks_system_create_test.py +++ b/test/unit/tasks_system_create_test.py @@ -57,6 +57,7 @@ class TestSystemCreateTask(object): self.task.command_args['create'] = False self.task.command_args['--root'] = '../data/root-dir' self.task.command_args['--target-dir'] = 'some-target' + self.task.command_args['--signing-key'] = ['some-key-file'] def test_process_system_create(self): self._init_command_args() diff --git a/test/unit/tasks_system_prepare_test.py b/test/unit/tasks_system_prepare_test.py index b9b32d5b..d7cc7a69 100644 --- a/test/unit/tasks_system_prepare_test.py +++ b/test/unit/tasks_system_prepare_test.py @@ -72,6 +72,7 @@ class TestSystemPrepareTask(object): self.task.command_args['--clear-cache'] = False self.task.command_args['--set-container-derived-from'] = None self.task.command_args['--set-container-tag'] = None + self.task.command_args['--signing-key'] = None def test_process_system_prepare(self): self._init_command_args() @@ -84,7 +85,7 @@ class TestSystemPrepareTask(object): self.abs_root_dir ) self.runtime_checker.check_repositories_configured.assert_called_once_with() - self.system_prepare.setup_repositories.assert_called_once_with(True) + self.system_prepare.setup_repositories.assert_called_once_with(True, None) self.system_prepare.install_bootstrap.assert_called_once_with( self.manager ) @@ -113,7 +114,7 @@ class TestSystemPrepareTask(object): self._init_command_args() self.task.command_args['--add-package'] = ['vim'] self.task.process() - self.system_prepare.setup_repositories.assert_called_once_with(False) + self.system_prepare.setup_repositories.assert_called_once_with(False, None) self.system_prepare.install_packages.assert_called_once_with( self.manager, ['vim'] ) @@ -122,7 +123,7 @@ class TestSystemPrepareTask(object): self._init_command_args() self.task.command_args['--delete-package'] = ['vim'] self.task.process() - self.system_prepare.setup_repositories.assert_called_once_with(False) + self.system_prepare.setup_repositories.assert_called_once_with(False, None) self.system_prepare.delete_packages.assert_called_once_with( self.manager, ['vim'] )