| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5938199 commit 4e2c5d2
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -325,6 +325,16 @@ else: | |||
| 325 | 325 | "with no podman but docker on PATH, falls back to docker", | |
| 326 | 326 | f"rc={rc} stdout={out!r} stderr={err!r}") | |
| 327 | 327 | ||
| 328 | + # Neither single-binary case above can catch an inverted if/else: with no | ||
| 329 | + # `docker` on PATH at all, a docker-first probe still lands on the `else` | ||
| 330 | + # branch and reports docker only when podman is also absent, so swapping | ||
| 331 | + # the branches would still pass both cases above. Only stubbing BOTH | ||
| 332 | + # proves which branch actually fires first. | ||
| 333 | + rc, out, err = _run_with_stub("podman", "docker") | ||
| 334 | + report(rc == 0 and out == "podman podman.socket", | ||
| 335 | + "with both podman and docker on PATH, podman wins", | ||
| 336 | + f"rc={rc} stdout={out!r} stderr={err!r}") | ||
| 337 | + | ||
| 328 | 338 | print() | |
| 329 | 339 | print(f"{passed} passed, {failed} failed") | |
| 330 | 340 | sys.exit(0 if failed == 0 else 1) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -608,7 +608,21 @@ sect "19. container runtime identity" | |||
| 608 | 608 | # `podman` itself - stubbing `docker` would prove nothing about which | |
| 609 | 609 | # runtime the gate actually saw. | |
| 610 | 610 | printf '#!/bin/sh\nexit 0\n' > /stub/podman; chmod +x /stub/podman | |
| 611 | - KEY=/repo/.secrets/bgrpiimage-recovery.key | ||
| 611 | + | ||
| 612 | + # The manifest is tampered below, so it has to be re-signed to reach the | ||
| 613 | + # runtime gate rather than being stopped earlier by signature verification - | ||
| 614 | + # same technique as section 10's foreign-key case, but the opposite trust | ||
| 615 | + # direction: that key proves an UNTRUSTED signer is refused, this one has to | ||
| 616 | + # be TRUSTED so what is actually exercised is the runtime gate. The real | ||
| 617 | + # release key is not an option here: it lives only in this developer's | ||
| 618 | + # gitignored .secrets/, or as a PEM in the CI env var BGRPIIMAGE_SIGNING_KEY | ||
| 619 | + # that is deliberately never written to disk (see .github/workflows/build.yml) | ||
| 620 | + # - and the test container mounts /repo read-only regardless. A throwaway | ||
| 621 | + # key, generated on the fly and trusted by THIS device only, is what works | ||
| 622 | + # unattended on every machine, CI included. | ||
| 623 | + openssl genpkey -algorithm ed25519 -out /tmp/runtime.key 2>/dev/null | ||
| 624 | + openssl pkey -in /tmp/runtime.key -pubout -out /tmp/runtime.pub 2>/dev/null | ||
| 625 | + KEY=/tmp/runtime.key | ||
| 612 | 626 | work=/tmp/runtime | |
| 613 | 627 | ||
| 614 | 628 | # A bundle explicitly built for Docker, applied to a Podman device. | |
@@ -621,6 +635,10 @@ openssl pkeyutl -sign -rawin -inkey "$KEY" \ | |||
| 621 | 635 | ( cd $work && tar czf "$DL/$(basename "$BUNDLE")" manifest.json manifest.json.sig root ) | |
| 622 | 636 | ( cd "$DL" && sha256sum "$(basename "$BUNDLE")" > "$(basename "$BUNDLE").sha256" ) | |
| 623 | 637 | seed_device 0.0.1 | |
| 638 | + # seed_device reseeds the trust store from the image's own shipped keys, so | ||
| 639 | + # the throwaway key has to be re-added after every seed and before the apply | ||
| 640 | + # that relies on it being trusted. | ||
| 641 | + cp /tmp/runtime.pub /usr/share/bgrpiimage/trusted-keys.d/ | ||
| 624 | 642 | $U apply --yes >/tmp/rt1 2>&1 | |
| 625 | 643 | grep -qi "bundle is built for docker" /tmp/rt1 \ | |
| 626 | 644 | && ok "runtime mismatch refused (bundle=docker, device=podman)" \ | |
@@ -642,6 +660,7 @@ openssl pkeyutl -sign -rawin -inkey "$KEY" \ | |||
| 642 | 660 | ( cd $work && tar czf "$DL/$(basename "$BUNDLE")" manifest.json manifest.json.sig root ) | |
| 643 | 661 | ( cd "$DL" && sha256sum "$(basename "$BUNDLE")" > "$(basename "$BUNDLE").sha256" ) | |
| 644 | 662 | seed_device 0.0.1 | |
| 663 | + cp /tmp/runtime.pub /usr/share/bgrpiimage/trusted-keys.d/ | ||
| 645 | 664 | $U apply --yes >/tmp/rt2 2>&1 | |
| 646 | 665 | grep -qi "predates the container-runtime contract" /tmp/rt2 \ | |
| 647 | 666 | && ok "legacy bundle with no container_runtime refused on a Podman device" \ | |
@@ -658,6 +677,31 @@ $U apply --yes >/tmp/rt3 2>&1; rc=$? | |||
| 658 | 677 | [ $rc -eq 0 ] && ok "matching container runtime (podman/podman) is not blocked" \ | |
| 659 | 678 | || { bad "a matching runtime was refused"; tail -8 /tmp/rt3; } | |
| 660 | 679 | ||
| 680 | + # Podman-first is the load-bearing property of detect_runtime(): this fixture | ||
| 681 | + # has no `docker` stub anywhere on PATH, so every case above would pass just | ||
| 682 | + # as well with the if/else branches swapped. Only stubbing BOTH binaries and | ||
| 683 | + # asserting podman still wins can catch an inverted discriminator. Extracted | ||
| 684 | + # and run standalone (rather than through a full apply) because that is the | ||
| 685 | + # only way to observe detect_runtime()'s own return value directly. | ||
| 686 | + rt_fn=$(sed -n '/^detect_runtime() {/,/^}/p' "$U") | ||
| 687 | + mkdir -p /tmp/bothstub | ||
| 688 | + printf '#!/bin/sh\nexit 0\n' > /tmp/bothstub/podman; chmod +x /tmp/bothstub/podman | ||
| 689 | + printf '#!/bin/sh\nexit 0\n' > /tmp/bothstub/docker; chmod +x /tmp/bothstub/docker | ||
| 690 | + # `PATH=... bash -c` would search the NEW PATH for `bash` itself and fail to | ||
| 691 | + # find it there - so bash is resolved by its absolute path first, and PATH is | ||
| 692 | + # only replaced once already running, for detect_runtime()'s own PATH lookups. | ||
| 693 | + BASH_BIN=$(command -v bash) | ||
| 694 | + result=$(PATH=/tmp/bothstub "$BASH_BIN" -c "$rt_fn"$'\n'"detect_runtime") | ||
| 695 | + [ "$result" = "podman" ] \ | ||
| 696 | + && ok "podman-first ordering: both podman and docker on PATH still yields podman" \ | ||
| 697 | + || bad "expected podman with both stubbed, got '${result:-<empty>}'" | ||
| 698 | + rm -rf /tmp/bothstub | ||
| 699 | + | ||
| 700 | + # Leave no stub behind: this is currently the last section, but a podman | ||
| 701 | + # stub surviving past it would silently turn every legacy-manifest fixture | ||
| 702 | + # added afterwards into a Podman device. | ||
| 703 | + rm -f /stub/podman | ||
| 704 | + | ||
| 661 | 705 | echo | |
| 662 | 706 | echo "================ $PASS passed, $FAIL failed ================" | |
| 663 | 707 | [ "$FAIL" -eq 0 ] | |
| Back | FazBrowse Home | New Git URL |
0 commit comments