Add live TLS certificate probing and improve restart error handling.

Configure CertificateCheckUrl per container for curl-like TLS checks, classify Sonic permission errors, and extend setup wizard for container management.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 13:16:21 +02:00
co-authored by Cursor
parent d20e0df618
commit 58b7826162
1430 changed files with 358394 additions and 71 deletions
+91 -11
View File
@@ -1651,7 +1651,8 @@ namespace ZA.CoreService.ESBCertificateManager
private async Task ProbeTargetCertificatesAsync(
IReadOnlySet<int>? preferLoadedCertificateForTargetIds = null)
{
CertificateProbeService probe = new();
CertificateProbeService fileProbe = new();
TlsEndpointProbeService tlsProbe = new();
string? password = _loadedCertificatePassword;
Func<string?>? passwordPrompt = password is null
? null
@@ -1664,8 +1665,37 @@ namespace ZA.CoreService.ESBCertificateManager
continue;
}
// Bevorzugt Live-TLS-Probe (curl-ähnlich), wenn URL am Container gesetzt.
if (!string.IsNullOrWhiteSpace(target.TlsHost)
&& target.TlsPort is int tlsPort)
{
string checkUrl =
string.IsNullOrWhiteSpace(target.TlsServerName)
? $"{target.TlsHost}:{tlsPort}"
: $"https://{target.TlsServerName}:{tlsPort}";
CertificateProbeResult tlsResult = await Task.Run(
() => tlsProbe.Probe(checkUrl));
if (IsDisposed || !dgvTargets.Columns.Contains("Expiry"))
{
return;
}
if (tlsResult.Success && tlsResult.Certificate is not null)
{
row.Cells["Expiry"].Value =
"TLS · "
+ FormatCertificateExpiryCell(tlsResult.Certificate);
continue;
}
row.Cells["Expiry"].Value = "TLS · nicht erreichbar";
continue;
}
CertificateProbeResult result = await Task.Run(
() => probe.Probe(target.FullTargetPath, passwordPrompt));
() => fileProbe.Probe(target.FullTargetPath, passwordPrompt));
if (IsDisposed || !dgvTargets.Columns.Contains("Expiry"))
{
@@ -1697,6 +1727,13 @@ namespace ZA.CoreService.ESBCertificateManager
continue;
}
if (result.AccessDenied)
{
row.Cells["Expiry"].Value =
CertificateProbeResult.AccessDeniedShortText;
continue;
}
row.Cells["Expiry"].Value = result.Success
? "Datei fehlt"
: "nicht erreichbar";
@@ -1940,13 +1977,27 @@ namespace ZA.CoreService.ESBCertificateManager
runResult.TargetResults
.Where(result => !result.Success)
.Select(result =>
$"{result.TargetName}: {result.StatusText}"
$"{result.TargetName}"
+ Environment.NewLine
+ (result.Detail ?? string.Empty)));
+ SonicErrorClassifier.FormatRestartFailure(
result.StatusText,
result.Detail)));
bool permissionIssue =
SonicErrorClassifier.LooksLikeMissingPermission(details);
if (permissionIssue)
{
SetStatus(
"Neustart nicht möglich fehlende Benutzerrechte.",
isError: true);
}
CopyableErrorDialog.Show(
this,
"Neustart fehlgeschlagen (MfApi)",
permissionIssue
? "Keine Rechte für den Neustart"
: "Neustart fehlgeschlagen (MfApi)",
string.IsNullOrWhiteSpace(details)
? "Neustart fehlgeschlagen (keine Details)."
: details);
@@ -1958,11 +2009,26 @@ namespace ZA.CoreService.ESBCertificateManager
}
catch (Exception ex)
{
SetStatus($"Neustart fehlgeschlagen: {ex.Message}", isError: true);
string formatted =
SonicErrorClassifier.FormatRestartFailure(
"Neustart fehlgeschlagen",
ex.ToString());
bool permissionIssue =
SonicErrorClassifier.LooksLikeMissingPermission(formatted);
SetStatus(
permissionIssue
? "Neustart nicht möglich fehlende Benutzerrechte."
: $"Neustart fehlgeschlagen: {ex.Message}",
isError: true);
CopyableErrorDialog.Show(
this,
"Neustart fehlgeschlagen (MfApi)",
ex.ToString());
permissionIssue
? "Keine Rechte für den Neustart"
: "Neustart fehlgeschlagen (MfApi)",
formatted);
}
finally
{
@@ -2078,13 +2144,27 @@ namespace ZA.CoreService.ESBCertificateManager
runResult.TargetResults
.Where(result => !result.Success)
.Select(result =>
$"{result.TargetName}: {result.StatusText}"
$"{result.TargetName}"
+ Environment.NewLine
+ (result.Detail ?? string.Empty)));
+ SonicErrorClassifier.FormatRestartFailure(
result.StatusText,
result.Detail)));
bool permissionIssue =
SonicErrorClassifier.LooksLikeMissingPermission(details);
if (permissionIssue)
{
SetStatus(
"Austausch/Neustart nicht möglich fehlende Benutzerrechte.",
isError: true);
}
CopyableErrorDialog.Show(
this,
"Austausch fehlgeschlagen",
permissionIssue
? "Keine Rechte für den Neustart"
: "Austausch fehlgeschlagen",
details);
await ProbeTargetCertificatesAsync(exchangedTargetIds);