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