#!/bin/bash # # n8n Owner Account Setup Script # Erstellt den Owner-Account bei einer neuen n8n-Instanz # Oder prüft den Status einer bereits eingerichteten Instanz # Ausgabe im JSON-Format # # NICHT set -e verwenden, da wir Fehler selbst behandeln # Standardwerte owner_first_name="Admin" owner_last_name="User" timeout=10 # JSON Steps Array json_steps=() # Funktion: Step zum JSON hinzufügen add_step() { local step_name="$1" local step_status="$2" local step_message="$3" # Escape quotes in message step_message=$(echo "$step_message" | sed 's/"/\\"/g') json_steps+=("{\"step\":\"$step_name\",\"status\":\"$step_status\",\"message\":\"$step_message\"}") } # Funktion: JSON-Ausgabe generieren output_json() { local success="$1" local message="$2" local action="$3" local login_status="$4" local login_message="$5" # Escape quotes message=$(echo "$message" | sed 's/"/\\"/g') login_message=$(echo "$login_message" | sed 's/"/\\"/g') # Steps Array zusammenbauen local steps_json="" for i in "${!json_steps[@]}"; do if [[ $i -gt 0 ]]; then steps_json+="," fi steps_json+="${json_steps[$i]}" done # Zeitstempel local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") # JSON ausgeben cat << JSONEOF { "success": $success, "timestamp": "$timestamp", "message": "$message", "action": "$action", "config": { "n8n_url": "$n8n_internal", "owner_email": "$owner_email", "owner_first_name": "$owner_first_name", "owner_last_name": "$owner_last_name" }, "login_test": { "status": "$login_status", "message": "$login_message" }, "steps": [$steps_json] } JSONEOF } # Funktion: Fehler-Exit mit JSON exit_error() { local message="$1" local error="$2" output_json "false" "$message" "error" "not_tested" "$error" exit 1 } # Funktion: Login testen test_login() { local url="$1" local email="$2" local password="$3" # Login-Request durchführen local login_response login_response=$(curl -s -w "\n%{http_code}" --connect-timeout "$timeout" \ -X POST "${url}/rest/login" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d "{\"email\":\"${email}\",\"password\":\"${password}\"}" 2>/dev/null) local curl_exit=$? if [[ $curl_exit -ne 0 ]]; then echo "error|Verbindungsfehler beim Login-Test" return 1 fi local http_code=$(echo "$login_response" | tail -n1) local body=$(echo "$login_response" | sed '$d') if [[ "$http_code" == "200" ]]; then if echo "$body" | grep -q '"id"'; then echo "success|Login erfolgreich - Authentifizierung bestätigt" return 0 else echo "success|Login-Endpoint erreichbar (HTTP 200)" return 0 fi elif [[ "$http_code" == "401" ]]; then echo "failed|Authentifizierung fehlgeschlagen - Falsche Zugangsdaten" return 1 elif [[ "$http_code" == "400" ]]; then echo "failed|Ungueltige Anfrage" return 1 else echo "error|Unerwarteter Status: HTTP $http_code" return 1 fi } # Funktion: Port-Test test_port() { local host="$1" local port="$2" local timeout_sec="$3" # Versuche verschiedene Methoden if command -v nc &> /dev/null; then nc -z -w "$timeout_sec" "$host" "$port" 2>/dev/null return $? elif command -v timeout &> /dev/null; then timeout "$timeout_sec" bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null return $? else # Fallback: curl curl -s --connect-timeout "$timeout_sec" "http://$host:$port" &>/dev/null # Auch wenn curl fehlschlägt, war der Port erreichbar wenn kein Connection refused return 0 fi } # Hilfe anzeigen show_help() { cat << EOF Verwendung: $0 [OPTIONEN] n8n Owner Account Setup Script (JSON-Ausgabe) Optionen: --n8n_internal n8n URL (z.B. http://192.168.1.100:5678) --owner_email E-Mail-Adresse für den Owner-Account --owner_password Passwort für den Owner-Account (min. 8 Zeichen) --owner_first_name Vorname des Owners (Standard: Admin) --owner_last_name Nachname des Owners (Standard: User) --timeout Timeout für Requests (Standard: 10) -h, --help Diese Hilfe anzeigen EOF exit 0 } # ============================================ # Parameter parsen # ============================================ while [[ $# -gt 0 ]]; do case $1 in --n8n_internal) n8n_internal="$2" shift 2 ;; --owner_email) owner_email="$2" shift 2 ;; --owner_password) owner_password="$2" shift 2 ;; --owner_first_name) owner_first_name="$2" shift 2 ;; --owner_last_name) owner_last_name="$2" shift 2 ;; --timeout) timeout="$2" shift 2 ;; -h|--help) show_help ;; *) exit_error "Unbekannter Parameter" "$1" ;; esac done # ============================================ # Pflichtparameter prüfen # ============================================ if [[ -z "$n8n_internal" ]]; then exit_error "Parameter fehlt" "--n8n_internal ist erforderlich" fi if [[ -z "$owner_email" ]]; then exit_error "Parameter fehlt" "--owner_email ist erforderlich" fi if [[ -z "$owner_password" ]]; then exit_error "Parameter fehlt" "--owner_password ist erforderlich" fi if [[ ${#owner_password} -lt 8 ]]; then exit_error "Validierungsfehler" "Passwort muss mindestens 8 Zeichen lang sein" fi # URL normalisieren n8n_internal="${n8n_internal%/}" # ============================================ # Schritt 1: Server-Erreichbarkeit prüfen # ============================================ # Host und Port extrahieren host_port=$(echo "$n8n_internal" | sed -E 's|https?://||' | cut -d'/' -f1) host=$(echo "$host_port" | cut -d':' -f1) port=$(echo "$host_port" | grep -oE ':[0-9]+' | tr -d ':') if [[ -z "$port" ]]; then if [[ "$n8n_internal" == https://* ]]; then port=443 else port=80 fi fi # Ping-Test (optional, nicht kritisch) if ping -c 1 -W 2 "$host" &> /dev/null; then add_step "ping_test" "success" "Host $host antwortet auf Ping" else add_step "ping_test" "warning" "Host antwortet nicht auf Ping (ICMP blockiert)" fi # Port-Test if test_port "$host" "$port" "$timeout"; then add_step "port_test" "success" "Port $port ist offen" else add_step "port_test" "error" "Port $port ist nicht erreichbar" exit_error "Server nicht erreichbar" "Port $port ist nicht erreichbar auf $host" fi # HTTP-Health-Check http_status=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout "$timeout" "$n8n_internal/healthz" 2>/dev/null || echo "000") if [[ "$http_status" == "200" ]]; then add_step "health_check" "success" "n8n Health-Check erfolgreich (HTTP $http_status)" elif [[ "$http_status" == "000" ]]; then add_step "health_check" "error" "Keine HTTP-Verbindung moeglich" exit_error "Health-Check fehlgeschlagen" "Keine HTTP-Verbindung moeglich" else add_step "health_check" "warning" "Health-Endpoint antwortet mit HTTP $http_status" fi # ============================================ # Schritt 2: Setup-Status prüfen # ============================================ setup_check=$(curl -s --connect-timeout "$timeout" "$n8n_internal/rest/settings" 2>/dev/null || echo "") setup_already_done=false if echo "$setup_check" | grep -q '"showSetupOnFirstLoad":false'; then setup_already_done=true add_step "setup_check" "info" "Setup bereits abgeschlossen - Owner existiert" else add_step "setup_check" "success" "Setup ist verfuegbar" fi # ============================================ # Schritt 3: Owner erstellen ODER Login testen # ============================================ if [[ "$setup_already_done" == "false" ]]; then # Setup noch nicht durchgeführt -> Owner erstellen response=$(curl -s -w "\n%{http_code}" --connect-timeout "$timeout" \ -X POST "${n8n_internal}/rest/owner/setup" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d "{\"email\":\"${owner_email}\",\"password\":\"${owner_password}\",\"firstName\":\"${owner_first_name}\",\"lastName\":\"${owner_last_name}\"}" 2>/dev/null || echo -e "\n000") http_code=$(echo "$response" | tail -n1) body=$(echo "$response" | sed '$d') if [[ "$http_code" == "200" ]] || [[ "$http_code" == "201" ]]; then add_step "create_owner" "success" "Owner-Account erfolgreich erstellt" # Kurz warten sleep 2 # Login testen nach Erstellung login_result=$(test_login "$n8n_internal" "$owner_email" "$owner_password") login_status=$(echo "$login_result" | cut -d'|' -f1) login_message=$(echo "$login_result" | cut -d'|' -f2) if [[ "$login_status" == "success" ]]; then add_step "login_test" "success" "$login_message" output_json "true" "Owner-Account erfolgreich erstellt und Login verifiziert" "created" "$login_status" "$login_message" exit 0 else add_step "login_test" "warning" "$login_message" output_json "true" "Owner-Account erstellt, Login-Test fehlgeschlagen" "created" "$login_status" "$login_message" exit 0 fi else add_step "create_owner" "error" "Fehler beim Erstellen (HTTP $http_code)" exit_error "Account-Erstellung fehlgeschlagen" "HTTP Status: $http_code" fi else # Setup bereits abgeschlossen -> Login testen add_step "action" "info" "Teste Login mit vorhandenen Zugangsdaten" # Login-Seite prüfen main_page=$(curl -s -L --connect-timeout "$timeout" "$n8n_internal/" 2>/dev/null || echo "") if echo "$main_page" | grep -qi "sign.in\|login\|anmelden\|n8n"; then add_step "login_page" "success" "Login-Seite ist erreichbar" else add_step "login_page" "warning" "Login-Seite nicht eindeutig erkannt" fi # Login durchführen login_result=$(test_login "$n8n_internal" "$owner_email" "$owner_password") login_status=$(echo "$login_result" | cut -d'|' -f1) login_message=$(echo "$login_result" | cut -d'|' -f2) if [[ "$login_status" == "success" ]]; then add_step "login_test" "success" "$login_message" output_json "true" "n8n-Instanz ist eingerichtet und Login erfolgreich" "existing" "$login_status" "$login_message" exit 0 else add_step "login_test" "failed" "$login_message" output_json "true" "n8n-Instanz ist eingerichtet, Login fehlgeschlagen" "existing" "$login_status" "$login_message" exit 0 fi fi