Secure Boot iPXE chain is the default for every UEFI client

Live since 2026-10-14: dnsmasq hands every UEFI client ipxe-shim.efi
(iPXE's shim, dual-signed under Microsoft UEFI CA 2011 + 2023), which
loads ipxe.efi from the TFTP root, now the iPXE v2.0.0 snponly build
(firmware network and USB drivers; the full build kills USB keyboards).
The per-MAC test tags and folders are gone; the old Broadcom-signed
1.21.1 build stays as ipxe-bcm.efi, the rollback.

- playbook: pinned sha256 vars, the new dnsmasq default line, and a
  verified, non-optional task that installs ipxe-shim.efi, ipxe.efi
  (snponly), ipxe.pxe and ipxe-bcm.efi (was: copy ipxe.efi and the never
  served undionly.kpxe, errors ignored).
- scripts/fetch-ipxe.sh downloads the pinned tarball and shim into
  boot-files/ for the USB build; README/SETUP list the step.
- iPXE page: ipxe.efi is staged from snponly.efi, a build that drives USB
  itself is refused, and the snponly-shim/snponly root files are gone.

Tested: the playbook task against the real release files (installs the
live hashes; a tampered file stops it before anything is replaced),
ansible --syntax-check, staging, and the full-build refusal.
This commit is contained in:
cproudlock
2026-10-14 16:37:49 -04:00
parent a94c20331a
commit 045a1fb97f
6 changed files with 168 additions and 70 deletions

61
scripts/fetch-ipxe.sh Executable file
View File

@@ -0,0 +1,61 @@
#!/bin/bash
#
# fetch-ipxe.sh - Download the pinned Secure Boot iPXE chain into boot-files/
# for the USB build (build-usb.sh copies boot-files/* to the USB root, and
# playbook/pxe_server_setup.yml installs them into the TFTP root).
#
# ipxeboot.tar.gz iPXE release (github.com/ipxe/ipxe). The playbook takes
# x86_64-sb/snponly.efi (installed as ipxe.efi: firmware
# network + USB drivers, so USB keyboards work at the menu)
# and x86_64/ipxe.pxe (legacy BIOS).
# ipxe-shimx64.efi iPXE's Microsoft-signed shim (github.com/ipxe/shim),
# dual-signed under Microsoft UEFI CA 2011 and 2023.
# Installed as ipxe-shim.efi, the boot file every UEFI
# client gets. Not the tarball's shimx64.efi, which is
# signed under the 2011 CA only.
#
# Every file is checked against the sha256 pinned below; a mismatch deletes
# it and fails. To move to a new release, change the pins here AND the
# matching ipxe_* vars in playbook/pxe_server_setup.yml.
#
# Usage: ./scripts/fetch-ipxe.sh [boot-files dir]
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)"
OUT_DIR="${1:-$REPO_ROOT/boot-files}"
IPXE_TAG="v2.0.0"
IPXE_TARBALL_SHA256="01a526d4cc791fc30362259c609d6c506cc64a7bdff51b9a5eb788354e17eee1"
SHIM_TAG="ipxe-16.1"
SHIM_SHA256="5eecca2780bd49c900565e124516a1bd666ec5e012825f34991b6ba1ef2fa6cf"
fetch() { # url dest sha256
local url="$1" dest="$2" sha="$3"
if [ -f "$dest" ] && echo "$sha $dest" | sha256sum -c --status; then
echo " ok (cached) $(basename "$dest")"
return
fi
rm -f "$dest"
# GitHub goes through Zscaler on GE networks: a TLS error here means the
# Zscaler root CA is missing from the system trust store.
curl -fsSL --retry 3 -o "$dest" "$url"
if ! echo "$sha $dest" | sha256sum -c --status; then
echo "ERROR: sha256 mismatch for $(basename "$dest"); removed it" >&2
rm -f "$dest"
exit 1
fi
echo " ok $(basename "$dest")"
}
mkdir -p "$OUT_DIR"
echo "Fetching the Secure Boot iPXE chain into $OUT_DIR"
fetch "https://github.com/ipxe/ipxe/releases/download/$IPXE_TAG/ipxeboot.tar.gz" \
"$OUT_DIR/ipxeboot.tar.gz" "$IPXE_TARBALL_SHA256"
fetch "https://github.com/ipxe/shim/releases/download/$SHIM_TAG/ipxe-shimx64.efi" \
"$OUT_DIR/ipxe-shimx64.efi" "$SHIM_SHA256"
if [ ! -f "$OUT_DIR/ipxe.efi" ]; then
echo "NOTE: $OUT_DIR/ipxe.efi (the old Broadcom-signed 1.21.1 build) is missing."
echo " The playbook installs it as ipxe-bcm.efi, the rollback boot file;"
echo " copy it from an existing PXE server's /srv/tftp/ipxe-bcm.efi."
fi