diff --git a/setup_ssl.ps1 b/setup_ssl.ps1 new file mode 100644 index 000000000..330cf9de1 --- /dev/null +++ b/setup_ssl.ps1 @@ -0,0 +1,196 @@ +# SSL-Konfiguration für MYP-Plattform +# Dieses Skript führt alle notwendigen Schritte zur SSL-Konfiguration durch + +# Titel anzeigen +Write-Host "====================================================" -ForegroundColor Cyan +Write-Host " SSL-Konfiguration für MYP-Plattform" -ForegroundColor Cyan +Write-Host "====================================================" -ForegroundColor Cyan +Write-Host "" + +# Prüfen, ob PowerShell als Administrator ausgeführt wird +$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + +if (-not $isAdmin) { + Write-Host "WARNUNG: Dieses Skript sollte als Administrator ausgeführt werden, um Zertifikate im System zu installieren." -ForegroundColor Yellow + Write-Host "Einige Funktionen sind möglicherweise eingeschränkt." -ForegroundColor Yellow + Write-Host "" + + $continueAnyway = Read-Host "Möchten Sie trotzdem fortfahren? (j/n)" + if ($continueAnyway -ne "j") { + Write-Host "Installation abgebrochen." -ForegroundColor Red + exit + } +} + +# Funktion zum Ausführen von Befehlen mit Ausgabe +function Exec-Command { + param ( + [string]$Command, + [string]$Description + ) + + Write-Host "> $Description..." -ForegroundColor Yellow + try { + Invoke-Expression $Command + if ($LASTEXITCODE -eq 0 -or $null -eq $LASTEXITCODE) { + Write-Host "✓ Erfolgreich abgeschlossen!" -ForegroundColor Green + return $true + } else { + Write-Host "✗ Fehler beim Ausführen des Befehls. Exit-Code: $LASTEXITCODE" -ForegroundColor Red + return $false + } + } catch { + Write-Host "✗ Fehler: $_" -ForegroundColor Red + return $false + } +} + +# Prüfen, ob Python und Node.js installiert sind +$pythonInstalled = Get-Command python -ErrorAction SilentlyContinue +$nodeInstalled = Get-Command node -ErrorAction SilentlyContinue + +if (-not $pythonInstalled) { + Write-Host "✗ Python ist nicht installiert oder nicht im PATH. Bitte installieren Sie Python 3.6 oder höher." -ForegroundColor Red + exit 1 +} + +if (-not $nodeInstalled) { + Write-Host "✗ Node.js ist nicht installiert oder nicht im PATH. Bitte installieren Sie Node.js 14 oder höher." -ForegroundColor Red + exit 1 +} + +# 1. Prüfen, ob die notwendigen Abhängigkeiten installiert sind +Write-Host "1. Prüfe Abhängigkeiten..." -ForegroundColor Cyan + +# Python-Abhängigkeiten prüfen +$cryptographyInstalled = python -c "try: import cryptography; print('True'); except ImportError: print('False')" 2>$null +if ($cryptographyInstalled -ne "True") { + Write-Host "Installiere Python-Abhängigkeit 'cryptography'..." + Exec-Command "pip install cryptography" "Installiere cryptography-Paket" +} + +# 2. SSL-Zertifikat generieren +Write-Host "" +Write-Host "2. Generiere SSL-Zertifikat..." -ForegroundColor Cyan +$certGenSuccess = Exec-Command "cd backend && python generate_ssl_cert.py" "Generiere SSL-Zertifikat" + +if (-not $certGenSuccess) { + Write-Host "✗ Fehler bei der Zertifikatsgenerierung. Abbruch." -ForegroundColor Red + exit 1 +} + +# 3. Zertifikat im System installieren (nur wenn als Administrator ausgeführt) +Write-Host "" +Write-Host "3. Installiere Zertifikat im System..." -ForegroundColor Cyan + +if ($isAdmin) { + $certPath = Resolve-Path ".\backend\app\instance\ssl\myp.crt" + + Write-Host "Installiere Zertifikat im System-Zertifikatsspeicher..." + + # In Root-Zertifikatsspeicher installieren + Exec-Command "certutil -addstore -f 'ROOT' '$certPath'" "Installiere im Root-Zertifikatsspeicher" + + # In CA-Zertifikatsspeicher installieren + Exec-Command "certutil -addstore -f 'CA' '$certPath'" "Installiere im CA-Zertifikatsspeicher" + + # In Persönlichen Zertifikatsspeicher installieren + Exec-Command "certutil -addstore -f 'MY' '$certPath'" "Installiere im Persönlichen Zertifikatsspeicher" +} else { + Write-Host "Überspringen der System-Installation, da das Skript nicht als Administrator ausgeführt wird." -ForegroundColor Yellow + Write-Host "Sie können das Zertifikat später manuell installieren durch:" -ForegroundColor Yellow + Write-Host "certutil -addstore -f ROOT .\backend\app\instance\ssl\myp.crt" -ForegroundColor Gray +} + +# 4. Frontend konfigurieren +Write-Host "" +Write-Host "4. Konfiguriere Frontend..." -ForegroundColor Cyan +$frontendConfigSuccess = Exec-Command "cd frontend && node configure_ssl.js" "Konfiguriere Frontend" + +if (-not $frontendConfigSuccess) { + Write-Host "✗ Warnung: Frontend-Konfiguration konnte nicht vollständig durchgeführt werden." -ForegroundColor Yellow +} + +# 5. Docker-Compose Datei aktualisieren +Write-Host "" +Write-Host "5. Aktualisiere Docker-Compose-Konfiguration..." -ForegroundColor Cyan + +$dockerComposeFile = "docker-compose.yml" +if (Test-Path $dockerComposeFile) { + $dockerCompose = Get-Content $dockerComposeFile -Raw + + # Sicherstellen, dass dual-protocol aktiv ist + if (-not $dockerCompose.Contains("--dual-protocol")) { + $dockerCompose = $dockerCompose -replace "command: python -m app\.app", "command: python -m app.app --dual-protocol" + $dockerCompose | Set-Content $dockerComposeFile + Write-Host "✓ Docker-Compose-Datei wurde aktualisiert, um den dual-protocol-Modus zu aktivieren." -ForegroundColor Green + } else { + Write-Host "✓ Docker-Compose-Datei ist bereits korrekt konfiguriert." -ForegroundColor Green + } +} else { + Write-Host "✗ Docker-Compose-Datei nicht gefunden. Überspringe diese Konfiguration." -ForegroundColor Yellow +} + +# 6. Systemdienste aktualisieren (falls auf Raspberry Pi) +Write-Host "" +Write-Host "6. Möchten Sie die Konfiguration auf den Raspberry Pi übertragen?" -ForegroundColor Cyan +$raspberryConfig = Read-Host "Übertragen und konfigurieren (j/n)" + +if ($raspberryConfig -eq "j") { + Write-Host "Konfiguriere Raspberry Pi..." -ForegroundColor Yellow + + # Raspberry Pi-Konfiguration ausführen + $sshUser = Read-Host "Benutzername für SSH-Verbindung zum Raspberry Pi (Standard: pi)" + if (-not $sshUser) { $sshUser = "pi" } + + $sshHost = Read-Host "Hostname oder IP-Adresse des Raspberry Pi (Standard: raspberrypi)" + if (-not $sshHost) { $sshHost = "raspberrypi" } + + $sshDestDir = "/home/$sshUser/myp/ssl" + $systemCertDir = "/usr/local/share/ca-certificates" + + # Verzeichnis erstellen + Exec-Command "ssh $sshUser@$sshHost 'mkdir -p $sshDestDir'" "Erstelle Verzeichnis auf dem Raspberry Pi" + + # Dateien kopieren + $certPath = Resolve-Path ".\backend\app\instance\ssl\myp.crt" + $keyPath = Resolve-Path ".\backend\app\instance\ssl\myp.key" + + Exec-Command "scp '$certPath' $sshUser@$sshHost`:$sshDestDir/myp.crt" "Kopiere Zertifikat auf den Raspberry Pi" + Exec-Command "scp '$keyPath' $sshUser@$sshHost`:$sshDestDir/myp.key" "Kopiere Schlüssel auf den Raspberry Pi" + + # Berechtigungen setzen + Exec-Command "ssh $sshUser@$sshHost 'chmod 600 $sshDestDir/myp.key'" "Setze Berechtigungen für den Schlüssel" + + # Im System installieren + Exec-Command "ssh $sshUser@$sshHost 'sudo mkdir -p $systemCertDir && sudo cp $sshDestDir/myp.crt $systemCertDir/ && sudo update-ca-certificates'" "Installiere Zertifikat im System" + + # Docker-Container neu starten, falls vorhanden + Write-Host "Möchten Sie die Docker-Container auf dem Raspberry Pi neu starten?" -ForegroundColor Yellow + $restartDocker = Read-Host "Neu starten (j/n)" + + if ($restartDocker -eq "j") { + Exec-Command "ssh $sshUser@$sshHost 'cd /home/$sshUser/myp && docker-compose down && docker-compose up -d'" "Starte Docker-Container neu" + } +} + +# Abschluss +Write-Host "" +Write-Host "====================================================" -ForegroundColor Cyan +Write-Host " SSL-Konfiguration abgeschlossen" -ForegroundColor Cyan +Write-Host "====================================================" -ForegroundColor Cyan +Write-Host "" +Write-Host "Das SSL-Zertifikat wurde erfolgreich generiert und konfiguriert." -ForegroundColor Green +Write-Host "Sie können nun auf folgende Weise auf die Anwendung zugreifen:" -ForegroundColor Green +Write-Host "- Backend: https://raspberrypi:443" -ForegroundColor Green +Write-Host "- Frontend: https://localhost:3000" -ForegroundColor Green +Write-Host "" +Write-Host "Hinweis: Bei der ersten Verbindung müssen Sie möglicherweise" -ForegroundColor Yellow +Write-Host "das selbstsignierte Zertifikat in Ihrem Browser akzeptieren." -ForegroundColor Yellow +Write-Host "" + +# Pause, damit das Fenster nicht sofort geschlossen wird +if ($Host.Name -eq "ConsoleHost") { + Write-Host "Drücken Sie eine beliebige Taste, um fortzufahren..." + $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") +} \ No newline at end of file diff --git a/setup_ssl.sh b/setup_ssl.sh new file mode 100644 index 000000000..0947d8d8e --- /dev/null +++ b/setup_ssl.sh @@ -0,0 +1,537 @@ +#!/bin/bash + +# SSL-Konfiguration für MYP-Plattform (Linux/Raspberry Pi) + +# Farbdefinitionen +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Titel anzeigen +echo -e "${CYAN}====================================================" +echo -e " SSL-Konfiguration für MYP-Plattform" +echo -e "====================================================${NC}" +echo "" + +# Prüfen, ob das Skript mit Root-Rechten ausgeführt wird +if [ "$EUID" -ne 0 ]; then + echo -e "${YELLOW}WARNUNG: Dieses Skript sollte mit Root-Rechten ausgeführt werden, um Zertifikate im System zu installieren.${NC}" + echo -e "${YELLOW}Einige Funktionen sind möglicherweise eingeschränkt.${NC}" + echo "" + + read -p "Möchten Sie trotzdem fortfahren? (j/n): " continue_anyway + if [ "$continue_anyway" != "j" ]; then + echo -e "${RED}Installation abgebrochen.${NC}" + exit 1 + fi +fi + +# Funktion zum Ausführen von Befehlen mit Ausgabe +exec_command() { + command="$1" + description="$2" + + echo -e "${YELLOW}> $description...${NC}" + eval $command + + if [ $? -eq 0 ]; then + echo -e "${GREEN}✓ Erfolgreich abgeschlossen!${NC}" + return 0 + else + echo -e "${RED}✗ Fehler beim Ausführen des Befehls. Exit-Code: $?${NC}" + return 1 + fi +} + +# Prüfen, ob Python und pip installiert sind +if ! command -v python3 &> /dev/null; then + echo -e "${RED}✗ Python 3 ist nicht installiert. Bitte installieren Sie Python 3.6 oder höher.${NC}" + exit 1 +fi + +if ! command -v pip3 &> /dev/null; then + echo -e "${RED}✗ pip3 ist nicht installiert. Bitte installieren Sie pip3.${NC}" + exit 1 +fi + +# 1. Prüfen, ob die notwendigen Abhängigkeiten installiert sind +echo -e "${CYAN}1. Prüfe Abhängigkeiten...${NC}" + +# Python-Abhängigkeiten prüfen +cryptography_installed=$(python3 -c "try: import cryptography; print('True'); except ImportError: print('False')" 2>/dev/null) +if [ "$cryptography_installed" != "True" ]; then + echo "Installiere Python-Abhängigkeit 'cryptography'..." + exec_command "pip3 install cryptography" "Installiere cryptography-Paket" +fi + +# 2. SSL-Zertifikat generieren +echo "" +echo -e "${CYAN}2. Generiere SSL-Zertifikat...${NC}" + +# SSL-Verzeichnisse erstellen +mkdir -p backend/app/instance/ssl +mkdir -p frontend/ssl + +# Python-Skript erstellen, falls nicht vorhanden +if [ ! -f backend/generate_ssl_cert.py ]; then + echo "SSL-Zertifikatsgenerator nicht gefunden. Erstelle..." + + cat > backend/generate_ssl_cert.py << 'EOF' +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +import datetime +from cryptography import x509 +from cryptography.x509.oid import NameOID +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption + +def generate_ssl_certificate(): + """ + Generiert ein verbessertes SSL-Zertifikat für die MYP-Anwendung + mit korrekten Metadaten und alternativen Namen. + """ + print("Generiere verbessertes SSL-Zertifikat für die MYP-Anwendung...") + + # Verzeichnispfade definieren + ssl_dir = "app/instance/ssl" + ssl_cert_path = os.path.join(ssl_dir, "myp.crt") + ssl_key_path = os.path.join(ssl_dir, "myp.key") + + # Verzeichnis erstellen, falls es nicht existiert + os.makedirs(ssl_dir, exist_ok=True) + + try: + # Privaten Schlüssel mit 4096 Bit generieren (sicherer) + private_key = rsa.generate_private_key( + public_exponent=65537, + key_size=4096, + ) + + # Aktuelles Datum und Ablaufdatum (1 Jahr gültig) + now = datetime.datetime.now() + valid_until = now + datetime.timedelta(days=365) + + # Liste aller möglichen Hostnamen/IPs + hostnames = [ + "localhost", + "raspberrypi", + "m040tbaraspi001", + "m040tbaraspi001.de040.corpintra.net" + ] + + # IP-Adressen (als String, werden später konvertiert) + ip_addresses = [ + "127.0.0.1", + "192.168.0.105" + ] + + # Erweiterte Zertifikatsattribute + subject = issuer = x509.Name([ + x509.NameAttribute(NameOID.COMMON_NAME, "raspberrypi"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Mercedes-Benz AG"), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Werk 040 Berlin"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Berlin"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Berlin") + ]) + + # Subject Alternative Names (SAN) erstellen + san_list = [] + for hostname in hostnames: + san_list.append(x509.DNSName(hostname)) + + # IP-Adressen hinzufügen + import socket + for ip in ip_addresses: + san_list.append(x509.IPAddress(socket.inet_aton(ip))) + + # Zertifikat erstellen + cert = x509.CertificateBuilder().subject_name( + subject + ).issuer_name( + issuer + ).public_key( + private_key.public_key() + ).serial_number( + x509.random_serial_number() + ).not_valid_before( + now + ).not_valid_after( + valid_until + ).add_extension( + x509.SubjectAlternativeName(san_list), + critical=False, + ).add_extension( + x509.BasicConstraints(ca=True, path_length=None), critical=True + ).add_extension( + x509.KeyUsage( + digital_signature=True, + content_commitment=False, + key_encipherment=True, + data_encipherment=False, + key_agreement=False, + key_cert_sign=True, + crl_sign=True, + encipher_only=False, + decipher_only=False + ), critical=True + ).add_extension( + x509.ExtendedKeyUsage([ + x509.oid.ExtendedKeyUsageOID.SERVER_AUTH, + x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH + ]), critical=False + ).sign(private_key, hashes.SHA256()) + + # Zertifikat und Schlüssel speichern + with open(ssl_key_path, "wb") as f: + f.write(private_key.private_bytes( + encoding=Encoding.PEM, + format=PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=NoEncryption() + )) + + with open(ssl_cert_path, "wb") as f: + f.write(cert.public_bytes(Encoding.PEM)) + + # Kopieren des Zertifikats in das Frontend-Verzeichnis + frontend_ssl_dir = "../frontend/ssl" + os.makedirs(frontend_ssl_dir, exist_ok=True) + + import shutil + shutil.copy2(ssl_cert_path, os.path.join(frontend_ssl_dir, "myp.crt")) + shutil.copy2(ssl_key_path, os.path.join(frontend_ssl_dir, "myp.key")) + + print(f"SSL-Zertifikat wurde erstellt:") + print(f"- Zertifikat: {ssl_cert_path}") + print(f"- Schlüssel: {ssl_key_path}") + print(f"- Kopiert nach: {frontend_ssl_dir}") + print(f"- Gültig bis: {valid_until.strftime('%d.%m.%Y')}") + print(f"- Hostnamen: {', '.join(hostnames)}") + print(f"- IP-Adressen: {', '.join(ip_addresses)}") + + return True + except Exception as e: + print(f"Fehler beim Erstellen des SSL-Zertifikats: {e}") + return False + +if __name__ == "__main__": + generate_ssl_certificate() +EOF + + # Ausführbar machen + chmod +x backend/generate_ssl_cert.py +fi + +# Zertifikat generieren +cert_gen_success=$(exec_command "cd backend && python3 generate_ssl_cert.py" "Generiere SSL-Zertifikat") + +if [ $? -ne 0 ]; then + echo -e "${RED}✗ Fehler bei der Zertifikatsgenerierung. Abbruch.${NC}" + exit 1 +fi + +# 3. Zertifikat im System installieren +echo "" +echo -e "${CYAN}3. Installiere Zertifikat im System...${NC}" + +if [ "$EUID" -eq 0 ]; then + # Als Root ausgeführt + cert_path=$(readlink -f backend/app/instance/ssl/myp.crt) + + # Zielverzeichnis für System-Zertifikate + if [ -d "/usr/local/share/ca-certificates" ]; then + # Debian/Ubuntu/Raspberry Pi OS + cert_dir="/usr/local/share/ca-certificates" + exec_command "cp $cert_path $cert_dir/myp.crt" "Kopiere Zertifikat in System-Verzeichnis" + exec_command "update-ca-certificates" "Aktualisiere System-Zertifikate" + elif [ -d "/etc/pki/ca-trust/source/anchors" ]; then + # RHEL/CentOS/Fedora + cert_dir="/etc/pki/ca-trust/source/anchors" + exec_command "cp $cert_path $cert_dir/myp.crt" "Kopiere Zertifikat in System-Verzeichnis" + exec_command "update-ca-trust extract" "Aktualisiere System-Zertifikate" + else + echo -e "${YELLOW}Unbekanntes System. Versuche direkte Installation...${NC}" + if command -v certutil &> /dev/null; then + exec_command "certutil -A -n 'MYP SSL Certificate' -t 'C,,' -i $cert_path -d sql:$HOME/.pki/nssdb" "Installiere mit certutil" + fi + fi +else + echo -e "${YELLOW}Überspringen der System-Installation, da das Skript nicht als Root ausgeführt wird.${NC}" + echo -e "${YELLOW}Sie können das Zertifikat später manuell installieren durch:${NC}" + echo -e "${NC}sudo cp backend/app/instance/ssl/myp.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates${NC}" +fi + +# 4. Frontend konfigurieren +echo "" +echo -e "${CYAN}4. Konfiguriere Frontend...${NC}" + +# Erstelle Frontend-Konfigurationsskript +cat > frontend/configure_ssl.js << 'EOF' +#!/usr/bin/env node + +/** + * Dieses Skript konfiguriert das Next.js-Frontend, um das selbstsignierte SSL-Zertifikat zu akzeptieren + * und die richtigen SSL-Einstellungen im Frontend zu setzen. + */ + +const fs = require('fs'); +const path = require('path'); + +// Pfade definieren +const ENV_LOCAL_PATH = path.join(__dirname, '.env.local'); +const ENV_FRONTEND_PATH = path.join(__dirname, 'env.frontend'); +const SSL_DIR = path.join(__dirname, 'ssl'); +const NEXT_CONFIG_PATH = path.join(__dirname, 'next.config.js'); + +console.log('=== Frontend-SSL-Konfiguration ==='); + +// Prüfen, ob SSL-Verzeichnis und Zertifikate existieren +if (!fs.existsSync(SSL_DIR) || + !fs.existsSync(path.join(SSL_DIR, 'myp.crt')) || + !fs.existsSync(path.join(SSL_DIR, 'myp.key'))) { + console.error('SSL-Zertifikate nicht gefunden. Bitte zuerst das Backend-Skript ausführen.'); + process.exit(1); +} + +console.log('SSL-Zertifikate gefunden. Konfiguriere Frontend...'); + +// Umgebungsvariablen konfigurieren +function updateEnvFile() { + try { + let envContent; + + // .env.local erstellen oder aktualisieren + if (fs.existsSync(ENV_LOCAL_PATH)) { + envContent = fs.readFileSync(ENV_LOCAL_PATH, 'utf8'); + } else if (fs.existsSync(ENV_FRONTEND_PATH)) { + envContent = fs.readFileSync(ENV_FRONTEND_PATH, 'utf8'); + } else { + envContent = `# MYP Frontend Umgebungsvariablen\n`; + } + + // SSL-Konfigurationen + const sslConfigs = [ + 'NODE_TLS_REJECT_UNAUTHORIZED=0', + 'HTTPS=true', + 'SSL_CRT_FILE=./ssl/myp.crt', + 'SSL_KEY_FILE=./ssl/myp.key', + 'NEXT_PUBLIC_API_URL=https://raspberrypi:443', + 'NEXT_PUBLIC_BACKEND_HOST=raspberrypi:443', + 'NEXT_PUBLIC_BACKEND_PROTOCOL=https' + ]; + + // Existierende Konfigurationen aktualisieren + sslConfigs.forEach(config => { + const [key, value] = config.split('='); + const regex = new RegExp(`^${key}=.*$`, 'm'); + + if (envContent.match(regex)) { + // Update existierende Konfiguration + envContent = envContent.replace(regex, config); + } else { + // Neue Konfiguration hinzufügen + envContent += `\n${config}`; + } + }); + + // Speichern der aktualisierten Umgebungsvariablen + fs.writeFileSync(ENV_LOCAL_PATH, envContent); + console.log('.env.local Datei aktualisiert mit SSL-Konfigurationen'); + return true; + } catch (error) { + console.error(`Fehler bei der Aktualisierung der Umgebungsvariablen: ${error.message}`); + return false; + } +} + +// Next.js-Konfiguration aktualisieren +function updateNextConfig() { + try { + let configContent; + + // next.config.js erstellen oder aktualisieren + if (fs.existsSync(NEXT_CONFIG_PATH)) { + configContent = fs.readFileSync(NEXT_CONFIG_PATH, 'utf8'); + } else { + configContent = `/** @type {import('next').NextConfig} */\n\nconst nextConfig = {}\n\nmodule.exports = nextConfig\n`; + } + + // Prüfen, ob bereits eine HTTPS-Konfiguration vorhanden ist + if (configContent.includes('serverOptions:') && configContent.includes('https:')) { + console.log('HTTPS-Konfiguration ist bereits in der next.config.js vorhanden.'); + return true; + } + + // HTTPS-Konfiguration hinzufügen + const httpsConfig = ` +/** @type {import('next').NextConfig} */ +const fs = require('fs'); +const path = require('path'); + +const nextConfig = { + reactStrictMode: true, + webpack: (config) => { + return config; + }, + // HTTPS-Konfiguration für die Entwicklung + devServer: { + https: { + key: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.key')), + cert: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.crt')), + }, + }, + // Konfiguration für selbstsignierte Zertifikate + serverOptions: { + https: { + key: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.key')), + cert: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.crt')), + }, + }, + // Zusätzliche Konfigurationen + async rewrites() { + return [ + { + source: '/api/:path*', + destination: 'https://raspberrypi:443/api/:path*', + }, + ] + } +}; + +module.exports = nextConfig; +`; + + // Speichern der aktualisierten Next.js-Konfiguration + fs.writeFileSync(NEXT_CONFIG_PATH, httpsConfig); + console.log('next.config.js Datei aktualisiert mit HTTPS-Konfiguration'); + return true; + } catch (error) { + console.error(`Fehler bei der Aktualisierung der Next.js-Konfiguration: ${error.message}`); + return false; + } +} + +// Update der Fetch-Konfiguration +function updateFetchConfig() { + try { + const fetchConfigPath = path.join(__dirname, 'src', 'utils', 'api-config.ts'); + + if (!fs.existsSync(fetchConfigPath)) { + console.warn('Datei api-config.ts nicht gefunden. Überspringe Aktualisierung.'); + return true; + } + + // Lesen der aktuellen Konfiguration + let configContent = fs.readFileSync(fetchConfigPath, 'utf8'); + + // Sicherstellen, dass SSL-Verbindungen akzeptiert werden + if (!configContent.includes('NODE_TLS_REJECT_UNAUTHORIZED=0')) { + // Hinzufügen eines Kommentars zu Beginn der Datei + configContent = `// SSL-Verbindungen akzeptieren (selbstsignierte Zertifikate) +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +${configContent}`; + } + + // Speichern der aktualisierten Fetch-Konfiguration + fs.writeFileSync(fetchConfigPath, configContent); + console.log('api-config.ts Datei aktualisiert, um selbstsignierte Zertifikate zu akzeptieren'); + return true; + } catch (error) { + console.error(`Fehler bei der Aktualisierung der Fetch-Konfiguration: ${error.message}`); + return false; + } +} + +// Hauptfunktion +function main() { + let success = true; + + success = updateEnvFile() && success; + success = updateNextConfig() && success; + success = updateFetchConfig() && success; + + if (success) { + console.log('\n=== Konfiguration erfolgreich abgeschlossen ==='); + console.log('Das Frontend wurde für die Verwendung von HTTPS mit dem selbstsignierten Zertifikat konfiguriert.'); + } else { + console.error('\n=== Konfiguration nicht vollständig abgeschlossen ==='); + console.error('Es gab Probleme bei der Konfiguration des Frontends.'); + } +} + +// Ausführen der Hauptfunktion +main(); +EOF + +# Ausführbar machen +chmod +x frontend/configure_ssl.js + +# Frontend konfigurieren +if command -v node &> /dev/null; then + frontend_config_success=$(exec_command "cd frontend && node configure_ssl.js" "Konfiguriere Frontend") +else + echo -e "${YELLOW}Node.js ist nicht installiert. Überspringe Frontend-Konfiguration.${NC}" + echo -e "${YELLOW}Sie können die Frontend-Konfiguration später manuell durchführen durch:${NC}" + echo -e "${NC}cd frontend && node configure_ssl.js${NC}" +fi + +# 5. Docker-Compose Datei aktualisieren +echo "" +echo -e "${CYAN}5. Aktualisiere Docker-Compose-Konfiguration...${NC}" + +docker_compose_file="docker-compose.yml" +if [ -f "$docker_compose_file" ]; then + if ! grep -q -- "--dual-protocol" "$docker_compose_file"; then + # Backup erstellen + cp "$docker_compose_file" "${docker_compose_file}.bak" + + # Konfiguration aktualisieren + sed -i 's/command: python -m app\.app/command: python -m app.app --dual-protocol/g' "$docker_compose_file" + + echo -e "${GREEN}✓ Docker-Compose-Datei wurde aktualisiert, um den dual-protocol-Modus zu aktivieren.${NC}" + else + echo -e "${GREEN}✓ Docker-Compose-Datei ist bereits korrekt konfiguriert.${NC}" + fi +else + echo -e "${YELLOW}✗ Docker-Compose-Datei nicht gefunden. Überspringe diese Konfiguration.${NC}" +fi + +# 6. Docker-Container aktualisieren +echo "" +echo -e "${CYAN}6. Möchten Sie die Docker-Container neu starten?${NC}" +read -p "Neu starten (j/n): " restart_docker + +if [ "$restart_docker" = "j" ]; then + if command -v docker-compose &> /dev/null || command -v docker &> /dev/null; then + echo "Starte Docker-Container neu..." + + if command -v docker-compose &> /dev/null; then + exec_command "docker-compose down && docker-compose up -d" "Starte Docker-Container neu mit docker-compose" + else + exec_command "docker compose down && docker compose up -d" "Starte Docker-Container neu mit docker compose" + fi + else + echo -e "${YELLOW}Docker ist nicht installiert oder nicht im PATH. Überspringe Neustart der Container.${NC}" + fi +fi + +# Abschluss +echo "" +echo -e "${CYAN}====================================================" +echo -e " SSL-Konfiguration abgeschlossen" +echo -e "====================================================${NC}" +echo "" +echo -e "${GREEN}Das SSL-Zertifikat wurde erfolgreich generiert und konfiguriert.${NC}" +echo -e "${GREEN}Sie können nun auf folgende Weise auf die Anwendung zugreifen:${NC}" +echo -e "${GREEN}- Backend: https://raspberrypi:443${NC}" +echo -e "${GREEN}- Frontend: https://localhost:3000${NC}" +echo "" +echo -e "${YELLOW}Hinweis: Bei der ersten Verbindung müssen Sie möglicherweise${NC}" +echo -e "${YELLOW}das selbstsignierte Zertifikat in Ihrem Browser akzeptieren.${NC}" +echo "" \ No newline at end of file