| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d418865 commit fe9926c
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -738,10 +738,19 @@ jobs: | |||
| 738 | 738 | # It is variant-independent, so one copy serves every image. | |
| 739 | 739 | run: | | |
| 740 | 740 | set -euo pipefail | |
| 741 | - src=src/modules/bgrpiimage-base/filesystem/root/usr/local/sbin/bgrpiimage-setup | ||
| 742 | - install -m 0755 "$src" release-assets/bgrpiimage-setup | ||
| 743 | - ( cd release-assets && sha256sum bgrpiimage-setup > bgrpiimage-setup.sha256 ) | ||
| 744 | - sha256sum release-assets/bgrpiimage-setup | ||
| 741 | + base=src/modules/bgrpiimage-base/filesystem/root | ||
| 742 | + install -m 0755 "$base/usr/local/sbin/bgrpiimage-setup" release-assets/bgrpiimage-setup | ||
| 743 | + install -m 0755 "$base/usr/local/sbin/bgrpiimage-update" release-assets/bgrpiimage-update | ||
| 744 | + # The trust keys too. They are public by definition, and publishing | ||
| 745 | + # them beside the bundle means a device from before signing can be | ||
| 746 | + # bootstrapped from the same release URL as everything else, instead | ||
| 747 | + # of needing a raw.githubusercontent path nobody can verify at a | ||
| 748 | + # glance. | ||
| 749 | + install -m 0644 "$base"/usr/share/bgrpiimage/trusted-keys.d/*.pub release-assets/ | ||
| 750 | + ( cd release-assets \ | ||
| 751 | + && sha256sum bgrpiimage-setup > bgrpiimage-setup.sha256 \ | ||
| 752 | + && sha256sum bgrpiimage-update > bgrpiimage-update.sha256 ) | ||
| 753 | + sha256sum release-assets/bgrpiimage-setup release-assets/bgrpiimage-update | ||
| 745 | 754 | ||
| 746 | 755 | # The GitHub release itself is created by release.yml (semantic-release) | |
| 747 | 756 | # when the version is bumped on main. Here we only *append* the image | |
@@ -757,7 +766,9 @@ jobs: | |||
| 757 | 766 | release-assets/*.manifest.json | |
| 758 | 767 | release-assets/*.confbundle.tar.gz | |
| 759 | 768 | release-assets/*.bundle.manifest.json.sig | |
| 769 | + release-assets/*.pub | ||
| 760 | 770 | release-assets/bgrpiimage-setup | |
| 771 | + release-assets/bgrpiimage-update | ||
| 761 | 772 | fail_on_unmatched_files: true | |
| 762 | 773 | append_body: true | |
| 763 | 774 | body: | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -488,8 +488,56 @@ dependency of `ca-certificates` — a signature format needing a package the | |||
| 488 | 488 | device cannot install without an update would be circular. | |
| 489 | 489 | ||
| 490 | 490 | > **Images from before signing carry no trust directory** and will refuse every | |
| 491 | - > bundle, saying so explicitly. Those devices need one reflash to a signed | ||
| 492 | - > image; after that they update in place like the rest. | ||
| 491 | + > bundle, saying so explicitly. They can be brought up by hand once — see | ||
| 492 | + > below — or reflashed. | ||
| 493 | + | ||
| 494 | + ### Bootstrapping a device from before in-place updates | ||
| 495 | + | ||
| 496 | + A unit flashed before this mechanism existed is missing four things: the | ||
| 497 | + updater itself, the trust directory, a current helper, and the identity fields | ||
| 498 | + the safety checks read. All four can be installed once, over SSH, without | ||
| 499 | + reflashing. Everything fetched here is a published release asset. | ||
| 500 | + | ||
| 501 | + ```bash | ||
| 502 | + R=https://github.com/bauer-group/XPD-RPIImage/releases/latest/download | ||
| 503 | + | ||
| 504 | + sudo curl -fsSL --proto '=https' -o /usr/local/sbin/bgrpiimage-update "$R/bgrpiimage-update" | ||
| 505 | + sudo curl -fsSL --proto '=https' -o /usr/local/sbin/bgrpiimage-setup "$R/bgrpiimage-setup" | ||
| 506 | + sudo chmod 0755 /usr/local/sbin/bgrpiimage-update /usr/local/sbin/bgrpiimage-setup | ||
| 507 | + | ||
| 508 | + sudo install -d /usr/share/bgrpiimage/trusted-keys.d | ||
| 509 | + sudo curl -fsSL --proto '=https' \ | ||
| 510 | + -o /usr/share/bgrpiimage/trusted-keys.d/bgrpiimage-recovery.pub \ | ||
| 511 | + "$R/bgrpiimage-recovery.pub" | ||
| 512 | + ``` | ||
| 513 | + | ||
| 514 | + Then record what the image was built from, which the old release file does not | ||
| 515 | + say: | ||
| 516 | + | ||
| 517 | + ```bash | ||
| 518 | + sudo tee -a /etc/bgrpiimage-release >/dev/null <<'EOF' | ||
| 519 | + BGRPIIMAGE_BASE_IMAGE_SHA256='acff736ca7945e3b305f07cda4abdb870910e12634991da69783611756e381b3' | ||
| 520 | + BGRPIIMAGE_APPLY_CONTRACT=1 | ||
| 521 | + EOF | ||
| 522 | + | ||
| 523 | + sudo bgrpiimage-update plan # look before you leap | ||
| 524 | + sudo bgrpiimage-update apply | ||
| 525 | + ``` | ||
| 526 | + | ||
| 527 | + **Why that hash is safe to write.** It is the base image every release since | ||
| 528 | + **v0.5.0** has been built on — the switch to Raspberry Pi OS Lite — and it has | ||
| 529 | + not changed since. Check the first line of `sudo bgrpiimage-setup status`: if | ||
| 530 | + the device reports **v0.5.0 or newer**, it is provably on that base and the | ||
| 531 | + value above is correct for it. | ||
| 532 | + | ||
| 533 | + > ⚠️ **A device older than v0.5.0 is on a different base OS.** Do not write | ||
| 534 | + > that hash there. Reflash instead — the whole point of the check is that | ||
| 535 | + > configuration built for one base must not be applied on top of another. | ||
| 536 | + | ||
| 537 | + Nothing here is a special code path: after the four files are in place the | ||
| 538 | + device is indistinguishable from one flashed with a current image, and every | ||
| 539 | + refusal and verification described above applies to it unchanged. The procedure | ||
| 540 | + is exercised end to end in `tests/test-update.sh`. | ||
| 493 | 541 | ||
| 494 | 542 | ### What it never touches | |
| 495 | 543 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -91,6 +91,12 @@ cp /repo/dist/*.bundle.manifest.json "$DL/" 2>/dev/null || \ | |||
| 91 | 91 | tar xzOf "$BUNDLE" manifest.json > "$DL/bgrpiimage-${VARIANT}-v${VERSION}.bundle.manifest.json" | |
| 92 | 92 | ( cd "$DL" && sha256sum "$(basename "$BUNDLE")" > "$(basename "$BUNDLE").sha256" ) | |
| 93 | 93 | ||
| 94 | + # Helpers and trust keys, exactly as the release job publishes them. | ||
| 95 | + B=/repo/src/modules/bgrpiimage-base/filesystem/root | ||
| 96 | + install -m 0755 "$B/usr/local/sbin/bgrpiimage-setup" "$DL/bgrpiimage-setup" | ||
| 97 | + install -m 0755 "$B/usr/local/sbin/bgrpiimage-update" "$DL/bgrpiimage-update" | ||
| 98 | + install -m 0644 "$B"/usr/share/bgrpiimage/trusted-keys.d/*.pub "$DL/" | ||
| 99 | + | ||
| 94 | 100 | cd "$WEB" || exit 1 | |
| 95 | 101 | python3 -c " | |
| 96 | 102 | import http.server, ssl, socketserver, os | |
@@ -318,6 +324,55 @@ grep -qi "no trusted keys" /tmp/sg5 \ | |||
| 318 | 324 | && ok "a device with no trust store refuses and explains" \ | |
| 319 | 325 | || { bad "device without trust store did not refuse clearly"; tail -4 /tmp/sg5; } | |
| 320 | 326 | ||
| 327 | + sect "11. bootstrapping hardware from before in-place updates" | ||
| 328 | + # What a device flashed at, say, v0.7.7 actually looks like: no updater, no | ||
| 329 | + # trust store, and a release file with none of the identity the checks need. | ||
| 330 | + # The documented procedure has to take it from there to a working update, or | ||
| 331 | + # an existing fleet can never join without a reflash. | ||
| 332 | + seed_device 0.0.1 | ||
| 333 | + rm -rf /usr/share/bgrpiimage/trusted-keys.d /usr/local/sbin/bgrpiimage-update | ||
| 334 | + cat > /etc/bgrpiimage-release <<EOF | ||
| 335 | + BGRPIIMAGE_DIST="bgrpiimage" | ||
| 336 | + BGRPIIMAGE_VARIANT='$VARIANT' | ||
| 337 | + BGRPIIMAGE_VERSION='0.7.7' | ||
| 338 | + EOF | ||
| 339 | + | ||
| 340 | + # It must refuse before the bootstrap - otherwise this proves nothing. | ||
| 341 | + if [ -x /usr/local/sbin/bgrpiimage-update ]; then | ||
| 342 | + bad "fixture is wrong: the updater is still installed" | ||
| 343 | + else | ||
| 344 | + ok "a pre-update device has no updater at all" | ||
| 345 | + fi | ||
| 346 | + | ||
| 347 | + # --- the documented procedure, run verbatim -------------------------------- | ||
| 348 | + R="$BGRPIIMAGE_UPDATE_DL/$REPO/releases/download/v$VERSION" | ||
| 349 | + curl -fsSL --proto '=https' -o /usr/local/sbin/bgrpiimage-update "$R/bgrpiimage-update" | ||
| 350 | + chmod 0755 /usr/local/sbin/bgrpiimage-update | ||
| 351 | + curl -fsSL --proto '=https' -o /usr/local/sbin/bgrpiimage-setup "$R/bgrpiimage-setup" | ||
| 352 | + chmod 0755 /usr/local/sbin/bgrpiimage-setup | ||
| 353 | + install -d /usr/share/bgrpiimage/trusted-keys.d | ||
| 354 | + curl -fsSL --proto '=https' \ | ||
| 355 | + -o /usr/share/bgrpiimage/trusted-keys.d/bgrpiimage-recovery.pub \ | ||
| 356 | + "$R/bgrpiimage-recovery.pub" | ||
| 357 | + # base_image.sha256 has been the same since v0.5.0, so any device from that | ||
| 358 | + # release onwards is provably on this base - see the note in the docs. | ||
| 359 | + { | ||
| 360 | + echo "BGRPIIMAGE_BASE_IMAGE_SHA256='$BASE_SHA'" | ||
| 361 | + echo "BGRPIIMAGE_APPLY_CONTRACT=1" | ||
| 362 | + } >> /etc/bgrpiimage-release | ||
| 363 | + | ||
| 364 | + $U apply --yes >/tmp/bs 2>&1; rc=$? | ||
| 365 | + [ $rc -eq 0 ] && ok "bootstrapped device applies the update" \ | ||
| 366 | + || { bad "apply failed after bootstrap"; tail -12 /tmp/bs; } | ||
| 367 | + grep -qi "signature verified" /tmp/bs \ | ||
| 368 | + && ok "and verifies the signature against the fetched key" \ | ||
| 369 | + || bad "signature was not verified after bootstrap" | ||
| 370 | + grep -q "BGRPIIMAGE_CONFIG_VERSION='$VERSION'" /etc/bgrpiimage-applied \ | ||
| 371 | + && ok "configuration version recorded" || bad "version not recorded" | ||
| 372 | + grep -q "BGRPIIMAGE_VERSION='0.7.7'" /etc/bgrpiimage-release \ | ||
| 373 | + && ok "still reports the originally flashed image" \ | ||
| 374 | + || bad "the flashed version was overwritten" | ||
| 375 | + | ||
| 321 | 376 | echo | |
| 322 | 377 | echo "================ $PASS passed, $FAIL failed ================" | |
| 323 | 378 | [ "$FAIL" -eq 0 ] | |
| Back | FazBrowse Home | New Git URL |
0 commit comments