diff --git a/CHANGELOG.md b/CHANGELOG.md index 59f6d32..abbaaa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,3 +47,4 @@ Alle Einträge verwenden ISO-8601-Timestamps in UTC. Mehrere Änderungen desselb - Browserinstaller korrigiert: Der initiale Administrator wird jetzt mit allen im `users`-Schema erforderlichen Pflichtfeldern angelegt. - Realm-Dashboard korrigiert: Es fragt nur noch die konfigurierte Portainer-Umgebung ab, benötigt keine globale Endpoint-Liste oder Endpoint-Metadaten mehr und verwendet direkt den Docker-Proxy. - Fehlgeschlagene, bereits bezahlte Provisionierungen können durch Administratoren erneut gestartet werden. +- Administratoren erhalten bei fehlgeschlagenen Instanzaktionen einen bereinigten technischen Diagnosehinweis. diff --git a/dashboard.php b/dashboard.php index 085bdd3..438053a 100644 --- a/dashboard.php +++ b/dashboard.php @@ -50,6 +50,12 @@ function dashboard_status(string $status): string { default => ucfirst($status), }; } +function dashboard_debug_detail(Throwable $exception): string { + $detail = trim($exception->getMessage()); + $detail = preg_replace('/(?:X-API-Key|Authorization|Bearer)\s*:\s*[^\s,;]+/i', '[credential redacted]', $detail) ?? $detail; + $detail = preg_replace('/("?(?:token|password|api[_-]?key|secret)"?\s*[:=]\s*)[^,;\s}]+/i', '$1[redacted]', $detail) ?? $detail; + return substr($detail !== '' ? $detail : 'Keine technische Fehlerbeschreibung vorhanden.', 0, 800); +} if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!pnpaas_valid_csrf((string)($_POST['csrf_token'] ?? ''))) { @@ -164,8 +170,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (in_array(($action ?? ''), ['approve_instance', 'instance_action'], true) && isset($instanceId)) { try { pnpaas_db()->prepare('UPDATE instances SET status = "error", error_message = :error WHERE id = :id')->execute(['error' => 'Die Bereitstellung oder Aktion konnte nicht abgeschlossen werden.', 'id' => $instanceId]); } catch (Throwable) {} } - error_log('PnPaaS instance action error: ' . $exception->getMessage()); + $debugDetail = dashboard_debug_detail($exception); + error_log('PnPaaS instance action error: ' . $debugDetail); $error = 'Die angeforderte Aktion konnte nicht ausgeführt werden. Bitte versuchen Sie es erneut.'; + if ($isAdmin) $error .= ' Technischer Hinweis: ' . $debugDetail; } } } diff --git a/includes/bootstrap.php b/includes/bootstrap.php index 919aa1d..4e77519 100644 --- a/includes/bootstrap.php +++ b/includes/bootstrap.php @@ -198,7 +198,10 @@ function pnpaas_portainer_request(string $path, string $method = 'GET', ?array $ throw new RuntimeException('Portainer ist nicht erreichbar.'); } if ($status < 200 || ($status >= 300 && $status !== 304)) { - throw new RuntimeException('Portainer hat die Anfrage abgelehnt.'); + $detail = trim(preg_replace('/\s+/', ' ', (string)$body) ?? ''); + $detail = preg_replace('/("?(?:token|password|api[_-]?key|secret)"?\s*:\s*)"[^"]*"/i', '$1"[redacted]"', $detail) ?? $detail; + $detail = substr($detail, 0, 600); + throw new RuntimeException('Portainer HTTP ' . $status . ($detail !== '' ? ': ' . $detail : '.')); } if ($body === '' || $body === null) { return [];