Skip to content

Commit 97c8bff

Browse files
committed
ci(deploy-runner): verify swap via PID + ActiveEnterTimestamp + sha256 [runner-from: 27345482938]
1 parent 1640831 commit 97c8bff

1 file changed

Lines changed: 48 additions & 3 deletions

File tree

.github/workflows/deploy-runner.yml

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ jobs:
277277
echo "rule_id=$RULE_ID" >> "$GITHUB_OUTPUT"
278278
echo "::notice::SG rule $RULE_ID added (22/tcp from $MY_IP/32)"
279279
280-
- name: SCP artifact + SSH-driven binary swap
280+
- name: SCP artifact + SSH-driven binary swap (verify PID + SHA256 changed)
281281
env:
282282
IP: ${{ steps.ec2.outputs.runner_ip }}
283283
KEY: ${{ steps.keypush.outputs.key_path }}
@@ -286,20 +286,65 @@ jobs:
286286
ARCHIVE=$(ls /tmp/runner-artifact/boxlite-runner-*-linux-amd64.tar.gz | head -1)
287287
[ -n "$ARCHIVE" ] || { echo "::error::No runner artifact found"; exit 1; }
288288
289+
# Compute expected binary sha256 from the artifact tarball — the
290+
# remote `sha256sum /usr/local/bin/boxlite-runner` after swap must
291+
# match this, otherwise the file on disk isn't what we shipped.
292+
EXPECTED_SHA=$(tar -xzOf "$ARCHIVE" boxlite-runner 2>/dev/null | sha256sum | awk '{print $1}') \
293+
|| EXPECTED_SHA=$(tar -tzf "$ARCHIVE" | grep -E 'boxlite-runner$' | head -1 \
294+
| xargs -I{} sh -c "tar -xzOf '$ARCHIVE' {} | sha256sum | awk '{print \$1}'")
295+
[ -n "$EXPECTED_SHA" ] || { echo "::error::Could not compute expected sha256 from $ARCHIVE"; exit 1; }
296+
echo "::notice::expected sha256: $EXPECTED_SHA"
297+
289298
SSH_OPTS="-i $KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=15"
290299
291300
# SCP the tarball
292301
scp $SSH_OPTS "$ARCHIVE" "ubuntu@${IP}:/tmp/boxlite-runner.tar.gz"
293302
294-
# In-place swap + restart + smoke-check
295-
ssh $SSH_OPTS "ubuntu@${IP}" 'bash -s' <<'REMOTE'
303+
# In-place swap + restart + verification. The remote script
304+
# captures MainPID + ActiveEnterTimestamp BEFORE the swap, then
305+
# asserts after restart: (a) new MainPID != old MainPID
306+
# (proves a real process replacement, not the old one still
307+
# running), (b) ActiveEnterTimestampMonotonic strictly
308+
# advanced (proves systemd marked it active after our start),
309+
# and (c) /usr/local/bin/boxlite-runner sha256 matches
310+
# EXPECTED_SHA passed from the GHA runner.
311+
ssh $SSH_OPTS "ubuntu@${IP}" "EXPECTED_SHA='$EXPECTED_SHA' bash -s" <<'REMOTE'
296312
set -euxo pipefail
313+
314+
BEFORE_PID=$(systemctl show -p MainPID --value boxlite-runner 2>/dev/null || echo 0)
315+
BEFORE_TS=$(systemctl show -p ActiveEnterTimestampMonotonic --value boxlite-runner 2>/dev/null || echo 0)
316+
echo "BEFORE: MainPID=$BEFORE_PID ActiveEnterTimestampMonotonic=$BEFORE_TS"
317+
297318
sudo systemctl stop boxlite-runner
298319
sudo tar xzf /tmp/boxlite-runner.tar.gz -C /usr/local/bin/
299320
sudo chmod +x /usr/local/bin/boxlite-runner
300321
sudo systemctl start boxlite-runner
301322
sleep 5
302323
sudo systemctl is-active --quiet boxlite-runner || { sudo journalctl -u boxlite-runner -n 50 --no-pager; exit 1; }
324+
325+
AFTER_PID=$(systemctl show -p MainPID --value boxlite-runner)
326+
AFTER_TS=$(systemctl show -p ActiveEnterTimestampMonotonic --value boxlite-runner)
327+
INSTALLED_SHA=$(sudo sha256sum /usr/local/bin/boxlite-runner | awk '{print $1}')
328+
echo "AFTER: MainPID=$AFTER_PID ActiveEnterTimestampMonotonic=$AFTER_TS"
329+
echo "AFTER: sha256=$INSTALLED_SHA"
330+
echo "EXPECT: sha256=$EXPECTED_SHA"
331+
332+
# (a) PID must have changed (proves real restart)
333+
if [ "$AFTER_PID" = "$BEFORE_PID" ] && [ "$BEFORE_PID" != "0" ]; then
334+
echo "::error::MainPID did not change ($AFTER_PID) — service did not actually restart"
335+
exit 1
336+
fi
337+
# (b) systemd's monotonic timestamp for last active-enter must have advanced
338+
if [ "$AFTER_TS" -le "$BEFORE_TS" ]; then
339+
echo "::error::ActiveEnterTimestampMonotonic did not advance ($BEFORE_TS -> $AFTER_TS)"
340+
exit 1
341+
fi
342+
# (c) installed binary sha256 must match the artifact we uploaded
343+
if [ "$INSTALLED_SHA" != "$EXPECTED_SHA" ]; then
344+
echo "::error::Installed binary sha256 mismatch — got $INSTALLED_SHA expected $EXPECTED_SHA"
345+
exit 1
346+
fi
347+
echo "Verified: PID swap + monotonic ts advance + sha256 match"
303348
/usr/local/bin/boxlite-runner --version 2>&1 || true
304349
REMOTE
305350
echo "::notice::Runner binary swap succeeded"

0 commit comments

Comments
 (0)