From ade63d0e43dfe27190f05dfdc84a5df76501e014 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 24 Jul 2026 12:20:26 +0200 Subject: [PATCH] Remove offline sample targets; load containers from appsettings KnownContainers. Co-authored-by: Cursor --- .../Data/ITargetRepository.cs | 9 - .../Data/JsonTargetRepository.cs | 46 -- .../Data/TargetRepositoryFactory.cs | 18 - .../Data/targets.sample.json | 22 - .../Docs/Komplette-Erklaerung.md | 530 ++++++++++++++++++ .../Docs/Neustart-und-Management-API.md | 371 ++++++++++++ ZA.CoreService.ESBCertificateManager/Form1.cs | 26 +- .../Models/AppSettings.cs | 8 +- .../Services/SonicContainerDiscovery.cs | 32 ++ ...A.CoreService.ESBCertificateManager.csproj | 6 +- .../appsettings.json | 19 +- 11 files changed, 956 insertions(+), 131 deletions(-) delete mode 100644 ZA.CoreService.ESBCertificateManager/Data/ITargetRepository.cs delete mode 100644 ZA.CoreService.ESBCertificateManager/Data/JsonTargetRepository.cs delete mode 100644 ZA.CoreService.ESBCertificateManager/Data/TargetRepositoryFactory.cs delete mode 100644 ZA.CoreService.ESBCertificateManager/Data/targets.sample.json create mode 100644 ZA.CoreService.ESBCertificateManager/Docs/Komplette-Erklaerung.md create mode 100644 ZA.CoreService.ESBCertificateManager/Docs/Neustart-und-Management-API.md diff --git a/ZA.CoreService.ESBCertificateManager/Data/ITargetRepository.cs b/ZA.CoreService.ESBCertificateManager/Data/ITargetRepository.cs deleted file mode 100644 index 3850ce9..0000000 --- a/ZA.CoreService.ESBCertificateManager/Data/ITargetRepository.cs +++ /dev/null @@ -1,9 +0,0 @@ -using ZA.CoreService.ESBCertificateManager.Models; - -namespace ZA.CoreService.ESBCertificateManager.Data; - -public interface ITargetRepository -{ - Task> GetActiveTargetsAsync(CancellationToken cancellationToken = default); - string SourceDescription { get; } -} diff --git a/ZA.CoreService.ESBCertificateManager/Data/JsonTargetRepository.cs b/ZA.CoreService.ESBCertificateManager/Data/JsonTargetRepository.cs deleted file mode 100644 index 763f19e..0000000 --- a/ZA.CoreService.ESBCertificateManager/Data/JsonTargetRepository.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using ZA.CoreService.ESBCertificateManager.Models; - -namespace ZA.CoreService.ESBCertificateManager.Data; - -public sealed class JsonTargetRepository : ITargetRepository -{ - private static readonly JsonSerializerOptions JsonOptions = new() - { - PropertyNameCaseInsensitive = true, - Converters = { new JsonStringEnumConverter() } - }; - - private readonly string _filePath; - - public JsonTargetRepository(string filePath) - { - _filePath = filePath; - } - - public string SourceDescription => $"Offline-Sample ({Path.GetFileName(_filePath)})"; - - public async Task> GetActiveTargetsAsync( - CancellationToken cancellationToken = default) - { - if (!File.Exists(_filePath)) - { - throw new FileNotFoundException( - $"Sample-Zieldatei wurde nicht gefunden: {_filePath}", - _filePath); - } - - await using FileStream stream = File.OpenRead(_filePath); - List? targets = await JsonSerializer.DeserializeAsync>( - stream, - JsonOptions, - cancellationToken); - - return (targets ?? []) - .Where(t => t.IsActive) - .OrderBy(t => t.SortOrder) - .ThenBy(t => t.Name) - .ToList(); - } -} diff --git a/ZA.CoreService.ESBCertificateManager/Data/TargetRepositoryFactory.cs b/ZA.CoreService.ESBCertificateManager/Data/TargetRepositoryFactory.cs deleted file mode 100644 index 607c6f1..0000000 --- a/ZA.CoreService.ESBCertificateManager/Data/TargetRepositoryFactory.cs +++ /dev/null @@ -1,18 +0,0 @@ -using ZA.CoreService.ESBCertificateManager.Models; - -namespace ZA.CoreService.ESBCertificateManager.Data; - -public static class TargetRepositoryFactory -{ - public static async Task<(ITargetRepository Repository, string LoadMessage)> CreateAsync( - AppSettings settings, - CancellationToken cancellationToken = default) - { - string samplePath = Path.GetFullPath( - Path.Combine(AppContext.BaseDirectory, settings.SampleTargetsPath)); - - ITargetRepository jsonRepo = new JsonTargetRepository(samplePath); - _ = await jsonRepo.GetActiveTargetsAsync(cancellationToken); - return (jsonRepo, $"Ziele geladen aus {jsonRepo.SourceDescription}."); - } -} diff --git a/ZA.CoreService.ESBCertificateManager/Data/targets.sample.json b/ZA.CoreService.ESBCertificateManager/Data/targets.sample.json deleted file mode 100644 index 14f657e..0000000 --- a/ZA.CoreService.ESBCertificateManager/Data/targets.sample.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "Id": 1, - "Name": "DE-Test / ct-ZADBService", - "Environment": "TEST", - "IsActive": true, - "TargetDirectory": "", - "CertificateFileName": "", - "ContainerName": "ct-ZADBService", - "RestartType": "SonicContainer", - "RestartCommand": "", - "RestartArguments": "", - "RestartTimeoutSeconds": 120, - "SonicConnectionName": "DE-Test", - "XapiSourcePath": "", - "TlsHost": "", - "TlsPort": null, - "TlsServerName": "", - "ExpectedFingerprint": null, - "SortOrder": 10 - } -] diff --git a/ZA.CoreService.ESBCertificateManager/Docs/Komplette-Erklaerung.md b/ZA.CoreService.ESBCertificateManager/Docs/Komplette-Erklaerung.md new file mode 100644 index 0000000..3ce607e --- /dev/null +++ b/ZA.CoreService.ESBCertificateManager/Docs/Komplette-Erklaerung.md @@ -0,0 +1,530 @@ +# Komplette Erklärung: ESB Certificate Manager + +Was passiert – **einzeln, von oben nach unten**. +Zertifikat prüfen · Ziele laden · Sonic-API · Container-Neustart. + +Diese Datei ist zum Erklären (Präsentation, Kollegen, Übergabe). +Technischer Fokus: aktueller Stand mit **MfApi-Neustart** und **lokaler Zertifikatserkennung**. + +--- + +# Teil A – Was die Anwendung ist + +## A1. Zweck in einem Satz + +Die WinForms-App hilft dabei, + +1. ein **Zertifikat als Datei zu erkennen und lokal zu prüfen**, und +2. einen **Sonic-/ESB-Container remote neu zu starten** – so ähnlich wie der Restart-Button in der **Sonic Management Console (SMC)**. + +## A2. Was sie bewusst *nicht* macht (aktuell) + +| Nicht aktiv | Erklärung | +|-------------|-----------| +| Zertifikat auf den Server **kopieren** | Deploy-Button ist ausgeblendet | +| Nach dem Deploy **TLS gegen den Endpoint prüfen** | früher TLS-Probe – entfernt/deaktiviert | +| **XApi** importieren | nicht mehr im Pfad | +| Neustart per **`stopcontainer.bat`** | oft in SMC-only-Installationen nicht vorhanden | +| Neustart per **WinRM / Windows-Login** | SMC-User ≠ Windows-User | +| Eigene **HTTP-REST-API** der App | die App *ist* kein Server; sie *ruft* Sonic auf | + +## A3. Die wichtigsten Namen in eurer Umgebung + +| Name | Typ | Beispiel | +|------|-----|----------| +| Verbindungs-Alias | Eintrag in `appsettings` | `DE-Test` | +| Domain | Sonic-Domain | `proalpha-test` | +| Container (kurz) | Laufzeit-Container | `ct-ZADBService` | +| ObjectName (JMX) | vollständige Agent-Adresse | `proalpha-test.ct-ZADBService:ID=AGENT` | +| ConnectionUrl | Domain-Manager wie in SMC | `tcp://dekun-painwbdet:13070` | +| Login | SMC-Credentials | `Administrator` / `Administrator` | +| Sonic-Libs | Client-JARs | `C:\DEV\MQ10.0\lib` | +| Java | Runtime für das Hilfstool | JRE 1.8+ | + +**Merksatz:** +`DE-Test` = Verbindung. `ct-ZADBService` = Container. Nicht vertauschen. + +--- + +# Teil B – Programmstart (was zuerst passiert) + +## B1. Start der App + +1. `Program.cs` startet `Form1`. +2. `AppSettingsLoader` liest `appsettings.json` (aus dem Output-Ordner der App). +3. Es werden gebaut: + - `DeploymentOrchestrator` (Neustart-Orchestrierung) + - `SonicContainerDiscovery` (Container-Liste optional laden) +4. Die UI (Dark-Design) wird aufgebaut. +5. Beim ersten Anzeigen (`Shown`) werden Ziele geladen. + +## B2. Ziele laden + +1. Ziele kommen aus `appsettings.json` → `SonicConnections[].KnownContainers` (kein Offline-JSON). +2. Jede Zeile hat u. a.: + - Anzeigename (`DE-Test / ct-ZADBService`) + - Umgebung = Domain + - **ContainerName** (z. B. `ct-ZADBService`) + - **SonicConnectionName** (z. B. `DE-Test`) + - Status-Spalte + +Optional: Button **„Container laden“** fragt Sonic live per API und merged mit `KnownContainers`. + +--- + +# Teil C – Zertifikat: Erkennen & Verifizieren (Schritt für Schritt) + +Hier geht es **nur um die lokale Datei**. Es wird nichts auf den ESB geschrieben und kein TLS zum Server aufgebaut. + +## C1. Benutzer wählt Datei + +1. Klick auf Dateiauswahl in der UI. +2. `OpenFileDialog` filtert: `.cer`, `.crt`, `.pem`, `.pfx`. +3. Abbruch → nichts ändert sich. +4. Dateiendung wird geprüft (`IsSupportedCertificateFile`). +5. Unbekanntes Format → Warnung, Ende. + +## C2. Datei lesen + +1. Aufruf `TryReadSelectedCertificate(pfad)`. +2. Intern: `X509Certificate2` laden. +3. **PFX-Sonderfall:** + - Zuerst Versuch *ohne* Passwort. + - Bei `CryptographicException` → Passwort-Dialog. + - Falsches Passwort → Fehlermeldung, kein Zertifikat geladen. +4. Andere Fehler (Datei kaputt, kein X.509) → Fehlermeldung. + +## C3. Was aus dem Zertifikat extrahiert wird + +| Feld | Quelle | Anzeige | +|------|--------|---------| +| Subject | `GetNameInfo(SimpleName)` bzw. `Subject` | „Ausgestellt für“ | +| Issuer | Issuer-SimpleName bzw. `Issuer` | „Ausgestellt von“ | +| Gültig von / bis | `NotBefore` / `NotAfter` | Datum | +| Fingerprint | SHA-256 Hash, mit `:` formatiert | z. B. `AB:CD:…` | +| Gültigkeitsstatus | `now` zwischen NotBefore und NotAfter? | grün GÜLTIG / rot UNGÜLTIG | + +## C4. Was „Verifizierung“ hier genau heißt + +| Prüfung | Passiert? | Bedeutung | +|---------|-----------|-----------| +| Datei lesbar als X.509 | ja | Format/Inhalt ok | +| Zeitlich gültig | ja | nicht abgelaufen / noch nicht gültig | +| Fingerprint anzeigen | ja | manueller Abgleich möglich | +| Signaturkette gegen Windows-CA | **nein** | nicht implementiert | +| Datei auf ESB kopieren | **nein** | Deploy aus | +| TLS-Handshake zum Live-System + Fingerprint vergleichen | **nein** | TLS-Probe aus | + +**Erklärsatz:** +> Wir verifizieren das Zertifikat **als Datei auf dem PC** (lesbar + Gültigkeitszeitraum + Fingerprint). +> Wir verifizieren **nicht**, dass genau dieses Zertifikat schon am laufenden ESB hängt. +> Der Neustart ist davon getrennt. + +## C5. UI nach erfolgreichem Laden + +1. Pfad steht im Textfeld. +2. Metadaten-Karte wird gefüllt. +3. Statuszeile: „Zertifikat ausgewählt: …“. +4. Sidebar-Schritt kann auf „Ziele“ springen. +5. Neustart braucht das Zertifikat **nicht zwingend** – der Neustart hängt am Container, nicht an der Datei. + +--- + +# Teil D – Vor dem Neustart (Preflight) + +## D1. Benutzer hakt Ziel(e) an + +Im Grid: Checkbox „Selected“ setzen. + +## D2. Button „ESB neu starten“ + +1. `GetSelectedTargets()` sammelt alle angehakten Zeilen. +2. `ValidateRestartOnly` prüft für jedes Ziel: + - `ContainerName` nicht leer + - `SonicConnectionName` nicht leer +3. Fehler → Dialog „Neustart blockiert“ mit Liste der Probleme. +4. OK → Bestätigungsdialog (Containername, Hinweis auf Management API). +5. Nein → Abbruch. Ja → Neustart startet. + +--- + +# Teil E – Neustart Gesamtablauf (C#-Seite) + +Alles von hier läuft **ohne** Zertifikatskopieren. + +```text +Form1.RunRestartOnlyAsync + → DeploymentOrchestrator.RestartOnlyAsync + → für jedes Ziel: + RestartExecutor.ExecuteAsync + → SonicManagementClient.RestartContainerAsync + → SonicMfApiExecutor.RestartAsync + → java SonicMfContainerTool restart … +``` + +## E1. Orchestrator + +Pro Ziel: + +1. Status im Grid: „Neustart…“ +2. `RestartExecutor.ExecuteAsync(target)` +3. Ergebnis + Detail in Logdatei unter `Logs\` +4. Status im Grid aktualisieren +5. Am Ende: Erfolgs-/Fehlerdialog mit Tool-Ausgabe + +## E2. RestartExecutor + +1. Liest `target.ContainerName` (z. B. `ct-ZADBService`). +2. Sucht in `appsettings` die `SonicConnection` mit `Name == SonicConnectionName` (`DE-Test`). +3. Fehlt die Verbindung → Fehler „Sonic-Verbindung nicht gefunden“. +4. Sonst: `new SonicManagementClient(connection)` und `RestartContainerAsync(containerName)`. + +## E3. SonicManagementClient + +Schlanke Fassade, nur MfApi: + +1. Ruft `_mfApi.RestartAsync(containerName)` auf. +2. Bei Erfolg: wartet `PostRestartDelaySeconds` (z. B. 20 s), damit der Container Zeit zum Hochfahren hat. +3. Liefert Status-Text + komplette Java-Ausgabe zurück. +4. Bei Fehler: Fehlermeldung + Output für den Dialog. + +--- + +# Teil F – SonicMfApiExecutor: Java vorbereiten und starten + +Das ist die Brücke von .NET zu Sonic. + +## F1. Java finden + +Reihenfolge grob: + +1. `JavaPath` aus appsettings (bevorzugt) +2. `JavaHome` +3. Umgebungsvariablen / PATH / Registry / unter SonicHome + +Bedingung: Runtime muss **Java 8+** können (Class-File major ≥ 52). +Zu alte Sonic-JREs (6/7) werden übersprungen. + +## F2. Classpath bauen (Sonic-JARs) + +1. `MfClientLibPath` (z. B. `C:\DEV\MQ10.0\lib`) oder Suche unter `SonicHome`. +2. Es müssen echte Client-JARs da sein, u. a.: + - `mgmt_client.jar` + - `mfcontext.jar` + - `sonic_Client.jar` +3. **Alle** `*.jar` im Lib-Ordner werden explizit in den Classpath geschrieben (kein fragiles `lib\*` mit kaputten Quotes). +4. Das Tool-Verzeichnis `Tools\` kommt **vorne** in den Classpath, damit die richtige `SonicMfContainerTool.class` geladen wird. + +## F3. Java-Tool laden + +1. Bevorzugt vorcompilierte `Tools\SonicMfContainerTool.class` (Java 8, major 52). +2. Alte/zu kleine Class-Dateien werden verworfen. +3. Temp-Cache alter Compilate wird gelöscht. +4. Falls nötig: aus `.java` mit `javac --release 8` neu bauen. + +## F4. Prozess starten + +Ungefähr: + +```text +"C:\...\java.exe" + -cp "C:\...\Tools;C:\DEV\MQ10.0\lib\mgmt_client.jar;...;C:\DEV\MQ10.0\lib\mfcontext.jar;..." + SonicMfContainerTool + restart + --domain proalpha-test + --url tcp://dekun-painwbdet:13070 + --user Administrator + --container ct-ZADBService + --timeout 120 +``` + +Wichtig: + +- Argumente über `ProcessStartInfo.ArgumentList` (keine doppelten Anführungszeichen). +- Passwort über Umgebung `ESB_SONIC_PASSWORD`, nicht in der sichtbaren Kommandozeile. +- stdout/stderr werden gelesen und an die UI zurückgegeben. + +## F5. Erfolgsauswertung in C# + +Neustart gilt nur als Erfolg, wenn die Ausgabe enthält: + +```text +OK:RestartInvoked +``` + +Sonst: Fehlerdialog mit kompletter Tool-Ausgabe. + +--- + +# Teil G – Die Sonic Management Application API (Java-Tool) + +Hier passiert der eigentliche „API-Call“ – **nicht REST**, sondern **JMS/JMX Management Framework**. + +Offizielle Produktwelt (Aurea CX Messenger / Sonic): + +- Index: `doc-10.0.10/CXMessenger_2017_R3.htm` +- Eintrag: **Management Application API Reference** (`Docs2017/api/mgmt_api/`) + +Das ist dieselbe API-Familie, die die SMC für Restart nutzt. + +## G1. Warum „API“ hier kompliziert klingt + +Die Sonic-Produkt-API enthält **sehr viele** Bereiche: + +- Broker / Queues / Topics +- ESB-Services +- Metrics / Notifications +- Directory / Config +- Agent Lifecycle + +**Für unseren Neustart brauchen wir nur einen schmalen Teil:** + +1. Verbinden zum Domain Manager +2. Agent-ObjectName ansprechen +3. Lifecycle: stop/restart + +Der Rest der JARs ist Produktumfang – nicht „unsere App-API mit 100 Features“. + +## G2. Schritt 1 – Tool startet + +Ausgabe: + +```text +INFO:ToolVersion=2026-07-24c-mbean-stop +``` + +Wenn diese Zeile fehlt → oft noch eine **alte** `.class` im Einsatz. + +## G3. Schritt 2 – Argumente parsen + +Pflicht: + +- Befehl: `ping` | `list` | `restart` +- `--domain` +- `--url` +- `--user` +- bei `restart`: `--container` +- Passwort: `--password` oder `ESB_SONIC_PASSWORD` + +## G4. Schritt 3 – Connect (der eigentliche API-Login) + +Java (vereinfacht, per Reflection): + +```text +Hashtable env: + ConnectionURLs = tcp://dekun-painwbdet:13070 + DefaultUser = Administrator + DefaultPassword = *** + +JMSConnectorAddress address = new JMSConnectorAddress(env) +JMSConnectorClient connector = new JMSConnectorClient() +connector.connect(address, timeout) +``` + +Klassen kommen aus den Sonic-JARs: + +- `com.sonicsw.mf.jmx.client.JMSConnectorAddress` +- `com.sonicsw.mf.jmx.client.JMSConnectorClient` + +Ausgabe bei Erfolg: + +```text +INFO:Connected url=tcp://dekun-painwbdet:13070 user=Administrator +``` + +Das entspricht dem SMC-Login gegen denselben Domain Manager. + +## G5. Schritt 4 – Ziel-Agent bestimmen + +ObjectName: + +```text +proalpha-test.ct-ZADBService:ID=AGENT +``` + +Muster: + +```text +{DomainName}.{ContainerName}:ID=AGENT +``` + +Optional: per `queryNames` nach vorhandenen Agenten suchen; wenn das scheitert, Preferred-Name verwenden. + +## G6. Schritt 5 – Lifecycle (Neustart) – drei Wege nacheinander + +### Weg 1 – MBean invoke (bevorzugt remote) + +```text +connector.invoke(objectName, "stop", [], []) +// oder "restart", "shutdown" +``` + +Warum zuerst `stop`? + +- Remote-Clients sind oft **„unbounded“**. +- `IAgentProxy.restart()` wirft dann häufig: + `Operation unsupported for unbounded client connector` +- SMC-Restart wirkt für den Operator oft wie: **Stop + automatischer Relaunch** durch Launch Daemon / Host Manager. + +Erfolg: + +```text +OK:RestartInvoked method=MBean.stop container=ct-ZADBService domain=proalpha-test +``` + +### Weg 2 – Typisierter Proxy + +```text +IAgentProxy agent = MFProxyFactory.createAgentProxy(connector, objectName) +agent.stop() / agent.restart() / agent.shutdown() +``` + +Schön dokumentiert, remote oft eingeschränkt (unbounded). + +### Weg 3 – DomainManager / Manager-MBeans + +Suche nach Operationen wie: + +- `restartContainer(containerName)` +- `stopContainer(containerName)` + +Fallback, falls Agent-direkt nicht klappt. + +## G7. Schritt 6 – Disconnect + +`connector.disconnect()` im `finally`. + +## G8. Befehle des Tools im Überblick + +| Befehl | Zweck | +|--------|--------| +| `ping` | Verbindungstest + Agenten zählen | +| `list` | Containernamen der Domain ausgeben | +| `restart` | Lifecycle auf einem Container | + +--- + +# Teil H – Komplette Kette als nummerierte Liste + +So kannst du es jemandem erzählen: + +### Zertifikat + +1. App starten +2. Zertifikatsdatei wählen +3. Datei als X.509 lesen (PFX ggf. mit Passwort) +4. Subject, Issuer, Fingerprint, Gültigkeit anzeigen +5. Lokal „verifiziert“ = lesbar + im Gültigkeitszeitraum + +### Neustart + +6. Ziel im Grid anhaken (`ct-ZADBService` / Verbindung `DE-Test`) +7. „ESB neu starten“ → Preflight → Bestätigung +8. C# findet Sonic-Verbindung in appsettings +9. C# findet Java 8+ und baut Classpath aus `C:\DEV\MQ10.0\lib` +10. C# startet `SonicMfContainerTool restart …` +11. Java verbindet per Management API an `tcp://…:13070` +12. Java adressiert `proalpha-test.ct-ZADBService:ID=AGENT` +13. Java ruft Stop/Restart per MBean (Fallback Proxy/Manager) +14. Java schreibt `OK:RestartInvoked` +15. C# wartet `PostRestartDelaySeconds` +16. UI zeigt Erfolg/Fehler + Logausgabe +17. Optional in SMC prüfen: Uptime/Status des Containers + +--- + +# Teil I – Konfiguration im Detail + +## I1. `appsettings.json` (Sonic-Block) + +| Feld | Rolle | +|------|--------| +| `Name` | Alias, von Zielen referenziert (`DE-Test`) | +| `DomainName` | Sonic-Domain | +| `ConnectionUrl` | Domain-Manager-URL (wie SMC) | +| `Username` / `Password` | SMC-Login | +| `SonicHome` | Installationsroot | +| `MfClientLibPath` | Ordner mit Client-JARs | +| `JavaPath` / `JavaHome` | Java 8+ | +| `KnownContainers` | Fallback-Liste, z. B. `ct-ZADBService` | +| `TimeoutSeconds` | Timeout Java/API | +| `PostRestartDelaySeconds` | Wartezeit nach erfolgreichem Invoke | + +Felder wie `WinRm*`, `Container*Path`, `ManagementHttpPort` können noch in der JSON stehen, werden vom schlanken MfApi-Client **nicht mehr genutzt**. + +## I2. Container-Liste + +Kein separates Sample-JSON. Container stehen in: + +```json +"KnownContainers": [ "ct-ZADBService" ] +``` + +Live-Erweiterung über UI-Button „Container laden“. + +--- + +# Teil J – Dateien und Verantwortlichkeiten + +| Datei | Verantwortung | +|-------|----------------| +| `Form1.cs` | UI, Zertifikat lesen, Neustart-Button, Dialoge | +| `DeploymentOrchestrator.cs` | Neustart über alle gewählten Ziele | +| `PreflightValidator.cs` | Pflichtfelder prüfen | +| `RestartExecutor.cs` | Ziel → SonicConnection | +| `SonicManagementClient.cs` | Fassade MfApi | +| `SonicMfApiExecutor.cs` | Java/Classpath/Prozess | +| `Tools/SonicMfContainerTool.java` | Connect + Lifecycle über Sonic-API | +| `appsettings.json` | Laufzeitkonfiguration inkl. KnownContainers | +| `Logs\` | Laufprotokolle | + +--- + +# Teil K – Erfolgs- und Fehlerbilder + +## K1. Gesunde Ausgabe (Auszug) + +```text +INFO:ToolVersion=2026-07-24c-mbean-stop +INFO:Connected url=tcp://dekun-painwbdet:13070 user=Administrator +INFO:PreferredObjectName=proalpha-test.ct-ZADBService:ID=AGENT +INFO:Trying MBean.invoke(stop) on … +OK:RestartInvoked method=MBean.stop container=ct-ZADBService domain=proalpha-test +``` + +## K2. Häufige Fehler + +| Meldung | Bedeutung | Typische Lösung | +|---------|-----------|-----------------| +| `ClassNotFoundException: JMSConnectorAddress` | JARs fehlen / Classpath kaputt | `MfClientLibPath`, neuer Build | +| `UnsupportedClassVersionError` | Java-Version mismatch | Tool als Java 8 + Runtime Java 8+ | +| `Operation unsupported for unbounded…` | Proxy-Restart remote gesperrt | MBean-stop-Pfad / aktuelles Tool | +| Kein `ToolVersion=` | Alte Class-Datei | Neu bauen, richtigen bin-Ordner starten | +| Container `DE-Test` | Alias statt Kurzname | `ct-ZADBService` | +| `stopcontainer.bat` fehlt | SMC-only | normal – MfApi nutzen | + +--- + +# Teil L – Wie man es jemandem erklärt (Kurzskript) + +1. **UI:** Zertifikat laden → wir sehen Subject/Fingerprint/Gültigkeit. Das ist lokale Dateiprüfung. +2. **Neustart:** Wir starten denselben Management-Weg wie die SMC, nicht per Batch-Datei und nicht per FTP. +3. **Technik:** C# orchestriert; ein kleines Java-Tool + Sonic-Client-JARs sprechen mit dem Domain Manager. +4. **API:** Sonic Management Application API (JMS/JMX). Sehr große Produkt-API, wir nutzen nur Connect + Agent-Stop/Restart. +5. **Haken:** Remote heißt „unbounded“ – deshalb oft `stop` per MBean statt `IAgentProxy.restart()`. +6. **Ergebnis:** Container `ct-ZADBService` in Domain `proalpha-test` wird neu gestartet; danach in der SMC Status/Uptime prüfen. + +--- + +# Teil M – Abgrenzung: Was ist „unsere API“ vs. Sonic-API? + +| Ebene | Beschreibung | +|-------|--------------| +| **Unsere App** | WinForms + C#-Services. Kein öffentlicher REST-Endpoint. | +| **Unser Java-Tool** | Dünner Adapter (`ping`/`list`/`restart`) mit Fallbacks. | +| **Sonic Management Application API** | Produkt-API in den JARs; offiziell dokumentiert; SMC nutzt dieselbe Familie. | +| **Unnötig für den Use-Case** | MQ Messaging API, ESB API, Metrics, XApi, WinRM, Bat-Scripts, TLS-Probe – solange nur „Datei prüfen + Neustart“ gefragt ist. | + +--- + +*Ende der kompletten Erklärung. Bei Abweichungen gilt der Code im Projekt (Branch mit MfApi-Neustart).* diff --git a/ZA.CoreService.ESBCertificateManager/Docs/Neustart-und-Management-API.md b/ZA.CoreService.ESBCertificateManager/Docs/Neustart-und-Management-API.md new file mode 100644 index 0000000..a11f488 --- /dev/null +++ b/ZA.CoreService.ESBCertificateManager/Docs/Neustart-und-Management-API.md @@ -0,0 +1,371 @@ +# ESB Certificate Manager – Neustart, Management-API & Zertifikatsprüfung + +Ausführliche Erklärung für Präsentation, Übergabe und Troubleshooting. +Stand: Branch `fix/mfapi-classpath-ct-zadbservice` (MfApi-Neustart, Zertifikat erkennen). + +--- + +## 1. Was die App heute macht (und was nicht) + +### Aktiv + +| Funktion | Kurzbeschreibung | +|----------|------------------| +| **Zertifikat erkennen** | Datei wählen (`.cer` / `.crt` / `.pem` / `.pfx`), Metadaten anzeigen, Gültigkeit prüfen | +| **Container laden** | Optional: Liste aus Sonic Domain Manager + Fallback `KnownContainers` | +| **ESB neu starten** | Container-Neustart über Sonic **Management Application API** (wie Restart in der SMC) | + +### Bewusst nicht (mehr) aktiv + +| Entfernt / deaktiviert | Warum | +|------------------------|--------| +| Zertifikat auf Zielpfad **kopieren** (Deploy) | UI-Button ausgeblendet; war eigener Deploy-Pfad | +| **TLS-Probe** nach Deploy | Fingerprint gegen laufenden Endpoint – nicht Teil des aktuellen Scope | +| **XApi-Import** | Extra-Skript/WinRM-Pfad, oft nicht vorhanden | +| **WinRM** / `stopcontainer.bat` | SMC-only-Installationen haben die Server-Scripts oft nicht; Logins ≠ Windows | +| **HTTP-REST** Management | Kein stabiler Endpoint in dieser Umgebung nachweisbar | +| **SQL- / Offline-Sample-Ziele** | Container kommen aus `KnownContainers` / Live-Discovery | + +Kurz: **Datei prüfen + Neustart**. Alles andere war Ballast für den aktuellen Use-Case. + +--- + +## 2. Begriffe (wichtig für die Erklärung) + +| Begriff | Bedeutung in diesem Projekt | +|---------|-----------------------------| +| **SMC** | Sonic Management Console – die GUI, mit der Operatoren Container starten/stoppen/neustarten | +| **Domain** | Logische Sonic-Domain, hier: `proalpha-test` | +| **Container** | Laufzeit-Container / Agent, hier: `ct-ZADBService` | +| **Verbindungs-Alias** | Name in `appsettings` (`DE-Test`) – **nicht** der Containername | +| **ObjectName** | JMX-Name: `proalpha-test.ct-ZADBService:ID=AGENT` | +| **Domain Manager / Broker-URL** | `tcp://dekun-painwbdet:13070` – dieselbe URL wie beim SMC-Login | +| **MfApi** | Unser Modusname für „Management Application API“ über Java-Client-JARs | +| **unbounded client connector** | Remote-JMS-Client (wie die SMC von außen). Manche Proxy-Methoden (z. B. `IAgentProxy.restart()`) sind dafür gesperrt | +| **Launch Daemon** | Prozess auf dem Host, der einen gestoppten Container oft automatisch wieder startet (SMC „Restart“ ≈ Stop + Auto-Relaunch) | + +**Merksatz für Präsentationen:** +> `DE-Test` ist die Verbindung. `ct-ZADBService` ist der Container. Die Domain heißt `proalpha-test`. + +--- + +## 3. Architektur – Überblick + +```text +┌─────────────────────────────────────────────────────────────┐ +│ WinForms UI (Form1) │ +│ - Zertifikat wählen / anzeigen │ +│ - Ziele anhaken │ +│ - Button „ESB neu starten“ │ +└───────────────────────────┬─────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ DeploymentOrchestrator.RestartOnlyAsync │ +│ → PreflightValidator (ContainerName + SonicConnection) │ +│ → RestartExecutor │ +└───────────────────────────┬─────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ SonicManagementClient (dünne Fassade, nur MfApi) │ +│ → SonicMfApiExecutor │ +└───────────────────────────┬─────────────────────────────────┘ + │ startet Prozess + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ java.exe (Java 8+) │ +│ Classpath: Tools\ + C:\DEV\MQ10.0\lib\*.jar │ +│ Klasse: SonicMfContainerTool │ +│ Befehl: restart --domain … --url … --user … --container …│ +└───────────────────────────┬─────────────────────────────────┘ + │ JMS / JMX (Management Framework) + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Sonic Domain Manager │ +│ tcp://dekun-painwbdet:13070 │ +│ Agent: proalpha-test.ct-ZADBService:ID=AGENT │ +└─────────────────────────────────────────────────────────────┘ +``` + +Es gibt **keine eigene REST-API der WinForms-App**. +Die „API“ ist die **Sonic Management Application API** (Java, JARs unter `MQ10.0\lib`), dieselbe Schicht, die auch die SMC nutzt. + +Offizielle Doku-Verweise (Index im Repo): + +- `doc-10.0.10/CXMessenger_2017_R3.htm` → **Management Application API Reference** (`Docs2017/api/mgmt_api/`) +- Bücher: MQ/ESB Configuration and Management Guide + +(Die PDF-/HTML-API-Ordner können im Checkout fehlen – der Index verlinkt sie trotzdem.) + +--- + +## 4. Zertifikat – Erkennen & „Verifizieren“ + +### 4.1 Was wir heute tun + +Die App **liest und prüft die Zertifikatsdatei lokal**. Sie spielt das Zertifikat **nicht** auf den ESB und prüft **nicht** per TLS-Handshake gegen einen Server (dieser Pfad ist deaktiviert). + +Ablauf in der UI (`Form1`): + +1. Benutzer wählt Datei (`.cer`, `.crt`, `.pem`, `.pfx`). +2. Datei wird mit `X509Certificate2` geladen. +3. Bei `.pfx` ggf. Passwort-Dialog. +4. Anzeige: + - Subject + - Issuer + - Gültig bis + - SHA-256-Fingerprint (formatiert mit `:`) + - Status **GÜLTIG** / **UNGÜLTIG / ABGELAUFEN** (Vergleich mit `DateTimeOffset.Now` und `NotBefore`/`NotAfter`) + +Das ist **Dateiverifikation / Metadaten-Check**, kein Deploy und kein Remote-TLS-Verify. + +### 4.2 Was „Zertifikat verifizieren“ bedeuten kann (für die Erklärung) + +| Stufe | Bedeutung | Status in dieser App | +|-------|-----------|----------------------| +| **A. Datei lesen** | Datei ist ein gültiges X.509, Parsing ok | ✅ aktiv | +| **B. Zeitliche Gültigkeit** | `now` zwischen NotBefore und NotAfter | ✅ aktiv | +| **C. Fingerprint anzeigen** | SHA-256 zum manuellen Abgleich | ✅ aktiv | +| **D. Auf Ziel kopieren** | Datei nach `TargetDirectory` legen | ❌ deaktiviert | +| **E. TLS-Probe** | TCP/TLS zum Host:Port, Remote-Zertifikat lesen, Fingerprint vergleichen | ❌ entfernt / nicht aktiv | +| **F. Trust-Chain / CA** | Kette gegen Windows-Truststore prüfen | ❌ nicht implementiert | + +Wenn jemand fragt „Wird das Zertifikat verifiziert?“: + +> Wir verifizieren die **Datei lokal** (lesbar, Gültigkeitszeitraum, Fingerprint). +> Ein Abgleich gegen den **laufenden ESB-Endpoint per TLS** ist aktuell nicht Teil der App. +> Der Neustart betrifft den **Container**, nicht automatisch die Zertifikatsinstallation. + +### 4.3 Typische Demo-Sätze + +- „Hier lade ich das Zertifikat – Subject/Issuer/Fingerprint erscheinen sofort.“ +- „Rot = abgelaufen oder außerhalb des Gültigkeitsfensters.“ +- „Den Fingerprint kann man mit dem erwarteten Wert aus der Doku/SMC abgleichen.“ +- „Kopieren auf den Server und TLS-Nachprüfung wären der nächste Ausbauschritt – bewusst getrennt vom Neustart.“ + +--- + +## 5. Die Sonic Management Application API – warum sie kompliziert wirkt + +### 5.1 Was Sonic bereitstellt (Produkt-API, nicht unsere Erfindung) + +Sonic/Aurea CX Messenger hat mehrere API-Welten: + +| API | Zweck | Nutzen wir für Neustart? | +|-----|--------|---------------------------| +| **Management Application API** (`mgmt_api`) | Domain Manager, Agenten, Restart/Stop wie SMC | ✅ ja | +| **CX Messenger MQ API** | Messaging (Queues, Producer/Consumer) | ❌ nein | +| **ESB API** | ESB-Services/Prozesse | ❌ nein | +| **Metrics / Notifications** | Monitoring | ❌ nein | +| **Administrative Programming Guide** | erweiterte Admin-Szenarien | nur indirekt als Konzept | + +Für den Container-Neustart ist laut Produkt-Doku-Index die **Management Application API** der richtige Einstieg – analog zum SMC-Button „Restart“. + +### 5.2 Kernklassen (die wirklich gebraucht werden) + +| Klasse / Konzept | Rolle | +|------------------|--------| +| `JMSConnectorAddress` | Verbindungsparameter (URL, User, Pass) | +| `JMSConnectorClient` | JMS/JMX-Verbindung zum Domain Manager | +| `ObjectName` | Ziel-Agent, z. B. `domain.container:ID=AGENT` | +| `MFProxyFactory.createAgentProxy` | Typisierter Proxy (`IAgentProxy`) | +| `IAgentProxy` / MBean-Operationen | `stop` / `restart` / `shutdown` … | +| Client-JARs unter `lib` | u. a. `mgmt_client.jar`, `mfcontext.jar`, `sonic_Client.jar` | + +### 5.3 Warum es trotzdem „viele unnötige Funktionen“ zu geben scheint + +**Ja – die Sonic-API ist enorm breit.** Sie deckt Broker-Verwaltung, Queues, Durable Subscribers, Metrics, Config-Beans, Directory Service, Host Manager usw. ab. +**Für unseren Use-Case brauchen wir nur einen schmalen Schnitt:** + +1. Verbinden +2. Agent-ObjectName finden +3. Lifecycle: Stop/Restart + +Alles andere in den JARs und in der `mgmt_api`-Javadoc ist **Produktumfang**, nicht „unsere App-API“. + +Zusätzlich wirkt **unser Java-Tool** (`SonicMfContainerTool`) kompliziert, weil es **Fallbacks** hat: + +| Schritt | Was | Warum | +|---------|-----|--------| +| 1 | `MBean.invoke("stop"|"restart"|"shutdown")` | Remote/„unbounded“ oft der Weg, den SMC faktisch nutzt | +| 2 | `IAgentProxy.stop/restart/shutdown` | „Schöner“ typisierter Pfad – scheitert oft mit *unbounded* | +| 3 | DomainManager/`restartContainer` | Weitere Fallback-Variante | + +Das ist **Absicherung**, kein Feature-Wahn. Man könnte später auf den einen Pfad reduzieren, der in eurer Umgebung stabil ist (vermutlich MBean `stop`). + +### 5.4 „Unbounded client connector“ – Kernpunkt für Erklärungen + +Remote-Clients (SMC, unser Tool) verbinden sich als **unbounded** JMS-Connector. + +Manche Methoden am typisierten Proxy prüfen das und werfen: + +```text +javax.management.JMRuntimeException: +Operation unsupported for unbounded client connector. +``` + +Deshalb: + +- `IAgentProxy.restart()` allein ist **kein** zuverlässiger Remote-Weg. +- Stattdessen: JMX `invoke` auf dem Agent-MBean, typischerweise **`stop`**. +- Wenn der Container unter einem Launch Daemon / Host Manager läuft, kommt er wieder hoch → Operator-Wirkung „Restart“. + +--- + +## 6. Neustart – End-to-End-Ablauf + +### 6.1 Konfiguration (`appsettings.json`) + +Beispiel (relevante Felder): + +```json +{ + "Name": "DE-Test", + "DomainName": "proalpha-test", + "ConnectionUrl": "tcp://dekun-painwbdet:13070", + "Username": "Administrator", + "Password": "Administrator", + "SonicHome": "C:\\DEV\\MQ10.0", + "JavaPath": "C:\\Program Files (x86)\\Java\\jre1.8.0_501\\bin\\java.exe", + "MfClientLibPath": "C:\\DEV\\MQ10.0\\lib", + "KnownContainers": [ "ct-ZADBService" ], + "TimeoutSeconds": 120, + "PostRestartDelaySeconds": 20 +} +``` + +Container in `appsettings` unter der Verbindung `DE-Test`: + +- `KnownContainers`: `[ "ct-ZADBService" ]` + +### 6.2 UI → C# + +1. Benutzer hakt Ziel an → **ESB neu starten**. +2. `PreflightValidator`: `ContainerName` + `SonicConnectionName` müssen gesetzt sein. +3. `RestartExecutor` sucht die `SonicConnection` und ruft `SonicManagementClient.RestartContainerAsync` auf. +4. `SonicMfApiExecutor`: + - Java 8+ finden + - Classpath aus allen JARs unter `MfClientLibPath` / `SonicHome\lib` bauen + - `Tools\SonicMfContainerTool.class` (Java-8-Bytecode) laden + - Prozess starten mit sauberer Argumentübergabe (`ArgumentList`, keine doppelten Quotes) + +Ungefährer Aufruf: + +```text +java -cp ";;;..." SonicMfContainerTool restart + --domain proalpha-test + --url tcp://dekun-painwbdet:13070 + --user Administrator + --container ct-ZADBService + --timeout 120 +``` + +Passwort: Umgebungsvariable `ESB_SONIC_PASSWORD` (nicht auf der Kommandozeile). + +### 6.3 Java-Tool (`SonicMfContainerTool`) + +1. Loggt `INFO:ToolVersion=…` (Build-Kontrolle). +2. `connect` über `JMSConnectorAddress` + `JMSConnectorClient`. +3. ObjectName: bevorzugt `proalpha-test.ct-ZADBService:ID=AGENT`. +4. Lifecycle-Versuche (siehe Abschnitt 5.3). +5. Erfolg: Zeile `OK:RestartInvoked method=…` +6. C# wertet `OK:RestartInvoked` als Erfolg und wartet `PostRestartDelaySeconds`. + +### 6.4 Erfolgsdefinition + +| Signal | Bedeutung | +|--------|-----------| +| `INFO:Connected …` | Login/URL ok | +| `INFO:ToolVersion=…` | Richtige Tool-Version läuft | +| `OK:RestartInvoked …` | Lifecycle-Aufruf durchgekommen | +| SMC zeigt Offline → Online / Uptime reset | Operative Bestätigung | + +--- + +## 7. Braucht die API „viele unnötige Funktionen“? + +### Kurze Antwort + +**Die Sonic-Produkt-API ja – unser benötigter Schnitt nein.** + +### Aufschlüsselung + +| Schicht | Viele Funktionen? | Für uns nötig? | +|---------|-------------------|----------------| +| Sonic `mgmt_api` + Client-JARs | Ja, sehr breit | Nur Connect + Agent-Lifecycle | +| Unser C#-Client früher (WinRM, HTTP, XApi, Bat) | Ja, historisch gewachsen | Nein – weitgehend entfernt | +| `SonicMfContainerTool` Fallbacks (MBean / IAgentProxy / DomainManager) | Mehrere Wege | Nützlich bis ein Weg überall stabil ist; danach ausdünnbar | +| Zertifikat TLS-Probe / Deploy | Extra-Komplexität | Aktuell nicht nötig | + +### Was man später noch verschlanken könnte + +1. Im Java-Tool nur noch den einen erfolgreichen Weg behalten (z. B. nur `MBean.invoke("stop")`). +2. In `appsettings` tote Felder entfernen (`WinRm*`, `Container*Path`, `ManagementHttpPort`, …) – stehen teils noch in JSON, werden vom schlanken Client nicht mehr genutzt. +3. `SonicMfApiExecutor` Java-Discovery vereinfachen, sobald `JavaPath` überall fest gesetzt ist. +4. Optional: Zertifikat-Deploy + TLS-Probe als **eigenes** Modul wieder einführen – klar getrennt vom Neustart. + +--- + +## 8. Voraussetzungen auf dem Rechner (Checkliste) + +| Voraussetzung | Beispiel / Hinweis | +|---------------|--------------------| +| SMC-Client / MQ-Libs | `C:\DEV\MQ10.0\lib` mit `mgmt_client.jar`, `mfcontext.jar`, `sonic_Client.jar` | +| Java 8+ | z. B. `jre1.8.0_501\bin\java.exe` (nicht zu alte Sonic-JRE 6/7) | +| Netzwerk | Port `13070` zum Domain Manager erreichbar | +| Credentials | Dieselben wie SMC-Login | +| Containername | Exakt wie in SMC (`ct-ZADBService`), nicht der Alias `DE-Test` | +| App-Build | Frische `Tools\SonicMfContainerTool.class` (Ausgabe muss `ToolVersion` zeigen) | + +--- + +## 9. Typische Fehler & Interpretation + +| Fehler / Symptom | Ursache | Maßnahme | +|------------------|---------|----------| +| `ClassNotFoundException: JMSConnectorAddress` | Classpath/JARs fehlen oder Quotes kaputt | `MfClientLibPath`, neuen Build, ArgumentList | +| `UnsupportedClassVersionError` | Tool mit zu neuem Java gebaut / zu alte Runtime | Tool major 52 + Java 8+ Runtime | +| `Operation unsupported for unbounded…` | `IAgentProxy.restart` remote gesperrt | MBean `stop` / neuer Tool-Build mit Fallbacks | +| Kein `INFO:ToolVersion=` | Alte `.class` im Output | Neu bauen, Debug/Release-Ordner prüfen | +| Container `DE-Test` | Alias statt Kurzname | `ct-ZADBService` setzen | +| `stopcontainer.bat` fehlt | SMC-only | Erwartet – MfApi nutzen, nicht Bat | + +--- + +## 10. Dateien im Code (Orientierung) + +| Datei | Rolle | +|-------|--------| +| `Form1.cs` | UI: Zertifikat + Ziele + Neustart (Design) | +| `Services/DeploymentOrchestrator.cs` | Nur `RestartOnlyAsync` | +| `Services/RestartExecutor.cs` | Mappt Ziel → Sonic-Verbindung | +| `Services/SonicManagementClient.cs` | Fassade MfApi | +| `Services/SonicMfApiExecutor.cs` | Java starten, Classpath, Tool | +| `Tools/SonicMfContainerTool.java` | Eigentliche Management-API-Aufrufe | +| `appsettings.json` | Domain, URL, Login, Java, Lib-Pfad, KnownContainers | + +--- + +## 11. Präsentations-Skript (kurz) + +1. **Problem:** Zertifikat prüfen und ESB-Container neu starten – ohne manuelle SMC-Klicks jedes Mal. +2. **Zertifikat:** Datei laden → Subject/Issuer/Fingerprint/Gültigkeit. Lokal verifiziert, noch kein Deploy. +3. **Neustart:** Dieselbe Management-API wie die SMC, nicht FTP, nicht `stopcontainer.bat`. +4. **Technik:** C# orchestriert, Java + Sonic-Client-JARs sprechen mit dem Domain Manager. +5. **Komplexität:** Die Sonic-API ist riesig; wir nutzen nur Connect + Agent-Stop/Restart. Fallbacks wegen „unbounded connector“. +6. **Ergebnis:** Container `ct-ZADBService` in Domain `proalpha-test` wird remote neu gestartet. + +--- + +## 12. Offene Punkte / nächste sinnvolle Ausbauten + +1. Zertifikat **nach** Erkennung auf den Zielhost legen (Deploy) – bewusst getrennt. +2. Optional **TLS-Probe** (Remote-Fingerprint) nach Deploy. +3. Java-Tool auf den einen erfolgreichen Lifecycle-Pfad reduzieren. +4. `appsettings` von Altlast-Feldern (WinRM/HTTP) bereinigen. +5. Fehlende offizielle `mgmt_api`-HTML/PDF ins Repo legen, damit man in Reviews direkt die Klassen verlinken kann. + +--- + +*Dokument erzeugt für Übergabe/Erklärung. Bei Abweichungen gilt der Code auf Branch `fix/mfapi-classpath-ct-zadbservice`.* diff --git a/ZA.CoreService.ESBCertificateManager/Form1.cs b/ZA.CoreService.ESBCertificateManager/Form1.cs index 1de8c15..c69bb80 100644 --- a/ZA.CoreService.ESBCertificateManager/Form1.cs +++ b/ZA.CoreService.ESBCertificateManager/Form1.cs @@ -1,7 +1,6 @@ using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using ZA.CoreService.ESBCertificateManager.Configuration; -using ZA.CoreService.ESBCertificateManager.Data; using ZA.CoreService.ESBCertificateManager.Models; using ZA.CoreService.ESBCertificateManager.Services; @@ -1292,17 +1291,26 @@ namespace ZA.CoreService.ESBCertificateManager return panel; } - private async Task LoadTargetsAsync() + private Task LoadTargetsAsync() { try { - SetStatus("Lade Bereitstellungsziele…", isError: false); - (ITargetRepository repository, string loadMessage) = - await TargetRepositoryFactory.CreateAsync(_settings); - - _loadedTargets = await repository.GetActiveTargetsAsync(); + SetStatus("Lade Container aus appsettings (KnownContainers)…", isError: false); + _loadedTargets = _sonicDiscovery.BuildTargetsFromConfig(); BindTargetsToGrid(_loadedTargets); - SetStatus(loadMessage, isError: false); + + if (_loadedTargets.Count == 0) + { + SetStatus( + "Keine KnownContainers in appsettings. SonicConnections[].KnownContainers setzen oder „Container laden“.", + isError: true); + } + else + { + SetStatus( + $"{_loadedTargets.Count} Container aus appsettings. Optional: „Container laden“ für Live-Liste.", + isError: false); + } } catch (Exception ex) { @@ -1314,6 +1322,8 @@ namespace ZA.CoreService.ESBCertificateManager { RefreshActionButtonStates(); } + + return Task.CompletedTask; } private void BindTargetsToGrid(IReadOnlyList targets) diff --git a/ZA.CoreService.ESBCertificateManager/Models/AppSettings.cs b/ZA.CoreService.ESBCertificateManager/Models/AppSettings.cs index 68e8635..4c239e8 100644 --- a/ZA.CoreService.ESBCertificateManager/Models/AppSettings.cs +++ b/ZA.CoreService.ESBCertificateManager/Models/AppSettings.cs @@ -2,16 +2,10 @@ namespace ZA.CoreService.ESBCertificateManager.Models; public sealed class AppSettings { - public string ConnectionString { get; set; } = string.Empty; - public bool UseOfflineSampleData { get; set; } = true; - public string SampleTargetsPath { get; set; } = "Data/targets.sample.json"; public string LogDirectory { get; set; } = "Logs"; - public int TlsTimeoutSeconds { get; set; } = 8; - public int TlsRetryCount { get; set; } = 2; /// - /// Verbindungskonfigurationen für Progress Sonic ESB Management Instanzen. - /// Jeder Eintrag entspricht einer Sonic-Domain (z.B. einer Umgebung oder Tochtergesellschaft). + /// Sonic-/SMC-Verbindungen. Container kommen aus KnownContainers bzw. Live-Discovery. /// public List SonicConnections { get; set; } = []; } diff --git a/ZA.CoreService.ESBCertificateManager/Services/SonicContainerDiscovery.cs b/ZA.CoreService.ESBCertificateManager/Services/SonicContainerDiscovery.cs index d03fe4b..739a156 100644 --- a/ZA.CoreService.ESBCertificateManager/Services/SonicContainerDiscovery.cs +++ b/ZA.CoreService.ESBCertificateManager/Services/SonicContainerDiscovery.cs @@ -18,6 +18,38 @@ public sealed class SonicContainerDiscovery public bool HasConnections => _connections.Count > 0; public IReadOnlyList Connections => _connections; + /// + /// Ziele nur aus appsettings KnownContainers (kein Offline-JSON). + /// + public IReadOnlyList BuildTargetsFromConfig() + { + List result = []; + int id = 1; + + foreach (SonicConnection connection in _connections) + { + foreach (string containerName in connection.KnownContainers + .Where(n => !string.IsNullOrWhiteSpace(n))) + { + result.Add(new DeploymentTarget + { + Id = id++, + Name = $"{connection.Name} / {containerName}", + Environment = connection.DomainName, + IsActive = true, + TargetDirectory = string.Empty, + CertificateFileName = string.Empty, + ContainerName = containerName.Trim(), + RestartType = RestartType.SonicContainer, + SonicConnectionName = connection.Name, + SortOrder = id * 10 + }); + } + } + + return result; + } + public async Task DiscoverAsync( string connectionName, IReadOnlyList knownTargets, diff --git a/ZA.CoreService.ESBCertificateManager/ZA.CoreService.ESBCertificateManager.csproj b/ZA.CoreService.ESBCertificateManager/ZA.CoreService.ESBCertificateManager.csproj index 9885c5f..52963b3 100644 --- a/ZA.CoreService.ESBCertificateManager/ZA.CoreService.ESBCertificateManager.csproj +++ b/ZA.CoreService.ESBCertificateManager/ZA.CoreService.ESBCertificateManager.csproj @@ -20,12 +20,12 @@ PreserveNewest - - PreserveNewest - Always + + PreserveNewest + diff --git a/ZA.CoreService.ESBCertificateManager/appsettings.json b/ZA.CoreService.ESBCertificateManager/appsettings.json index 6277230..f807e9d 100644 --- a/ZA.CoreService.ESBCertificateManager/appsettings.json +++ b/ZA.CoreService.ESBCertificateManager/appsettings.json @@ -1,10 +1,5 @@ { - "ConnectionString": "", - "UseOfflineSampleData": true, - "SampleTargetsPath": "Data/targets.sample.json", "LogDirectory": "Logs", - "TlsTimeoutSeconds": 8, - "TlsRetryCount": 2, "SonicConnections": [ { "Name": "DE-Test", @@ -20,20 +15,8 @@ "KnownContainers": [ "ct-ZADBService" ], - "WinRmUsername": "", - "WinRmPassword": "", - "WinRmPort": 5985, "TimeoutSeconds": 120, - "PostRestartDelaySeconds": 20, - "ManagementHttpPort": 8080, - "ApiBasePath": "/api/v1", - "ContainerListPath": "", - "ContainerRestartPath": "", - "ContainerStopPath": "", - "ContainerStartPath": "", - "WinRmRestartScript": "", - "WinRmContainerListScript": "", - "WinRmXapiImportScript": "" + "PostRestartDelaySeconds": 20 } ] }