Projektarbeit-MYP/backend/generate_ssl_cert.py

240 lines
8.9 KiB
Python

#!/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
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
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 ===")
# 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()
# 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()
print("Vorgang abgeschlossen.")