#!/usr/bin/env bash
# crwlr-upload.sh — sanitize a FortiGate config and upload it to CRWLR for analysis.
#
# Usage:
#   CRWLR_API_KEY=crwlr_xxx ./crwlr-upload.sh <config.conf> [firewall-id]
#
#   With firewall-id : re-scans that firewall   (POST /api/v1/scans)
#   Without          : registers a new firewall (POST /api/v1/scans/register,
#                      nickname = file name, vendor auto-detected)
#
# Environment:
#   CRWLR_API_KEY  (required)  write-scoped API key — create one under
#                              Account → API keys. Never hardcode it here.
#   CRWLR_API_URL  (optional)  default https://api.crwlr.io
#   CRWLR_VENDOR   (optional)  default fortinet (re-scan path only)
#
# Sanitization: if sanitize-fortigate-config.js sits next to this script and
# `node` is available, the config is sanitized locally BEFORE upload (secrets
# never leave this machine). Pass --raw to skip. Analysis results are identical
# either way — see docs/roadmaps/sanitized-import.md.
#
# Cron example (daily 06:10, after your nightly backup lands in /backups):
#   10 6 * * * CRWLR_API_KEY=$(cat /etc/crwlr/key) /opt/crwlr/crwlr-upload.sh /backups/fw1.conf 4f0c...

set -euo pipefail

API_URL="${CRWLR_API_URL:-https://api.crwlr.io}"
VENDOR="${CRWLR_VENDOR:-fortinet}"
RAW=0
ARGS=()
for a in "$@"; do
  if [ "$a" = "--raw" ]; then RAW=1; else ARGS+=("$a"); fi
done

CONFIG="${ARGS[0]:-}"
FIREWALL_ID="${ARGS[1]:-}"
[ -n "$CONFIG" ] || { echo "usage: crwlr-upload.sh <config.conf> [firewall-id] [--raw]" >&2; exit 2; }
[ -f "$CONFIG" ] || { echo "config not found: $CONFIG" >&2; exit 1; }
[ -n "${CRWLR_API_KEY:-}" ] || { echo "CRWLR_API_KEY is not set" >&2; exit 1; }

# ── Sanitize locally before anything leaves this machine ─────────────────────
UPLOAD_FILE="$CONFIG"
CLEANUP=""
SANITIZER="$(dirname "$0")/sanitize-fortigate-config.js"
[ -f "$SANITIZER" ] || SANITIZER="$(dirname "$0")/../sanitize-fortigate-config.js"
if [ "$RAW" -eq 0 ] && head -1 "$CONFIG" | grep -q '^#config-version=' && command -v node >/dev/null 2>&1 && [ -f "$SANITIZER" ]; then
  UPLOAD_FILE="$(mktemp --suffix=.conf 2>/dev/null || mktemp)"
  CLEANUP="$UPLOAD_FILE"
  node "$SANITIZER" "$CONFIG" --out "$UPLOAD_FILE" >/dev/null
  echo "sanitized locally → uploading redacted copy"
elif [ "$RAW" -eq 0 ]; then
  echo "NOTE: sanitizer not available — uploading config as-is (use --raw to silence)" >&2
fi
trap '[ -n "$CLEANUP" ] && rm -f "$CLEANUP"' EXIT

# ── Upload ────────────────────────────────────────────────────────────────────
if [ -n "$FIREWALL_ID" ]; then
  RESP=$(curl -fsS -X POST "$API_URL/api/v1/scans" \
    -H "Authorization: Bearer $CRWLR_API_KEY" \
    -F "file=@$UPLOAD_FILE" -F "firewallId=$FIREWALL_ID" -F "vendor=$VENDOR")
else
  NICK="$(basename "$CONFIG" .conf)"
  RESP=$(curl -fsS -X POST "$API_URL/api/v1/scans/register" \
    -H "Authorization: Bearer $CRWLR_API_KEY" \
    -F "file=@$UPLOAD_FILE" -F "nickname=$NICK" -F "vendor=auto")
fi

SCAN_ID=$(printf '%s' "$RESP" | grep -o '"scanId":"[^"]*"' | head -1 | cut -d'"' -f4)
[ -n "$SCAN_ID" ] || { echo "upload failed: $RESP" >&2; exit 1; }
echo "scan queued: $SCAN_ID"

# ── Poll until complete ───────────────────────────────────────────────────────
for _ in $(seq 1 60); do
  sleep 5
  S=$(curl -fsS "$API_URL/api/v1/scans/$SCAN_ID" -H "Authorization: Bearer $CRWLR_API_KEY")
  STATUS=$(printf '%s' "$S" | grep -o '"status":"[^"]*"' | head -1 | cut -d'"' -f4)
  case "$STATUS" in
    complete)
      SCORE=$(printf '%s' "$S" | grep -o '"score":[0-9]*' | head -1 | cut -d: -f2)
      echo "scan complete — posture score: ${SCORE:-n/a}"
      exit 0 ;;
    failed)
      echo "scan failed" >&2; exit 1 ;;
  esac
done
echo "timed out waiting for scan $SCAN_ID (still processing — check the dashboard)" >&2
exit 1
