#!/usr/bin/env bash
# Each image provides exactly one scanner. Syft and Grype exchange SBOM files.
set -euo pipefail
root=/opt/devsecops
export PATH="$root/bin:$PATH"
tool="${DEVSECOPS_TOOL:?Missing tool identity}"
mode="${1:?Use source, image, or sbom as supported by this tool}"
input="$(realpath "${2:?Input path}")"
mkdir -p "${3:?Report directory}"
reports="$(realpath "$3")"
case "$reports/" in "$input/"*) echo 'Reports must be outside input' >&2; exit 2;; esac
cd /tmp
case "$tool:$mode" in
  gitleaks:source)
    test -d "$input"
    status=0
    if git -C "$input" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
      [[ "$(git -C "$input" rev-parse --is-shallow-repository)" == false ]] || {
        echo 'Full Git history is required' >&2; exit 2;
      }
      gitleaks git "$input" --redact --config "$root/config/gitleaks.toml" \
        --report-format json --report-path "$reports/gitleaks-history.json" || status=1
    fi
    gitleaks dir "$input" --redact --config "$root/config/gitleaks.toml" \
      --report-format json --report-path "$reports/gitleaks-files.json" || status=1
    exit "$status"
    ;;
  trivy:source)
    test -d "$input"
    cache="${TRIVY_CACHE_DIR:-$root/cache/trivy}"
    python3 "$root/scripts/check-db-age.py" "$cache"
    common=(--cache-dir "$cache" --offline-scan --skip-db-update --skip-java-db-update
      --skip-check-update --skip-version-check --disable-telemetry)
    status=0
    trivy fs "${common[@]}" --scanners vuln,misconfig --severity HIGH,CRITICAL \
      --exit-code 1 --format json --output "$reports/trivy-source.json" "$input" || status=1
    trivy fs "${common[@]}" --scanners vuln --format cyclonedx \
      --output "$reports/source.cdx.json" "$input" || status=1
    exit "$status"
    ;;
  trivy:image)
    exec bash "$root/scripts/scan-image.sh" "$input" "$reports"
    ;;
  syft:source|syft:image)
    kind=dir
    if [[ "$mode" == image ]]; then kind=docker-archive; test -s "$input"; else test -d "$input"; fi
    export SYFT_CHECK_FOR_APP_UPDATE=false
    exec syft scan -c "$root/config/syft-offline.yaml" "$kind:$input" \
      -o "syft-json=$reports/sbom.syft.json" -o "cyclonedx-json=$reports/sbom.cdx.json"
    ;;
  grype:sbom)
    test -s "$input"
    export GRYPE_CHECK_FOR_APP_UPDATE=false GRYPE_DB_AUTO_UPDATE=false
    export GRYPE_DB_VALIDATE_AGE=true GRYPE_DB_MAX_ALLOWED_BUILT_AGE=168h
    export GRYPE_DB_CACHE_DIR="${GRYPE_DB_CACHE_DIR:-$root/cache/grype}"
    grype -c "$root/config/grype-offline.yaml" db status -o json > "$reports/grype-db.json"
    exec grype -c "$root/config/grype-offline.yaml" "sbom:$input" \
      --fail-on high -o json --file "$reports/grype.json"
    ;;
  *) echo "Unsupported mode: $tool $mode" >&2; exit 2;;
esac
