#!/usr/bin/env bash TAPM_FLEET_STATE_DIR="${TAPM_FLEET_STATE_DIR:-/var/lib/ta-proxmenu}" TAPM_FLEET_IDENTITY_FILE="${TAPM_FLEET_IDENTITY_FILE:-${TAPM_FLEET_STATE_DIR}/identity.env}" TAPM_FLEET_INSTALLATION_ID='' TAPM_FLEET_CREDENTIAL='' TAPM_FLEET_LAST_VERSION='' TAPM_FLEET_ENROLLED=0 TAPM_FLEET_REGISTERED=0 TAPM_FLEET_STARTED_AT=0 TAPM_FLEET_VERSION='' TAPM_FLEET_HOSTNAME='' TAPM_FLEET_READ_VALUE() { local key="$1" local value='' if [[ -r "$TAPM_FLEET_IDENTITY_FILE" ]]; then value="$( sed -n "s/^${key}=//p" "$TAPM_FLEET_IDENTITY_FILE" | tail -n 1 )" fi printf '%s' "$value" } TAPM_FLEET_LOAD_IDENTITY() { TAPM_FLEET_INSTALLATION_ID="$(TAPM_FLEET_READ_VALUE INSTALLATION_ID)" TAPM_FLEET_CREDENTIAL="$(TAPM_FLEET_READ_VALUE CREDENTIAL)" TAPM_FLEET_LAST_VERSION="$(TAPM_FLEET_READ_VALUE LAST_VERSION)" TAPM_FLEET_ENROLLED="$(TAPM_FLEET_READ_VALUE ENROLLED)" [[ "$TAPM_FLEET_ENROLLED" == 1 ]] || TAPM_FLEET_ENROLLED=0 } TAPM_FLEET_VALID_IDENTITY() { [[ "$TAPM_FLEET_INSTALLATION_ID" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ && "$TAPM_FLEET_CREDENTIAL" =~ ^[0-9a-f]{64}$ ]] } TAPM_FLEET_WRITE_IDENTITY() { local temporary_file mkdir -p "$TAPM_FLEET_STATE_DIR" 2>/dev/null || return 1 chmod 0700 "$TAPM_FLEET_STATE_DIR" 2>/dev/null || return 1 temporary_file="$(mktemp "${TAPM_FLEET_IDENTITY_FILE}.tmp.XXXXXX")" || return 1 if ! { printf 'INSTALLATION_ID=%s\n' "$TAPM_FLEET_INSTALLATION_ID" printf 'CREDENTIAL=%s\n' "$TAPM_FLEET_CREDENTIAL" printf 'LAST_VERSION=%s\n' "$TAPM_FLEET_LAST_VERSION" printf 'ENROLLED=%s\n' "$TAPM_FLEET_ENROLLED" } >"$temporary_file" || ! chmod 0600 "$temporary_file" || ! mv -f "$temporary_file" "$TAPM_FLEET_IDENTITY_FILE"; then rm -f "$temporary_file" return 1 fi } TAPM_FLEET_ENSURE_IDENTITY() { TAPM_FLEET_LOAD_IDENTITY TAPM_FLEET_VALID_IDENTITY && return 0 command -v openssl >/dev/null 2>&1 || return 1 if [[ -r /proc/sys/kernel/random/uuid ]]; then IFS= read -r TAPM_FLEET_INSTALLATION_ID /dev/null 2>&1; then TAPM_FLEET_INSTALLATION_ID="$(uuidgen | tr '[:upper:]' '[:lower:]')" else return 1 fi TAPM_FLEET_CREDENTIAL="$(openssl rand -hex 32)" || return 1 TAPM_FLEET_LAST_VERSION='' TAPM_FLEET_ENROLLED=0 TAPM_FLEET_WRITE_IDENTITY } TAPM_FLEET_COLLECT_METADATA() { TAPM_FLEET_HOSTNAME="$(hostname -s 2>/dev/null || hostname 2>/dev/null || true)" TAPM_FLEET_GIT_COMMIT="$(git -C "${FOLDER:-/opt/idssys/ta-proxmenu}" rev-parse HEAD 2>/dev/null || true)" TAPM_FLEET_PVE_VERSION="$(pveversion 2>/dev/null | head -n 1 || true)" TAPM_FLEET_OS_VERSION="$( if [[ -r /etc/os-release ]]; then ( # shellcheck disable=SC1091 source /etc/os-release printf '%s' "${PRETTY_NAME:-}" ) fi )" TAPM_FLEET_KERNEL_VERSION="$(uname -r 2>/dev/null || true)" TAPM_FLEET_ARCHITECTURE="$( dpkg --print-architecture 2>/dev/null || uname -m 2>/dev/null || true )" if [[ -s /etc/pve/corosync.conf ]]; then TAPM_FLEET_CLUSTERED=true else TAPM_FLEET_CLUSTERED=false fi } TAPM_FLEET_JSON() { local event="$1" local result="$2" local error_code="${3:-}" local duration="${4:-0}" TAPM_FLEET_EVENT="$event" \ TAPM_FLEET_RESULT="$result" \ TAPM_FLEET_ERROR_CODE="$error_code" \ TAPM_FLEET_DURATION="$duration" \ TAPM_FLEET_INSTALLATION_ID="$TAPM_FLEET_INSTALLATION_ID" \ TAPM_FLEET_HOSTNAME="$TAPM_FLEET_HOSTNAME" \ TAPM_FLEET_CREDENTIAL="$TAPM_FLEET_CREDENTIAL" \ TAPM_FLEET_VERSION="$TAPM_FLEET_VERSION" \ TAPM_FLEET_GIT_COMMIT="$TAPM_FLEET_GIT_COMMIT" \ TAPM_FLEET_PVE_VERSION="$TAPM_FLEET_PVE_VERSION" \ TAPM_FLEET_OS_VERSION="$TAPM_FLEET_OS_VERSION" \ TAPM_FLEET_KERNEL_VERSION="$TAPM_FLEET_KERNEL_VERSION" \ TAPM_FLEET_ARCHITECTURE="$TAPM_FLEET_ARCHITECTURE" \ TAPM_FLEET_CLUSTERED="$TAPM_FLEET_CLUSTERED" \ TAPM_FLEET_INCLUDE_CREDENTIAL="${TAPM_FLEET_INCLUDE_CREDENTIAL:-0}" \ python3 -c ' import json, os, sys payload = { "schema_version": 1, "installation_id": os.environ["TAPM_FLEET_INSTALLATION_ID"], "hostname": os.environ["TAPM_FLEET_HOSTNAME"], "event": os.environ["TAPM_FLEET_EVENT"], "result": os.environ["TAPM_FLEET_RESULT"], "proxmenu_version": os.environ["TAPM_FLEET_VERSION"], "git_commit": os.environ["TAPM_FLEET_GIT_COMMIT"], "pve_version": os.environ["TAPM_FLEET_PVE_VERSION"], "os_version": os.environ["TAPM_FLEET_OS_VERSION"], "kernel_version": os.environ["TAPM_FLEET_KERNEL_VERSION"], "architecture": os.environ["TAPM_FLEET_ARCHITECTURE"], "clustered": os.environ["TAPM_FLEET_CLUSTERED"] == "true", "error_code": os.environ["TAPM_FLEET_ERROR_CODE"], "duration_seconds": int(os.environ["TAPM_FLEET_DURATION"]), } if os.environ.get("TAPM_FLEET_INCLUDE_CREDENTIAL") == "1": payload["credential"] = os.environ["TAPM_FLEET_CREDENTIAL"] json.dump(payload, sys.stdout, separators=(",", ":")) ' } TAPM_FLEET_REGISTER() { TAPM_FLEET_INCLUDE_CREDENTIAL=1 TAPM_FLEET_JSON installed success | curl --fail --silent --show-error \ --connect-timeout 3 --max-time 10 \ --header 'Content-Type: application/json' \ --data-binary @- \ "${TAPM_BROKER_URL}/api/v1/hosts/register" \ >/dev/null 2>&1 } TAPM_FLEET_EVENT_SEND() { local event="$1" local result="$2" local error_code="${3:-}" local duration="${4:-0}" local event_payload='' (( TAPM_FLEET_REGISTERED == 1 )) || return 1 event_payload="$(mktemp "${TMPDIR:-/tmp}/tapm-fleet-event.XXXXXX")" || return 1 chmod 0600 "$event_payload" 2>/dev/null || { rm -f "$event_payload" return 1 } if ! TAPM_FLEET_JSON "$event" "$result" "$error_code" "$duration" >"$event_payload"; then rm -f "$event_payload" return 1 fi if printf 'header = "Content-Type: application/json"\nheader = "Authorization: Bearer %s"\nurl = "%s/api/v1/hosts/events"\n' \ "$TAPM_FLEET_CREDENTIAL" "$TAPM_BROKER_URL" | curl --fail --silent --show-error \ --connect-timeout 3 --max-time 10 \ --config - --data-binary "@${event_payload}" \ >/dev/null 2>&1; then rm -f "$event_payload" return 0 fi rm -f "$event_payload" return 1 } TAPM_FLEET_START() { TAPM_FLEET_VERSION="$1" TAPM_FLEET_STARTED_AT="$(date +%s)" TAPM_FLEET_ENSURE_IDENTITY || return 0 command -v python3 >/dev/null 2>&1 || return 0 command -v curl >/dev/null 2>&1 || return 0 TAPM_FLEET_COLLECT_METADATA if (( TAPM_FLEET_ENROLLED == 1 )); then TAPM_FLEET_REGISTERED=1 elif TAPM_FLEET_REGISTER; then TAPM_FLEET_REGISTERED=1 TAPM_FLEET_ENROLLED=1 TAPM_FLEET_WRITE_IDENTITY || true fi } TAPM_FLEET_FINISH() { local exit_status="${1:-0}" local duration=0 local event_sent=0 if [[ "$TAPM_FLEET_STARTED_AT" =~ ^[0-9]+$ ]] && (( TAPM_FLEET_STARTED_AT > 0 )); then duration="$(( $(date +%s) - TAPM_FLEET_STARTED_AT ))" fi if (( exit_status == 0 )); then TAPM_FLEET_EVENT_SEND run_completed success '' "$duration" && event_sent=1 else TAPM_FLEET_EVENT_SEND run_failed failure exit_nonzero "$duration" && event_sent=1 fi if (( event_sent == 1 )) && TAPM_FLEET_VALID_IDENTITY; then TAPM_FLEET_LAST_VERSION="$TAPM_FLEET_VERSION" else # A failed event may mean the broker no longer recognizes this local # credential. Re-enroll on the next invocation, not during this one. TAPM_FLEET_ENROLLED=0 fi TAPM_FLEET_VALID_IDENTITY && TAPM_FLEET_WRITE_IDENTITY || true return 0 }