#!/bin/sh # fleet-bootstrap — fetch this machine's published fleet script, run it, report back. # # Installed to /usr/local/bin/fleet-bootstrap on every endpoint, driven by a systemd # timer. What it is FOR: getting each machine into CheckMK monitoring without anybody # SSHing into eleven hosts and pasting the same installer. # # THIS IS REMOTE CODE EXECUTION, AND IT IS SUPPOSED TO BE. There is no way to # "distribute a script to the endpoints" that is not. So the honesty is in the # constraints rather than in pretending otherwise: # # 1. It runs the PUBLISHED version only. An upload is a draft and is invisible here # until a human publishes it deliberately — see workshop/fleet.py. # 2. It verifies the sha256 the server sent against the body it received, and refuses # to run on a mismatch. That is not protection against a malicious server (the # server chose both), it is protection against a truncated download, which is the # failure that actually happens. # 3. It runs a version ONCE. The recorded state file is what stops a timer from # re-running an installer every fifteen minutes forever. # 4. It reports what it ran, pass or fail. A script that was served is not a script # that succeeded, and only the endpoint knows which. # 5. It is opt-in per host: no WORKSHOP_URL, no execution. # # The whole capability is worth one sentence in your own words before enabling it: # anyone who can publish to that service can run code as root on every machine here. # Treat WORKSHOP_TOKEN accordingly — it is the most powerful credential in this project. set -eu CONFIG="${FLEET_CONFIG:-/etc/fleet-bootstrap.conf}" [ -f "$CONFIG" ] && . "$CONFIG" WORKSHOP_URL="${WORKSHOP_URL:-}" WORKSHOP_TOKEN="${WORKSHOP_TOKEN:-}" FLEET_PLATFORM="${FLEET_PLATFORM:-}" STATE_DIR="${FLEET_STATE_DIR:-/var/lib/fleet-bootstrap}" if [ -z "$WORKSHOP_URL" ] || [ -z "$WORKSHOP_TOKEN" ] || [ -z "$FLEET_PLATFORM" ]; then echo "fleet-bootstrap: not configured (need WORKSHOP_URL, WORKSHOP_TOKEN, FLEET_PLATFORM in $CONFIG)" >&2 exit 0 # Not an error: an unconfigured host is a host that opted out. fi command -v curl >/dev/null 2>&1 || { echo "fleet-bootstrap: curl is required" >&2; exit 1; } mkdir -p "$STATE_DIR" HOSTNAME_NOW="$(hostname)" RESPONSE="$(curl -fsS -H "Authorization: Bearer ${WORKSHOP_TOKEN}" \ "${WORKSHOP_URL%/}/fleet/script/${FLEET_PLATFORM}" 2>/dev/null || true)" if [ -z "$RESPONSE" ]; then # No published script for this platform yet is the normal state before somebody # uploads one. Silence beats a daily error mail about a thing nobody has done yet. echo "fleet-bootstrap: nothing published for ${FLEET_PLATFORM}" exit 0 fi # python3 rather than jq: every image in this project already has python3, and the # script body is JSON-escaped text that a shell parser would mangle. VERSION="$(printf '%s' "$RESPONSE" | python3 -c 'import json,sys;print(json.load(sys.stdin).get("version",""))')" EXPECTED_SHA="$(printf '%s' "$RESPONSE" | python3 -c 'import json,sys;print(json.load(sys.stdin).get("sha256",""))')" SCRIPT_FILE="${STATE_DIR}/${FLEET_PLATFORM}.v${VERSION}.sh" printf '%s' "$RESPONSE" | python3 -c 'import json,sys;sys.stdout.write(json.load(sys.stdin).get("body",""))' > "$SCRIPT_FILE" ACTUAL_SHA="$(sha256sum "$SCRIPT_FILE" | cut -d" " -f1)" if [ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]; then echo "fleet-bootstrap: checksum mismatch (expected $EXPECTED_SHA, got $ACTUAL_SHA) — refusing to run" >&2 rm -f "$SCRIPT_FILE" exit 1 fi STATE_FILE="${STATE_DIR}/ran-${FLEET_PLATFORM}" if [ -f "$STATE_FILE" ] && [ "$(cat "$STATE_FILE")" = "$ACTUAL_SHA" ]; then echo "fleet-bootstrap: v${VERSION} already ran here" exit 0 fi echo "fleet-bootstrap: running ${FLEET_PLATFORM} v${VERSION} (${ACTUAL_SHA})" chmod 0700 "$SCRIPT_FILE" set +e OUTPUT="$(sh "$SCRIPT_FILE" 2>&1)" RC=$? set -e if [ "$RC" -eq 0 ]; then # Recorded only on success, so a failed run is retried on the next timer rather than # being remembered as done. printf '%s' "$ACTUAL_SHA" > "$STATE_FILE" fi # Report either way. The failure case is the one worth having on the admin page. curl -fsS -X POST -H "Authorization: Bearer ${WORKSHOP_TOKEN}" -H "Content-Type: application/json" \ -d "$(python3 -c 'import json,sys print(json.dumps({"hostname": sys.argv[1], "platform": sys.argv[2], "version": int(sys.argv[3]) if sys.argv[3] else None, "sha256": sys.argv[4], "ok": sys.argv[5] == "0", "detail": sys.argv[6][-2000:]}))' \ "$HOSTNAME_NOW" "$FLEET_PLATFORM" "$VERSION" "$ACTUAL_SHA" "$RC" "$OUTPUT")" \ "${WORKSHOP_URL%/}/fleet/report" >/dev/null 2>&1 || \ echo "fleet-bootstrap: ran, but could not report back" >&2 exit "$RC"