Commit Graph

462 Commits

Author SHA1 Message Date
cproudlock
a54df7ebd9 Webapp redesign: imaging floor at laptop widths, keyboard tips, placeholders
From the design review:
- Floor rows reserve 150px for actions instead of 190px; stage text is
  one line with the full text in a tip (safety text still wraps); the PC
  type hides first; rows stack only below 960px of panel width, with the
  actions on the status line instead of their own row.
- Tips also show on keyboard focus.
- Placeholders use the muted token (dark-theme contrast was 3.6:1).
- Save bar focus ring uses the save bar's accent (2.8:1 before).
2026-10-14 14:52:45 -04:00
cproudlock
2ed2cbe2e9 Webapp redesign: fixes from the functional regression test
- Unattend: a command's '...' menu stayed open after Move up/down and
  covered the next row's menu, so the next click could stage removing the
  wrong command. The menu now closes and focus returns to its button.
- '...' menus close on an outside click, on Escape and when another
  opens (static/app.js), for every page.
- Drivers: Remove asks to confirm again, as before the redesign. Long zip
  paths in a row body wrap (the page scrolled sideways at 390 px).
- Rollback review returns to the page it was opened from (Dell page or
  Updates overview), for both Cancel and the rollback itself.
- To-do: the ServiceNow period offers a year again (366 days).
- Imaging floor: a search that matches a log-only bay opens that group;
  its open state survives the live refresh. 'Clear all' states the
  number of session files it deletes, hidden finished ones included.
- Dashboard: the image key pattern is valid under the browser's v flag
  (client-side validation was silently skipped).
- Import: allowed_import_source() compares real paths, so
  '<upload dir>/../..' is refused. This path traversal predates the
  redesign; the import moves the source tree, so it mattered.
2026-10-14 14:48:10 -04:00
cproudlock
2bcc9d8016 Webapp redesign: fixes from the code review
Blocker
- /reports/export returned 500: REPORT_EXPORT_RANGES and _months_ago were
  deleted with the old reports route. Restored.

Major
- A session without stage_index/stage_total took down /, /imaging and
  /imaging/tiles (int filter on Undefined). The templates default both;
  saving a LAPS password for a session that no longer exists is refused
  (it created a bare session).
- /reports/todo parsed every report four times (23 s at 700 reports).
  blancco_report.parse() now caches by path, mtime and size: 0.09 s.
- Stored XSS through the session serial in the Clear confirm (the
  browser decodes &#39; before running an inline handler). The message
  moves to data-confirm, and update_session() only accepts serials of
  letters, digits, '.', '_' and '-' (400 from /imaging/status otherwise).
- Reports without a document id and with odd characters in the file name
  got a key the mark routes rejected, so they could never be cleared.
  report_key() now always produces a valid key.

Minor
- failure_note() handles a list-valued erasure target (500 on the report
  and to-do pages).
- _recently_marked() tolerates naive, 'Z' and non-dict state entries.
- Key regexes use fullmatch (a trailing newline was accepted).
- Unreadable reports are no longer counted as to tick / to destroy; the
  reports page already flags them as Unreadable.
- Rollback review recounts restorable files after reading the backups.
- Enrollment: the startnet fallback package (no or empty ppkg.conf) and a
  quoted SOURCE_PPKG are protected too.
- Backup upload overwrite check is case-insensitive (SMB share) and
  replaces the existing file rather than adding a case twin.
- Overview polling keeps the last good rows on an error and pauses while
  the tab is hidden. A shown or typed LAPS password survives the floor's
  refresh.
- hardware_dismiss only redirects to same-site paths; tiles ?limit is
  clamped; the Updates overview survives an unreadable Dell scan or iPXE
  state; describe() uses aversion(); a client cannot label its session
  'inferred'.
2026-10-14 14:42:21 -04:00
cproudlock
fd00d5ff89 Webapp redesign phase 6: the remaining pages
Restyled to the same row pattern (one line, details in an expandable
body, one action plus a menu, tokens for light and dark):
- hardware coverage, audit log (family chips, destructive actions in
  red, client-side filters, first 300 rows), Clonezilla backups,
  enrollment packages (active package marked and undeletable, MCL flags
  with a visible legend)
- image Overview, OS and packages, Unattend (sticky save bar), Import
- Dell, iPXE, Blancco and BPRT update pages; Dell history links to the
  rollback review instead of rolling back on one click
- boot menu editor (tabs, rows with a menu, lint chips that jump to the
  line, tokens instead of hard-coded dark colours) and the imaging
  session detail page

Fixes found on the way:
- BPRT batch Activate never asked to confirm: a hidden input named
  'confirm' shadowed window.confirm in the inline handler, so the form
  submitted without a prompt. It now calls window.confirm.
- Backup upload refused when a backup with that name exists, unless
  'Replace the existing backup' is ticked (it overwrote silently).
- app.js: em dashes in comments replaced (plain ASCII).
2026-10-14 14:29:03 -04:00
cproudlock
a6f95fcca1 Webapp redesign phase 5: Blancco reports, report and to-do
Reports (/reports):
- Grouped by month of the erasure date inside each report (not the file
  date), newest first; older months fold. Each month header shows the
  evidence pack state (builds on the 1st, to upload with Download, or
  uploaded).
- One line per report: erasure date, system serial, model, drives,
  result ('Successful, fallback' when a failed attempt fell back to
  another standard), cloud and ServiceNow state. The row body lists every
  drive and erasure attempt with the failure reason.
- Search by system serial, model, drive serial or file; filters for
  failed, not in cloud and to tick. 'To tick' uses the to-do's 30-day
  window; older unticked reports read 'Not ticked'.
- Export and the evidence pack download moved into header popovers.

Report (/reports/view/<file>):
- Header with serial, model and the per-drive result; a notice names
  the drive to destroy until its COD is recorded; Copy ServiceNow note.
- One card per drive with every attempt, a step track and the failure
  reason; steps and error counts fold. System, customer and provenance
  (integrity signature folded, copyable) on the side. Sizes in decimal
  units, as on the list.
- blancco_evidence.failure_note() is shared with the ServiceNow list.

To-do (/reports/todo):
- The ServiceNow tick list is now its first section (period and show
  ticked filters); /reports/servicenow redirects there.
- Five counters; one line per item with details in the row body.
- COD recorded, Mark uploaded and Resolved confirm first (the attribute
  quoting is safe for JSON) and can be undone for 24 hours from the
  page. The header total includes hardware gaps, matching the sidebar.
2026-10-14 14:00:54 -04:00
cproudlock
cc1e76f3ab Webapp redesign phase 4: Updates overview and rollback review
- GET /updates/: one card per updater (Dell, iPXE, Blancco, BPRT) with
  its state, a Check now / Open action and details in accordions; the
  shared download cap is a small popover.
- Dell applies list: one line per apply titled by its first change
  ('Latitude 5350 pack A11 to A12', model looked up in the maps) and
  'and n more'; the chip says how many written files are unchanged since
  the apply. The body lists every change, skipped item, error and file.
- dell_updates.file_status(): per file an apply wrote, unchanged /
  changed / missing by content hash, the same test rollback uses.
  describe(), history_view() and rollback_preview() build on it.
- GET /updates/dell/rollback/<id>: review a rollback before doing it,
  with the files that would be restored and a diff of each. The POST
  route is unchanged; both forms can return to the overview.
2026-10-14 13:54:41 -04:00
cproudlock
731d7b044d Webapp redesign phase 3: Drivers tab
- One line per entry: position, model tokens, pack, OS, size and status
  chips; family, friendly name, osId, folder, zip state, Dell hint and
  the verbatim lint findings are in the row body.
- Status chips compare the staged map with the saved one: New, Edited,
  Moved from #n, Removing, the worst current finding, and 'Clears on
  save' / 'Clears n' when the staged changes resolve this entry's
  findings. The toolbar and a sticky save bar show lint now and after.
- Removing an entry is staged with Undo remove instead of deleting the
  row; Undo edit puts an edited entry back.
- Reordering moved into the row menu (Move up / down / to position).
  The Move dialog shows the order after the move and re-lints the staged
  map with the move applied, listing any new errors before staging it.
- An edit that changes the tokens but keeps the old friendly name is
  flagged in the row and in the review step.
- Filters: Win11/Win10 with counts, 'Findings or unsaved', 'Zip
  problems' (missing, trap and case); a status key explains the chips.
- _image_header.html: new header and underline tabs for every image tab;
  the shared review modal and diff use the design tokens.
2026-10-14 13:51:04 -04:00
cproudlock
0b86255711 Webapp redesign phase 2: Overview and imaging floor
Imaging floor (/imaging, /imaging/tiles):
- One line per PC: status chip, serial with machine number, hostname
  and IP, stage text with a segmented stage track, one action plus a
  '...' menu. Everything else (description, error, timestamps, Intune
  ID + QR, Set category / ARTS links, LAPS QR, log tail) is in the row's
  expandable body.
- Order: failed, needs action (stage 7), in progress, done; log-only
  bays fold into one collapsed group. imaging_status.floor_state() and
  floor_order() compute this.
- Status filter buttons with live counts next to the text filter. SSE
  refresh, expanded-row memory and LAPS handling are unchanged.
- Stage text is never truncated; BIOS updates and erasing are bold.

Overview (/):
- Services popover, technician to-do line, the six most urgent floor
  rows (?limit=6 partial, refreshed every 15 s), and image cards with
  lint warnings, map errors and missing zips as separate chips. New,
  clone, delete and unattend stay on the cards' menus.

Copy buttons are now handled once in static/app.js, with a fallback for
plain-http pages where navigator.clipboard is unavailable.
2026-10-14 13:44:07 -04:00
cproudlock
35cad62733 Webapp redesign phase 1: shell, tokens and shared components
- static/pxe-ui.css: the redesign's colour tokens (light and dark),
  shell, chips, stage track, expandable rows, menus and buttons. The
  legacy tokens (--bg-card, --border, --text-light, ...) alias onto the
  new ones so pages not yet redesigned blend in.
- base.html: new sidebar (Operate, Images, Updates, Tools) with the GE
  Aerospace logo on the brand blue, to-do count, theme toggle with
  aria-pressed, and a menu button on narrow screens. The to-do banner is
  now a one-line strip. Skip link and <main> landmark added.
- _ui.html: Jinja macros for chip, track, the actions menu and the page
  header.
2026-10-14 13:38:05 -04:00
cproudlock
dfd57bef17 Webapp: fix six live bugs found in the page inventory
- Report view: the hero summarised only the first erasure, so a drive whose
  Purge failed and Clear fallback succeeded showed Failed while the list said
  Successful. It now uses the per-drive outcome (report_result) and lists the
  standards that wiped each drive.
- To-do and ServiceNow: reports with no usable document id could never be
  ticked or cleared (400). They are now tracked by file name (file:<name>).
- Imaging: the LAPS password field is masked, with a Show/Hide toggle.
- Imaging: succeeded sessions not updated for ACTIVE_WINDOW_HOURS are hidden
  from the dashboard (failed and in-progress always stay), with Show all.
- Enrollment: the active SFLD package can no longer be deleted, which left
  ppkg.conf pointing at a missing file; its row is marked Active.
- Import: confirm before importing, saying upload-folder sources are moved
  and same-name files in the image are overwritten.
2026-10-14 13:29:00 -04:00
cproudlock
24b4d9df66 Dell updates: say when the results predate the last apply
After an apply the tables still showed the check from before it, so a pack
just applied looked like it still needed updating until the next check.
2026-10-13 17:38:14 -04:00
cproudlock
aa026bace0 BIOS manifest: replace the 24250 line with QB24250, QC24250 and QC24251
'24250' also matched the Dell 24 All-in-One EC24250, which needs a different
BIOS (Dell_EC27250_EC24250). The three exact models are the ones the combined
file is built for. Found by the webapp's Dell check (ambiguous match).
2026-10-13 17:23:57 -04:00
cproudlock
6187219378 BPRT sync: point the page and docstrings at static/Sync-BPRT.ps1
Follow-up to 92f1e62, which moved the file but missed these references.
2026-10-13 17:12:51 -04:00
cproudlock
92f1e62966 BPRT sync: ship Sync-BPRT.ps1 with the webapp so the page can serve it
The download link 404'd on the server: deploys copy only webapp/, and the
script lived in scripts/windows/. One copy now, in webapp/static/.
2026-10-13 17:12:41 -04:00
cproudlock
ae806cf98e CMM imaging: goCMM 2.17.0.0 instead of 2.12.3
FileVersion detection on goCMM.exe so an older 2.x does not satisfy it. Same
NSIS installer and /S switch. Deployed to installers-post/cmm and the share's
shopfloor-setup copy; 2.12.3 moved to installers-post/cmm-archive so it is not
copied to every CMM image.
2026-10-13 17:10:09 -04:00
cproudlock
28cd977c9e goCMM restore: drop the 1.1 Installation Directory value on 2.x PCs
Per-bay backups were taken under goCMM 1.1, so goCMM.reg restores
Installation Directory = the 1.1 folder. goCMM 2.x never reads it, but the 2.x
installer sees it as '1.1 installed' and shows a dialog /S cannot answer,
which hung GE-Enforce on CMM11 and CMM12. Kept when 1.1 really is installed.
2026-10-13 16:58:55 -04:00
cproudlock
bfd5c5b75e Blancco init: optional blancco.base= so a staged release can be test-booted
Default is unchanged. Takes effect only after kexec-initrd-70.img is rebuilt.
2026-10-13 16:58:55 -04:00
cproudlock
dd9ee33cd5 Playbook: tools and Zscaler root CA the webapp Updates pages need
sbsigntool, zip and curl, the Zscaler root CA in the system store (GitHub is
TLS-intercepted on the corporate NIC; downloads.dell.com is not), and
/var/lib/pxe-webapp/updates.
2026-10-13 16:58:55 -04:00
cproudlock
397063f987 Webapp: Updates pages, image page tabs with review-before-save, BPRT sync
Updates group:
- Dell drivers and BIOS: check Dell's catalogs against all three driver maps
  and models.txt, download with a shared speed cap, repack, preview, apply
  with backups and rollback.
- iPXE boot files: check GitHub for the signed Secure Boot set, verify the
  sha256 and each file's signer, install atomically, roll back. Includes the
  by-hand procedure.
- Blancco: upload a release, stage it, test-boot it from the menu, activate,
  roll back.
- BPRT sync: validate a batch uploaded from the MediaCreator Lite cache
  (scripts/windows/Sync-BPRT.ps1 or a zip), show the diff, swap with the site
  overlay files kept.

Images: one sidebar entry per image with Overview, Drivers, Unattend and OS and
Packages tabs. Every save shows a diff first, keeps the file's format, makes a
backup and can be undone. Driver lint runs inline.

Enrollment: upload standard/engineer MCL packages, one per tenant/purpose,
with archive and restore. Hardware coverage counts engineer as Win11.
2026-10-13 16:58:55 -04:00
cproudlock
ddf0a2fdf2 BIOS manifest: update to Dell's current releases, fix wrong-platform lines
Scanned against Dell's per-model catalogs (CatalogIndexPC, 2026-10-09).
About 40 lines were behind, nine pointed at another platform's BIOS
(Latitude 7450 -> OptiPlex 7450, Latitude 5530/5540 -> Precision
5530/5540, Precision 5490/7770/7780 -> OptiPlex AIO, Precision 5550 ->
Latitude 5550, OptiPlex 7400/7410/7420 AIO -> Latitude 7x00/7x10/7x20),
and '7320 2-in-1 Detachable' never matched the WMI name. Specific lines
now precede general ones (5430 Rugged, 7090 Ultra, 3000 Thin Client)
because check-bios.cmd takes the first substring match.
2026-10-12 17:02:47 -04:00
cproudlock
6fac73c947 startnet: map Y: before status push and preflight on every path
The gea-standard/gea-engineer path (purpose -> tenant -> enroll_staged)
never mapped the enrollment share, so winpe-status-push.ps1 and
preflight.ps1 silently skipped those builds. Map it at :end if absent.
2026-10-09 09:59:11 -04:00
cproudlock
f0c049376c Report hardware from the BIOS check, so every WinPE path is covered
The hardware report went out from winpe-status-push.ps1 on the
enrollment share (Y:), but startnet.cmd never maps Y: on the
gea-standard / gea-engineer path (choices 1/2 go purpose -> tenant ->
enroll_staged), so those builds never reported. The same gap means
neither the status push nor preflight.ps1's driver check has ever run
for standard/engineer images.

The BIOS share is mapped by every WinPE boot before the menu, and
check-bios.cmd lives on it, so it now calls hardware-report.ps1 from
the same folder (best effort, output discarded). winpe-status-push.ps1
goes back to status only, so shopfloor bays are not counted twice. The
playbook deploys hardware-report.ps1 with the other BIOS files.
2026-10-09 09:46:11 -04:00
cproudlock
b691a82530 Hardware coverage: flag models the server has no drivers or BIOS for
WinPE now reports each machine's WMI model, manufacturer, Dell system
SKU and BIOS version to /hardware/seen (winpe-status-push.ps1, best
effort, wmic only). The webapp records every model seen and checks it
against what the server has:
  - each image's Deploy/Control/HardwareDriver.json, matched exactly as
    PESetup's GetDriverByModel does (as reimplemented in
    lint-driver-catalogue.py), plus whether the pack's zip is on disk;
  - the WinPE BIOS manifest (substring match like check-bios.cmd).

/hardware lists every model with per-image driver status and BIOS
status. A model missing a Win11 pack or a BIOS entry becomes item 5 on
the Technician To-Do (and the banner count) until the pack/BIOS is added
or it is dismissed. Virtual machines are ignored.

Also deploys the repo winpe-status-push.ps1 over the live copy, which
predated the -CurrentStage/-StageIndex parameters startnet.cmd passes
for the BIOS-flash stage, so that status post was failing.
2026-10-09 09:23:52 -04:00
cproudlock
e43ab2a652 webapp: 12-hour times (e.g. 2026-10-05 1:54 PM EDT)
CSV exports keep ISO 8601 24-hour timestamps.
2026-10-05 14:16:58 -04:00
cproudlock
83ba4865e8 Show every time in US Eastern (America/New_York)
Webapp: config.DISPLAY_TZ (default America/New_York) and a local_dt
filter that renders datetimes, ISO strings and Unix timestamps as e.g.
"2026-10-05 13:54 EDT", DST included. Used for the ServiceNow tick list,
technician to-do, imaging tiles and detail page; timestamp_fmt (reports,
backups, enrollment) goes through it too instead of relying on the
process TZ. CSV report_date is Eastern with its offset. Evidence-pack
months are Eastern calendar months, so a wipe late on the 31st lands in
that month rather than the next.

Blancco: init points the new root's /etc/localtime at America/New_York
so the GUI clock is local. Report timestamps keep their explicit
offset; report.utc_offset stays 0 since a fixed offset cannot follow DST.
Report file names stay UTC, as Blancco's own Save names them.
2026-10-05 14:16:14 -04:00
cproudlock
121577f090 webapp: wrap destruction notes instead of widening the table
The theme sets white-space: nowrap on every table cell, so the
ServiceNow tick list's destruction note (and the to-do failure column)
ran as one line and pushed the Done buttons off to the right. A
td.wrap utility lets prose cells wrap within 16-28rem.
2026-10-05 14:04:40 -04:00
cproudlock
6fcdc8ddb5 webapp: keep a tile's Log tail open across refreshes
Each SSE/poll refresh replaces the tiles' HTML, so the nested Log tail
<details> snapped shut on every update while a wipe was running. Its
open state is now remembered per tile in localStorage like the tile
itself, and its scroll position is kept: following the bottom keeps
following new lines, scrolled up stays put.
2026-10-05 14:02:51 -04:00
cproudlock
8c36d1ba5d blancco-init: post_status uses sed, not tr
The initrd's busybox has the tr applet but no /bin/tr link, so the
quiet boot printed "/init: line 140: tr: not found" and the stage 1/2
dashboard posts were skipped. sed is linked.
2026-10-05 14:01:26 -04:00
cproudlock
12f6f00cdb blancco-progress: take the final state from the report file
First normal (non-debug) run stuck at 6/7 "Report sent to cloud": outside
Blancco's debug mode Albus does not log erasureFinishedForEntity, Report
saving success or "Auto process reached the final step", which the
parser had been taken from a debug-mode journal.

A watcher thread now reads each new /reports/*.xml (auto mode always
saves there) once it is stable and posts 7: "Wipe complete" (succeeded)
or "Erasure FAILED: <model serial, ...>" (failed). Judged per drive, so
a failed Purge with a successful Clear fallback on the same drive is a
wipe. --outcome FILE prints the verdict for a report.
2026-10-05 13:59:09 -04:00
cproudlock
020f043d8b webapp: technician to-do for the manual CMMC steps; count fallbacks as wiped
Technician To-Do (sidebar link with a count, and a banner on every page
while anything is open) lists the playbook steps the server cannot do:
  1. wipes still to tick on the Onsite Bin RITM (ENT-045/159)
  2. monthly evidence packs to upload to Box (ENT-056/158), Mark uploaded
  3. drives that failed to wipe, to destroy (COD recorded)
  4. reports Blancco could not upload to the cloud (Resolved)
Marks are stored in the Blancco state file; the counts are cached for 60s
and refreshed on every mark, ServiceNow tick and cloud-status post.

Results are now judged per drive. Blancco keeps every attempt in the
report, so a NIST Purge that failed followed by a successful Clear
fallback on the same drive appeared as two entries, and the Reports page
rolled the whole report up to Failed. 20 such wipes since May showed as
Failed; they were wiped (the work instruction counts the fallback as a
success). The CSV marks those rows "Fallback: ... then erased with ...".
One genuine failure remains: HNMD1V3, Seagate Z500R4KG, 2026-08-11.
2026-10-05 13:50:26 -04:00
cproudlock
44a7eeae95 blancco: CMMC evidence pack, ServiceNow tick list, cloud-upload status
Automates the Blancco parts of the onsite-support CMMC playbook:

- ENT-056/158 evidence pack: /reports/evidence?month=YYYY-MM returns
  ENT-056_<Site>_<YYYY-MM>.zip (summary.csv, README, each report's XML
  and PDF). pxe-blancco-evidence.timer saves last month's pack to the
  reports share's evidence/ folder on the 1st (Persistent).
- ENT-045/159 ServiceNow tick list: /reports/servicenow lists recent
  reports as "Wiped" or "Blancco Wipe failed" with a pre-written
  destruction note, copy buttons and Done (CSRF-protected).
- Cloud upload: blancco-progress.py posts each report's upload result
  ("Sending report document id" -> "Report sent to MC") to
  /reports/cloud-status (CSRF-exempt like /imaging/status); the Reports
  page and the CSVs show it, so a wipe missing from BMP is visible.
- CSV gains failure_reason (exception messages, failed steps, error
  counts), business_location and cloud_upload.
- Preferences: business_location "West Jefferson" (config.BLANCCO_SITE)
  and pdf+xml reports; the report copier now copies the PDF too, named
  after its XML. .part and hidden files are not listed as reports.

State (cloud confirmations, ServiceNow ticks) is a JSON file at
/var/lib/pxe-webapp/blancco-state.json, off the report share.
2026-10-05 13:43:16 -04:00
cproudlock
eff956ae6c webapp: Blancco variant of the /imaging tiles
Sessions with source/pctype "blancco" (posted by blancco-init.sh and
blancco-progress.py) now render with their own stage labels
(Downloading, Starting, Licensing, Erasing, Erasure finished, Report
sent, Wipe complete; Erasure FAILED on failure), a WIPE badge with the
drive percentage instead of "no DeviceId", the current step beside the
stage, and an Erasure reports link. The drive percentage is folded into
the bar across stage 4. The LAPS QR card is hidden for Blancco tiles.

Also render the bar percentage as an integer: round() returns a float,
so every tile showed e.g. "57.0%".
2026-10-05 12:52:08 -04:00
cproudlock
19049e6b1f blancco: live erase progress on the /imaging dashboard
Each Blancco PC now gets a tile on /imaging, keyed by BIOS serial with
pctype "blancco", using the /imaging/status endpoint the WinPE clients
already post to (stage_total 7):

  1 Downloading Blancco, 2 Starting Blancco   (blancco-init.sh, wget)
  3 Waiting for licence / Licence OK (N left)
  4 Erasing: step N - <step> [NN%]
  5 Erasure finished / Report saved
  6 Report sent to cloud
  7 Done (succeeded), or Erasure FAILED (failed, sticks)

playbook/blancco-progress.py follows the AlbusSeven journal inside the
Blancco rootfs and maps its lines to those stages; patterns taken from
a real 7.20 auto-mode run and replayed with --replay/--dry-run, plus a
synthetic failed step. Init fetches it from the web root at boot and
installs it as blancco-progress.service; the playbook deploys it there.
The report copier adds a "Report copied to share" log line. Stage 1
resets a finished tile for the same serial. All posts are best effort.
2026-10-05 12:50:40 -04:00
cproudlock
a97faf9fad blancco-init: auto-save reports to the SMB share in process=auto
process=auto erases unattended but Albus forces auto_backup off outside
workflow/manual, so every report needed a manual Save to reach the
share. Debug SSH on a live 7.20 run showed Albus does keep each report
at /reports/<document_id>.xml ("Report saving success", "CRC verified")
and uploads it to MC, with /mnt/share already mounted.

Install blancco-report-sync as a systemd service in the new root: every
10s copy each finished /reports/*.xml (older than 5s, not yet copied)
to /mnt/share as YYYYMMDD_HHMMSS_report.xml (UTC, as a manual Save
names it), via a .part file and rename. Verified live: the auto-run
report landed as 20261005_164520_report.xml.
2026-10-05 12:46:48 -04:00
cproudlock
165d6d34a3 blancco-init: debug boots open SSH for root
With blancco.debug=1 the init now also creates /etc/debug.environment in
the new root (Blancco's isDebugMode, so 2_sshd starts sshd) and installs
root's authorized_keys from http://<server>/blancco/debug_authorized_keys.
Root is locked and sshd is key-only, so normal boots stay closed and a
debug boot without that file on the server stays closed too.

Used to find where Albus keeps the finished report in process=auto, which
never auto-backs-up to the share. Live GetPxeScript.aspx has a matching
"Blancco Drive Eraser (debug / SSH)" item (UEFI, 7.0 kernel, verbose);
not in the playbook menu.
2026-10-05 12:42:10 -04:00
cproudlock
b50ff36f71 blancco-preferences: back to process=auto until MC has a default workflow
process=workflow failed on the first real run: "failed to fetch the
default workflow ... there is no default workflow for user
api.wipecheck@ge.com". The GE Blancco console needs a default workflow
assigned to that account. Until then run auto, as live 7.15 did:
unattended erasure once licensed, report to the cloud automatically,
SMB share copy via Save (auto_backup is forced off outside
workflow/manual).
2026-10-05 12:32:54 -04:00
cproudlock
143c27c3bf blancco-preferences: run the cloud workflow process
Live 7.15 ran process=auto: it erased unattended but Albus forces
auto_backup off outside workflow/manual ("... not workflow or manual:
Report auto backup must be disabled"), so every report needed a manual
Save to reach the share. 7.20 was set to manual, which honours
auto_backup but waits at "Select devices" (seen on the first real run).

workflow is the only process that both runs unattended (the account's
default MC workflow, workflow default=true, fetched over WiFi) and
auto-backs-up the report ("Start file watcher for auto backup of
workflow process"). Live preferences.xml and config.img updated
(backups .bak-20261005-pre-workflow).
2026-10-05 12:29:38 -04:00
cproudlock
b3ed4cda81 blancco-init: give Blancco /run/initramfs from config.img on UEFI
On a native boot config.img is an initrd and archiso leaves its files in
/run/initramfs, where /opt/scripts/inc/1_reportKey, 2_certificate,
1_config and 2_flexible_container install report.key, ca.pem,
hybrid.ids and the flexible container. The Ubuntu-kernel UEFI path never
created /run/initramfs, so 1_reportKey wrote an empty /albus/report.key
and the rest were skipped (true since 7.15). Fetch config.img, unpack it
on a tmpfs mounted at the new root's /run (systemd keeps an existing
/run), and fail loudly if report.key is missing.

First real 7.20 run (Dell Pro 5 14, Panther Lake, 7.0 kernel) licensed
and erased, but did not start the cloud workflow on its own or save the
report without a click; the missing report key is the leading suspect.
2026-10-05 12:24:29 -04:00
cproudlock
14eab13a1a blancco-init: per-kernel kmod tarball, lazy umount of the report share
- Fetch kmod-$KVER.tar.gz first, falling back to kmod.tar.gz, so more
  than one boot kernel can share the web root. Live now boots the UEFI
  path on Ubuntu's 24.04 HWE 7.0.0-34-generic kernel: Panther Lake
  laptops (Dell Pro 14, AX211 on CNVi) need iwlwifi firmware API 100,
  which the 6.8 driver cannot load. 6.8 stays deployed as the rollback.
- The 10s DefaultTimeoutStopSec did not reach the /mnt/share mount: a
  mount unit's timeout is TimeoutSec=, defaulting to the start timeout.
  Add a mnt-share.mount drop-in with TimeoutSec=10s, LazyUnmount=yes and
  ForceUnmount=yes.

NOT in the playbook yet: it builds the initrd and kmod tarball from the
server's running kernel (6.8). The 7.0 artifacts on 172.16.9.1 were
built off-box; installing linux-generic-hwe-24.04 on the server is what
makes a playbook run reproduce them.
2026-10-05 12:17:11 -04:00
cproudlock
783f2fece0 blancco: quiet PXE boot, full trace with blancco.debug=1
The UEFI loader ran under set -x and printed modprobe -v, ip link and
ip addr, and neither kernel cmdline had quiet, so the screen scrolled
hundreds of lines before the Blancco GUI. Now:

- quiet loglevel=3 on both Blancco kernel lines (also quiets systemd)
- init clears the screen and prints one line per step
- blancco.debug=1 on the cmdline restores the old trace
- failure paths still print their diagnostics and drop to a shell

Live GetPxeScript.aspx changed to match (backup
.bak-20261005-pre-quiet) and kexec-initrd.img rebuilt.
2026-10-05 12:05:30 -04:00
cproudlock
1f5f9eb60a blancco-init: cap systemd stop jobs at 10s
Restarting Blancco after an erasure stalled on "A stop job is running
for /mnt/share": the network goes down before the SMB report share is
unmounted, and the CIFS umount waits out the 90s default. Reports are
written long before shutdown, so set DefaultTimeoutStopSec=10s in the
switched-to rootfs.
2026-10-05 12:02:43 -04:00
cproudlock
77655bbfcd pxe: ship Ubuntu iwlwifi firmware with the Blancco kmod tarball
The UEFI Blancco path boots the Ubuntu 6.8 kernel on Blancco's rootfs, so
iwlwifi loads firmware from the Blancco image. 7.20 dropped the API 86
ucode for AX201/AX210/AX211 and ships only API 89, which the 6.8 driver
cannot use: WiFi never came up, so no cloud licence (seen 2026-10-05).

kmod.tar.gz now also carries the host's lib/firmware/iwlwifi-* (183
files, .zst, which the kernel prefers over the image's .xz). Files only:
on the Blancco rootfs lib is a symlink to usr/lib. Live tarball rebuilt
(backup kmod.tar.gz.bak-20261005-pre-iwlfw); the task's creates: guard
means an existing server needs the file removed to pick this up.
2026-10-05 12:00:24 -04:00
cproudlock
372c3802e5 pxe: Blancco initrd pulls in module deps and NIC firmware
The kexec-initrd build copied a fixed set of module directories plus
drivers/net/mii.ko. Ubuntu ships that as mii.ko.zst, so the -e test
skipped it, and usbnet, r8152 and cdc_ether then failed to load with
"Unknown symbol mii_*": USB-C to RJ45 adapters never appeared (seen
2026-10-05, Dell USB-C adapter). igb lacked dca and i2c-algo-bit the
same way.

Walk the host modules.dep from the copied modules and copy every
dependency (73 on 6.8.0-71). Also copy rtl_nic, tigon, bnx2, bnx2x and
e100 firmware, which those drivers request at probe.
2026-10-05 11:56:16 -04:00
cproudlock
25f65424c7 blancco-init: load xhci_pci so USB-C NICs work, report why a link fails
The initrd has no udev, so only modules init names get loaded, and
xhci_pci is a module in the Ubuntu kernel. USB 3 / USB-C ports were
therefore dead in the UEFI Blancco path and a Dell USB-C to RJ45 adapter
never appeared; init took the onboard e1000e port with no cable.

- modprobe xhci_pci and xhci_pci_renesas before the NIC drivers
- bring up interfaces inside the carrier wait too, since USB NICs
  enumerate seconds after onboard ports
- on no-link, print each interface's driver and the NIC/firmware/link
  kernel messages before dropping to a shell

Live kexec-initrd.img also now carries the NIC firmware set from the
Blancco 7.20 early cpio (rtl_nic, tigon, bnx2x, ...) under /lib/firmware.
The playbook build does not add it yet.
2026-10-05 11:48:17 -04:00
cproudlock
29e0d97f59 blancco-init: use the cabled NIC, and stop hanging on a dead link
The UEFI init took the first interface in /sys/class/net and put
172.16.9.250 on it. On a PC with a second port, dock or USB NIC that can
be the unplugged one; wget then sat at "Connecting to 172.16.9.1:80"
forever (seen 2026-10-05 on a Dell, serial GGX6BN4). Bring every wired
interface up and use the first with carrier; with no link anywhere,
list the interfaces and drop to a shell. wget calls get -T 30 so a
stalled transfer fails loudly instead of hanging.

Live kexec-initrd.img was rebuilt with only init swapped (backup
kexec-initrd.img.bak-20261005-pre-carrier).
2026-10-05 11:38:57 -04:00
cproudlock
b474ac376e pxe: let BIOS Blancco boots load iwlwifi for cloud licensing
7.20 licenses through the Blancco cloud, and on the air-gapped PXE LAN
the only route out is WiFi INTERNETACCESS. The legacy BIOS cmdline still
blacklisted iwlwifi/iwlmvm, so BIOS boots could never license. btusb
stays blacklisted; rd.udev.timeout=10 bounds the udev hang iwlwifi
caused on some Intel machines. Live GetPxeScript.aspx changed to match
(backup .bak-20261005-pre-bios-wifi).
2026-10-05 10:14:57 -04:00
cproudlock
96c4e5dd11 webapp: export Blancco reports for the last 1/3/6/12 months
/reports/export?range=1m|3m|6m|12m&format=csv|zip. CSV has one row per
erased drive (system and drive serials, standard, result, times, licence
consumption id). ZIP holds the original XML/PDF reports plus summary.csv.
Reports are selected by the date inside each XML, falling back to mtime
only when it is missing. Exports are audit-logged.
2026-10-05 09:32:32 -04:00
cproudlock
678d10d5c2 blancco: upgrade to Drive Eraser 7.20.0
playbook/blancco-preferences.xml is now the vendor 7.20 preferences
(schema 4.20, "Non_GEAE_Wired" profile) with only our site overrides:
SMB report share on 172.16.9.1 with auto_backup, WiFi INTERNETACCESS for
cloud licensing (wired stays up for SMB), manual as the fallback process,
bootable report, screensaver 86400. workflow default=true is kept: the
cloud workflow erases unattended, as live 7.15 already did. No custom
fields, matching both the vendor image and live 7.15.

prepare-boot-tools.sh:
- 7.20 initramfs is an uncompressed early cpio (NIC firmware, itself
  .xz files) followed by the XZ archive. The old patch decompressed from
  byte 0, failed, warned and carried on, so PXE boots would drop network
  after copytoram. Walk the cpio to its trailer and patch the XZ part.
- Patch exactly one copytoram match or fail. The looser fallback pattern
  matches five hooks in 7.20.
- config.img now carries playbook/blancco-preferences.xml, so the BIOS
  (native kernel) and UEFI (HTTP) paths read the same settings. Refuses
  to build if the playbook preferences are for another Blancco version.
- The old global replace() also set the 802.1x, WiFi and repeater
  passwords to "blancco". Gone with the above.
- Keep preferences.xml size by refilling the NUL gap before the trailing
  filler comment (7.20), or trimming the comment (7.15).
- OUT_DIR can be overridden to stage a build outside boot-tools/.
2026-10-05 09:32:32 -04:00
cproudlock
737a729548 fix(shopfloor): clear imaging AutoLogonCount at ShopFloor handover
Run-ShopfloorSetup and Stage-Dispatcher top AutoLogonCount up to 10 so
SupportUser survives vendor-forced reboots. Sysinternals Autologon, which
lockdown uses to switch the bay to ShopFloor, leaves the counter in place,
so ShopFloor inherited the remainder. Windows counts it down on every
autologon and at 0 sets AutoAdminLogon=0: the bay boots to a ShopFloor
password prompt a few reboots after imaging.

Delete the counter once Winlogon shows ShopFloor:
- Monitor-IntuneProgress.ps1, on the poll that sees the handover
- SetShopfloorAutoLogon.bat, after sfld_autologon.ps1
- Force-Lockdown.bat, on success

The SupportUser top-ups stay. Tested in the win11 VM: the Monitor block
removes the counter for ShopFloor, keeps it for SupportUser, and is a
no-op when clean; both batch files leave ShopFloor autologon on with no
counter.
2026-10-02 10:06:42 -04:00
cproudlock
47f5d4603a fix(e10): --e10 passed bare silently skipped the controller
Three bugs, all found by actually running the thing rather than reading it.

1. `--e10` with no value did nothing. Making the flag optional-valued gave it
   an empty-string constant, and the code deciding whether to drive the
   controller used a truth test - so the documented `--e10` form printed the
   full translation and quietly skipped the hardware. No error, because
   nothing failed. Now gated on `is not None`, with a comment saying why.

2. A missing part program dumped a traceback. The top-level handler tidied
   e10 errors and re-raised everything else. Now a clean message that lists
   the part programs it can actually see, which also covers Windows path
   confusion.

3. Errors could vanish when piped. stdout is block-buffered and stderr is
   not, so the message printed before the output it referred to and a `| tail`
   dropped it entirely - looking like a silent failure. stdout is flushed
   before writing an error.
2026-08-27 13:55:00 -04:00