image: add LUKS support and --[no-]encryption CLI flag to build & inspect subcommands

This commit is contained in:
InsanePrawn 2023-07-09 03:20:33 +02:00
parent 39b9cebc54
commit 6a7bfbb49b
5 changed files with 236 additions and 49 deletions

View file

@ -6,7 +6,7 @@ from signal import pause
from typing import Optional
from config.state import config, Profile
from constants import BASE_LOCAL_PACKAGES, BASE_PACKAGES
from constants import BASE_LOCAL_PACKAGES, BASE_PACKAGES, LUKS_MAPPER_DEFAULT
from devices.device import get_profile_device
from exec.file import makedir
from flavours.flavour import get_profile_flavour
@ -14,6 +14,7 @@ from packages.build import build_enable_qemu_binfmt, build_packages, filter_pkgb
from wrapper import enforce_wrap
from .boot import cmd_boot
from .cryptsetup import encryption_option, get_cryptmapper_path, luks_close, luks_create, luks_open
from .flash import cmd_flash
from .image import (
IMG_FILE_BOOT_DEFAULT_SIZE,
@ -84,6 +85,7 @@ sectorsize_option = click.option(
default=False,
is_flag=True,
)
@encryption_option
@sectorsize_option
def cmd_build(
profile_name: Optional[str] = None,
@ -93,6 +95,9 @@ def cmd_build(
block_target: Optional[str] = None,
sector_size: Optional[int] = None,
skip_part_images: bool = False,
encryption: Optional[bool] = None,
encryption_password: Optional[str] = None,
encryption_mapper: str = LUKS_MAPPER_DEFAULT,
):
"""
Build a device image.
@ -110,9 +115,15 @@ def cmd_build(
flavour = get_profile_flavour(profile_name)
rootfs_size_mb = flavour.parse_flavourinfo().rootfs_size * 1000 + int(profile.size_extra_mb)
if encryption is None:
encryption = profile.encryption
packages = BASE_LOCAL_PACKAGES + [device.package.name, flavour.pkgbuild.name]
packages_extra = BASE_PACKAGES + profile.pkgs_include
if encryption:
packages_extra += ['cryptsetup', 'util-linux'] # TODO: select osk-sdl here somehow
if arch != config.runtime.arch:
build_enable_qemu_binfmt(arch)
@ -140,6 +151,7 @@ def cmd_build(
boot_dev: str
root_dev: str
root_dev_raw: str
loop_boot = loop_device + 'p1'
loop_root = loop_device + 'p2'
if skip_part_images:
@ -150,8 +162,23 @@ def cmd_build(
boot_dev = create_img_file(get_image_path(device, flavour, 'boot'), IMG_FILE_BOOT_DEFAULT_SIZE)
root_dev = create_img_file(get_image_path(device, flavour, 'root'), f'{rootfs_size_mb - 200}M')
create_boot_fs(boot_dev, sector_size)
root_dev_raw = root_dev
if encryption:
encryption_password = encryption_password or profile.encryption_password
if not encryption_password:
encryption_password = click.prompt(
"Please enter your encryption password (input hidden)",
hide_input=True,
confirmation_prompt=True,
)
luks_create(root_dev, password=encryption_password)
luks_open(root_dev, mapper_name=encryption_mapper, password=encryption_password)
root_dev = get_cryptmapper_path(encryption_mapper)
assert os.path.exists(root_dev)
create_root_fs(root_dev, sector_size)
create_boot_fs(boot_dev, sector_size)
install_rootfs(
root_dev,
@ -162,14 +189,17 @@ def cmd_build(
list(set(packages) | set(packages_extra)),
local_repos,
profile,
encrypted=bool(encryption),
)
if encryption:
luks_close(mapper_name=encryption_mapper)
if not skip_part_images:
logging.info('Copying partition image files into full image:')
logging.info(f'Block-copying /boot to {image_path}')
dd_image(input=boot_dev, output=loop_boot)
logging.info(f'Block-copying rootfs to {image_path}')
dd_image(input=root_dev, output=loop_root)
dd_image(input=root_dev_raw, output=loop_root)
logging.info(f'Done! Image saved to {image_path}')
@ -178,17 +208,20 @@ def cmd_build(
@click.option('--shell', '-s', is_flag=True)
@click.option('--use-local-repos', '-l', is_flag=True)
@sectorsize_option
@encryption_option
@click.argument('profile', required=False)
def cmd_inspect(
profile: Optional[str] = None,
shell: bool = False,
sector_size: Optional[int] = None,
use_local_repos: bool = False,
encryption: Optional[bool] = None,
):
"""Loop-mount the device image for inspection."""
config.enforce_profile_device_set()
config.enforce_profile_flavour_set()
enforce_wrap()
profile_conf = config.get_profile(profile)
device = get_profile_device(profile)
arch = device.arch
flavour = get_profile_flavour(profile).name
@ -198,7 +231,7 @@ def cmd_inspect(
image_path = get_image_path(device, flavour)
loop_device = losetup_rootfs_image(image_path, sector_size)
partprobe(loop_device)
mount_chroot(loop_device + 'p2', loop_device + 'p1', chroot)
mount_chroot(loop_device + 'p2', loop_device + 'p1', chroot, password=profile_conf.encryption_password)
logging.info(f'Inspect the rootfs image at {chroot.path}')