261 lines
9.9 KiB
Python
261 lines
9.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
|
|
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
|
|
import os
|
|
ssl_cert_path = os.path.abspath(os.path.join("app", "instance", "ssl", "myp.crt"))
|
|
|
|
# Prüfen, ob Datei existiert
|
|
if not os.path.exists(ssl_cert_path):
|
|
print(f"Zertifikat nicht gefunden unter: {ssl_cert_path}")
|
|
# Alternativen Pfad versuchen
|
|
alt_path = os.path.abspath(os.path.join("backend", "app", "instance", "ssl", "myp.crt"))
|
|
if os.path.exists(alt_path):
|
|
ssl_cert_path = alt_path
|
|
print(f"Verwende alternativen Pfad: {ssl_cert_path}")
|
|
else:
|
|
print("Zertifikat konnte nicht gefunden werden.")
|
|
return False
|
|
|
|
# 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.") |