lomavuokraus/scripts/run-test-suite.sh
2025-12-11 20:36:04 +02:00

146 lines
4.8 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# Master test/security runner.
# - npm audit (high+)
# - lint / type-check / format check / tests
# - Trivy file-system scan (HIGH/CRITICAL)
# - OWASP ZAP baseline (unauthenticated)
#
# Outputs are written under reports/runs/<timestamp>/ and summarized in summary.html.
#
# Env vars:
# TARGET - URL to scan with ZAP (default: https://test.lomavuokraus.fi)
# TRIVY_TARGET - Path or image to scan (default: current directory)
# TRIVY_MODE - "fs" (default) or "image"
# ZAP_IMAGE - Override ZAP image (default in zap-baseline.sh)
# TIMEOUT_MINUTES - ZAP timeout minutes (default in zap-baseline.sh)
RUN_TS=$(date +"%Y%m%d-%H%M%S")
RUN_DIR="reports/runs/${RUN_TS}"
mkdir -p "$RUN_DIR"
SUMMARY_ROWS=()
SUMMARY_TEXT_ROWS=()
log() {
echo "[$(date +"%H:%M:%S")] $*"
}
record_result() {
local name="$1"; shift
local status="$1"; shift
local detail="$1"; shift
local detail_text="$1"; shift
SUMMARY_ROWS+=("<tr><td>${name}</td><td>${status}</td><td>${detail}</td></tr>")
SUMMARY_TEXT_ROWS+=("${name}: ${status}${detail_text:+ - ${detail_text}}")
}
# 1) npm audit
if command -v npm >/dev/null 2>&1; then
log "Running npm audit (high)..."
AUDIT_JSON="$RUN_DIR/npm-audit.json"
AUDIT_TXT="$RUN_DIR/npm-audit.txt"
if npm audit --audit-level=high --json >"$AUDIT_JSON" 2>"$AUDIT_TXT"; then
record_result "npm audit" "PASS" "<a href=\"npm-audit.txt\">text</a> | <a href=\"npm-audit.json\">json</a>" "reports: ${AUDIT_TXT}, ${AUDIT_JSON}"
else
record_result "npm audit" "FAIL" "<a href=\"npm-audit.txt\">text</a> | <a href=\"npm-audit.json\">json</a>" "reports: ${AUDIT_TXT}, ${AUDIT_JSON}"
fi
else
log "npm not found; skipping npm audit"
record_result "npm audit" "SKIP" "npm not available" "npm not available"
fi
# 2) Lint / type-check / format / tests
run_npm_check() {
local name="$1"; shift
local outfile="$RUN_DIR/${name}.txt"
if ! command -v npm >/dev/null 2>&1; then
log "npm not found; skipping ${name}"
record_result "${name}" "SKIP" "npm not available" "npm not available"
return
fi
if npm run 2>/dev/null | grep -qE "^ ${name}$"; then
log "Running ${name}..."
if npm run "${name}" >"$outfile" 2>&1; then
record_result "${name}" "PASS" "<a href=\"${name}.txt\">log</a>" "log: ${outfile}"
else
record_result "${name}" "FAIL" "<a href=\"${name}.txt\">log</a>" "log: ${outfile}"
fi
else
log "npm script '${name}' not defined; skipping"
record_result "${name}" "SKIP" "script not defined" "script not defined"
fi
}
run_npm_check "lint"
run_npm_check "type-check"
run_npm_check "format:check"
run_npm_check "test"
# 3) Trivy (fs by default)
TRIVY_TARGET="${TRIVY_TARGET:-.}"
TRIVY_MODE="${TRIVY_MODE:-fs}"
if command -v trivy >/dev/null 2>&1; then
log "Running Trivy (${TRIVY_MODE}) on ${TRIVY_TARGET}..."
TRIVY_TXT="$RUN_DIR/trivy.txt"
if trivy "${TRIVY_MODE}" --severity HIGH,CRITICAL --timeout 5m "$TRIVY_TARGET" >"$TRIVY_TXT"; then
record_result "Trivy (${TRIVY_MODE})" "PASS" "<a href=\"trivy.txt\">report</a>" "report: ${TRIVY_TXT}"
else
record_result "Trivy (${TRIVY_MODE})" "FAIL" "<a href=\"trivy.txt\">report</a>" "report: ${TRIVY_TXT}"
fi
else
log "Trivy not found; skipping"
record_result "Trivy" "SKIP" "trivy not available" "trivy not available"
fi
# 4) OWASP ZAP baseline
TARGET="${TARGET:-https://test.lomavuokraus.fi}"
ZAP_DIR="$RUN_DIR/zap"
mkdir -p "$ZAP_DIR"
log "Running ZAP baseline against ${TARGET}..."
if TARGET="$TARGET" REPORT_DIR="$ZAP_DIR" "${BASH_SOURCE%/*}/zap-baseline.sh"; then
record_result "OWASP ZAP baseline" "PASS" "<a href=\"zap/zap-report.html\">HTML</a> | <a href=\"zap/zap-report.json\">JSON</a>" "reports: ${ZAP_DIR}/zap-report.html, ${ZAP_DIR}/zap-report.json"
else
record_result "OWASP ZAP baseline" "FAIL" "<a href=\"zap/zap-report.html\">HTML</a> | <a href=\"zap/zap-report.json\">JSON</a>" "reports: ${ZAP_DIR}/zap-report.html, ${ZAP_DIR}/zap-report.json"
fi
# Summary HTML
SUMMARY_FILE="$RUN_DIR/summary.html"
cat >"$SUMMARY_FILE" <<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Test Suite Summary - ${RUN_TS}</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; background: #0b0d11; color: #e9ecf1; }
table { border-collapse: collapse; width: 100%; margin-top: 12px; }
th, td { border: 1px solid #333; padding: 8px; }
th { background: #111827; }
a { color: #7cc7ff; }
</style>
</head>
<body>
<h1>Test Suite Summary</h1>
<div>Run: ${RUN_TS}</div>
<div>Target: ${TARGET}</div>
<table>
<thead><tr><th>Check</th><th>Status</th><th>Details</th></tr></thead>
<tbody>
${SUMMARY_ROWS[*]}
</tbody>
</table>
</body>
</html>
EOF
log "Summary:"
for row in "${SUMMARY_TEXT_ROWS[@]}"; do
echo " - ${row}"
done
log "Done. Reports in ${RUN_DIR}"
echo "Open ${SUMMARY_FILE} in a browser for the summary."