#!/usr/bin/env python # -*- 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 import ipaddress import argparse 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 for ip in ip_addresses: san_list.append(x509.IPAddress(ipaddress.IPv4Address(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 def install_certificate_system(): """ Installiert das Zertifikat im System-Zertifikatsspeicher (Windows). Nur für Windows-Systeme. """ import platform if platform.system() != "Windows": print("Diese Funktion ist nur unter Windows verfügbar.") return False try: import subprocess ssl_cert_path = os.path.abspath("app/instance/ssl/myp.crt") # Befehle zum Installieren des Zertifikats im Windows-Zertifikatsspeicher commands = [ ["certutil", "-addstore", "-f", "ROOT", ssl_cert_path], ["certutil", "-addstore", "-f", "CA", ssl_cert_path], ["certutil", "-addstore", "-f", "MY", ssl_cert_path] ] for cmd in commands: subprocess.run(cmd, check=True, capture_output=True) print("Zertifikat wurde erfolgreich im System-Zertifikatsspeicher installiert.") return True except Exception as e: print(f"Fehler bei der Installation des Zertifikats im System: {e}") return False def copy_to_raspberry(): """ Kopiert das Zertifikat auf den Raspberry Pi. Erfordert SSH-Zugriff auf den Raspberry Pi. """ try: import subprocess ssl_cert_path = os.path.abspath("app/instance/ssl/myp.crt") ssl_key_path = os.path.abspath("app/instance/ssl/myp.key") # Raspberry Pi-Zugangsdaten raspberry_host = "raspberrypi" raspberry_user = "pi" raspberry_dest = "/home/pi/myp/ssl" # Befehle zum Kopieren der Dateien auf den Raspberry Pi scp_commands = [ ["scp", ssl_cert_path, f"{raspberry_user}@{raspberry_host}:{raspberry_dest}/myp.crt"], ["scp", ssl_key_path, f"{raspberry_user}@{raspberry_host}:{raspberry_dest}/myp.key"] ] # SSH-Befehl zum Erstellen des Verzeichnisses auf dem Raspberry Pi ssh_command = ["ssh", f"{raspberry_user}@{raspberry_host}", f"mkdir -p {raspberry_dest}"] # Verzeichnis auf dem Raspberry Pi erstellen print(f"Erstelle Verzeichnis auf dem Raspberry Pi: {raspberry_dest}") subprocess.run(ssh_command, check=True) # Dateien kopieren for cmd in scp_commands: print(f"Kopiere {cmd[1]} nach {cmd[2]}") subprocess.run(cmd, check=True) print(f"Zertifikate wurden erfolgreich auf den Raspberry Pi kopiert nach {raspberry_dest}") # Berechtigungen setzen chmod_command = ["ssh", f"{raspberry_user}@{raspberry_host}", f"chmod 600 {raspberry_dest}/myp.key"] subprocess.run(chmod_command, check=True) # Zertifikat im System-Zertifikatsspeicher installieren install_command = ["ssh", f"{raspberry_user}@{raspberry_host}", f"sudo cp {raspberry_dest}/myp.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates"] subprocess.run(install_command, check=True) print("Zertifikat wurde erfolgreich auf dem Raspberry Pi installiert und registriert.") return True except Exception as e: print(f"Fehler beim Kopieren des Zertifikats auf den Raspberry Pi: {e}") return False 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) # 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() # 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.")