Findings from a full review (auth/API, CA and rack channel, config generation, integrations, UI/agents/scripts), each verified in code: - rack binary endpoint read any region file via arch=../.. (CA key) - render endpoint traversal; machine-reported MACs used as file paths - delegated intermediates could mint admin/rack identities and IPs; identities now require root-issued certs, intermediates are ServerAuth-only with both name types constrained - rack certs were ServerAuth for rack-chosen SANs: now client-only; racks accept only the region's own cert; join checks the CA fingerprint; unbound join codes cannot take an existing name; job results bound to the rack that took them - rack self-update: region signs binaries with the CA key, the root unit verifies against the join-time CA in a root-owned dir - dnsmasq reads a checked, root-owned copy limited to generated options - commissioning could overwrite deployed machines; MAC takeover of PXE - injection into dnsmasq/cloud-init/PXE/udev/DNS via names and machine-reported strings; stored XSS in the UI; CSP and cross-origin protection; deploy agent shell injection and seed traversal - Redfish requests confined to the BMC's /redfish/ tree - admin_http defaults to loopback; body limits and timeouts; secrets off command lines Also: IPAM claim/reconcile race, sync stopping on one error, watchdog race, release wiping the wrong disk, SAN LUNs as auto targets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
45 lines
2.3 KiB
Bash
Executable File
45 lines
2.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# Installs a rollcall binary the rack controller staged (rollcall-rack-update.path).
|
|
#
|
|
# The staging directory belongs to the rack's unprivileged user, so nothing in
|
|
# it is trusted: the binary is copied into a directory of root's and installed
|
|
# only if the region's signature over it verifies against the CA certificate
|
|
# written at join (root's, from rack.json ca_file). Then the running binary is
|
|
# kept as .prev, the rack restarted, and the previous binary put back if the
|
|
# rack does not register with the region in 60 s.
|
|
set -u
|
|
D=/var/lib/rollcall/update
|
|
BIN=/usr/local/bin/rollcall
|
|
[ -f "$D/ready" ] || exit 0
|
|
want=$(head -c 64 "$D/ready" | tr -cd 'A-Za-z0-9._+-'); rm -f "$D/ready"
|
|
W=$(mktemp -d /run/rollcall-update.XXXXXX) || exit 1
|
|
trap 'rm -rf "$W"' EXIT
|
|
# last-result is read by the rack (backoff); renamed in, so a link planted there is replaced, not followed
|
|
result() { echo "$(date -Is) $*" > "$W/result" && mv -fT "$W/result" "$D/last-result"; echo "$*"; }
|
|
CA=$(jq -r '.ca_file // "/etc/rollcall/rack/ca.pem"' /etc/rollcall/rack.json 2>/dev/null)
|
|
[ -n "$CA" ] && [ "$(stat -c %u "$CA" 2>/dev/null)" = 0 ] || { result "$want: no root-owned CA certificate ($CA), not installed"; exit 1; }
|
|
cp -- "$D/rollcall.new" "$W/bin" && cp -- "$D/rollcall.new.sig" "$W/sig" || { result "$want: staged files missing, not installed"; exit 1; }
|
|
openssl x509 -in "$CA" -pubkey -noout > "$W/pub" 2>/dev/null &&
|
|
openssl dgst -sha256 -verify "$W/pub" -signature "$W/sig" "$W/bin" >/dev/null 2>&1 ||
|
|
{ result "$want: signature does not verify against $CA, not installed"; exit 1; }
|
|
chmod 0755 "$W/bin"
|
|
got=$("$W/bin" version 2>/dev/null | awk '{print $2}')
|
|
[ "$got" = "$want" ] || { result "$want: binary reports '$got', not installed"; exit 1; }
|
|
cur=$("$BIN" version 2>/dev/null | awk '{print $2}')
|
|
cp -p "$BIN" "$BIN.prev"
|
|
install -m 0755 "$W/bin" "$BIN.tmp" && mv -f "$BIN.tmp" "$BIN"
|
|
rm -f "$D/rollcall.new" "$D/rollcall.new.sha256" "$D/rollcall.new.sig"
|
|
since=$(date +%s)
|
|
systemctl restart rollcall-rack.service
|
|
for _ in $(seq 1 30); do
|
|
sleep 2
|
|
if journalctl -u rollcall-rack.service --since "@$since" -o cat 2>/dev/null | grep -q "^.*registered with"; then
|
|
result "updated $cur -> $want"
|
|
exit 0
|
|
fi
|
|
done
|
|
cp -p "$BIN.prev" "$BIN.tmp" && mv -f "$BIN.tmp" "$BIN"
|
|
systemctl restart rollcall-rack.service
|
|
result "$want did not register within 60s; rolled back to $cur"
|
|
exit 1
|