No description
  • Python 92.4%
  • Shell 6.5%
  • Makefile 1.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Stefan Huber c95d2a32f0 docs: restructure fw-update README for operators; fix stale-image trap
All four products are flashed and verified end to end, so the docs should
now read as instructions rather than as a debugging journal.

README: split into two parts. Part 1 is operational and comes first --
running an update (including WHICH two lines to check before pressing
Enter), swapping in a new firmware version, adding a new board, and where
the logs are when something goes wrong. Part 2 keeps the existing
implementation notes essentially verbatim, since nearly every rule there
exists because a real board broke the obvious implementation; it is now
explicitly framed as "read before simplifying any of it".

The firmware-swap section is written for someone doing this without the
author around: verify the .ima really is what its filename claims (via
the same FW_DESC/UFW_VERSION strings the tool itself reads), replace the
file, update product-map.json, check version_hints if the version SERIES
moved, rebuild, and confirm from the boot output that the old image is
gone. Every command in it was executed and checked, including against a
synthetic .ima to confirm the verify step matches scan_firmware_images().

build.sh: fixed a real trap the docs would otherwise have had to warn
about. It copied *.ima into the recipe staging directory but never
cleaned it, and mksquashfs bundles whatever sits there -- so an image
deleted from fw-update/ kept shipping inside the ISO, wasting ~64MB and
still appearing as a flashable option in the manual menu. It now clears
stale staged images first (after the "no images found" check, so a
missing source can never leave us with nothing) and prints exactly what
it bundled.

CLAUDE.md: the fw-update summary was factually wrong -- it still claimed
flashing only happens from a fallback menu shown when identification
fails. Replaced with the actual pipeline, and a pointer that the README
is authoritative. Also flags that fw-update's Redfish.get() is
status-aware while bmc-lockdown's is not.

Makefile: dropped the stale "READ-ONLY, Phase 1, no flashing" help text.
2026-08-27 23:52:36 +02:00
fw-update docs: restructure fw-update README for operators; fix stale-image trap 2026-08-27 23:52:36 +02:00
recipe bmc-lockdown: also retry PATCH on HttpStatus.1.0.PreconditionFailed 2026-08-20 10:08:07 +02:00
scripts Add Makefile (iso/usb/add_partition) and add_report_partition.py 2026-08-20 10:19:54 +02:00
.gitignore fw-update: post_flash_harden reuses authenticate() for PasswordChangeRequired 2026-08-27 16:01:03 +02:00
build.sh Initial import: BMC lockdown appliance recipe 2026-08-18 13:37:43 +02:00
CLAUDE.md docs: restructure fw-update README for operators; fix stale-image trap 2026-08-27 23:52:36 +02:00
Makefile docs: restructure fw-update README for operators; fix stale-image trap 2026-08-27 23:52:36 +02:00
README.md Initial import: BMC lockdown appliance recipe 2026-08-18 13:37:43 +02:00

BMC Lockdown Appliance

A SystemRescue-based walk-up tool for hardening ASRock Rack / AMI MegaRAC BMCs over a direct Ethernet link. Plug a laptop into the management port, boot, and it discovers the BMC and disables bonding, IPv6 autoconfiguration, and network services via Redfish.

Layout

build.sh                                    wraps sysrescue-customize
recipe/
  iso_add/
    autorun/autorun1                        interactive entry point
    sysrescue.d/500-bmc-lockdown.yaml        boot config
  build_into_srm/
    usr/local/bin/bmc-lockdown              the tool
    usr/local/bin/bmc-lease-hook            dnsmasq dhcp-script hook
    etc/dnsmasq-bmc.conf                    addressing

Build

sudo ./build.sh systemrescue-12.00-amd64.iso bmc-lockdown.iso
sudo dd if=bmc-lockdown.iso of=/dev/sdX bs=4M status=progress oflag=sync

Verify dnsmasq, arp-scan and ipmitool are actually in the resulting image — stock SystemRescue does not ship all three.

Discovery strategy

Layered, cheapest and most reliable first:

Round Method Catches
1 ping ff02::1 + neighbour table any IPv6-capable BMC, no DHCP needed
1 dnsmasq dhcp-script hook BMCs configured for DHCPv4/v6
2 arp-scan on the served subnet BMCs that leased but went quiet
3 arp-scan on 192.168.0/24, 10.0.0/24, 192.168.1/24 static + AMI DHCP-timeout fallbacks

Every candidate is confirmed by a real GET /redfish/v1/ before use. Link-local IPv6 targets are preferred because they survive every v4 reconfiguration the tool subsequently performs.

Ordering hazards

These are the ways this workflow strands you. The tool handles each, but understand them before running it unattended.

  1. HTTPS is the transport. Disabling it removes Redfish itself. It is excluded by default; --kill-https is a one-way door whose only recovery is in-band ipmitool raw 0x32 0x66 from the host OS.
  2. Bonding changes relocate the BMC. Disabling the bond pins the BMC to one interface, which may not be the one you are plugged into. The tool re-runs discovery after the bond change and refuses to continue blind. Always use the dedicated port.
  3. Link-local cannot be removed. fe80::/10 is mandatory per RFC 4291. Redfish can disable SLAAC and DHCPv6, so no global v6 address forms, but the interface remains reachable on-link. Only disabling the interface outright removes that, and doing so over the network is self-defeating.
  4. Bonding is not standard Redfish. MegaRAC exposes it as an OEM extension or not at all. The tool tries Oem/Ami then falls back to ipmitool -I lanplus raw 0x32 0x71 .... Note lanplus over IPv6 link-local is unreliable — the raw fallback wants a v4 target.

Why not ip neigh polling

Neighbour entries only materialise once traffic flows in one direction, so polling races the BMC's DHCP backoff (which can be 30–120s on AMI firmware). The dhcp-script hook fires synchronously on lease events instead. Keep the hook fast: dnsmasq blocks on it and a slow hook delays the DHCP ACK.

Credentials

The ISO contains no password. autorun1 prompts on tty1. If you need full automation, put the password on a separately-labelled LUKS volume rather than baking it into an image that will outlive the laptop.

Pre-flight

  • Cable in the dedicated IPMI port.
  • Target chassis has PSU power — the BMC runs in S5, but if you are working the shared/NCSI port the host NIC may have dropped the sideband. See Keep Share NIC UP in the MegaRAC UI.
  • If the BMC is on a tagged VLAN, add ip link add link eth0 name eth0.N type vlan id N before discovery; the tool does not guess VLAN tags.
  • Know your recovery path before you start.