From 366ed9b4fe8759a1b5c76fd73bb9a67fd71b396b Mon Sep 17 00:00:00 2001 From: ldericher Date: Mon, 17 Aug 2020 17:56:29 +0200 Subject: [PATCH] Rootkit implementation for copyconf (and other commands as root) --- src/kiwi/subcommands/copy_conf.py | 39 +++-------- src/kiwi/subcommands/utils/rootkit.py | 99 +++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 30 deletions(-) create mode 100644 src/kiwi/subcommands/utils/rootkit.py diff --git a/src/kiwi/subcommands/copy_conf.py b/src/kiwi/subcommands/copy_conf.py index 805640b..db694ea 100644 --- a/src/kiwi/subcommands/copy_conf.py +++ b/src/kiwi/subcommands/copy_conf.py @@ -10,6 +10,7 @@ from .._constants import KIWI_ROOT from ._subcommand import SubCommand from .utils.dockercommand import DockerCommand from .utils.project import list_projects, get_project_dir +from .utils.rootkit import Rootkit, prefix_path def _add_prefix(prefix, path): @@ -27,43 +28,21 @@ class CopyConfCommand(SubCommand): ) def run(self, runner, config, args): - logging.info("Building image kiwi-config/auxiliary:rsync") - DockerCommand('docker').run( - config, args, - [ - 'build', - '-t', 'kiwi-config/auxiliary:rsync', - '-f', f"{KIWI_ROOT}/images/rsync.Dockerfile", - f"{KIWI_ROOT}/images" - ], - stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL - ) - - conf_sources = [] + conf_dirs = [] for project_name in list_projects(config): project_conf = f"{get_project_dir(config, project_name)}/conf" if os.path.isdir(project_conf): - conf_sources.append(project_conf) + conf_dirs.append(project_conf) - if conf_sources: - print(f"Syncing {conf_sources} to '{config['runtime:storage']}'") - conf_sources = [f"'{_add_prefix('/mnt', src)}'" for src in conf_sources] - conf_sources = ' '.join(conf_sources) + if conf_dirs: + # add target directory + conf_dirs.append(config['runtime:storage']) + logging.info(f"Sync directories: {conf_dirs}") - conf_target = f"'{_add_prefix('/mnt', config['runtime:storage'])}'" - logging.debug(f"Config sources {conf_sources}, Config target {conf_target}") - - DockerCommand('docker').run( - config, args, - [ - 'run', '--rm', - '-v', '/:/mnt', - '-u', 'root', - 'kiwi-config/auxiliary:rsync', - 'ash', '-c', f"rsync -r {conf_sources} {conf_target}" - ], + Rootkit('rsync').run( + config, args, ['rsync', '-r', *prefix_path(conf_dirs)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) diff --git a/src/kiwi/subcommands/utils/rootkit.py b/src/kiwi/subcommands/utils/rootkit.py new file mode 100644 index 0000000..c18e5ac --- /dev/null +++ b/src/kiwi/subcommands/utils/rootkit.py @@ -0,0 +1,99 @@ +# system +import logging +import os +import subprocess + +# parent +from ..._constants import KIWI_ROOT + +# local +from .dockercommand import DockerCommand + + +def _prefix_path(prefix, path): + abs_path = os.path.abspath(path) + return os.path.realpath(prefix + '/' + abs_path) + + +def prefix_path(path): + if isinstance(path, str): + return _prefix_path('/mnt/', path) + elif isinstance(path, list): + return [_prefix_path('/mnt/', p) for p in path] + + +def _image_name(image_tag): + if image_tag is not None: + return f"kiwi-config/auxiliary:{image_tag}" + else: + return "alpine:latest" + + +class Rootkit: + class __Rootkit: + __image_tag = None + + def __init__(self, image_tag=None): + self.__image_tag = image_tag + + def __exists(self, config, args): + ps = DockerCommand('docker').run( + config, args, [ + 'images', + '--filter', f"reference={_image_name(self.__image_tag)}", + '--format', '{{.Repository}}:{{.Tag}}' + ], + stdout=subprocess.PIPE + ) + + return str(ps.stdout, 'utf-8').strip() == _image_name(self.__image_tag) + + def __build_image(self, config, args): + if self.__exists(config, args): + logging.info(f"Using image {_image_name(self.__image_tag)}") + else: + if self.__image_tag is None: + logging.info(f"Pulling image {_image_name(self.__image_tag)}") + DockerCommand('docker').run( + config, args, ['pull', _image_name(self.__image_tag)], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL + ) + + else: + logging.info(f"Building image {_image_name(self.__image_tag)}") + DockerCommand('docker').run( + config, args, + [ + 'build', + '-t', _image_name(self.__image_tag), + '-f', f"{KIWI_ROOT}/images/{self.__image_tag}.Dockerfile", + f"{KIWI_ROOT}/images" + ], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL + ) + + def run(self, config, args, process_args, **kwargs): + self.__build_image(config, args) + DockerCommand('docker').run( + config, args, + [ + 'run', '--rm', + '-v', '/:/mnt', + '-u', 'root', + _image_name(self.__image_tag), + *process_args + ], + **kwargs + ) + + __image_tag = None + __instances = {} + + def __init__(self, image_tag=None): + self.__image_tag = image_tag + + if _image_name(self.__image_tag) not in Rootkit.__instances: + Rootkit.__instances[_image_name(self.__image_tag)] = Rootkit.__Rootkit(image_tag) + + def __getattr__(self, item): + return getattr(self.__instances[_image_name(self.__image_tag)], item)