From f063d07232957b9e0b970883ed9da6d74ff4f67b Mon Sep 17 00:00:00 2001 From: Till Tomczak Date: Mon, 26 May 2025 10:48:36 +0200 Subject: [PATCH] "Update SSL certificate generation process" --- backend/app/app.py | 94 +++++++++++++++++++-------------- backend/app/config/settings.py | 6 +-- backend/app/database/myp.db | Bin 32768 -> 32768 bytes backend/generate_ssl_cert.py | 28 ++++++---- 4 files changed, 74 insertions(+), 54 deletions(-) diff --git a/backend/app/app.py b/backend/app/app.py index 5b23666c..394120c2 100644 --- a/backend/app/app.py +++ b/backend/app/app.py @@ -18,7 +18,8 @@ from flask_wtf.csrf import CSRFProtect from config.settings import ( SECRET_KEY, TAPO_USERNAME, TAPO_PASSWORD, PRINTERS, FLASK_HOST, FLASK_PORT, FLASK_DEBUG, SESSION_LIFETIME, - SCHEDULER_INTERVAL, SCHEDULER_ENABLED, get_ssl_context, FLASK_FALLBACK_PORT + SCHEDULER_INTERVAL, SCHEDULER_ENABLED, get_ssl_context, FLASK_FALLBACK_PORT, + SSL_ENABLED, SSL_CERT_PATH, SSL_KEY_PATH ) from utils.logging_config import setup_logging, get_logger, log_startup_info from models import User, Printer, Job, Stats, get_db_session, init_database, create_initial_admin @@ -1396,6 +1397,9 @@ def check_jobs(): if __name__ == "__main__": import argparse import threading + import ssl + import socket + import logging # Kommandozeilenargumente parsen parser = argparse.ArgumentParser(description='MYP Platform - 3D-Drucker Reservierungssystem') @@ -1411,56 +1415,64 @@ if __name__ == "__main__": port = args.port if args.port else FLASK_PORT # SSL-Kontext abrufen - ssl_context = None if args.no_ssl else get_ssl_context() - - # Funktion zum Starten des Servers - def start_server(use_ssl=True, server_port=None): - if server_port is None: - server_port = port - + ssl_context = None + if SSL_ENABLED and not args.no_ssl: try: - if use_ssl and ssl_context: - protocol = "HTTPS" - app_logger.info(f"{protocol}-Server wird auf Port {server_port} gestartet...") - app.run(host=FLASK_HOST, port=server_port, debug=FLASK_DEBUG, ssl_context=ssl_context) + if SSL_CERT_PATH and SSL_KEY_PATH: + ssl_context = (SSL_CERT_PATH, SSL_KEY_PATH) + logging.info(f"SSL aktiviert mit Zertifikat: {SSL_CERT_PATH}") else: - protocol = "HTTP" - app_logger.info(f"{protocol}-Server wird auf Port {server_port} gestartet...") - app.run(host=FLASK_HOST, port=server_port, debug=FLASK_DEBUG) + ssl_context = 'adhoc' + logging.info("SSL aktiviert mit selbstsigniertem Ad-hoc-Zertifikat") except Exception as e: - app_logger.error(f"Fehler beim Starten des {protocol}-Servers auf Port {server_port}: {str(e)}") - if server_port == FLASK_PORT: - fallback_port = FLASK_FALLBACK_PORT - app_logger.info(f"Versuche auf Fallback-Port {fallback_port} zu starten...") - try: - if use_ssl and ssl_context: - app.run(host=FLASK_HOST, port=fallback_port, debug=FLASK_DEBUG, ssl_context=ssl_context) - else: - app.run(host=FLASK_HOST, port=fallback_port, debug=FLASK_DEBUG) - except Exception as e2: - app_logger.error(f"Auch Fallback-Port fehlgeschlagen: {str(e2)}") - app_logger.info("Versuche auf Standard-Port 5000 zu starten...") - if use_ssl and ssl_context: - app.run(host=FLASK_HOST, port=5000, debug=FLASK_DEBUG, ssl_context=ssl_context) - else: - app.run(host=FLASK_HOST, port=5000, debug=FLASK_DEBUG) + logging.error(f"Fehler beim Laden des SSL-Kontexts: {e}") + ssl_context = None - # Dual-Protokoll-Modus: HTTP und HTTPS parallel starten + # Dual-Protokoll-Modus: HTTP und HTTPS gleichzeitig if args.dual_protocol: - app_logger.info("Starte Server im Dual-Protokoll-Modus (HTTP und HTTPS)...") + # Funktion zum Starten des HTTP-Servers + def start_http_server(): + try: + logging.info(f"Starte HTTP-Server auf Port 80...") + # Kopie der App erstellen + from werkzeug.serving import run_simple + run_simple('0.0.0.0', 80, app, threaded=True) + except socket.error as e: + logging.error(f"Konnte HTTP-Server nicht starten: {e}") + + # Funktion zum Starten des HTTPS-Servers + def start_https_server(): + try: + if ssl_context: + logging.info(f"Starte HTTPS-Server auf Port {port}...") + app.run(host='0.0.0.0', port=port, ssl_context=ssl_context, threaded=True) + else: + logging.warning("HTTPS deaktiviert aufgrund fehlender Zertifikate") + app.run(host='0.0.0.0', port=port, threaded=True) + except socket.error as e: + logging.error(f"Konnte HTTPS-Server nicht starten: {e}") - # HTTPS auf Hauptport (443) - https_thread = threading.Thread(target=start_server, kwargs={"use_ssl": True, "server_port": port}) + # Beide Server in separaten Threads starten + http_thread = threading.Thread(target=start_http_server) + https_thread = threading.Thread(target=start_https_server) + + http_thread.daemon = True https_thread.daemon = True + + http_thread.start() https_thread.start() - # HTTP auf Alternativport (80) - http_port = FLASK_FALLBACK_PORT - start_server(use_ssl=False, server_port=http_port) + # Warten, bis beide Threads beendet sind (was sie normalerweise nicht sein sollten) + http_thread.join() + https_thread.join() else: - # Normaler Start mit einem Protokoll - app_logger.info(f"Server wird auf Port {port} mit {'HTTPS' if ssl_context else 'HTTP'} gestartet...") - start_server(use_ssl=bool(ssl_context)) + # Normaler Modus - entweder HTTP oder HTTPS + if ssl_context: + logging.info(f"Starte HTTPS-Server auf Port {port}...") + app.run(host='0.0.0.0', port=port, ssl_context=ssl_context, threaded=True) + else: + logging.info(f"Starte HTTP-Server auf Port {port}...") + app.run(host='0.0.0.0', port=port, threaded=True) # Content Security Policy anpassen @app.after_request diff --git a/backend/app/config/settings.py b/backend/app/config/settings.py index a5bd6205..4595db6b 100644 --- a/backend/app/config/settings.py +++ b/backend/app/config/settings.py @@ -34,9 +34,9 @@ SESSION_LIFETIME = timedelta(days=7) # SSL-Konfiguration SSL_ENABLED = True -SSL_CERT_PATH = "instance/ssl/myp.crt" -SSL_KEY_PATH = "instance/ssl/myp.key" -SSL_HOSTNAME = "localhost" +SSL_CERT_PATH = "app/instance/ssl/myp.crt" +SSL_KEY_PATH = "app/instance/ssl/myp.key" +SSL_HOSTNAME = "raspberrypi" # Scheduler-Konfiguration SCHEDULER_INTERVAL = 60 # Sekunden diff --git a/backend/app/database/myp.db b/backend/app/database/myp.db index 2ccc5c1069714cfa77b5fde1883f6958edfb47f2..6a9844c068d8a5856e8a738ea3fc09fb70372acf 100644 GIT binary patch delta 78 zcmZo@U}|V!njp=%aH5Pej%9|q`9T(DCK;wduKHnxzUE;?{zYMq>19z7 ifvFV*DQV^go*6lwK_=!I*=d<&X6{u+o3F_0Bme;Xn;Lik delta 78 zcmZo@U}|V!njptY_VT8wzNJwWk*Std9vRMwQJGbtxrt`3rRgqN9>u{y i!4aNCewl7L5k_GZ<|Xc-!G$>$#W`uYo3F_0Bme*|n;ZcE diff --git a/backend/generate_ssl_cert.py b/backend/generate_ssl_cert.py index ee04da7c..ad5927ce 100644 --- a/backend/generate_ssl_cert.py +++ b/backend/generate_ssl_cert.py @@ -8,6 +8,8 @@ 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 +import ipaddress +import argparse def generate_ssl_certificate(): """ @@ -65,9 +67,8 @@ def generate_ssl_certificate(): 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))) + san_list.append(x509.IPAddress(ipaddress.IPv4Address(ip))) # Zertifikat erstellen cert = x509.CertificateBuilder().subject_name( @@ -221,20 +222,27 @@ def copy_to_raspberry(): if __name__ == "__main__": print("=== MYP SSL-Zertifikatsgenerator ===") + # Kommandozeilenargumente parsen + parser = argparse.ArgumentParser(description='MYP SSL-Zertifikatsgenerator') + parser.add_argument('--no-install', action='store_true', help='Zertifikat nicht im System installieren') + parser.add_argument('--no-raspberry', action='store_true', help='Zertifikat nicht auf den Raspberry Pi kopieren') + parser.add_argument('--quiet', action='store_true', help='Keine Benutzerinteraktion') + args = parser.parse_args() + # Zertifikat generieren cert_generated = generate_ssl_certificate() if not cert_generated: print("Generierung des Zertifikats fehlgeschlagen.") exit(1) - # Fragen, ob das Zertifikat im System installiert werden soll - install_system = input("Möchten Sie das Zertifikat im System-Zertifikatsspeicher installieren? (j/n): ").lower() == 'j' - if install_system: - install_certificate_system() + # System-Installation des Zertifikats + if not args.no_install: + if args.quiet or input("Möchten Sie das Zertifikat im System-Zertifikatsspeicher installieren? (j/n): ").lower() == 'j': + install_certificate_system() - # Fragen, ob das Zertifikat auf den Raspberry Pi kopiert werden soll - copy_raspberry = input("Möchten Sie das Zertifikat auf den Raspberry Pi kopieren? (j/n): ").lower() == 'j' - if copy_raspberry: - copy_to_raspberry() + # Kopieren auf Raspberry Pi + if not args.no_raspberry: + if args.quiet or input("Möchten Sie das Zertifikat auf den Raspberry Pi kopieren? (j/n): ").lower() == 'j': + copy_to_raspberry() print("Vorgang abgeschlossen.") \ No newline at end of file