File disk-encryption-tool-1+git20250505.aa666d1.obscpio of Package disk-encryption-tool

07070100000000000081A40000000000000000000000016818B1A100000026000000000000000000000000000000000000003A00000000disk-encryption-tool-1+git20250505.aa666d1/.dir-locals.el((sh-mode . ((sh-basic-offset . 8))))
07070100000001000081A40000000000000000000000016818B1A10000013B000000000000000000000000000000000000003900000000disk-encryption-tool-1+git20250505.aa666d1/.editorconfig# EditorConfig configuration for sdbootutil
# http://EditorConfig.org

# Top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file, utf-8 charset
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = tab
indent_size = 8
07070100000002000041ED0000000000000000000000026818B1A100000000000000000000000000000000000000000000003300000000disk-encryption-tool-1+git20250505.aa666d1/.github07070100000003000041ED0000000000000000000000026818B1A100000000000000000000000000000000000000000000003D00000000disk-encryption-tool-1+git20250505.aa666d1/.github/workflows07070100000004000081A40000000000000000000000016818B1A10000026B000000000000000000000000000000000000004600000000disk-encryption-tool-1+git20250505.aa666d1/.github/workflows/test.ymlname: MicroOS in QEMU
on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Install dependencies
      run: |
        sudo apt update
        sudo apt install -y qemu-system-x86 ovmf
        # Normally setfacl -m u:$USER:rw /dev/kvm should work, but for some
        # reason this only sticks around for a single QEMU run. udev?
        sudo usermod -a -G kvm "$USER"
    - name: Test
      run: |
        # Needed to activate the new kvm group membership
        sudo -u "$USER" bash test/test.sh
07070100000005000081A40000000000000000000000016818B1A10000042E000000000000000000000000000000000000003300000000disk-encryption-tool-1+git20250505.aa666d1/LICENSEMIT License

Copyright (c) 2023 Ludwig Nussel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
07070100000006000081A40000000000000000000000016818B1A1000006DC000000000000000000000000000000000000003500000000disk-encryption-tool-1+git20250505.aa666d1/README.mdTool to turn a plain text image into one using LUKS full disk
encryption. There are three modes:

* Directly encrypt a disk image on a host system. The image can then
  be deployed somewhere else
* Prime a disk image by adding code to the initrd of the image that
  encrypts the image on first boot
* Include the initrd code already when building an image. The image
  would then encrypt itself on first boot.

In general the tool is developed with [kiwi](https://github.com/OSInside/kiwi)
in mind. It assumes that the image contains a single root fs using btrfs in the
third partition. Both grub2 and systemd-boot are supported. The tool generates
a

Example to directly encrypt an image:

    disk-encryption-tool -v SLE-Micro.x86_64-5.4.0-Default-GM.raw

Example to prime a plain text image to encrypt on first boot:

    disk-encryption-tool -v --prime SLE-Micro.x86_64-5.4.0-Default-GM.raw


When run on first boot the tool integrates with
[jeos-firstboot](https://github.com/openSUSE/jeos-firstboot/). The encryption
in initrd deploys an automatically generated recovery key, compatible with
[systemd-cryptenroll](https://www.freedesktop.org/software/systemd/man/latest/systemd-cryptenroll.html).
Later in the real root a jeos-firsboot module then offers to deploy
either the root password or another custom passphrase as well.

Parameters for cryptsetup-reencrypt(8) can be passed via
`/etc/encrypt_options`. One option per line, e.g.

   --type=luks1
   --iter-time=2000

It's also possible to integrate with combustion. The combustion
script would have to look like this:

    #!/bin/bash
    # combustion: prepare
    if [ "$1" = "--prepare" ]; then
        echo 12345 | disk-encryption-tool -v
    else
        echo root:12345 | chpasswd
    fi
07070100000007000081ED0000000000000000000000016818B1A1000024DD000000000000000000000000000000000000004000000000disk-encryption-tool-1+git20250505.aa666d1/disk-encryption-tool#!/bin/bash
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
set -e
shopt -s nullglob

unset "${!LC_@}"
LANG="C.utf8"
export LANG

verbose=
password=
keyring=
crypttab_options=
root_mp=

is_generated=1
is_rootfs=1
switched_rw=
cr_name=
cr_dev=
blkdev=
blkpart=
mp=
mounted=
keyid=

tmpdir=$(mktemp -d -t disk-encryption-tool.XXXXXX)

cleanup()
{
	set +e
	if [ -n "$mp" ]; then
		while read -r i; do
			[ -z "$is_rootfs" ] || [ "$i" != "$mp" ] || make_ro
			umount "$i"
		done < <(findmnt -o TARGET -Rn --list "$mp" | tac)
	fi
	if [ -n "$mounted" ]; then
		if [ -e "$tmpdir/mounts" ]; then
			# restore previous mounts
			while read -r line; do
				eval "$line"
				mapfile -td, options < <(echo -n "$OPTIONS")
				if [ -n "$cr_dev" ] && [ "$SOURCE" = "$blkpart" ]; then
					SOURCE="$cr_dev"
				fi
				mount "$SOURCE" "$TARGET" -t "$FSTYPE" -o "$OPTIONS"
			done < "$tmpdir/mounts"
		fi
	fi
	[ -d "$tmpdir" ] && ! mountpoint -q "$tmpdir/mnt" && rm -rf "$tmpdir"
}
trap cleanup EXIT

helpandquit()
{
	cat <<-EOF
		Usage: $0 [OPTIONS] [MOUNTPOINT|BLOCKDEV] [VOLUME_NAME]

		Encrypt MOUNTPOINT or BLOCKDEV.  If not specified, uses /sysroot
		Default VOLUME_NAME is cr_root

		OPTIONS:
		  --verbose       verbose
		  --key           LUKS2 key (use --verbose to print the key if generated)
		  --keyring       store the generated key in the specified keyring
		  --options	  /etc/crypttab options
				  auto: (default) set x-initrd.{mount,attach} if required
				  none: set empty options
				  <options>: set <options>
		  --root          root filesystem (when different from device to encrypt)
		  -h              help screen

	EOF
	exit 0
}

log_info()
{
	[ "${verbose:-0}" -gt 0 ] || return 0
	echo "$@"
}

err()
{
	echo "Error: $*" >&2
	exit 1
}

warn()
{
	echo "Warning: $*" >&2
}

isdigits()
{
       local v="${1:?}"
       [ -z "${v//[0-9]*/}" ]
}

settle_umount_events()
{
	# Manual umount confuses systemd sometimes because it's async
	# and the .mount unit might still be active when the "start"
	# is queued, making it a noop, which ultimately leaves
	# /sysroot unmounted.
	#
	# (see https://github.com/systemd/systemd/issues/20329)
	#
	# To avoid that, wait until systemd processed the umount
	# events. In a chroot (or with SYSTEMD_OFFLINE=1) systemctl
	# always succeeds, so avoid an infinite loop.
	#
	if [ "$mounted" = "/sysroot" ] && ! systemctl --quiet is-active does-not-exist.mount; then
		while systemctl --quiet is-active sysroot.mount; do sleep 0.5; done
	fi
}

encrypt()
{
	local encrypt_options=(
		--reduce-device-size=32m
		--progress-frequency=1
	)
	if [ -e "${ENCRYPTION_CONFIG:-/etc/encrypt_options}" ]; then
		while read -r op; do
			[ "${op//#}" = "$op" ] || continue
			encrypt_options+=("$op")
		done < "${ENCRYPTION_CONFIG:-/etc/encrypt_options}"
	fi
	log_info "encrypt with options ${encrypt_options[*]}"
	if [ -n "$password" ]; then
		# XXX: hopefully we can use the kernel keyring in the future here
		cryptsetup reencrypt --force-password --verbose --encrypt "${encrypt_options[@]}" "$@" "${blkpart}" "$cr_name" <<<"$password"
		[ -z "$is_generated" ] || echo '{"type":"enrollment-key","keyslots":["0"]}' | cryptsetup token import "${blkpart}"
	else
		cryptsetup reencrypt --batch-mode --verify-passphrase --force-password --verbose --encrypt "${encrypt_options[@]}" "$@" "${blkpart}" "$cr_name"
	fi
	cr_dev="/dev/mapper/$cr_name"
}

make_rw()
{
	local mp="${1:-$mp}"
	local prop
	read -r prop < <(btrfs prop get -t s "$mp" ro)
	[ "$prop" = "ro=true" ] || return 0
	log_info "switch to rw"
	btrfs prop set -t s "$mp" ro false
	switched_rw=1
}

make_ro()
{
	local mp="${1:-$mp}"
	[ -n "$switched_rw" ] || return 0
	unset switched_rw
	log_info "set ro again"
	btrfs prop set -t s "$mp" ro true
}


####### main #######
getopttmp=$(getopt -o hv --long help,verbose,key:,keyring:,options:,root: -n "${0##*/}" -- "$@")
eval set -- "$getopttmp"

while true ; do
        case "$1" in
                -h|--help) helpandquit ;;
		-v|--verbose) verbose=$((++verbose)); shift ;;
		--key) password="$2"; is_generated=; shift 2 ;;
		--keyring) keyring="$2"; shift 2 ;;
		--options) crypttab_options="$2"; shift 2 ;;
		--root) root_mp="$2"; is_rootfs=; shift 2 ;;
                --) shift ; break ;;
                *) echo "Internal error!" ; exit 1 ;;
        esac
done

[ -z "$1" ] && [ -e /etc/initrd-release ] && set -- /sysroot cr_root

{ [ -n "$1" ] && [ -n "$2" ]; } || helpandquit

cr_name="$2"
[ -e "/dev/mapper/$cr_name" ] && err "$cr_name exists. Exit."

if [ -d "$1" ] || [ -b "$1" ]; then
	if [ -b "$1" ]; then
		blkpart="$1"
	else
		mountpoint -q "$1" || err "$1 is not a valid mountpoint"
		mp="$1"
		mounted="$1"
		blkpart="$(findmnt -nvo SOURCE "$mp")"
	fi

	[ -L "/sys/class/block/${blkpart##*/}" ] || err "$blkpart is not a partition"
	blkdev="$(readlink -f "/sys/class/block/${blkpart##*/}")"
	blkdev="${blkdev%/*}"
	blkdev="/dev/${blkdev##*/}"
	read -r partno < "/sys/class/block/${blkpart##*/}"/partition
fi
shift 2

declare loop_TYPE is_btrfs is_swap
eval "$(blkid -c /dev/null -o export "$blkpart"|sed 's/^/loop_/')"
[ "$loop_TYPE" != crypto_LUKS ] || { echo "Already encrypted"; exit 0; }
[ "$loop_TYPE" != btrfs ] || is_btrfs=1
[ "$loop_TYPE" != swap ] || is_swap=1

if [ -n "$is_btrfs" ]; then
	if [ -z "$mounted" ]; then
		log_info "mounting fs"
		mkdir -p "$tmpdir/mnt"
		mount -t btrfs -o rw "${blkpart}" "$tmpdir/mnt"
		mp="$tmpdir/mnt"
	else
		mountpoint -q "$mp" || err "$mp is not mounted"
		findmnt -o SOURCE,TARGET,FSTYPE,OPTIONS -Rvn --pairs "$mp" > "$tmpdir/mounts"
		mount -o remount,rw "$mp"
	fi

	read -r minsize bytes _rest < <(btrfs inspect-internal min-dev-size "$mp")
	isdigits "$minsize" || err "Failed to read minimum btrfs size"
	[ "$bytes" = 'bytes' ] || err "Failed to read minimum btrfs size"

	log_info "resizing fs"
	btrfs filesystem resize "$minsize" "$mp"

	if [ -e "$tmpdir/mounts" ]; then
		# Subshell intentional here
		tac "$tmpdir/mounts" | while read -r line; do
			eval "$line"
			umount "$TARGET"
		done
	else
		umount "$mp"
	fi
	unset mp

	settle_umount_events
elif [ -n "$is_swap" ]; then
	# sfdisk returns the size in Kilobytes. We choose a very small
	# size, as in any case we need to do the mkswap later again
	minsize=$(($(sfdisk --show-size "$blkpart")*1024))
	minswap=$((512*1024))
	minsize=$((minsize < minswap ? minsize : minswap))
fi

if [ -n "$is_btrfs" ] || [ -n "$is_swap" ]; then
	# Shrink partition to a minimum so reencryption doesn't write
	# everything
	log_info "resizing partition"
	echo "size=$((minsize/1024+32*1024))KiB" | sfdisk --force --no-reread -q -N "$partno" "$blkdev" &> /dev/null
	udevadm settle
	if [ -e /etc/initrd-release ]; then
		# Seems to be the only way to tell the kernel about a
		# specific partition change
		partx -u --nr "$partno" "$blkdev" || :
	fi
fi

# If a keyring is set, see if the password is stored there and recover
# it.  It is useful for multidisk setups
if [ -n "$keyring" ]; then
	keyid="$(keyctl id %user:"$keyring" 2> /dev/null)" || :
	if [ -n "$keyid" ]; then
		password="$(keyctl pipe "$keyid")"
	fi
fi

if [ -z "$password" ]; then
	password="$(dd if=/dev/urandom bs=8 count=1 2> /dev/null | base64)"
	[ -z "$keyring" ] || echo -n "$password" | keyctl padd user "$keyring" @u > /dev/null
	[ -z "$verbose" ] || echo -e "Enrollment key: \e[1m$password\e[m"
fi

echo "Encrypting..."
encrypt "$@"

if [ -n "$is_btrfs" ] || [ -n "$is_swap" ]; then
	log_info "grow partition again"
	# TODO: recover the size back
	echo ", +" | sfdisk --no-reread -q -N "$partno" "$blkdev" &> /dev/null
	if [ -e /etc/initrd-release ]; then
		# Seems to be the only way to tell the kernel about a
		# specific partition change
		partx -u --nr "$partno" "$blkdev" || :
		cryptsetup resize "$cr_name" <<<"$password"
	fi
fi

if [ -n "$is_btrfs" ]; then
	if [ -z "$mounted" ]; then
		mount -o rw "$cr_dev" "$tmpdir/mnt"
		mp="$tmpdir/mnt"
	else
		read -r line < "$tmpdir/mounts"
		eval "$line"
		mapfile -td, options < <(echo -n "$OPTIONS")
		for ((i=0;i<${#options};++i)); do [ "${options[i]}" = ro ] && options[i]=rw; done
		OPTIONS="$(IFS=, eval echo '"${options[*]}"')"
		[ "$SOURCE" = "$blkpart" ] && SOURCE="$cr_dev"
		mount "$cr_dev" "$TARGET" -t "$FSTYPE" -o "$OPTIONS"
		mp="$TARGET"
	fi

	log_info "resizing fs to max again"
	btrfs filesystem resize max "$mp"

	root_mp="${root_mp:-$mp}"

	make_rw "$root_mp"
elif [ -n "$is_swap" ]; then
	declare loop_UUID
	eval "$(blkid -c /dev/null -o export "$cr_dev"|sed 's/^/loop_/')"
	if [ -n "$loop_UUID" ]; then
		mkswap --uuid "$loop_UUID" "$cr_dev"
	else
		warn "Can't determine device UUID. Can't recreate swap with same UUID"
		mkswap "$cr_dev"
	fi
fi

declare loop_UUID
eval "$(blkid -c /dev/null -o export "$blkpart"|sed 's/^/loop_/')"
if [ -n "$loop_UUID" ]; then
	opts=
	if [ -z "$crypttab_options" ] || [ "$crypttab_options" = "auto" ]; then
		# TODO: should cr_etc and/or cr_var be attached to
		# initrd in MicroOS?
		if [ "$cr_name" = "cr_root" ]; then
			opts="x-initrd.attach"
		fi
	elif [ "$crypttab_options" != "none" ]; then
		opts="$crypttab_options"
	fi
	[ -n "$opts" ] && echo "$cr_name /dev/disk/by-uuid/$loop_UUID none $opts" >> "$root_mp"/etc/crypttab
	[ -z "$opts" ] && echo "$cr_name /dev/disk/by-uuid/$loop_UUID none" >> "$root_mp"/etc/crypttab
else
	warn "Can't determine device UUID. Can't generate crypttab"
fi

if [ -n "$is_btrfs" ]; then
	make_ro "$root_mp"
fi

echo "Image encryption completed"
07070100000008000081ED0000000000000000000000016818B1A100000878000000000000000000000000000000000000004700000000disk-encryption-tool-1+git20250505.aa666d1/disk-encryption-tool-dracut#!/bin/sh

exec < /dev/console >/dev/console 2>&1
type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh

# get systemd credential
# https://systemd.io/CREDENTIALS/
get_credential()
{
	local var="${1:?}"
	local name="${2:?}"
	[ -n "$CREDENTIALS_DIRECTORY" ] || return 1
	[ -e "$CREDENTIALS_DIRECTORY/$name" ] || return 1
	read -r "$var" < "$CREDENTIALS_DIRECTORY/$name" || [ -n "${!var}" ]
}

get_credentials()
{
	local var="${1:?}"
	local name="${2:?}"
	[ -n "$CREDENTIALS_DIRECTORY" ] || return 1
	[ -e "$CREDENTIALS_DIRECTORY/$name" ] || return 1
	readarray -t "$var" < "$CREDENTIALS_DIRECTORY/$name" || [ -n "${!var}" ]
}

encrypt=
if get_credential encrypt disk-encryption-tool-dracut.encrypt && [ "$encrypt" = "no" ]; then
	exit 0
fi

# check whether encryption was explicitly turned off
if ! getargbool 1 rd.encrypt; then
	exit 0
fi

# XXX: this is so dirty
systemctl start sysroot.mount
mount --target-prefix /sysroot --fstab /sysroot/etc/fstab /var
if [ ! -e /sysroot/var/lib/YaST2/reconfig_system ] && [ "$encrypt" != "force" ]; then
	echo "system already configured, no encryption"
	umount /sysroot/var
	exit 0
fi
umount /sysroot/var

# silence systemd
kill -SIGRTMIN+21 1
inhibitor=
if [ "$encrypt" != "force" ]; then
	echo -ne '\n\n\a'
	read -n1 -s -r -t 10 -p "*** Press ESC to prevent encrypting the disk" inhibitor
	echo
fi
if [ "$inhibitor" != $'\e' ]; then
	root_device="$(findmnt -nvo SOURCE /sysroot)"
	root_cr_name="cr_root"
	root_options="auto"
	if get_credentials partitions disk-encryption-tool-dracut.partitions; then
		for line in "${partitions[@]}"; do
			read -r cr_name device options <<<"$line"
			[ "$device" = "$root_device" ] && root_cr_name="$cr_name" && root_options="$options" && continue
			echo "Encrypt $device"
			/usr/bin/disk-encryption-tool --keyring cryptenroll --options "${options:-auto}" --root /sysroot "$device" "$cr_name" || die "Encryption failed"
		done
	fi
	if [ "$root_options" != "skip" ]; then
		echo "Encrypt /sysroot"
		/usr/bin/disk-encryption-tool --keyring cryptenroll --options "${root_options:-auto}" "/sysroot" "$root_cr_name" || die "Encryption failed"
	fi
fi
# turn messages on again
kill -SIGRTMIN+20 1
07070100000009000081A40000000000000000000000016818B1A100000355000000000000000000000000000000000000004F00000000disk-encryption-tool-1+git20250505.aa666d1/disk-encryption-tool-dracut.service[Unit]
Description=Encrypt root disk
DefaultDependencies=false

# /sysroot needs to be available, but it's temporarily stopped
# for remounting so a direct requirement is not possible
Requires=initrd-root-device.target
After=initrd-root-device.target

After=combustion.service

# After ignition completed its stuff
After=ignition-complete.target

# So that /etc/fstab's x-initrd.mount entries are read (again) later
Before=initrd-parse-etc.service

Conflicts=initrd-switch-root.target umount.target
Conflicts=dracut-emergency.service emergency.service emergency.target

# Without this it goes into an endless loop on failure
OnFailure=emergency.target
OnFailureJobMode=isolate

[Service]
Type=oneshot
KeyringMode=shared
ExecStart=/usr/bin/disk-encryption-tool-dracut
ImportCredential=disk-encryption-tool-dracut.*

[Install]
RequiredBy=firstboot.target
0707010000000A000081A40000000000000000000000016818B1A100000787000000000000000000000000000000000000004500000000disk-encryption-tool-1+git20250505.aa666d1/disk-encryption-tool.spec#
# spec file for package disk-encryption-tool
#
# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.

# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
# icecream 0

Name:           disk-encryption-tool
Version:        0
Release:        0
Summary:        Tool to reencrypt kiwi raw images
License:        MIT
URL:            https://github.com/openSUSE/disk-encryption-tool
Source:         disk-encryption-tool-%{version}.tar
Requires:       cryptsetup
Requires:       keyutils
ExclusiveArch:  aarch64 x86_64
BuildArch:      noarch

%description
Convert a plain text kiwi image into one with LUKS full disk
encryption. Supports both raw and qcow2 images. It assumes that the
third partition is the root fs using btrfs.
After encrypting the disk, the fs is mounted and a new initrd
created as well as the grub2 config adjusted.

%prep
%setup -q

%build

%install
mkdir -p %buildroot/usr/lib/dracut/modules.d/95disk-encryption-tool
for i in disk-encryption-tool{,-dracut,-dracut.service} module-setup.sh; do
  cp "$i" %buildroot/usr/lib/dracut/modules.d/95disk-encryption-tool/"$i"
done
mkdir -p %buildroot/usr/bin
ln -s ../lib/dracut/modules.d/95disk-encryption-tool/disk-encryption-tool %buildroot/usr/bin

%files
%license LICENSE
/usr/bin/disk-encryption-tool
%dir /usr/lib/dracut
%dir /usr/lib/dracut/modules.d
/usr/lib/dracut/modules.d/95disk-encryption-tool

%changelog
0707010000000B000081ED0000000000000000000000016818B1A1000003A8000000000000000000000000000000000000003B00000000disk-encryption-tool-1+git20250505.aa666d1/module-setup.sh#!/bin/bash

# called by dracut
check() {
	require_any_binary cryptsetup || return 1
	return 0
}

# called by dracut
depends() {
	echo "crypt"
	return 0
}

# called by dracut
install() {
	instmods dmi_sysfs # for systemd credentials via smbios
	inst_multiple -o cryptsetup-reencrypt
	inst_multiple cryptsetup btrfs mkswap mktemp getopt mountpoint findmnt sfdisk tac sed keyctl partx

	inst_script "$moddir"/disk-encryption-tool /usr/bin/disk-encryption-tool
	inst_script "$moddir"/disk-encryption-tool-dracut /usr/bin/disk-encryption-tool-dracut

	for service in "disk-encryption-tool-dracut.service"; do
		inst_simple "${moddir}/$service" "${systemdsystemunitdir}/$service"
		$SYSTEMCTL -q --root "$initdir" enable "$service"
		#$SYSTEMCTL -q --root "$initdir" enable "debug-shell.service"
	done

	: "${ENCRYPTION_CONFIG:=/etc/encrypt_options}"
	[ -e "$ENCRYPTION_CONFIG" ] && inst_simple "$ENCRYPTION_CONFIG" "/etc/encrypt_options"
}
0707010000000C000041ED0000000000000000000000026818B1A100000000000000000000000000000000000000000000003000000000disk-encryption-tool-1+git20250505.aa666d1/test0707010000000D000081A40000000000000000000000016818B1A10000029D000000000000000000000000000000000000003B00000000disk-encryption-tool-1+git20250505.aa666d1/test/config.ign{
  "ignition": {
    "version": "3.2.0"
  },
  "passwd": {
    "users": [
      {
        "name": "root",
        "passwordHash": "$2a$10$IGzLVVX6jfMoe4Qoog2v.e24woQJiys9Doe8.taWrqdDkZyrXiGZu"
      }
    ]
  },
  "storage": {
    "filesystems": [
      {
        "device": "/dev/disk/by-label/ROOT",
        "format": "btrfs",
        "mountOptions": [
          "subvol=/@/home"
        ],
        "path": "/home",
        "wipeFilesystem": false
      }
    ],
    "files": [
      {
        "path": "/etc/locale.conf",
        "mode": 420,
        "overwrite": true,
        "contents": {
          "source": "data:,LANG=en_US.UTF-8"
        }
      }
    ]
  }
}
0707010000000E000081ED0000000000000000000000016818B1A10000102B000000000000000000000000000000000000003800000000disk-encryption-tool-1+git20250505.aa666d1/test/test.sh#!/bin/bash
set -euxo pipefail

# Some basic combustion testing:
# 1. Download the latest MicroOS image
# 2. Use its combustion to install the disk-encryption-tool to test and transfer kernel + initrd to the host using 9pfs
# 3. Revert the image to the original state and perform tests using the generated kernel + initrd

# Skip the generation of a new initrd with the changed disk-encryption-tool.
# Only useful when iterating this test script.
reuseinitrd=
if [ "${1-}" = "--reuseinitrd" ]; then
	reuseinitrd=1
	shift
fi

# Working dir which is also exposed to the VM through 9pfs.
# If not specified, create a temporary directory which is deleted on exit.
if [ -n "${1-}" ]; then
	tmpdir="$(realpath "$1")"
else
	tmpdir="$(mktemp -d)"
	cleanup() {
		rm -rf "$tmpdir"
	}
	trap cleanup EXIT
fi

QEMU_BASEARGS=(
	# -accel tcg was here after -accel kvm but the fallback hid a weird bug
	# that in GH actions only the first instance of QEMU was able to access /dev/kvm.
	-accel kvm -cpu host -nographic -m 1024
	# Reading from stdin doesn't work, configure serial and monitor appropriately.
	-chardev null,id=serial,logfile=/dev/stdout,logappend=on -serial chardev:serial -monitor none
	-virtfs "local,path=${tmpdir},mount_tag=tmpdir,security_model=none")

if [ -e /usr/share/qemu/ovmf-x86_64.bin ]; then
	QEMU_BASEARGS+=(-bios /usr/share/qemu/ovmf-x86_64.bin)
elif [ -e /usr/share/qemu/OVMF.fd ]; then
	QEMU_BASEARGS+=(-bios /usr/share/qemu/OVMF.fd)
else
	echo "No OVMF found"
	exit 1
fi

# Prepare the temporary dir: Install disk-encryption-tool and copy resources.
testdir="$(dirname "$0")"
# TODO: Use a Makefile for this and in the .spec file.
mkdir -p "${tmpdir}/install/usr/lib/dracut/modules.d/95disk-encryption-tool"
for i in disk-encryption-tool{,-dracut,-dracut.service} module-setup.sh; do
	cp "${testdir}/../${i}" "${tmpdir}/install/usr/lib/dracut/modules.d/95disk-encryption-tool/${i}"
done
cp "${testdir}/"{testscript,config.ign} "${tmpdir}"
cd "$tmpdir"

# Download latest MicroOS image
if ! [ -f openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2 ]; then
	wget --progress=bar:force:noscroll https://download.opensuse.org/tumbleweed/appliances/openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2
	qemu-img snapshot -c initial openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2
else
	qemu-img snapshot -a initial openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2
fi

# First step: Use combustion in the downloaded image to generate an initrd with the new disk-encryption-tool.
if ! [ -n "${reuseinitrd}" ] || ! [ -e "${tmpdir}/vmlinuz" ] || ! [ -e "${tmpdir}/initrd" ]; then
	rm -f "${tmpdir}/done"
	cat >create-initrd <<'EOF'
#!/bin/bash
set -euxo pipefail
exec &>/dev/ttyS0
trap '[ $? -eq 0 ] || poweroff -f' EXIT
mount -t 9p -o trans=virtio tmpdir /mnt
# Install new disk-encryption-tool, make sure the old remnants are gone
rpm -e --nodeps --noscripts disk-encryption-tool
cp -av /mnt/install/usr /
cp /usr/lib/modules/$(uname -r)/vmlinuz /mnt/vmlinuz
dracut -f --no-hostonly /mnt/initrd
touch /mnt/done
umount /mnt
SYSTEMD_IGNORE_CHROOT=1 poweroff -f
EOF

	timeout 300 qemu-system-x86_64 "${QEMU_BASEARGS[@]}" -drive if=virtio,file=openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2 \
		-fw_cfg name=opt/org.opensuse.combustion/script,file=create-initrd

	if ! [ -e "${tmpdir}/done" ]; then
		echo "Initrd generation failed"
		exit 1
	fi
fi

# Test using a config drive
rm -f "${tmpdir}/done"
qemu-img snapshot -a initial openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2

rm -rf configdrv
mkdir -p configdrv/combustion/
cp testscript configdrv/combustion/script
mkdir -p configdrv/ignition/
cp config.ign configdrv/ignition/config.ign
/sbin/mkfs.ext4 -F -d configdrv -L ignition combustion.raw 16M

timeout 300 qemu-system-x86_64 "${QEMU_BASEARGS[@]}" -drive if=virtio,file=openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2 \
	-kernel vmlinuz -initrd initrd -append "root=LABEL=ROOT console=ttyS0 quiet systemd.show_status=1 systemd.log_target=console systemd.journald.forward_to_console=1 rd.emergency=poweroff rd.shell=0" \
	-drive if=virtio,file=combustion.raw

if ! [ -e "${tmpdir}/done" ]; then
	echo "Test failed"
	exit 1
fi
0707010000000F000081A40000000000000000000000016818B1A100000A86000000000000000000000000000000000000003B00000000disk-encryption-tool-1+git20250505.aa666d1/test/testscript#!/bin/bash
# combustion: prepare
set -euxo pipefail
exec &>/dev/ttyS0

# Poweroff immediately on any failure to avoid unnecessary waiting.
trap '[ $? -eq 0 ] || poweroff -f' EXIT

if [ "${1-}" = "--prepare" ]; then
	# We set disk-encryption-tool-dracut.encryption credential to
	# "force".  This will make disk-encryption-tool-dracut force the
	# encryption, ignoring that Combusion configured the system, and
	# will skip the permission countdown
	#
	# After the encryption the recovery key is registered in the
	# kernel keyring %user:cryptenroll
	mkdir -p /run/credstore
	echo "force" > /run/credstore/disk-encryption-tool-dracut.encrypt
	exit 0
fi

# Create a valid machine-id, as this will be required to create later
# the host secret
systemd-machine-id-setup

# We want to persist the host secret key created via systemd-cred
# (/var/lib/systemd/credential.secret)
mount /var

mkdir -p /etc/credstore.encrypted
credential="$(mktemp disk-encryption-tool.XXXXXXXXXX)"

# Enroll extra password
# echo "SECRET_PASSWORD" > "$credential"
echo "linux" > "$credential"
systemd-creds encrypt --name=disk-encryption-tool-enroll.pw "$credential" \
	      /etc/credstore.encrypted/disk-encryption-tool-enroll.pw

# # Enroll TPM2 with secret PIN
# echo "SECRET_PIN" > "$credential"
# systemd-creds encrypt --name=disk-encryption-tool-enroll.tpm2+pin "$credential" \
# 	      /etc/credstore.encrypted/disk-encryption-tool-enroll.tpm2+pin

# # Enroll TPM2
# echo "1" > "$credential"
# systemd-creds encrypt --name=disk-encryption-tool-enroll.tpm2 "$credential" \
# 	      /etc/credstore.encrypted/disk-encryption-tool-enroll.tpm2

# # Enroll FIDO2
# echo "1" > "$credential"
# systemd-creds encrypt --name=disk-encryption-tool-enroll.fido2 "$credential" \
# 	      /etc/credstore.encrypted/disk-encryption-tool-enroll.fido2

shred -u "$credential"

# Umount back /var to not confuse tukit later
umount /var

# Keyboard
systemd-firstboot --force --keymap=es

# Make sure that the system comes up good, leave a marker in the shared FS
# and power off the VM.
cat >>/usr/bin/combustion-validate <<'EOF'
#!/bin/bash
set -euxo pipefail
exec &>/dev/ttyS0
trap '[ $? -eq 0 ] || poweroff -f' EXIT
findmnt
lsblk
if [ "$(findmnt -nrvo SOURCE /)" != "/dev/mapper/cr_root" ]; then
	echo "Not encrypted?"
	exit 1
fi
mount -t 9p -o trans=virtio tmpdir /mnt
touch /mnt/done
umount /mnt
poweroff -f
EOF
chmod a+x /usr/bin/combustion-validate

cat >>/etc/systemd/system/combustion-validate.service <<'EOF'
[Service]
ExecStart=/usr/bin/combustion-validate
[Install]
RequiredBy=default.target
EOF
systemctl enable combustion-validate.service

# Leave a marker
echo "Configured with combustion" > /etc/issue.d/combustion
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!58 blocks
openSUSE Build Service is sponsored by