#!/bin/bash
# mesh_heartbeat.sh — Hardened mesh heartbeat reporter
# Runs every 60s via cron
set -euo pipefail
shopt -s inherit_errexit 2>/dev/null || true
IFS=$'\n\t'

readonly NODE_ID="${NODE_ID:-414342}"
readonly API_BASE="${API_BASE:-https://10.69.69.1:8443}"
readonly API_URL="${API_BASE}/api/mesh"
readonly VAULT_KEY="${VAULT_KEY:-$(cat /dev/shm/vault.key 2>/dev/null || printf '%s' '')}"
readonly LOG="/var/log/s3rv1c3agent/heartbeat.log"
readonly LOCK_FILE="/run/se/.mesh_hb.lock"

# ── Validate prerequisites ─────────────────────────────────────────────────
if [[ -z "${VAULT_KEY}" ]]; then
    printf 'ERR: no vault key available\n' >&2
    exit 1
fi

# ── File lock ──────────────────────────────────────────────────────────────
exec 300>"${LOCK_FILE}"
if ! flock -n 300; then
    printf 'ERR: another heartbeat is running\n' >&2
    exit 1
fi

# ── Build request ──────────────────────────────────────────────────────────
ts="$(date +%s)"
body="$(jq -n --arg nid "${NODE_ID}" '{"node_id":$nid}')"

# Derive HMAC key from vault key — NO hardcoded keys
sig="$(printf '%s:%s' "${ts}" "${body}" | openssl dgst -sha256 -hmac "${VAULT_KEY}" | awk '{print $NF}')"

# ── Send heartbeat ─────────────────────────────────────────────────────────
mkdir -p "$(dirname "${LOG}")"
result=''
result="$(curl -sS --connect-timeout 5 --max-time 10 \
    -X POST "${API_URL}?action=report-heartbeat" \
    -H "Content-Type: application/json" \
    -H "X-Mesh-Sig: ${sig}" \
    -H "X-Mesh-Ts: ${ts}" \
    -d "${body}" \
    2>/dev/null)" || result='{"error":"curl_failed"}'

printf '%s hb %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "${result}" >> "${LOG}" 2>/dev/null || true

# Validate response is valid JSON
if ! printf '%s' "${result}" | jq -e '.' >/dev/null 2>&1; then
    printf 'ERR: invalid response from mesh API\n' >&2
    exit 1
fi
