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:
@@ -159,8 +159,14 @@
|
||||
# the wired NIC much later). Removing these options entirely lets
|
||||
# Windows route internet via WiFi and same-subnet PXE/SMB traffic
|
||||
# via wired, no migration script needed.
|
||||
# dhcp-option=3,10.9.100.1
|
||||
# dhcp-option=6,8.8.8.8
|
||||
#
|
||||
# Important: dnsmasq DEFAULTS to sending its own listening address as
|
||||
# both router and DNS when these options are unset. Commenting them
|
||||
# out is NOT the same as disabling - imaged PCs (and Blancco PXE
|
||||
# clients) end up with 10.9.100.1 as gateway. The empty-value form
|
||||
# below explicitly suppresses both options.
|
||||
dhcp-option=3
|
||||
dhcp-option=6
|
||||
enable-tftp
|
||||
tftp-root={{ tftp_dir }}
|
||||
# Arch-aware NBP: legacy BIOS PXE ROMs (client-arch=0) cannot run
|
||||
@@ -863,9 +869,8 @@
|
||||
args:
|
||||
creates: "{{ web_root }}/blancco/kmod.tar.gz"
|
||||
|
||||
- name: "Deploy Blancco config and preferences (null-stripped)"
|
||||
- name: "Extract config-clean.xml from config.img (strip null bytes)"
|
||||
shell: |
|
||||
# Strip null bytes from config.img files and deploy
|
||||
if [ -f "{{ web_root }}/blancco/config.img" ]; then
|
||||
WORK=$(mktemp -d)
|
||||
cd "$WORK"
|
||||
@@ -873,11 +878,30 @@
|
||||
tr -d '\000' < config.xml > "{{ web_root }}/blancco/config-clean.xml"
|
||||
rm -rf "$WORK"
|
||||
fi
|
||||
# Deploy preferences from playbook (pre-configured with network share)
|
||||
cp "{{ usb_root }}/playbook/blancco-preferences.xml" "{{ web_root }}/blancco/preferences.xml"
|
||||
args:
|
||||
creates: "{{ web_root }}/blancco/config-clean.xml"
|
||||
|
||||
# Idempotent file copy (was bundled into the previous shell task with a
|
||||
# 'creates:' gate, so playbook re-runs never picked up edits to the
|
||||
# source XML - stale prefs survived deploys).
|
||||
- name: "Deploy Blancco preferences.xml from playbook source"
|
||||
copy:
|
||||
src: "{{ usb_root }}/playbook/blancco-preferences.xml"
|
||||
dest: "{{ web_root }}/blancco/preferences.xml"
|
||||
mode: '0644'
|
||||
|
||||
# Hard gate: blancco-init.sh in initramfs drops to shell if the served
|
||||
# preferences.xml is malformed or missing the SMB target. Fail the
|
||||
# playbook here too so the problem surfaces at deploy time, not at the
|
||||
# next erasure attempt.
|
||||
- name: "Validate deployed preferences.xml is well-formed + targets the right SMB share"
|
||||
shell: |
|
||||
set -e
|
||||
python3 -c 'import xml.etree.ElementTree as ET; ET.parse("{{ web_root }}/blancco/preferences.xml")'
|
||||
grep -q '<hostname>10.9.100.1</hostname>' "{{ web_root }}/blancco/preferences.xml"
|
||||
grep -q '<path>blancco-reports</path>' "{{ web_root }}/blancco/preferences.xml"
|
||||
changed_when: false
|
||||
|
||||
- name: "Ensure Samba user for Blancco reports exists (idempotent)"
|
||||
shell: |
|
||||
id blancco >/dev/null 2>&1 || useradd -r -s /usr/sbin/nologin blancco
|
||||
@@ -994,6 +1018,11 @@
|
||||
Environment=BLANCCO_REPORTS=/srv/samba/blancco-reports
|
||||
Environment=ENROLLMENT_SHARE=/srv/samba/enrollment
|
||||
Environment=AUDIT_LOG=/var/log/pxe-webapp-audit.log
|
||||
# Lock TZ so report/backup mtimes and audit-log timestamps render
|
||||
# in Eastern time regardless of how the host's /etc/localtime ends
|
||||
# up. Without this, a Python process started before timedatectl
|
||||
# finishes can cache UTC for its lifetime.
|
||||
Environment=TZ=America/New_York
|
||||
ExecStart=/usr/bin/python3 app.py
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
Reference in New Issue
Block a user