blancco: fix silent prefs fallback, suspend trap, display blank + add View
End-to-end fixes for Blancco Drive Eraser PXE flow uncovered by chasing
"reports never reach SMB share" across two air-gapped sites:
playbook/blancco-init.sh:
* Drop silent || true on wget of preferences.xml + config.xml. Fail
loud with shell-drop if download or marker grep fails. Background:
airootfs /opt/scripts/validate_preferences.sh restores
/albus/preferences.save (factory defaults, empty network_share) if
xmllint fails. wget failure made every report silently land nowhere.
* Clobber /albus/preferences.save with the same served file so even if
the validator fallback fires, the SMB target survives.
* Bind-mount /dev/null over /sys/power/{state,disk,mem_sleep,autosleep}
before switch_root. Albus's license-retry path writes /sys/power/state
directly (bypassing systemd targets); this is the last-line block.
* /dev/null symlinks for sleep/suspend/hibernate systemd targets in the
airootfs overlay + logind drop-in with IdleAction/Handle*=ignore.
Three independent layers because cmdline systemd.mask alone is bypassed
by direct /sys/power/state writes.
* xinitrc.d/00-no-screen-blank.sh runs xset s off -dpms + setterm
-blank 0 -powerdown 0 so the Blancco GUI doesn't blank during long
erasures.
* Removed the 20-failsafeDriver.conf "modesetting" pin. modesetting
needs DRM/KMS which we disable on kernel cmdline; "vesa" also failed
on NVIDIA. With the pin gone Xorg auto-picks fbdev which uses the
kernel framebuffer from vga=normal - works across Intel, AMD, and
older NVIDIA without nouveau.
playbook/pxe_server_setup.yml:
* dnsmasq.conf: explicit empty-value dhcp-option=3 + dhcp-option=6.
Without them, dnsmasq defaults to sending its own IP as router AND
DNS. Commenting the configured-value lines did NOT disable the push
(root cause of "wired keeps picking up 10.9.100.1 as gateway").
* Split the Blancco config.img extraction and preferences.xml deploy
into separate tasks. The previous shell-with-creates: gate caused
playbook re-runs to skip the prefs deploy entirely after first run.
* Added a validation task that runs python3 xml parse + grep on the
deployed preferences.xml to fail the playbook at deploy time if the
SMB markers are missing.
* Added Environment=TZ=America/New_York to the pxe-webapp systemd
service so report mtimes and audit log render in Eastern time even
if the Python process is started before timedatectl converges.
webapp:
* services/blancco_report.py: parse Blancco's XML report format
(recursive <entries name="..."> walker) into a friendly dict.
* templates/report_view.html: Bootstrap "Drive Erasure Certificate"
layout - hero summary, customer + system cards, per-drive cards with
step-by-step erasure timeline, document signing footer with
integrity hash detail.
* /reports/view/<filename> route + View button on the reports list
(XML reports only; PDFs still download).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -105,22 +105,96 @@ wget -O /tmp/kmod.tar.gz http://$SERVER/blancco/kmod.tar.gz 2>&1
|
||||
[ -s /tmp/kmod.tar.gz ] && (cd /run/newroot && gunzip -c /tmp/kmod.tar.gz | tar xf - && rm -f /tmp/kmod.tar.gz)
|
||||
|
||||
mkdir -p /run/newroot/albus
|
||||
wget -O /run/newroot/albus/config.xml http://$SERVER/blancco/config-clean.xml 2>&1 || true
|
||||
wget -O /run/newroot/albus/preferences.xml http://$SERVER/blancco/preferences.xml 2>&1 || true
|
||||
cp -f /run/newroot/albus/preferences.xml /run/newroot/albus/preferences.save 2>/dev/null || true
|
||||
|
||||
# preferences.xml REQUIRED. Without valid file, Blancco airootfs's
|
||||
# /opt/scripts/validate_preferences.sh silently restores
|
||||
# /albus/preferences.save (factory defaults, empty network_share) so
|
||||
# erasure reports never reach SMB. Fail loud here instead.
|
||||
PREFS=/run/newroot/albus/preferences.xml
|
||||
if ! wget -O "$PREFS" "http://$SERVER/blancco/preferences.xml"; then
|
||||
echo "ERROR: preferences.xml download failed from http://$SERVER/blancco/preferences.xml"
|
||||
echo "Reports would fall back to factory defaults (no SMB target)."
|
||||
echo "Dropping to shell - check Apache + network."
|
||||
exec /bin/sh
|
||||
fi
|
||||
# Busybox initramfs has no xmllint. Grep for required SMB markers instead;
|
||||
# if either is missing, the prefs file in web_root is stale or corrupted.
|
||||
if [ ! -s "$PREFS" ] || ! grep -q "<hostname>$SERVER</hostname>" "$PREFS" \
|
||||
|| ! grep -q '<path>blancco-reports</path>' "$PREFS"; then
|
||||
echo "ERROR: preferences.xml missing required network_share entries."
|
||||
echo "Expected <hostname>$SERVER</hostname> + <path>blancco-reports</path>."
|
||||
echo "=== first 60 lines of $PREFS ==="
|
||||
head -60 "$PREFS"
|
||||
exec /bin/sh
|
||||
fi
|
||||
# Clobber preferences.save too. validate_preferences.sh in airootfs falls
|
||||
# back to preferences.save on any future xmllint failure; if that ever
|
||||
# fires, we want the fallback to still have the right SMB target.
|
||||
cp -f "$PREFS" /run/newroot/albus/preferences.save
|
||||
|
||||
if ! wget -O /run/newroot/albus/config.xml "http://$SERVER/blancco/config-clean.xml"; then
|
||||
echo "ERROR: config.xml (license container) download failed."
|
||||
exec /bin/sh
|
||||
fi
|
||||
|
||||
mkdir -p /run/newroot/etc/X11/xorg.conf.d
|
||||
cat > /run/newroot/etc/X11/xorg.conf.d/20-failsafeDriver.conf << XEOF
|
||||
Section "Device"
|
||||
Identifier "Failsafe Video Device"
|
||||
Driver "modesetting"
|
||||
EndSection
|
||||
# Don't pin a single Xorg driver - hardware varies per site (Intel iGPU,
|
||||
# NVIDIA GK208, AMD, etc). Let Xorg auto-pick. With nomodeset + KMS
|
||||
# blacklist on kernel cmdline, Xorg falls back to fbdev (uses
|
||||
# kernel-provided framebuffer from vga=normal) which works on most boxes.
|
||||
# Previous "modesetting" pin needed KMS we disabled; "vesa" pin also
|
||||
# didn't drive NVIDIA cards. Removing the pin entirely.
|
||||
rm -f /run/newroot/etc/X11/xorg.conf.d/20-failsafeDriver.conf 2>/dev/null || true
|
||||
|
||||
# Hard-mask sleep/suspend/hibernate targets in the airootfs overlay. systemd
|
||||
# kernel cmdline systemd.mask= only blocks systemd-side activation; userspace
|
||||
# can still write /sys/power/state directly. /dev/null symlinks under
|
||||
# /etc/systemd/system/ block ALL systemd-mediated paths AND stop logind from
|
||||
# advertising sleep capability to userland. Combined with the logind drop-in
|
||||
# below, /sys/power/state writes from non-root userland (Albus) also fail.
|
||||
mkdir -p /run/newroot/etc/systemd/system
|
||||
for tgt in sleep.target suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target; do
|
||||
ln -sf /dev/null "/run/newroot/etc/systemd/system/$tgt"
|
||||
done
|
||||
|
||||
mkdir -p /run/newroot/etc/systemd/logind.conf.d
|
||||
cat > /run/newroot/etc/systemd/logind.conf.d/no-suspend.conf << XEOF
|
||||
[Login]
|
||||
IdleAction=ignore
|
||||
HandleSuspendKey=ignore
|
||||
HandleHibernateKey=ignore
|
||||
HandleLidSwitch=ignore
|
||||
HandleLidSwitchDocked=ignore
|
||||
HandlePowerKey=ignore
|
||||
XEOF
|
||||
|
||||
# Disable Xorg screensaver + DPMS so display stays on during long erasures.
|
||||
# Numbered 00-* to run before vendor xinitrc.d hooks.
|
||||
mkdir -p /run/newroot/etc/X11/xinit/xinitrc.d
|
||||
cat > /run/newroot/etc/X11/xinit/xinitrc.d/00-no-screen-blank.sh << 'XEOF'
|
||||
#!/bin/sh
|
||||
xset s off -dpms 2>/dev/null || true
|
||||
xset s noblank 2>/dev/null || true
|
||||
setterm -blank 0 -powerdown 0 2>/dev/null || true
|
||||
XEOF
|
||||
chmod +x /run/newroot/etc/X11/xinit/xinitrc.d/00-no-screen-blank.sh
|
||||
|
||||
mkdir -p /run/newroot/proc /run/newroot/sys /run/newroot/dev /run/newroot/run /run/newroot/tmp
|
||||
mount --move /proc /run/newroot/proc
|
||||
mount --move /sys /run/newroot/sys
|
||||
mount --move /dev /run/newroot/dev
|
||||
|
||||
# Hard-block kernel suspend/hibernate path. Bind-mount /dev/null over the
|
||||
# sysfs power-control files so any userland write (Albus auto-suspend,
|
||||
# pm-utils, etc) becomes a no-op. This is the LAST line of defense - kernel
|
||||
# cmdline systemd.mask, /dev/null symlinks for sleep targets, and logind
|
||||
# drop-ins were all bypassed by Albus writing /sys/power/state directly.
|
||||
# Bind-mount works at the VFS layer below sysfs, so even kernel-side mount
|
||||
# remounts wouldn't undo it.
|
||||
mount --bind /dev/null /run/newroot/sys/power/state 2>/dev/null || true
|
||||
mount --bind /dev/null /run/newroot/sys/power/disk 2>/dev/null || true
|
||||
mount --bind /dev/null /run/newroot/sys/power/mem_sleep 2>/dev/null || true
|
||||
mount --bind /dev/null /run/newroot/sys/power/autosleep 2>/dev/null || true
|
||||
|
||||
echo "Switching root..."
|
||||
exec switch_root /run/newroot /sbin/init
|
||||
|
||||
Reference in New Issue
Block a user