- Python 92.4%
- Shell 6.5%
- Makefile 1.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
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. |
||
| fw-update | ||
| recipe | ||
| scripts | ||
| .gitignore | ||
| build.sh | ||
| CLAUDE.md | ||
| Makefile | ||
| README.md | ||
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.
- HTTPS is the transport. Disabling it removes Redfish itself. It is
excluded by default;
--kill-httpsis a one-way door whose only recovery is in-bandipmitool raw 0x32 0x66from the host OS. - 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.
- Link-local cannot be removed.
fe80::/10is 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. - Bonding is not standard Redfish. MegaRAC exposes it as an OEM extension
or not at all. The tool tries
Oem/Amithen falls back toipmitool -I lanplus raw 0x32 0x71 .... Notelanplusover 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 UPin the MegaRAC UI. - If the BMC is on a tagged VLAN, add
ip link add link eth0 name eth0.N type vlan id Nbefore discovery; the tool does not guess VLAN tags. - Know your recovery path before you start.