Improve certificate path probing with demo UNC target and remove Sonic container scan.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -900,7 +900,7 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
|
||||
Label hint = new Label
|
||||
{
|
||||
Text = "Unterstützte Formate: .cer, .crt, .pem, .pfx",
|
||||
Text = "Unterstützte Formate: .cer, .crt, .pem, .pfx, .p12",
|
||||
ForeColor = MutedTextColor,
|
||||
Font = new Font("Segoe UI", 8.5f),
|
||||
AutoSize = true,
|
||||
@@ -920,11 +920,11 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
{
|
||||
Title = "Zertifikatsdatei auswählen",
|
||||
Filter =
|
||||
"Unterstützte Zertifikatsdateien (*.cer;*.crt;*.pem;*.pfx)|*.cer;*.crt;*.pem;*.pfx|" +
|
||||
"Unterstützte Zertifikatsdateien (*.cer;*.crt;*.pem;*.pfx;*.p12)|*.cer;*.crt;*.pem;*.pfx;*.p12|" +
|
||||
"CER-Zertifikate (*.cer)|*.cer|" +
|
||||
"CRT-Zertifikate (*.crt)|*.crt|" +
|
||||
"PEM-Zertifikate (*.pem)|*.pem|" +
|
||||
"PFX-Zertifikate (*.pfx)|*.pfx",
|
||||
"PFX/P12-Zertifikate (*.pfx;*.p12)|*.pfx;*.p12",
|
||||
FilterIndex = 1,
|
||||
Multiselect = false,
|
||||
CheckFileExists = true,
|
||||
@@ -947,7 +947,7 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Bitte wähle eine Zertifikatsdatei in einem der folgenden Formate aus:\n" +
|
||||
".cer, .crt, .pem oder .pfx",
|
||||
".cer, .crt, .pem, .pfx oder .p12",
|
||||
"Nicht unterstütztes Dateiformat",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
@@ -971,15 +971,17 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
|
||||
private CertificateInfo? TryReadSelectedCertificate(string selectedPath)
|
||||
{
|
||||
bool isPfx = Path.GetExtension(selectedPath)
|
||||
.Equals(".pfx", StringComparison.OrdinalIgnoreCase);
|
||||
string extension = Path.GetExtension(selectedPath);
|
||||
bool needsPassword =
|
||||
extension.Equals(".pfx", StringComparison.OrdinalIgnoreCase)
|
||||
|| extension.Equals(".p12", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
try
|
||||
{
|
||||
// Zuerst ohne Passwort versuchen
|
||||
return ReadCertificate(selectedPath, null);
|
||||
}
|
||||
catch (CryptographicException) when (isPfx)
|
||||
catch (CryptographicException) when (needsPassword)
|
||||
{
|
||||
// Passwort nur abfragen, wenn das Laden ohne Passwort fehlgeschlagen ist
|
||||
string? pfxPassword = PromptForPfxPassword();
|
||||
@@ -1141,8 +1143,12 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
|
||||
string extension = Path.GetExtension(certificatePath);
|
||||
|
||||
using X509Certificate2 certificate =
|
||||
bool passwordProtected =
|
||||
extension.Equals(".pfx", StringComparison.OrdinalIgnoreCase)
|
||||
|| extension.Equals(".p12", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
using X509Certificate2 certificate =
|
||||
passwordProtected
|
||||
? new X509Certificate2(
|
||||
certificatePath,
|
||||
pfxPassword,
|
||||
@@ -1245,7 +1251,8 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
".cer",
|
||||
".crt",
|
||||
".pem",
|
||||
".pfx"
|
||||
".pfx",
|
||||
".p12"
|
||||
};
|
||||
|
||||
return supportedExtensions.Contains(
|
||||
@@ -1389,9 +1396,9 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
});
|
||||
|
||||
dgvTargets.Columns.Add("Target", "Ziel");
|
||||
dgvTargets.Columns.Add("Environment", "Umgebung");
|
||||
dgvTargets.Columns.Add("Container", "Container / Service");
|
||||
dgvTargets.Columns.Add("Tls", "TLS-Prüfung");
|
||||
dgvTargets.Columns.Add("Path", "Zertifikat-Pfad");
|
||||
dgvTargets.Columns.Add("Expiry", "Aktuelles Zertifikat");
|
||||
dgvTargets.Columns.Add("Container", "Neustart-Container");
|
||||
dgvTargets.Columns.Add("Status", "Status");
|
||||
|
||||
dgvTargets.CurrentCellDirtyStateChanged += (_, _) =>
|
||||
@@ -1527,10 +1534,12 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
"Bereitstellungsziele werden aus SQL geladen ...",
|
||||
isError: false);
|
||||
|
||||
_loadedTargets =
|
||||
IReadOnlyList<DeploymentTarget> fromSql =
|
||||
await _deploymentTargetRepository.GetActiveAsync(
|
||||
_settings.EnvironmentCode);
|
||||
|
||||
_loadedTargets = EnsureDemoTarget(fromSql);
|
||||
|
||||
BindTargetsToGrid(_loadedTargets);
|
||||
|
||||
if (_loadedTargets.Count == 0)
|
||||
@@ -1542,9 +1551,38 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
return;
|
||||
}
|
||||
|
||||
// Demo: erstes Ziel vorauswählen
|
||||
if (dgvTargets.Rows.Count > 0)
|
||||
{
|
||||
dgvTargets.Rows[0].Cells["Selected"].Value = true;
|
||||
}
|
||||
|
||||
SetStatus(
|
||||
$"{_loadedTargets.Count} Bereitstellungsziel(e) aus SQL geladen.",
|
||||
$"{_loadedTargets.Count} Bereitstellungsziel(e) geladen"
|
||||
+ (_settings.Demo.Enabled
|
||||
? $" · Demo: {Path.Combine(_settings.Demo.TargetDirectory, _settings.Demo.TargetFileName)}"
|
||||
: string.Empty),
|
||||
isError: false);
|
||||
|
||||
await ProbeTargetCertificatesAsync();
|
||||
}
|
||||
catch (Exception ex) when (_settings.Demo.Enabled)
|
||||
{
|
||||
// Demo trotzdem möglich, wenn SQL kurz nicht erreichbar ist
|
||||
_loadedTargets = EnsureDemoTarget([]);
|
||||
BindTargetsToGrid(_loadedTargets);
|
||||
|
||||
if (dgvTargets.Rows.Count > 0)
|
||||
{
|
||||
dgvTargets.Rows[0].Cells["Selected"].Value = true;
|
||||
}
|
||||
|
||||
SetStatus(
|
||||
$"SQL-Ziele nicht geladen ({ex.Message}). "
|
||||
+ "Demo-Pfad ist trotzdem verfügbar.",
|
||||
isError: true);
|
||||
|
||||
await ProbeTargetCertificatesAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -1565,23 +1603,118 @@ namespace ZA.CoreService.ESBCertificateManager
|
||||
|
||||
foreach (DeploymentTarget target in targets)
|
||||
{
|
||||
int tlsPort = target.TlsPort is > 0 ? target.TlsPort.Value : 443;
|
||||
string tls = string.IsNullOrWhiteSpace(target.TlsHost)
|
||||
? "—"
|
||||
: $"{target.TlsHost}:{tlsPort}";
|
||||
|
||||
int rowIndex = dgvTargets.Rows.Add(
|
||||
false,
|
||||
target.Name,
|
||||
target.Environment,
|
||||
target.ContainerName,
|
||||
tls,
|
||||
target.FullTargetPath,
|
||||
"wird geprüft …",
|
||||
string.IsNullOrWhiteSpace(target.ContainerName)
|
||||
? "—"
|
||||
: target.ContainerName,
|
||||
"Bereit");
|
||||
|
||||
dgvTargets.Rows[rowIndex].Tag = target;
|
||||
}
|
||||
}
|
||||
|
||||
private IReadOnlyList<DeploymentTarget> EnsureDemoTarget(
|
||||
IReadOnlyList<DeploymentTarget> fromSql)
|
||||
{
|
||||
if (!_settings.Demo.Enabled)
|
||||
{
|
||||
return fromSql;
|
||||
}
|
||||
|
||||
string directory = _settings.Demo.TargetDirectory.Trim();
|
||||
string fileName = _settings.Demo.TargetFileName.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(directory)
|
||||
|| string.IsNullOrWhiteSpace(fileName))
|
||||
{
|
||||
return fromSql;
|
||||
}
|
||||
|
||||
bool alreadyPresent = fromSql.Any(target =>
|
||||
string.Equals(
|
||||
target.TargetDirectory.TrimEnd('\\', '/'),
|
||||
directory.TrimEnd('\\', '/'),
|
||||
StringComparison.OrdinalIgnoreCase)
|
||||
&& string.Equals(
|
||||
target.CertificateFileName,
|
||||
fileName,
|
||||
StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (alreadyPresent)
|
||||
{
|
||||
return fromSql;
|
||||
}
|
||||
|
||||
List<DeploymentTarget> merged = [.. fromSql];
|
||||
|
||||
merged.Insert(
|
||||
0,
|
||||
new DeploymentTarget
|
||||
{
|
||||
Id = -1,
|
||||
Name = _settings.Demo.DisplayName,
|
||||
Environment = _settings.EnvironmentCode,
|
||||
IsActive = true,
|
||||
TargetDirectory = directory,
|
||||
CertificateFileName = fileName,
|
||||
BackupEnabled = true,
|
||||
BackupDirectoryName = "Backup",
|
||||
ContainerName = _settings.Demo.ContainerName,
|
||||
RestartType = RestartType.None,
|
||||
SonicConnectionName =
|
||||
_settings.Demo.SonicConnectionName,
|
||||
RestartTimeoutSeconds = 180
|
||||
});
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
private async Task ProbeTargetCertificatesAsync()
|
||||
{
|
||||
CertificateProbeService probe = new();
|
||||
|
||||
foreach (DataGridViewRow row in dgvTargets.Rows)
|
||||
{
|
||||
if (row.Tag is not DeploymentTarget target)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CertificateProbeResult result = await Task.Run(
|
||||
() => probe.Probe(target.FullTargetPath));
|
||||
|
||||
if (IsDisposed || !dgvTargets.Columns.Contains("Expiry"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.Success && result.Certificate is not null)
|
||||
{
|
||||
string expiry = result.Certificate.ValidUntil
|
||||
.ToLocalTime()
|
||||
.ToString("dd.MM.yyyy");
|
||||
|
||||
row.Cells["Expiry"].Value = result.Certificate.IsCurrentlyValid
|
||||
? $"gültig bis {expiry}"
|
||||
: $"abgelaufen {expiry}";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result.FileExists)
|
||||
{
|
||||
row.Cells["Expiry"].Value = "Datei da · Kennwort nötig";
|
||||
continue;
|
||||
}
|
||||
|
||||
row.Cells["Expiry"].Value = result.Success
|
||||
? "Datei fehlt"
|
||||
: "nicht erreichbar";
|
||||
}
|
||||
}
|
||||
|
||||
private List<DeploymentTarget> GetSelectedTargets()
|
||||
{
|
||||
List<DeploymentTarget> selected = [];
|
||||
|
||||
Reference in New Issue
Block a user