feat: SSH-Key-Auth als primäre Methode, Bitwarden als Fallback
- Neuer Step I (ssh_key_versuch.py): liest SSH-Keys aus DB, testet Verbindung per paramiko; erfolgreiche Server in server_creds, fehlgeschlagene in needs_bitwarden - Step G (Bitwarden) ist jetzt No-Op wenn alle Server per Key OK - paramiko.DSSKey in allen Dateien entfernt (nicht in paramiko 4.0) - failure_module (flow_fehler_handler.py): sendet bei jedem Flow-Fehler eine Nextcloud-Talk-Nachricht und bereinigt DB/Session - Bitwarden-Step überspringt fehlgeschlagene Server statt abzubrechen Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import wmill, json, paramiko, io, mysql.connector
|
||||
|
||||
|
||||
def _load_pkey(key_str: str):
|
||||
for cls in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey, paramiko.DSSKey]:
|
||||
for cls in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey]:
|
||||
try:
|
||||
return cls.from_private_key(io.StringIO(key_str))
|
||||
except Exception:
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import wmill, json, paramiko, io, mysql.connector, re
|
||||
|
||||
def _load_pkey(key_str: str):
|
||||
for cls in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey, paramiko.DSSKey]:
|
||||
for cls in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey]:
|
||||
try:
|
||||
return cls.from_private_key(io.StringIO(key_str))
|
||||
except Exception:
|
||||
|
||||
+21
-4
@@ -75,14 +75,31 @@ def main(
|
||||
raise Exception("Vault konnte nicht entsperrt werden")
|
||||
env["BW_SESSION"] = bw_session
|
||||
|
||||
server_creds = prev.get("server_creds", {})
|
||||
server_creds = prev.get("server_creds", {})
|
||||
failed_servers = []
|
||||
|
||||
for server in servers:
|
||||
hostname = server["hostname"]
|
||||
print(f"Hole Creds fuer: {hostname}")
|
||||
creds = bw_lookup(hostname, env, run)
|
||||
server_creds[hostname] = creds
|
||||
print(f" -> OK: {creds['username']}@{hostname}")
|
||||
try:
|
||||
creds = bw_lookup(hostname, env, run)
|
||||
server_creds[hostname] = creds
|
||||
print(f" -> OK: {creds['username']}@{hostname}")
|
||||
except Exception as e:
|
||||
print(f" -> WARNUNG: {e} – Server wird übersprungen")
|
||||
failed_servers.append(hostname)
|
||||
|
||||
run(["bw", "logout"], check=False)
|
||||
|
||||
if failed_servers:
|
||||
print(f"\nWARNUNG: Keine Credentials für: {failed_servers}")
|
||||
# Server aus target_servers entfernen damit C/D sie nicht anfassen
|
||||
remaining = [s for s in prev.get("target_servers", [])
|
||||
if s["hostname"] not in failed_servers]
|
||||
if not remaining:
|
||||
raise Exception(
|
||||
f"Keine Restore-Server verfügbar – Bitwarden-Lookup fehlgeschlagen für: {failed_servers}"
|
||||
)
|
||||
return {**prev, "server_creds": server_creds, "target_servers": remaining}
|
||||
|
||||
return {**prev, "server_creds": server_creds}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import wmill, mysql.connector, json, paramiko, io
|
||||
|
||||
def _load_pkey(key_str: str):
|
||||
for cls in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey, paramiko.DSSKey]:
|
||||
for cls in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey]:
|
||||
try:
|
||||
return cls.from_private_key(io.StringIO(key_str))
|
||||
except Exception:
|
||||
@@ -19,14 +19,19 @@ def main(prev: dict):
|
||||
|
||||
hostnames = [s["hostname"] for s in servers]
|
||||
placeholders = ",".join(["%s"] * len(hostnames))
|
||||
cur.execute(f"""
|
||||
SELECT hostname, ip, ssh_private_key, ssh_key_user
|
||||
FROM Kunden.`bronze.restore.server`
|
||||
WHERE hostname IN ({placeholders})
|
||||
AND ssh_private_key IS NOT NULL
|
||||
AND ssh_private_key != ''
|
||||
""", hostnames)
|
||||
key_rows = {row["hostname"]: row for row in cur.fetchall()}
|
||||
try:
|
||||
cur.execute(f"""
|
||||
SELECT hostname, ip, ssh_private_key, ssh_key_user
|
||||
FROM Kunden.`bronze.restore.server`
|
||||
WHERE hostname IN ({placeholders})
|
||||
AND ssh_private_key IS NOT NULL
|
||||
AND ssh_private_key != ''
|
||||
""", hostnames)
|
||||
key_rows = {row["hostname"]: row for row in cur.fetchall()}
|
||||
except Exception as e:
|
||||
print(f"WARNUNG: SSH-Key-Spalten nicht in DB vorhanden ({e})")
|
||||
print("Alle Server werden über Bitwarden authentifiziert.")
|
||||
key_rows = {}
|
||||
cur.close(); conn.close()
|
||||
|
||||
server_creds = {}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import wmill, json, mysql.connector, paramiko, io, re, base64
|
||||
|
||||
def _load_pkey(key_str: str):
|
||||
for cls in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey, paramiko.DSSKey]:
|
||||
for cls in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey]:
|
||||
try:
|
||||
return cls.from_private_key(io.StringIO(key_str))
|
||||
except Exception:
|
||||
|
||||
Reference in New Issue
Block a user