forked from heavy-duty/rig
test: drive bootstrap undo safety gates
This commit is contained in:
parent
8b4a55a712
commit
c0272cbae6
3 changed files with 101 additions and 7 deletions
32
README.md
32
README.md
|
|
@ -237,11 +237,33 @@ the only shapes it manages — every other role refuses an effective
|
|||
`tag:server` after join, one rule instead of per-role exceptions.
|
||||
|
||||
After the tag verification passes, bootstrap writes `/etc/rig/role` — one
|
||||
line, `role=… root-door=… host=… join=…` — recording the **effective** traits,
|
||||
overrides and all, so an overridden role never lies to the commands that read
|
||||
the marker later (`rig users` keys root policy off `root-door=`). Written
|
||||
post-join and cmp-guarded, so a marker never describes a box that failed to
|
||||
become what it claims.
|
||||
line, `role=… root-door=… host=… join=… join-by=…` — recording the
|
||||
**effective** traits, overrides and all, plus whether this run performed the
|
||||
tailnet join. `join-by=rig` means bootstrap called `tailscale up`;
|
||||
`join-by=preexisting` means it found the node already joined. Old markers name
|
||||
neither and are treated as unknown, never as permission to remove a join.
|
||||
Written post-join and cmp-guarded, so a marker never describes a box that
|
||||
failed to become what it claims.
|
||||
|
||||
### `rig bootstrap --undo`
|
||||
|
||||
```sh
|
||||
sudo rig bootstrap --undo
|
||||
```
|
||||
|
||||
Leaves the tailnet and then removes `/etc/rig/role`, but only when the marker
|
||||
says `join-by=rig`. A pre-existing join, an old marker with no provenance, or
|
||||
no marker at all is refused without calling `tailscale logout`; the refusal
|
||||
names the manual repair. Re-running bootstrap writes the current marker shape.
|
||||
|
||||
Undo also refuses while a GitHub runner is installed and points at
|
||||
`rig runner remove`, because restoring the local machine while leaving an
|
||||
off-box runner registration would create a ghost in the repository. If
|
||||
`tailscale logout` fails, the marker stays in place so the command is retryable.
|
||||
|
||||
This is intentionally not a general rollback. It does not uninstall packages,
|
||||
reverse sshd hardening, remove Docker, Node, agent CLIs, or users. Those changes
|
||||
are convergent rather than transactional and cannot be safely inferred away.
|
||||
|
||||
Immediately after it, bootstrap stamps `/etc/rig/manifest` — **provenance**:
|
||||
which rig converged this box and when (see [`rig
|
||||
|
|
|
|||
|
|
@ -6,12 +6,21 @@ log() { printf 'rig-bootstrap: %s\n' "$*"; }
|
|||
die() { printf 'rig-bootstrap: ERROR: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
MARKER="${RIG_ROLE_MARKER:-/etc/rig/role}"
|
||||
RUNNER_DIR="${RIG_RUNNER_DIR:-/home/github-runner/actions-runner}"
|
||||
|
||||
[ "$(id -u)" -eq 0 ] || die "must run as root"
|
||||
[ -e "$MARKER" ] || die "no /etc/rig/role marker — refusing to touch the tailnet"
|
||||
|
||||
if [ -e "$RUNNER_DIR/.runner" ]; then
|
||||
runner_installed=0
|
||||
if [ -n "${RIG_RUNNER_DIR:-}" ]; then
|
||||
[ -e "$RIG_RUNNER_DIR/.runner" ] && runner_installed=1
|
||||
else
|
||||
for runner_config in /home/*/actions-runner/.runner /root/actions-runner/.runner; do
|
||||
[ -e "$runner_config" ] && runner_installed=1
|
||||
done
|
||||
compgen -G '/etc/systemd/system/actions.runner.*.service' >/dev/null \
|
||||
&& runner_installed=1
|
||||
fi
|
||||
if [ "$runner_installed" -eq 1 ]; then
|
||||
die "a GitHub runner is installed — run 'rig runner remove' first so undo does not leave a ghost runner in the repository"
|
||||
fi
|
||||
|
||||
|
|
|
|||
63
test/cli.sh
63
test/cli.sh
|
|
@ -143,6 +143,69 @@ check "bootstrap: login verify fails closed on a stalled backend" 0 "" \
|
|||
# The marker is the traits' ground truth for rig users; assert the write exists.
|
||||
check "bootstrap: role marker write is present" 0 "" \
|
||||
grep -q "/etc/rig/role" "$ROOT/commands/bootstrap.sh"
|
||||
check "bootstrap: role marker records join provenance" 0 "join-by=%s" \
|
||||
grep -F "join-by=%s" "$ROOT/commands/bootstrap.sh"
|
||||
# shellcheck disable=SC2016
|
||||
check "bootstrap: both first-join paths record join-by=rig" 0 "2" \
|
||||
bash -c 'test "$(grep -c "^[[:space:]]*JOIN_BY=rig$" "$1")" -eq 2; echo 2' _ \
|
||||
"$ROOT/commands/bootstrap.sh"
|
||||
check "bootstrap: already-joined path defaults to join-by=preexisting" 0 "JOIN_BY=preexisting" \
|
||||
grep -F "JOIN_BY=preexisting" "$ROOT/commands/bootstrap.sh"
|
||||
|
||||
# Drive the narrow inverse end to end. Every refusal also asserts the tailscale
|
||||
# shim was NOT called: exit status alone would miss the destructive regression.
|
||||
UNDO_FIX="$(mktemp -d)"
|
||||
UNDO_BIN="$UNDO_FIX/bin"
|
||||
UNDO_MARKER="$UNDO_FIX/role"
|
||||
UNDO_RUNNER="$UNDO_FIX/runner"
|
||||
UNDO_CALLS="$UNDO_FIX/tailscale.calls"
|
||||
mkdir -p "$UNDO_BIN" "$UNDO_RUNNER"
|
||||
cat > "$UNDO_BIN/tailscale" <<'SH'
|
||||
#!/usr/bin/env bash
|
||||
printf '%s\n' "$*" >> "$UNDO_CALLS"
|
||||
if [ "${TAILSCALE_LOGOUT_FAIL:-0}" = 1 ]; then exit 1; fi
|
||||
SH
|
||||
cat > "$UNDO_BIN/id" <<'SH'
|
||||
#!/usr/bin/env bash
|
||||
if [ "${1:-}" = -u ]; then printf '0\n'; else exec /usr/bin/id "$@"; fi
|
||||
SH
|
||||
chmod +x "$UNDO_BIN/tailscale" "$UNDO_BIN/id"
|
||||
undo() {
|
||||
env PATH="$UNDO_BIN:$PATH" UNDO_CALLS="$UNDO_CALLS" \
|
||||
RIG_ROLE_MARKER="$UNDO_MARKER" RIG_RUNNER_DIR="$UNDO_RUNNER" \
|
||||
"$ROOT/bin/rig" bootstrap --undo
|
||||
}
|
||||
undo_untouched() {
|
||||
: > "$UNDO_CALLS"
|
||||
if undo >/tmp/rig-undo.out 2>&1; then return 1; fi
|
||||
[ ! -s "$UNDO_CALLS" ]
|
||||
}
|
||||
rm -f "$UNDO_MARKER"
|
||||
check "bootstrap --undo: no marker refuses without touching tailnet" 0 "" undo_untouched
|
||||
printf '%s\n' 'role=workload-server root-door=open host=no join=authkey' > "$UNDO_MARKER"
|
||||
check "bootstrap --undo: old marker names missing provenance" \
|
||||
1 "marker predates join-by provenance" undo
|
||||
check "bootstrap --undo: old marker leaves tailnet untouched" 0 "" undo_untouched
|
||||
printf '%s\n' 'role=workload-server root-door=open host=no join=authkey join-by=preexisting' > "$UNDO_MARKER"
|
||||
check "bootstrap --undo: pre-existing join refuses by name" 1 "join-by=preexisting" undo
|
||||
check "bootstrap --undo: pre-existing join leaves tailnet untouched" 0 "" undo_untouched
|
||||
printf '%s\n' 'role=runner-server root-door=open host=no join=authkey join-by=rig' > "$UNDO_MARKER"
|
||||
printf '%s\n' '{}' > "$UNDO_RUNNER/.runner"
|
||||
check "bootstrap --undo: installed runner points at its removal verb" \
|
||||
1 "rig runner remove" undo
|
||||
check "bootstrap --undo: installed runner leaves tailnet untouched" 0 "" undo_untouched
|
||||
rm -f "$UNDO_RUNNER/.runner"
|
||||
check "bootstrap --undo: failed logout is loud" \
|
||||
1 "role marker kept" env TAILSCALE_LOGOUT_FAIL=1 PATH="$UNDO_BIN:$PATH" \
|
||||
UNDO_CALLS="$UNDO_CALLS" RIG_ROLE_MARKER="$UNDO_MARKER" \
|
||||
RIG_RUNNER_DIR="$UNDO_RUNNER" "$ROOT/bin/rig" bootstrap --undo
|
||||
check "bootstrap --undo: failed logout preserves the marker" 0 "" test -e "$UNDO_MARKER"
|
||||
: > "$UNDO_CALLS"
|
||||
check "bootstrap --undo: proven rig join succeeds" 0 "tailnet join removed" undo
|
||||
check "bootstrap --undo: successful logout was called" 0 "logout" cat "$UNDO_CALLS"
|
||||
check "bootstrap --undo: success removes the marker" 1 "" test -e "$UNDO_MARKER"
|
||||
check "bootstrap --undo: second run refuses cleanly" 1 "no /etc/rig/role marker" undo
|
||||
rm -rf "$UNDO_FIX" /tmp/rig-undo.out
|
||||
# ...and that it is written in the CURRENT vocabulary (#77). New markers say
|
||||
# root-door=; the retired class= spelling is something rig READS forever and
|
||||
# WRITES never, so a marker line that reintroduces it must not ship green.
|
||||
|
|
|
|||
Loading…
Reference in a new issue