#!/usr/bin/env bash
# Download the latest Grype vulnerability DB (run on an Internet-connected host),
# import it into ./cache, then package grype-db/ for transfer to the air-gapped host.
#
#   ./download-db.sh              # download + import + package
#   ./download-db.sh --no-package # download + import only
#
# The package ships the compressed archive (~150 MB), not the imported cache (~2 GB);
# run ./import-db.sh on the target after extracting it.
set -euo pipefail

ROOT="$(cd "$(dirname "$0")" && pwd)"
GRYPE="${GRYPE:-$ROOT/bin/grype}"
UPDATE_URL="${GRYPE_DB_UPDATE_URL:-https://grype.anchore.io/databases}"
SCHEMA=v6   # grype 0.118 supports DB schema 6

log() { printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*"; }
die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
for tool in curl jq sha256sum; do command -v "$tool" >/dev/null || die "$tool is required"; done
[[ -x "$GRYPE" ]] || die "grype not found at $GRYPE"

mkdir -p "$ROOT/archive" "$ROOT/metadata"
log "listing <- $UPDATE_URL/$SCHEMA/latest.json"
listing="$(curl -fsSL --retry 5 "$UPDATE_URL/$SCHEMA/latest.json")"
file="$(jq -r .path <<<"$listing")"
sha="$(jq -r '.checksum | sub("^sha256:";"")' <<<"$listing")"
[[ "$file" == vulnerability-db_* && ${#sha} -eq 64 ]] || die "unexpected listing: $listing"

dest="$ROOT/archive/$file"
if [[ -f "$dest" ]] && echo "$sha  $dest" | sha256sum --check --status; then
  log "ok (cached) $file"
else
  log "downloading $file"
  curl -fL --retry 5 --retry-delay 3 -o "$dest.part" "$UPDATE_URL/$SCHEMA/$file"
  echo "$sha  $dest.part" | sha256sum --check --status || { rm -f "$dest.part"; die "checksum mismatch for $file"; }
  mv "$dest.part" "$dest"
fi
echo "$listing" > "$ROOT/metadata/latest.json"
# Keep only the current archive so the package does not grow.
find "$ROOT/archive" -maxdepth 1 -name 'vulnerability-db_*.tar.zst' ! -name "$file" -delete

GRYPE="$GRYPE" "$ROOT/import-db.sh" "$dest"

(cd "$ROOT" && sha256sum bin/* archive/*.tar.zst) > "$ROOT/SHA256SUMS"

if [[ "${1:-}" != "--no-package" ]]; then
  pkg="$(dirname "$ROOT")/grype-db-offline-$(date -u +%Y%m%d).tar.gz"
  log "packaging -> $pkg"
  tar -C "$(dirname "$ROOT")" --exclude='grype-db/cache' --exclude='grype-db/cache.new' \
      -czf "$pkg" "$(basename "$ROOT")"
  sha256sum "$pkg" > "$pkg.sha256"
  log "done: $(du -h "$pkg" | cut -f1)"
fi
