Fix: Verify the initial Panama revision

This commit is contained in:
Gabriel Brown
2026-08-27 10:06:13 -04:00
parent ba4e5e6677
commit 0d1841cf86
3 changed files with 335 additions and 83 deletions
+86 -25
View File
@@ -2,8 +2,9 @@
# Panama's front door: the one command a fresh Fedora machine needs.
#
# bash <(curl -fsSL https://git.gbrown.org/gib/Panama/raw/branch/main/boot)
# bash <(curl -fsSL https://git.gbrown.org/gib/Panama/raw/branch/main/boot) --server
# Download this file from the documented commit URL, verify its documented
# SHA-256, then pass both immutable values as PANAMA_BOOT_REVISION and
# PANAMA_BOOT_SHA256 when invoking it.
#
# Deliberately dumb, because a copy of this script leaves the repository the
# moment somebody curls it -- nothing here can be fixed by re-running
@@ -17,9 +18,85 @@
set -euo pipefail
if [[ ! "${PANAMA_BOOT_REVISION:-}" =~ ^[0-9a-f]{40}$ ]]; then
echo "boot: PANAMA_BOOT_REVISION must be a full lowercase commit" >&2
exit 1
fi
if [[ ! "${PANAMA_BOOT_SHA256:-}" =~ ^[0-9a-f]{64}$ ]]; then
echo "boot: PANAMA_BOOT_SHA256 must be a lowercase SHA-256" >&2
exit 1
fi
actual_boot_sha="$(sha256sum "${BASH_SOURCE[0]}" | cut -d' ' -f1)"
if [[ "$actual_boot_sha" != "$PANAMA_BOOT_SHA256" ]]; then
echo "boot: downloaded boot file does not match PANAMA_BOOT_SHA256" >&2
exit 1
fi
REPO_URL="https://git.gbrown.org/gib/Panama.git"
PANAMA_PATH="${PANAMA_PATH:-$HOME/.local/share/Panama}"
export PANAMA_PATH
BOOTSTRAP_USER=""
checkout_command() {
if [[ -n "$BOOTSTRAP_USER" ]]; then
runuser -u "$BOOTSTRAP_USER" -- "$@"
else
"$@"
fi
}
prepare_panama_checkout() {
local checkout="$1" actual_head checkout_status
if [[ -e "$checkout" && ! -d "$checkout/.git" ]]; then
printf 'boot: %s exists but is not a Panama Git checkout\n' "$checkout" >&2
return 1
fi
if [[ -d "$checkout/.git" ]]; then
checkout_status="$(checkout_command git -C "$checkout" status --porcelain)" || {
printf 'boot: could not inspect the existing checkout at %s\n' "$checkout" >&2
return 1
}
if [[ -n "$checkout_status" ]]; then
printf 'boot: existing checkout at %s has local changes\n' "$checkout" >&2
return 1
fi
echo "Panama is already cloned at $checkout; fetching the verified revision"
checkout_command git -C "$checkout" fetch origin "$PANAMA_BOOT_REVISION" || return 1
if ! checkout_command git -C "$checkout" merge-base --is-ancestor \
HEAD "$PANAMA_BOOT_REVISION"; then
echo "boot: existing checkout cannot fast-forward to the verified revision" >&2
return 1
fi
checkout_command git -C "$checkout" merge --ff-only "$PANAMA_BOOT_REVISION" || return 1
else
checkout_command mkdir -p "$(dirname "$checkout")" || return 1
checkout_command git init "$checkout" || return 1
checkout_command git -C "$checkout" remote add origin "$REPO_URL" || return 1
checkout_command git -C "$checkout" fetch --depth=1 origin \
"$PANAMA_BOOT_REVISION" || return 1
checkout_command git -C "$checkout" checkout --detach \
"$PANAMA_BOOT_REVISION" || return 1
actual_head="$(checkout_command git -C "$checkout" rev-parse 'HEAD^{commit}')" || return 1
if [[ "$actual_head" != "$PANAMA_BOOT_REVISION" ]]; then
echo "boot: fetched checkout does not match PANAMA_BOOT_REVISION" >&2
return 1
fi
checkout_command git -C "$checkout" checkout -b main || return 1
checkout_command git -C "$checkout" config branch.main.remote origin || return 1
checkout_command git -C "$checkout" config branch.main.merge refs/heads/main || return 1
fi
actual_head="$(checkout_command git -C "$checkout" rev-parse 'HEAD^{commit}')" || return 1
if [[ "$actual_head" != "$PANAMA_BOOT_REVISION" ]]; then
echo "boot: checkout HEAD does not match PANAMA_BOOT_REVISION" >&2
return 1
fi
}
SERVER=0
INSTALL_ARGS=()
@@ -397,18 +474,11 @@ if [[ "$(id -u)" -eq 0 ]]; then
dnf install -y git
fi
# Cloned straight into the user's home and owned by them: this is the
# checkout `panama update` will pull from for the life of the machine, and
# a root-owned .git in a user's home is a wound that never heals.
# Create or advance the checkout as the target user. A root-owned .git in a
# user's home would break every later update.
PANAMA_PATH="$bootstrap_home/.local/share/Panama"
if [[ -d "$PANAMA_PATH/.git" ]]; then
echo "Panama is already cloned at $PANAMA_PATH; updating"
runuser -u "$username" -- git -C "$PANAMA_PATH" pull --ff-only \
|| echo "Could not fast-forward; installing from the clone as it is" >&2
else
runuser -u "$username" -- mkdir -p "$bootstrap_home/.local/share"
runuser -u "$username" -- git clone "$REPO_URL" "$PANAMA_PATH"
fi
BOOTSTRAP_USER="$username"
prepare_panama_checkout "$PANAMA_PATH"
echo "Handing off to install as $username"
exec runuser -u "$username" -- env PANAMA_PATH="$PANAMA_PATH" \
@@ -422,19 +492,10 @@ if ! command -v git >/dev/null 2>&1; then
sudo dnf install -y git
fi
if [[ -d "$PANAMA_PATH/.git" ]]; then
# An existing clone makes this the recovery command too. Only a fast-forward:
# local work is never rewritten, and a diverged clone still installs from
# what it has rather than stopping someone mid-repair.
echo "Panama is already cloned at $PANAMA_PATH; updating"
git -C "$PANAMA_PATH" pull --ff-only \
|| echo "Could not fast-forward; installing from the clone as it is" >&2
else
git clone "$REPO_URL" "$PANAMA_PATH"
fi
prepare_panama_checkout "$PANAMA_PATH"
# `curl | bash` and `bash <(curl ...)` can leave stdin as the pipe, and the
# first thing install runs is the interview, which has to be able to ask.
# A shell invoked from automation can have a pipe as stdin, while the first
# thing install runs is the interview, which has to be able to ask.
# Reattach the terminal when there is one; without one the interview will say
# so itself.
# The probe actually opens /dev/tty rather than testing -r: a process with no