Files
vulncheck/setup.sh
T
vulncheck de6d41cdd3 feat(https): serve the UI over TLS with a CA per installation
TrueVuln spoke plain HTTP only. HTTPS needed a foreign reverse proxy, the
hop behind it stayed unencrypted, and the frontend port 3003 was open on
every interface, so anyone on the network could read the vulnerability
data around the proxy.

A bundled nginx (Compose profile "tls", on by default via
COMPOSE_PROFILES) now terminates TLS 1.2/1.3 on 443: forward secrecy and
AEAD only, HSTS, port 80 only redirects. Frontend and backend are bound to
127.0.0.1. A reverse proxy on another host connects to nginx via HTTPS; one
on the same host may leave the profile out and use 127.0.0.1:3003.

On first start the backend creates a CA for the installation and issues
the server certificate from it for TLS_SERVER_NAMES, the DASHBOARD_URL host
and localhost, renewed in lifespan and nightly at 03:45. The CA carries
name constraints on exactly those names, because its key sits on the
vulnerability server and an unconstrained root in every browser would let
whoever steals it impersonate any site. A name it does not cover creates a
new CA, with an audit row. The CA lives in a backend-only volume; nginx
mounts only the certificate and key, and reloads itself when they change,
so nothing needs the Docker socket.

Admins can download the CA, or upload a certificate from the internal PKI
(PEM with chain, DER or PFX) under Settings > Security > HTTPS Certificate.
It is checked (key matches, chain complete, covers the DASHBOARD_URL host,
valid, not self-signed, RSA >= 2048 or ECDSA P-256/P-384, SHA-256+) and
served without a restart; renewal never overwrites it, a reset goes back to
the CA. The key stays in the volume (0600), never in the database or the
CONFIG_CHANGE audit rows.

The Next.js proxy now forwards request bodies as bytes: request.text()
mangled binary DER and PFX uploads.

Existing proxies on http://<host>:3003 from another machine must be
switched; README has the upgrade steps.
2026-10-24 13:29:10 +02:00

108 lines
4.3 KiB
Bash
Executable File

#!/bin/bash
set -e
echo "╔══════════════════════════════════════════════════════╗"
echo "║ VulnManager Setup ║"
echo "║ Vulnerability Management Dashboard ║"
echo "╚══════════════════════════════════════════════════════╝"
echo ""
# Prüfe Docker Installation
if ! command -v docker &> /dev/null; then
echo "❌ Docker ist nicht installiert. Bitte installieren: https://docs.docker.com/get-docker/"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
echo "❌ Docker Compose ist nicht installiert."
exit 1
fi
echo "✅ Docker und Docker Compose gefunden"
echo ""
# Erstelle .env falls nicht vorhanden
if [ ! -f .env ]; then
echo "📝 Erstelle .env aus Vorlage..."
cp .env.example .env
# Generiere sicheren JWT Secret. Die ganze Zeile ersetzen statt einen
# Platzhalter-String zu suchen — der Platzhalter in .env.example wandert,
# und ein sed das nichts trifft würde hier lautlos "Erfolg" melden.
JWT_SECRET=$(openssl rand -hex 32)
sed -i.bak "s|^JWT_SECRET_KEY=.*|JWT_SECRET_KEY=${JWT_SECRET}|" .env
rm .env.bak
if grep -q '^JWT_SECRET_KEY=CHANGE-ME' .env || ! grep -q "^JWT_SECRET_KEY=${JWT_SECRET}$" .env; then
echo "❌ JWT_SECRET_KEY konnte nicht gesetzt werden. Bitte in .env manuell eintragen:"
echo " JWT_SECRET_KEY=\$(openssl rand -hex 32)"
exit 1
fi
# Admin-Passwort ebenso: das Backend legt den Admin beim ersten Start aus
# DEFAULT_ADMIN_PASSWORD an und lehnt schwache Werte ab.
ADMIN_PW=$(openssl rand -base64 24)
sed -i.bak "s|^DEFAULT_ADMIN_PASSWORD=.*|DEFAULT_ADMIN_PASSWORD=${ADMIN_PW}|" .env
rm .env.bak
# HTTPS: Name und erste IP dieses Hosts kommen ins Zertifikat, das die
# CA dieser Installation beim ersten Start ausstellt.
FQDN=$(hostname -f 2>/dev/null || hostname)
HOST_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
sed -i.bak "s|^TLS_SERVER_NAMES=.*|TLS_SERVER_NAMES=${FQDN}${HOST_IP:+,${HOST_IP}}|" .env
sed -i.bak "s|^DASHBOARD_URL=.*|DASHBOARD_URL=https://${FQDN}|" .env
rm .env.bak
echo "✅ .env erstellt mit generiertem JWT_SECRET_KEY"
echo ""
echo "⚠️ WICHTIG: Bitte bearbeite .env und setze folgende Werte:"
echo " - WAZUH_API_URL"
echo " - WAZUH_API_USERNAME"
echo " - WAZUH_API_PASSWORD"
echo " - INFOMANIAK_AI_API_KEY"
echo ""
read -p "Drücke Enter um fortzufahren..."
else
echo "✅ .env bereits vorhanden"
fi
# Starte Docker Compose
echo ""
echo "🐳 Starte Docker Container..."
docker-compose up -d
# Warte auf PostgreSQL
echo ""
echo "⏳ Warte auf PostgreSQL..."
sleep 10
# Führe Alembic Migrationen aus
echo ""
echo "📦 Führe Datenbank-Migrationen aus..."
docker-compose exec -T backend alembic upgrade head
# Der Admin-User wird beim Backend-Start von create_initial_data() aus
# DEFAULT_ADMIN_PASSWORD angelegt (inkl. Stärke-Prüfung) — hier nichts
# selbst anlegen, das würde diese Prüfung umgehen.
echo ""
echo "👤 Admin-User: wird vom Backend aus DEFAULT_ADMIN_PASSWORD in .env angelegt."
echo ""
echo "╔══════════════════════════════════════════════════════╗"
echo "║ Setup abgeschlossen! 🎉 ║"
echo "╚══════════════════════════════════════════════════════╝"
echo ""
echo "🔒 TrueVuln: $(grep '^DASHBOARD_URL=' .env | cut -d= -f2-)"
echo " Der Browser warnt, bis die TrueVuln-CA importiert ist:"
echo " Settings > Security > HTTPS Certificate > Download CA (oder per GPO/MDM verteilen)"
echo "🔐 Login: admin / <DEFAULT_ADMIN_PASSWORD aus .env>"
echo ""
echo "Nächste Schritte:"
echo "1. Login mit admin-Credentials"
echo "2. Passwort ändern: POST /auth/change-password"
echo "3. Wazuh-Sync starten: POST /api/v1/vulnerabilities/sync/wazuh"
echo ""
echo "Logs anzeigen: docker-compose logs -f backend"
echo "Stoppen: docker-compose down"
echo ""