Files
narOS/tests/smoke-rootfs.sh
T

108 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Per-flavor rootfs smoke test (NAROS.md §10.3).
#
# smoke-rootfs.sh <flavor> <image> <arch>
#
# <flavor> is the build-rootfs.sh tier: base | vm | vm-desktop.
# <image> is an ALREADY-IMPORTED docker image (the caller runs `docker import` on the
# tarball, because it usually wants the named image for later steps too).
# <arch> amd64 | arm64 — passed to --platform.
#
# Assertions run inside the image under nash. They live here rather than inline in
# naros.yml because the vm and vm-desktop jobs are one matrix over a single set of steps:
# the flavors differ ONLY in what is asserted, and inlining that difference is what forced
# the two near-identical jobs the matrix replaced.
#
# Exit: 0 all assertions hold, non-zero on the first failure (the container shell is `set -e`).
set -euo pipefail
FLAVOR="${1:?usage: smoke-rootfs.sh <flavor> <image> <arch>}"
IMAGE="${2:?missing image}"
ARCH="${3:?missing arch}"
run() { docker run --rm --platform "linux/$ARCH" "$IMAGE" /usr/bin/nash -lc "$1"; }
# Sourced by every flavor: narOS identity plus the forced-nash /bin/sh with the real bash kept
# aside. Leaves os-release variables ($VARIANT_ID, $VERSION_ID) in scope for the flavor blocks.
COMMON='
set -e
. /etc/os-release; test "$ID" = naros
readlink /bin/sh | grep -q nash
test -x /usr/bin/bash.real
# nash trusted policy (NASH.md §4.3): present, root-owned, not group/other-writable —
# the three properties nash checks before it honors an operator lever. A packaging
# slip on any of them silently returns the levers to nobody (or, worse, to the agent).
test -f /etc/nucleic/nash.conf
grep -q "^require_observation=1" /etc/nucleic/nash.conf
test "$(stat -c %u:%a /etc/nucleic/nash.conf)" = "0:644"
# The bypass the image used to publish to every shell it started.
! grep -rq NUCLEIC_REAL_BASH /etc/profile.d/
'
# A runtime-clean sources.list (no build-time copy:// pool left in), scoped away from
# sources.list.d so the not-yet-live hosted-repo entry (naros-keyring) cannot fail this
# before the apt domain is provisioned.
APT_CLEAN='
apt-get update -q -o Dir::Etc::SourceParts=-
'
case "$FLAVOR" in
base)
echo "smoke: base rootfs ($ARCH)"
run "$COMMON"'
naros version
naros info --json > /dev/null
# Kernel identity shim (NAROS.md §2.3). Every command in this smoke test already runs
# under the global preload, so a broken .so fails the job long before here; these assert
# the tag is actually applied and correctly scoped.
grep -qxF /usr/lib/naros/libnaros-uname.so /etc/ld.so.preload
# VERSION_ID comes from the os-release sourced above.
uname -r | grep -q -- "-naros$VERSION_ID"
# sysname must stay "Linux" — build tooling switches on it.
test "$(uname -s)" = Linux
# The escape hatch /lib/modules consumers depend on must really bypass. Compare against
# procfs, which the shim cannot touch (a file read, not a syscall).
test "$(NAROS_UNAME_PASSTHROUGH=1 uname -r)" = "$(cat /proc/sys/kernel/osrelease)"
'"$APT_CLEAN"
;;
vm)
echo "smoke: vm rootfs — identity + forced shell + systemd present ($ARCH)"
# nash directly (systemd is PID 1 only under a real boot); assert the bootable base is sane.
run "$COMMON"'
test "$VARIANT_ID" = vm
test -x /usr/lib/systemd/systemd || test -x /lib/systemd/systemd
command -v systemctl > /dev/null
naros version
# The control-plane agent IS baked (from the local pool): it is the only way the host can
# reach the guest, and the phase-1 bootstrap no longer overlays a GHCR copy on top. The
# rest of the tier still arrives at firstboot via `apt install naros-tier-vm`.
test -x /usr/local/bin/nucleic-linux-agent
test -L /etc/systemd/system/multi-user.target.wants/nucleic-linux-agent.service
'"$APT_CLEAN"
;;
vm-desktop)
echo "smoke: vm-desktop rootfs — GNOME 50 + agent user + semantic surface ($ARCH)"
run "$COMMON"'
test "$VARIANT_ID" = vm
naros info --json | jq -e ".variant == \"vm\" and .flavor == \"desktop\"" > /dev/null
test "$(id -u agent)" = 501
test -x /usr/lib/systemd/systemd || test -x /lib/systemd/systemd
command -v gnome-shell > /dev/null
gnome-shell --version | grep -qE "GNOME Shell 5[0-9]"
command -v gdm3 > /dev/null || test -x /usr/sbin/gdm3
test -x /usr/local/bin/nucleic-a11y-agent
test -x /usr/local/bin/nucleic-linux-agent
test -f /usr/share/gnome-shell/extensions/[email protected]/metadata.json
grep -q "AutomaticLogin=agent" /etc/gdm3/daemon.conf'
;;
*)
echo "unknown flavor: $FLAVOR (expected base, vm, or vm-desktop)" >&2
exit 2
;;
esac
echo "smoke OK ($FLAVOR/$ARCH)"