diff --git a/schluesseldienst_admin.sh b/schluesseldienst_admin.sh new file mode 100644 index 0000000..b061c43 --- /dev/null +++ b/schluesseldienst_admin.sh @@ -0,0 +1,159 @@ +#!/bin/bash + +# --- Konfiguration (BITTE ANPASSEN!) --- + +# Der Name deines rclone-Remotes für Nextcloud +# Beispiel: Wenn du in rclone config "nextcloud3" als Namen vergeben hast. +RCLONE_REMOTE="nextcloud3" + +# Pfade in Nextcloud, relativ zum Root deines rclone-Remotes (z.B. nextcloud3:/) +# Hier legen Benutzer ihre Public Keys ab. +NEXTCLOUD_INCOMING_DIR="CA/Eingang" +# Hier werden die signierten Zertifikate abgelegt. +NEXTCLOUD_SIGNED_DIR="CA/Ausgang" +# Hierher werden verarbeitete Public Keys verschoben. +NEXTCLOUD_ARCHIVE_DIR="CA/Archiv" + +# Lokales Verzeichnis auf dem CA-System, in dem Dateien temporär verarbeitet werden. +# Stelle sicher, dass dieses Verzeichnis existiert und für den Skript-Benutzer schreibbar ist. +LOCAL_PROCESSING_DIR="/$HOME/tmp" + +# Absoluter Pfad zu deinem privaten CA-Schlüssel auf diesem System. +# WICHTIG: Dieser Schlüssel MUSS EXTREM SICHER SEIN (z.B. Berechtigungen 600, nur für den Skript-User lesbar). +CA_KEY_PATH="/$HOME/ca_key" + +# Standard-Gültigkeitsdauer für die ausgestellten Zertifikate. +# Beispiele: '+1d' für 1 Tag, '+1w' für 1 Woche, '+52w' für 1 Jahr. +CERTIFICATE_VALIDITY='+10w' + +USERNAME="root" +# --- Ende Konfiguration --- + + +# --- Funktionen --- + +# Prüft, ob alle benötigten Befehle (ssh-keygen, rclone, jq) verfügbar sind. +check_dependencies() { + local missing=0 + for cmd in ssh-keygen rclone jq; do + if ! command -v "$cmd" &> /dev/null; then + echo "Fehler: Befehl '$cmd' nicht gefunden. Bitte installieren Sie ihn." >&2 + missing=1 + fi + done + if [ "$missing" -eq 1 ]; then + exit 1 + fi +} + +# --- Hauptlogik --- + +# Schritt 1: Prüfe Abhängigkeiten +check_dependencies + +echo "--- Starte SSH CA Automatisierungs-Skript ---" + +# Schritt 2: Lokales Verarbeitungsverzeichnis vorbereiten +mkdir -p "$LOCAL_PROCESSING_DIR" || { echo "Fehler: Konnte '$LOCAL_PROCESSING_DIR' nicht erstellen." >&2; exit 1; } +chmod 700 "$LOCAL_PROCESSING_DIR" # Setzt restriktive Berechtigungen + +# Schritt 3: CA-Schlüssel Berechtigungen prüfen +if [ ! -f "$CA_KEY_PATH" ] || [ ! -r "$CA_KEY_PATH" ]; then + echo "Fehler: Privater CA-Schlüssel nicht gefunden oder nicht lesbar unter '$CA_KEY_PATH'." >&2 + echo "Bitte stellen Sie sicher, dass die Berechtigungen (z.B. 600) korrekt gesetzt sind." >&2 + exit 1 +fi + +echo "Suche nach neuen Public Keys im Nextcloud-Ordner '$RCLONE_REMOTE:$NEXTCLOUD_INCOMING_DIR'..." + +# Schritt 4: Public Keys aus Nextcloud auflisten +# rclone lsjson gibt eine JSON-Liste der Dateien zurück. +# --files-only filtert nur Dateien, --include "*.pub" nur .pub-Dateien. +# 2>/dev/null unterdrückt rclone-Fehlermeldungen, falls das Verzeichnis leer ist. +PUBLIC_KEYS_JSON=$(rclone lsjson "$RCLONE_REMOTE:$NEXTCLOUD_INCOMING_DIR" --files-only --include "*.pub" 2>/dev/null) + +# Prüfe, ob die JSON-Ausgabe leer ist oder nur "[]" enthält +if [ -z "$PUBLIC_KEYS_JSON" ] || [ "$PUBLIC_KEYS_JSON" == "[]" ]; then + echo "Keine neuen Public Keys zum Verarbeiten gefunden." +else + echo "Gefundene Public Keys:" + # Zeigt die Namen der gefundenen Dateien an (setzt 'jq' voraus). + echo "$PUBLIC_KEYS_JSON" | jq -r '.[].Name' + + # Lese die Dateinamen sicher in ein Bash-Array ein. + # Dies ist entscheidend, um doppelte Verarbeitung zu vermeiden, + # da das Array eine Momentaufnahme der Dateinamen vor der Verarbeitung darstellt. + readarray -t PUBLIC_KEYS_ARRAY < <(echo "$PUBLIC_KEYS_JSON" | jq -r '.[].Name') + + if [ ${#PUBLIC_KEYS_ARRAY[@]} -eq 0 ]; then + echo "Hinweis: Obwohl JSON gefunden wurde, konnten keine Dateinamen extrahiert werden (eventuell falsches Format?)." >&2 + else + # Schritt 5: Iteriere und verarbeite jeden Public Key + for pub_key_filename in "${PUBLIC_KEYS_ARRAY[@]}"; do + echo "--- Verarbeite Public Key: '$pub_key_filename' ---" + + # Extrahiere den Benutzernamen aus dem Dateinamen (z.B. "alf" aus "alf_id_ed25519.pub") + # USERNAME=$(echo "$pub_key_filename" | cut -d'_' -f1) + # USERNAME wird oben gesetzt! + + if [ -z "$USERNAME" ]; then + echo "Warnung: Konnte Benutzernamen nicht aus Dateinamen '$pub_key_filename' extrahieren. Überspringe." >&2 + continue # Springe zur nächsten Datei + fi + + # Definiere lokale Pfade für den Public Key und das zukünftige Zertifikat + local_pub_key_path="${LOCAL_PROCESSING_DIR}/${pub_key_filename}" + local_cert_path="${LOCAL_PROCESSING_DIR}/${pub_key_filename%.pub}-cert.pub" + + # 5.1: Public Key von Nextcloud herunterladen + echo "Lade '$pub_key_filename' von Nextcloud herunter nach '$local_pub_key_path'..." >&2 + if ! rclone copy "$RCLONE_REMOTE:$NEXTCLOUD_INCOMING_DIR/$pub_key_filename" "$LOCAL_PROCESSING_DIR" --progress; then + echo "Fehler beim Herunterladen von '$pub_key_filename'. Überspringe diesen Schlüssel." >&2 + rm -f "$local_pub_key_path" "$local_cert_path" # Aufräumen, falls teilweise heruntergeladen + continue + fi + + # 5.2: Public Key signieren + echo "Signiere Schlüssel für Benutzer '$USERNAME'..." >&2 + # ssh-keygen fragt nach der Passphrase, wenn der CA-Schlüssel passwortgeschützt ist. + ssh-keygen -s "$CA_KEY_PATH" -V "$CERTIFICATE_VALIDITY" -n "$USERNAME" -I "CA für ${USERNAME}" "$local_pub_key_path" 2>&1 + + if [ $? -ne 0 ]; then + echo "Fehler beim Signieren von '$pub_key_filename'. Überspringe diesen Schlüssel." >&2 + rm -f "$local_pub_key_path" "$local_cert_path" # Aufräumen + continue + fi + echo "Schlüssel erfolgreich signiert: '$local_cert_path'." >&2 + + # 5.3: Signiertes Zertifikat nach Nextcloud hochladen + echo "Lade signiertes Zertifikat '$local_cert_path' nach Nextcloud hoch zu '$RCLONE_REMOTE:$NEXTCLOUD_SIGNED_DIR'..." >&2 + if ! rclone copy "$local_cert_path" "$RCLONE_REMOTE:$NEXTCLOUD_SIGNED_DIR" --progress; then + echo "Fehler beim Hochladen des signierten Zertifikats '$local_cert_path'. Überspringe diesen Schlüssel." >&2 + rm -f "$local_pub_key_path" "$local_cert_path" # Aufräumen + continue + fi + + # 5.4: Ursprünglichen Public Key nach der Verarbeitung archivieren + echo "Verschiebe Public Key '$pub_key_filename' nach '$RCLONE_REMOTE:$NEXTCLOUD_ARCHIVE_DIR'..." >&2 + if ! rclone move "$RCLONE_REMOTE:$NEXTCLOUD_INCOMING_DIR/$pub_key_filename" "$RCLONE_REMOTE:$NEXTCLOUD_ARCHIVE_DIR" --progress; then + echo "Warnung: Konnte Public Key '$pub_key_filename' nicht nach '$RCLONE_REMOTE:$NEXTCLOUD_ARCHIVE_DIR' verschieben." >&2 + else + echo "Public Key '$pub_key_filename' nach '$RCLONE_REMOTE:$NEXTCLOUD_ARCHIVE_DIR' verschoben." >&2 + fi + + # 5.5: Lokale temporäre Dateien aufräumen + rm -f "$local_pub_key_path" "$local_cert_path" + echo "Lokale temporäre Dateien für '$pub_key_filename' entfernt." >&2 + + done # Ende der for-Schleife + fi # Ende if [ ${#PUBLIC_KEYS_ARRAY[@]} -eq 0 ] + echo "--- Alle Public Keys verarbeitet. ---" +fi # Ende if [ -z "$PUBLIC_KEYS_JSON" ] + +# Schritt 6: Lokales Verarbeitungsverzeichnis aufräumen +# rmdir entfernt nur leere Verzeichnisse. 2>/dev/null || true unterdrückt Fehler. +rmdir "$LOCAL_PROCESSING_DIR" 2>/dev/null || true + +echo "--- SSH CA Automatisierungs-Skript beendet. ---" + +exit 0 diff --git a/signierdienst.sh b/signierdienst.sh new file mode 100644 index 0000000..a151936 --- /dev/null +++ b/signierdienst.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +# --- Konfiguration --- +# Nextcloud rclone Remote Name (wie in deiner rclone.conf definiert) +RCLONE_REMOTE="nextcloud3" + +# Basisverzeichnis für SSH-Schlüssel auf dem Client (normalerweise ~/.ssh/) +SSH_DIR="$HOME/Schluessel" + +# Verzeichnis auf Nextcloud, wo ungesignierte Schlüssel hochgeladen werden +# MUSS ÜBEREINSTIMMEN MIT DEM SIGNIERUNGSSTELLEN-SKRIPT! +NEXTCLOUD_UPLOAD_DIR="CA/Eingang" + +# Verzeichnis auf Nextcloud, wo signierte Schlüssel heruntergeladen werden +# MUSS ÜBEREINSTIMMEN MIT DEM SIGNIERUNGSSTELLEN-SKRIPT! +NEXTCLOUD_SIGNED_DIR="CA/Ausgang" + +# Verzeichnis auf Nextcloud, wohin der signierte Schlüssel nach dem Download verschoben wird +# MUSS ÜBEREINSTIMMEN MIT DEM SIGNIERUNGSSTELLEN-SKRIPT! +NEXTCLOUD_ARCHIVE_DIR="CA/Archiv" # NEU: Archiv-Verzeichnis + +# Name des neuen SSH-Schlüsselpaars (z.B. id_rsa_clientname) +# ACHTUNG: Wenn diese Datei existiert, wird sie überschrieben! +read -p "Schlüsselname " KEY_NAME +# KEY_NAME="id_rsa_$(hostname)" # Verwendet den Hostnamen als Teil des Schlüsselnamens + +# Kommentierungsoption für den Schlüssel (identifiziert den Schlüssel in ~/.ssh/authorized_keys) +KEY_COMMENT="$(whoami)@$(hostname) $(date +%F) Signierdienst" + +# --- Skript Start --- + +echo "Starte die Automatisierung der SSH-Schlüsselerstellung und Signierung..." +echo "--------------------------------------------------------" + +# 1. Sicherstellen, dass das SSH-Verzeichnis existiert +if [ ! -d "$SSH_DIR" ]; then + echo "Erstelle SSH-Verzeichnis: $SSH_DIR" + mkdir -p "$SSH_DIR" + chmod 700 "$SSH_DIR" +fi + +# 2. Erstellen des neuen SSH-Schlüsselpaars +PRIVATE_KEY_PATH="$SSH_DIR/$KEY_NAME" +PUBLIC_KEY_PATH="$SSH_DIR/$KEY_NAME.pub" + +if [ -f "$PRIVATE_KEY_PATH" ]; then + read -p "Warnung: SSH-Schlüssel '$KEY_NAME' existiert bereits. Überschreiben? (j/N): " OVERWRITE + if [[ ! "$OVERWRITE" =~ ^[Jj]$ ]]; then + echo "Vorgang abgebrochen. Vorhandener Schlüssel wird nicht überschrieben." + exit 1 + fi + echo "Überschreibe vorhandenen Schlüssel..." +fi + +echo "Erstelle neues SSH-Schlüsselpaar ($KEY_NAME)..." +ssh-keygen -t rsa -b 4096 -C "$KEY_COMMENT" -f "$PRIVATE_KEY_PATH" +# Es wird empfohlen, eine Passphrase zu verwenden! Der Benutzer wird hiernach gefragt. +if [ $? -ne 0 ]; then + echo "Fehler beim Erstellen des SSH-Schlüsselpaars. Abbruch." + exit 1 +fi +echo "Schlüsselpaar erfolgreich erstellt: $PRIVATE_KEY_PATH und $PUBLIC_KEY_PATH" +echo "" + +# 3. Hochladen des öffentlichen Schlüssels zur Signierung auf Nextcloud +echo "Lade öffentlichen Schlüssel '$PUBLIC_KEY_PATH' zur Signierung auf Nextcloud hoch..." +UPLOAD_TARGET="$RCLONE_REMOTE:$NEXTCLOUD_UPLOAD_DIR/" +rclone copy "$PUBLIC_KEY_PATH" "$UPLOAD_TARGET" --progress + +if [ $? -ne 0 ]; then + echo "Fehler beim Hochladen des öffentlichen Schlüssels auf Nextcloud. Abbruch." + exit 1 +fi +echo "Öffentlicher Schlüssel erfolgreich hochgeladen nach: $UPLOAD_TARGET$(basename "$PUBLIC_KEY_PATH")" +echo "" + +# 4. Warten auf den signierten Schlüssel (Polling) +SIGNED_KEY_NAME="${KEY_NAME}-cert.pub" +SIGNED_KEY_PATH="$SSH_DIR/$SIGNED_KEY_NAME" +NEXTCLOUD_SIGNED_SOURCE="$RCLONE_REMOTE:$NEXTCLOUD_SIGNED_DIR/$SIGNED_KEY_NAME" +NEXTCLOUD_ARCHIVE_TARGET="$RCLONE_REMOTE:$NEXTCLOUD_ARCHIVE_DIR/" # Ziel für das Archivieren + +echo "Warte auf den signierten Schlüssel auf Nextcloud..." +echo "Dies kann einen Moment dauern, bis die Signierungsstelle den Schlüssel verarbeitet hat." + +MAX_ATTEMPTS=120 # Maximal 60 Versuche (ca. 10 Minuten bei 10s Pause) +ATTEMPT=0 + +while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do + ATTEMPT=$((ATTEMPT + 1)) + echo "Versuch $ATTEMPT von $MAX_ATTEMPTS: Prüfe, ob signierter Schlüssel verfügbar ist..." + + # Liste die Dateien im Zielverzeichnis auf und filtere nach dem erwarteten Namen + rclone lsf "$RCLONE_REMOTE:$NEXTCLOUD_SIGNED_DIR" | grep -q "$(basename "$SIGNED_KEY_NAME")" + + if [ $? -eq 0 ]; then + echo "Signierter Schlüssel gefunden! Lade '$SIGNED_KEY_NAME' herunter..." + rclone copy "$NEXTCLOUD_SIGNED_SOURCE" "$SSH_DIR" --progress + if [ $? -ne 0 ]; then + echo "Fehler beim Herunterladen des signierten Schlüssels. Bitte manuell prüfen." + exit 1 + fi + echo "Signierter Schlüssel erfolgreich heruntergeladen nach: $SIGNED_KEY_PATH" + + # NEU: Verschieben des signierten Schlüssels ins Archiv + echo "Verschiebe den signierten Schlüssel von '$NEXTCLOUD_SIGNED_DIR' nach '$NEXTCLOUD_ARCHIVE_DIR'..." + rclone moveto "$NEXTCLOUD_SIGNED_SOURCE" "$NEXTCLOUD_ARCHIVE_TARGET$(basename "$SIGNED_KEY_NAME")" + + if [ $? -ne 0 ]; then + echo "Warnung: Fehler beim Verschieben des signierten Schlüssels ins Archiv auf Nextcloud." + echo "Bitte manuell prüfen: $NEXTCLOUD_SIGNED_SOURCE" + else + echo "Signierter Schlüssel erfolgreich archiviert." + fi + break + else + echo "Signierter Schlüssel noch nicht verfügbar. Warte 10 Sekunden..." + sleep 10 + fi + + if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then + echo "Maximale Wartezeit erreicht. Der signierte Schlüssel wurde nicht gefunden." + echo "Bitte überprüfe die Signierungsstelle und die Nextcloud-Verzeichnisse manuell." + exit 1 + fi +done + +# 5. Berechtigungen setzen (optional, aber empfohlen für signierte Schlüssel) +echo "Setze Berechtigungen für den signierten Schlüssel..." +chmod 644 "$SIGNED_KEY_PATH" +echo "Berechtigungen gesetzt: $SIGNED_KEY_PATH (644)" +echo "" + +echo "Automatisierung abgeschlossen." +echo "Du kannst nun versuchen, dich mit dem signierten Schlüssel anzumelden." +echo "Der private Schlüssel ist: $PRIVATE_KEY_PATH" +echo "Der signierte öffentliche Schlüssel ist: $SIGNED_KEY_PATH" +echo "" +echo "Um den Schlüssel in den ssh-agent zu laden, verwende:" +echo "ssh-add $PRIVATE_KEY_PATH" +echo "" +echo "Vergiss nicht, den öffentlichen Teil des signierten Schlüssels (id_rsa-cert.pub) in deine SSH-Konfiguration einzutragen," +echo "falls du explizit Keys für bestimmte Hosts definieren möchtest (obwohl das Zertifikat für SSH-Server mit der CA-Konfiguration funktioniert)." +echo "" +echo "Bitte vergewissere dich, dass deine SSH-Konfiguration auf den Servern die Zertifikatsautorität korrekt nutzt." + +exit 0 +