Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions tools/image/install-test.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#!/usr/bin/env bash
# Install from the medium, boot the result from firmware alone (medium gone,
# variables reset), and check that the installer's refusals refuse.
# Install from the medium, boot the result from firmware alone, and check the installer's refusals.
#
# tools/image/install-test.sh --usb IMG [--disk FILE] [--size 12G]
# [--vars clean|enrolled] [--timeout N] [--quick]
#
# step 1 install unattended onto a blank disk; check the transcript and,
# from the host, the partition table
# step 1 install onto a blank disk; check the transcript and the partition table
# step 2 boot the disk alone: first boot, login, reboot, login, poweroff
# step 3 cold boot it again (not with --quick)
# step 4 a disk too small, a read-only disk, and an I/O error in the root
Expand Down Expand Up @@ -208,11 +206,9 @@ EOF
refusal_case ioerror "$SIZE" 'writing the root image failed' --blkdebug "${VMDIR}/blkdebug.conf"
fi

# The runner always passes --yes, so none of these refusals is the ERASE
# prompt waiting.
# The runner always passes --yes, so no refusal here is the ERASE prompt waiting.

# The disk this system runs from: the medium, the one USB disk in the guest.
# No flag opens it.
# The medium, the guest's one USB disk, is the disk this system runs from: no flag opens it.
ctl="${VMDIR}/testctl-medium.img"
"${SELF}/mk-testctl.sh" --out "$ctl" --key "$TESTCTL_KEY" install_target=/dev/sda install_replace=1 smoke_poweroff=1 install_wait=5 > /dev/null
d="${VMDIR}/refuse-medium.img"; rm -f "$d"; truncate -s "$SIZE" "$d"
Expand All @@ -222,9 +218,7 @@ want "$t" 'KRYPTIK_INSTALL: BEGIN target=/dev/sda' "medium:
want "$t" 'KRYPTIK_INSTALL: .*is the disk this system is running from' "medium: refused as the disk this system runs from, even with --replace-kryptik"
deny "$t" 'KRYPTIK_INSTALL: rc=0' "medium: never reported success"

# A control disk signed by some other key: the medium honours the
# kryptik-testctl key its anchor lists and no other, so nothing is armed. The
# disk's poweroff is ignored with the rest, so this boot runs to its timeout.
# The medium ignores a control disk its testctl key did not sign, poweroff too: this boot times out.
ssh-keygen -q -t ed25519 -N '' -C stranger -f "${VMDIR}/stranger-key" < /dev/null
ctl="${VMDIR}/testctl-stranger.img"
"${SELF}/mk-testctl.sh" --out "$ctl" --key "${VMDIR}/stranger-key" install_target=/dev/vda smoke_poweroff=1 install_wait=5 > /dev/null
Expand All @@ -241,7 +235,7 @@ state_uuid() {
[[ -n "$start" ]] && blkid -p -O "$(( start * 512 ))" -s UUID -o value "$1" 2>/dev/null
}

# An old installation: refused without the flag, and left exactly as it was.
# An old installation is refused without the flag, and left as it was.
old="${VMDIR}/old-install.img"; rm -f "$old"; cp --sparse=always "$DISK" "$old"
ctl="${VMDIR}/testctl-oldinstall.img"
"${SELF}/mk-testctl.sh" --out "$ctl" --key "$TESTCTL_KEY" install_target=/dev/vda smoke_poweroff=1 install_wait=5 > /dev/null
Expand Down
14 changes: 4 additions & 10 deletions tools/image/state-test.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env bash
# The installed system's state partition: found on the system's own disk, and
# a boot that says so when it cannot use it (docs/design/boot-and-updates.md,
# sysinit.sh).
# The installed system's state partition: found on its own disk, and a degraded boot when unusable.
#
# tools/image/state-test.sh --usb IMG [--disk FILE] [--timeout N]
#
Expand All @@ -16,8 +14,7 @@
# step 8 root changes the passphrase with `kryptik state passphrase`: the
# old one no longer unlocks, the new one does
#
# A degraded boot has no accounts, so only its console is checked; after each
# repair a login must find the user's file. Every disk is a file made here.
# After each repair a login must find the user's file. Every disk is a file made here.
set -uo pipefail
SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=/dev/null
Expand Down Expand Up @@ -46,9 +43,7 @@ source "${SELF}/suite-lib.sh"
VARSF="${VMDIR}/state-vars.fd"; cp /usr/share/OVMF/OVMF_VARS_4M.fd "$VARSF"


# A boot that must come up degraded. Nobody can log in to power it off, so it
# is stopped once its report ends, and only its transcript is checked: every
# line below comes before the report's END.
# Nobody can log in to a degraded boot: stop it at its report's END and check the transcript.
degraded_boot() { # degraded_boot NAME REASON-REGEX
start_vm "$1"
DRIVE_TIMEOUT=150 drive "expect:KRYPTIK_SMOKE: END" > /dev/null
Expand Down Expand Up @@ -144,10 +139,9 @@ sfdisk --part-label "$DISK" 4 kryptik-state >/dev/null 2>&1 || die "relabel back
normal_boot state-p5b

# ----------------------------------------------------------------- step 6 --
# Stop the feeder rather than kill it (s6 would restart it): to the timer that
# is a hung userspace, and only the watchdog's reset can bring a second boot.
step "step 6: nothing feeds the watchdog: the machine resets itself and comes back with its data"
start_vm state-p6
# The feeder stopped, not killed (s6 would restart it): a hung userspace only the watchdog resets.
p6=( "expect:KRYPTIK_SMOKE: END" "login:${TUSER}:${TPASS}"
"$(ROOTSH 's6-svc -p /run/service/watchdog && echo FEEDER-STOPPED')" "expect:FEEDER-STOPPED"
"expect:KRYPTIK_SMOKE: BEGIN" "expect:KRYPTIK_SMOKE: END"
Expand Down
21 changes: 7 additions & 14 deletions tools/image/suite-lib.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/env bash
# Shared by the installed-system suites: the verdict, the preseeded accounts,
# and wrappers for run-ovmf.sh and vm-drive.py. Source after common.sh with
# SELF set; start_vm reads DISK and VARSF, drive reads DRIVE_TIMEOUT.
# Shared by the installed-system suites; source it after common.sh, with SELF set.
# start_vm reads DISK and VARSF, install_disk TIMEOUT and VMDIR, drive DRIVE_TIMEOUT.
# shellcheck disable=SC2034 # read by the suite that sources this

PASS=0; FAIL=0
Expand All @@ -12,21 +11,17 @@ step() { printf '\n==> %s\n' "$*"; }
# The plaintext exists only in the harness; the hashes are what lands on disk.
TUSER=tester; TPASS=tester-pw; RPASS=root-pw
TUSER_HASH="$(openssl passwd -6 "$TPASS")"; ROOT_HASH="$(openssl passwd -6 "$RPASS")"
# The state passphrase: the installer reads it from the control disk, and
# vm-drive.py (hence the export) answers sysinit with it at every boot.
# The installer reads it from the control disk; vm-drive.py answers sysinit with it (hence export).
export KRYPTIK_STATE_PASSPHRASE=state-pw
PRESEED=( "preseed_user=${TUSER}" "preseed_password_hash=${TUSER_HASH}" "preseed_root_hash=${ROOT_HASH}"
"state_passphrase=${KRYPTIK_STATE_PASSPHRASE}" )
# The control disks are signed with the kryptik-testctl key the medium's
# anchor lists: the developer keys' for a development medium, and for the
# production pair the one tools/production-pair.sh keeps beside it.
# The testctl key the medium's anchor lists signs the control disks: the developer one, or the
# production pair's (KRYPTIK_TESTCTL_KEY, tools/production-pair.sh).
TESTCTL_KEY="${KRYPTIK_TESTCTL_KEY:-${KRYPTIK_WORK}/keys/release/kryptik-testctl}"

DRV="${SELF}/vm-drive.py"

# A smoke boot with a transcript of its own. run-ovmf.sh repoints the
# ovmf-serial.latest.log link at every boot on this host, another suite's
# included, so a suite never reads through it.
# A smoke boot with its own transcript: ovmf-serial.latest.log may be another suite's boot.
BOOTS=0
smoke() { # smoke NAME [run-ovmf args] -> BOOTLOG; run-ovmf.sh's status
BOOTS=$((BOOTS + 1))
Expand All @@ -35,9 +30,7 @@ smoke() { # smoke NAME [run-ovmf args] -> BOOTLOG; run-ovmf.sh's status
}
boot_txt() { tr -d '\r' < "$BOOTLOG"; }

# Every suite starts from a fresh install: a DISK sized from the medium, not a
# constant (see test-disk-size.sh), then the medium's installer run onto it
# with the preseeded accounts.
# Every suite starts from a fresh install onto a DISK sized from the medium (test-disk-size.sh).
fresh_disk() { # fresh_disk MEDIUM [test-disk-size.sh args]
local size; size="$("${SELF}/test-disk-size.sh" --medium "$@")" || die "could not size the test disk from the medium"
rm -f "$DISK"; truncate -s "$size" "$DISK"
Expand Down
Loading
Loading