diff --git a/Dockerfile b/Dockerfile index d3c5ffd..ec3cea4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,11 +2,11 @@ FROM archlinux:base-devel RUN pacman-key --init && \ pacman -Sy --noconfirm archlinux-keyring && \ - pacman -Su --noconfirm \ + pacman -Su --noconfirm --needed \ python python-pip \ arch-install-scripts rsync \ aarch64-linux-gnu-gcc aarch64-linux-gnu-binutils aarch64-linux-gnu-glibc aarch64-linux-gnu-linux-api-headers \ - git \ + git sudo \ android-tools openssh inetutils \ parted @@ -32,5 +32,7 @@ RUN pip install -r requirements.txt COPY . . RUN python -c "from distro import distro; distro.get_kupfer_local(arch=None,in_chroot=False).repos_config_snippet()" | tee -a /etc/pacman.conf +RUN useradd -m -g users kupfer +RUN echo "kupfer ALL=(ALL) NOPASSWD: ALL" | tee /etc/sudoers.d/kupfer WORKDIR / diff --git a/local/bin/wrapper_su_helper b/local/bin/wrapper_su_helper new file mode 120000 index 0000000..a1f5932 --- /dev/null +++ b/local/bin/wrapper_su_helper @@ -0,0 +1 @@ +../../wrapper_su_helper.py \ No newline at end of file diff --git a/wrapper/docker.py b/wrapper/docker.py index 0b101c1..94952de 100644 --- a/wrapper/docker.py +++ b/wrapper/docker.py @@ -62,10 +62,13 @@ class DockerWrapper(BaseWrapper): wrapped_config = self.generate_wrapper_config() + target_user = 'root' if config.runtime.uid == 0 else 'kupfer' + target_home = '/root' if target_user == 'root' else f'/home/{target_user}' + ssh_dir = os.path.join(pathlib.Path.home(), '.ssh') if not os.path.exists(ssh_dir): os.makedirs(ssh_dir, mode=0o700) - volumes = self.get_bind_mounts_default(wrapped_config) + volumes = self.get_bind_mounts_default(wrapped_config, ssh_dir=ssh_dir, target_home=target_home) volumes |= dict({config.get_path(vol_name): vol_dest for vol_name, vol_dest in DOCKER_PATHS.items()}) docker_cmd = [ 'docker', @@ -78,7 +81,9 @@ class DockerWrapper(BaseWrapper): '--privileged', ] + docker_volumes_args(volumes) + [tag] - kupfer_cmd = ['kupferbootstrap', '--config', '/root/.config/kupfer/kupferbootstrap.toml'] + self.filter_args_wrapper(sys.argv[1:]) + kupfer_cmd = ['kupferbootstrap', '--config', volumes[wrapped_config]] + self.filter_args_wrapper(sys.argv[1:]) + if config.runtime.uid: + kupfer_cmd = ['wrapper_su_helper', '--uid', str(config.runtime.uid), '--username', 'kupfer', '--'] + kupfer_cmd cmd = docker_cmd + kupfer_cmd logging.debug('Wrapping in docker:' + repr(cmd)) diff --git a/wrapper/wrapper.py b/wrapper/wrapper.py index 4dcc6b3..5a0adb3 100644 --- a/wrapper/wrapper.py +++ b/wrapper/wrapper.py @@ -27,7 +27,7 @@ class Wrapper(Protocol): class BaseWrapper(Wrapper): - id: str + uuid: str identifier: str type: str wrapped_config_path: str diff --git a/wrapper_su_helper.py b/wrapper_su_helper.py new file mode 100755 index 0000000..40031e5 --- /dev/null +++ b/wrapper_su_helper.py @@ -0,0 +1,37 @@ +#!/bin/python3 + +import click +import os +import pwd + +from logger import logging, setup_logging + +from exec.cmd import run_cmd +from exec.file import chown + + +@click.command('kupferbootstrap_su') +@click.option('--username', default='kupfer', help="The user's name. If --uid is provided, the user's uid will be changed to this in passwd") +@click.option('--uid', default=1000, type=int, help='uid to change $username to and run as') +@click.argument('cmd', type=str, nargs=-1) +def kupferbootstrap_su(cmd: list[str], uid: int = 1000, username: str = 'kupfer'): + "Changes `username`'s uid to `uid` and executes kupferbootstrap as that user" + cmd = list(cmd) + user = pwd.getpwnam(username) + home = user.pw_dir + if uid != user.pw_uid: + run_cmd(['usermod', '-u', str(uid), username]).check_returncode() # type: ignore[union-attr] + chown(home, username, recursive=False) + env = os.environ | { + 'HOME': home, + 'USER': username, + } + logging.debug(f'wrapper: running {cmd} as {repr(username)}') + result = run_cmd(cmd, attach_tty=True, switch_user=username, env=env) + assert isinstance(result, int) + exit(result) + + +if __name__ == '__main__': + setup_logging(True) + kupferbootstrap_su(prog_name='kupferbootstrap_su_helper')