"Update SSL certificate generation process"

This commit is contained in:
Till Tomczak 2025-05-26 10:48:36 +02:00
parent 0d7264524f
commit f063d07232
4 changed files with 74 additions and 54 deletions

View File

@ -18,7 +18,8 @@ from flask_wtf.csrf import CSRFProtect
from config.settings import ( from config.settings import (
SECRET_KEY, TAPO_USERNAME, TAPO_PASSWORD, PRINTERS, SECRET_KEY, TAPO_USERNAME, TAPO_PASSWORD, PRINTERS,
FLASK_HOST, FLASK_PORT, FLASK_DEBUG, SESSION_LIFETIME, 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 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 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__": if __name__ == "__main__":
import argparse import argparse
import threading import threading
import ssl
import socket
import logging
# Kommandozeilenargumente parsen # Kommandozeilenargumente parsen
parser = argparse.ArgumentParser(description='MYP Platform - 3D-Drucker Reservierungssystem') 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 port = args.port if args.port else FLASK_PORT
# SSL-Kontext abrufen # SSL-Kontext abrufen
ssl_context = None if args.no_ssl else get_ssl_context() ssl_context = None
if SSL_ENABLED and not args.no_ssl:
# Funktion zum Starten des Servers
def start_server(use_ssl=True, server_port=None):
if server_port is None:
server_port = port
try: try:
if use_ssl and ssl_context: if SSL_CERT_PATH and SSL_KEY_PATH:
protocol = "HTTPS" ssl_context = (SSL_CERT_PATH, SSL_KEY_PATH)
app_logger.info(f"{protocol}-Server wird auf Port {server_port} gestartet...") logging.info(f"SSL aktiviert mit Zertifikat: {SSL_CERT_PATH}")
app.run(host=FLASK_HOST, port=server_port, debug=FLASK_DEBUG, ssl_context=ssl_context)
else: else:
protocol = "HTTP" ssl_context = 'adhoc'
app_logger.info(f"{protocol}-Server wird auf Port {server_port} gestartet...") logging.info("SSL aktiviert mit selbstsigniertem Ad-hoc-Zertifikat")
app.run(host=FLASK_HOST, port=server_port, debug=FLASK_DEBUG)
except Exception as e: except Exception as e:
app_logger.error(f"Fehler beim Starten des {protocol}-Servers auf Port {server_port}: {str(e)}") logging.error(f"Fehler beim Laden des SSL-Kontexts: {e}")
if server_port == FLASK_PORT: ssl_context = None
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)
# Dual-Protokoll-Modus: HTTP und HTTPS parallel starten # Dual-Protokoll-Modus: HTTP und HTTPS gleichzeitig
if args.dual_protocol: 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) # Beide Server in separaten Threads starten
https_thread = threading.Thread(target=start_server, kwargs={"use_ssl": True, "server_port": port}) http_thread = threading.Thread(target=start_http_server)
https_thread = threading.Thread(target=start_https_server)
http_thread.daemon = True
https_thread.daemon = True https_thread.daemon = True
http_thread.start()
https_thread.start() https_thread.start()
# HTTP auf Alternativport (80) # Warten, bis beide Threads beendet sind (was sie normalerweise nicht sein sollten)
http_port = FLASK_FALLBACK_PORT http_thread.join()
start_server(use_ssl=False, server_port=http_port) https_thread.join()
else: else:
# Normaler Start mit einem Protokoll # Normaler Modus - entweder HTTP oder HTTPS
app_logger.info(f"Server wird auf Port {port} mit {'HTTPS' if ssl_context else 'HTTP'} gestartet...") if ssl_context:
start_server(use_ssl=bool(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 # Content Security Policy anpassen
@app.after_request @app.after_request

View File

@ -34,9 +34,9 @@ SESSION_LIFETIME = timedelta(days=7)
# SSL-Konfiguration # SSL-Konfiguration
SSL_ENABLED = True SSL_ENABLED = True
SSL_CERT_PATH = "instance/ssl/myp.crt" SSL_CERT_PATH = "app/instance/ssl/myp.crt"
SSL_KEY_PATH = "instance/ssl/myp.key" SSL_KEY_PATH = "app/instance/ssl/myp.key"
SSL_HOSTNAME = "localhost" SSL_HOSTNAME = "raspberrypi"
# Scheduler-Konfiguration # Scheduler-Konfiguration
SCHEDULER_INTERVAL = 60 # Sekunden SCHEDULER_INTERVAL = 60 # Sekunden

Binary file not shown.

View File

@ -8,6 +8,8 @@ from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
import ipaddress
import argparse
def generate_ssl_certificate(): def generate_ssl_certificate():
""" """
@ -65,9 +67,8 @@ def generate_ssl_certificate():
san_list.append(x509.DNSName(hostname)) san_list.append(x509.DNSName(hostname))
# IP-Adressen hinzufügen # IP-Adressen hinzufügen
import socket
for ip in ip_addresses: for ip in ip_addresses:
san_list.append(x509.IPAddress(socket.inet_aton(ip))) san_list.append(x509.IPAddress(ipaddress.IPv4Address(ip)))
# Zertifikat erstellen # Zertifikat erstellen
cert = x509.CertificateBuilder().subject_name( cert = x509.CertificateBuilder().subject_name(
@ -221,20 +222,27 @@ def copy_to_raspberry():
if __name__ == "__main__": if __name__ == "__main__":
print("=== MYP SSL-Zertifikatsgenerator ===") 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 # Zertifikat generieren
cert_generated = generate_ssl_certificate() cert_generated = generate_ssl_certificate()
if not cert_generated: if not cert_generated:
print("Generierung des Zertifikats fehlgeschlagen.") print("Generierung des Zertifikats fehlgeschlagen.")
exit(1) exit(1)
# Fragen, ob das Zertifikat im System installiert werden soll # System-Installation des Zertifikats
install_system = input("Möchten Sie das Zertifikat im System-Zertifikatsspeicher installieren? (j/n): ").lower() == 'j' if not args.no_install:
if install_system: if args.quiet or input("Möchten Sie das Zertifikat im System-Zertifikatsspeicher installieren? (j/n): ").lower() == 'j':
install_certificate_system() install_certificate_system()
# Fragen, ob das Zertifikat auf den Raspberry Pi kopiert werden soll # Kopieren auf Raspberry Pi
copy_raspberry = input("Möchten Sie das Zertifikat auf den Raspberry Pi kopieren? (j/n): ").lower() == 'j' if not args.no_raspberry:
if copy_raspberry: if args.quiet or input("Möchten Sie das Zertifikat auf den Raspberry Pi kopieren? (j/n): ").lower() == 'j':
copy_to_raspberry() copy_to_raspberry()
print("Vorgang abgeschlossen.") print("Vorgang abgeschlossen.")