# BizTalk Checkmk Pulse `BizTalk Checkmk Pulse` ist ein robuster Checkmk-2.4-Local-Check fuer Microsoft BizTalk Server 2020 auf Windows Server 2019. Die Anwendung trennt den berechtigten BizTalk-Datenzugriff vollstaendig vom Checkmk-Agenten: ```text Scheduled Task (normales dediziertes Servicekonto) | | jede Minute: BizTalkCheckmkPulse.exe --collect v lokales BizTalk-WMI + BizTalk-SQL + Application Event Log | | atomarer, versionierter, SHA-256-geschuetzter Snapshot v %ProgramData%\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot ^ | nur lesen: BizTalkCheckmkPulse.exe --consume | Checkmk Windows Agent (LocalSystem) | v neun kompakte Checkmk Local Checks ``` Damit bekommt `LocalSystem` keine BizTalk- oder SQL-Berechtigung. Nur das dedizierte Provider-Konto wird in die konfigurierte BizTalk Server Read Only Users-Gruppe aufgenommen. Der Checkmk-Consumer liest keine BizTalk-Datenbank, verwendet kein WMI und nimmt keine Identitaetswechsel vor. ## Warum die Architektur geaendert wurde Der ACC-Test vom 29.07.2026 zeigte: ```text Login failed for user 'BEW\AV23AGPWBIO1$' ``` Der Checkmk-Agent lief korrekt als `NT AUTHORITY\SYSTEM` und erreichte lokales BizTalk-WMI. Datenbankgestuetzte WMI-Abfragen wurden jedoch am SQL Server als Maschinenkonto `BEW\AV23AGPWBIO1$` abgewiesen. Eine Mitgliedschaft des Computerkontos wuerde die BizTalk-Netzwerkberechtigung allen als `LocalSystem` laufenden Diensten des Servers geben. Die neue Trennung reduziert diesen Berechtigungsumfang. Fuer BizTalk Server 2020 ist die konfigurierte `BizTalk Server Read Only Users`-Gruppe mit der SQL-Datenbankrolle `BTS_READONLY_USERS` die bevorzugte Grenze. Die `BizTalk Server Operators`-Gruppe ist nur ein dokumentierter Fallback, wenn eine konkret benoetigte WMI-Klasse trotz bestaetigter Read-Only-Zuordnung abgewiesen wird. Direkte SQL-Logins, manuelle Datenbankrollen und `sysadmin` sind keine Loesung. ## Robustheit Der Datenaustausch ist bewusst defensiv: - Der Provider schreibt zuerst eine eindeutige Temporaerdatei im Zielordner, leert Betriebssystempuffer und ersetzt danach den Snapshot atomar. - Der Snapshot enthaelt Formatversion, UTC-Zeit, Quellmaschine, Provider-Identitaet, Zeilenanzahl und SHA-256 des Payloads. - Der Consumer akzeptiert nur denselben Rechner, gueltiges UTF-8, intakte Checkmk-Zeilen, korrekte SHA-256-Pruefsumme und ein maximales Alter von standardmaessig 180 Sekunden. - Fehlende, veraltete, abgeschnittene, manipulierte oder unlesbare Dateien ergeben neun gueltige `UNKNOWN`-Services statt einer kaputten Agent-Ausgabe. - Ein exklusives Lock und die Task-Einstellung `IgnoreNew` verhindern ueberlappende Providerlaeufe. - Ein unerwarteter Providerfehler erzeugt nach Moeglichkeit einen aktuellen `UNKNOWN`-Snapshot und einen ungleich null lautenden Task-Exitcode. - Provider und Consumer protokollieren in taegliche Dateien; die Aufbewahrung ist standardmaessig 30 Tage. - Snapshotgroesse, WMI-/SQL-Timeouts, Log-Retention und Stale-Grenze sind begrenzt und konfigurierbar. ## Erzeugte Services Standardmaessig entstehen: - `BizTalk Platform` - `BizTalk SQL Access` - `BizTalk Suspended Instances` - `BizTalk Host Instances` - `BizTalk Receive Locations` - `BizTalk Send Ports` - `BizTalk Endpoint Reachability` - `BizTalk Orchestrations` - `BizTalk Event Log` Die drei Artefaktbereiche sind absichtlich getrennte Services. Dadurch sind Zustand und Graphen direkt erkennbar, ohne eine lange Sammelzeile zu lesen: - Suspensions: total, resumable, non-resumable und Routing Failure Reports - Receive Locations: total, enabled, unerwartet/bewusst disabled und unbekannt - Send Ports: total, started, stopped, bound, unbekannt sowie bewusst inactive - Endpoint Reachability: nur aktive Send-/Receive-Artefakte; im OK-Fall nur eine Gesamtaussage, im Fehlerfall ausschliesslich nicht erreichbare Ziele - Orchestrations: total, started, stopped, bound, unbound und unbekannt Der Provider nutzt fuer die Endpoint-Discovery keine neue WMI-Klasse. Er liest `PTAddress`, `STAddress`, `PTTransportType`, `STTransportType`, `InboundTransportURL` und `AdapterName` aus den bereits vorhandenen `MSBTS_SendPort`-/`MSBTS_ReceiveLocation`-Abfragen. Der Check selbst ist ein reiner Host/Port-Test: HTTP(S), SFTP, FTP, WCF/net.tcp und UNC werden per TCP geprueft; explizite `udp://`-Ziele per UDP-Datagramm. Es werden keine HTTP-Requests, Anmeldungen oder fachlichen Nachrichten gesendet. Der geheimnisfreie Katalog liegt unter `%ProgramData%\BizTalkCheckmkPulse\data\endpoints.xml`. Fehlt er, wird er beim naechsten erfolgreichen Providerlauf erstellt. Alle 168 Stunden wird er gegen die Umgebung abgeglichen. Automatisch verwaltete Eintraege fuer inzwischen inaktive Artefakte verschwinden beim Abgleich; bei jedem Minutenlauf werden sie zusaetzlich gegen den aktuellen Started-/Enabled-Zustand gefiltert. Pro Service werden standardmaessig maximal fuenf betroffene Namen gezeigt. Weitere Treffer erscheinen nur als `(+n more)`; Details sind zusaetzlich auf 1600 Zeichen begrenzt. Metriken bleiben trotzdem vollstaendig. Mit `EnvironmentName=ACC`, `DEV`, `TST` oder `PRD` wird die Umgebung in den Servicenamen aufgenommen, zum Beispiel `BizTalk ACC Platform`. Statuslogik und Metriken: [docs/CheckmkServices.md](docs/CheckmkServices.md) Beispielausgaben: [docs/ExampleOutput.md](docs/ExampleOutput.md) Endpoint-Katalog, manuelle Overrides und Protokollgrenzen: [docs/EndpointCatalog.md](docs/EndpointCatalog.md) ## Voraussetzungen Build-Host: - Visual Studio 2019/2022 Build Tools oder Visual Studio - MSBuild im `PATH` - .NET Framework 4.7.2 Developer Pack BizTalk-Server: - Windows Server 2019 - BizTalk Server 2020 und lokaler Namespace `root\MicrosoftBizTalkServer` - .NET Framework 4.7.2 - Checkmk Windows Agent - administrativer Zugriff fuer die einmalige Installation - normales dediziertes AD-Servicekonto fuer den Provider Das Provider-Konto benoetigt: - lokales Recht zur Ausfuehrung als Scheduled Task - lokalen Lese-/Ausfuehrungszugriff auf die installierte EXE - Schreibzugriff nur auf Snapshot- und Logverzeichnis - Mitgliedschaft in der exakt konfigurierten BizTalk Server Read Only Users-Gruppe Es soll weder lokaler Administrator noch SQL-`sysadmin` sein. Der Scheduled Task laeuft mit `RunLevel Limited`. Das Servicekonto braucht ein gespeichertes Task-Kennwort und das Recht `Log on as a batch job`. Ein gMSA bleibt optional, ist aber fuer diese Installation nicht vorausgesetzt. ## Build und Tests ```cmd scripts\build-release.cmd scripts\test-release.cmd scripts\package-release.cmd ``` Das Paket wird unter `artifacts\BizTalkCheckmkPulse-deploy` erzeugt: ```text BizTalkCheckmkPulse-deploy\ Install-BizTalkCheckmkPulse.ps1 Uninstall-BizTalkCheckmkPulse.ps1 biztalk_checkmk_pulse.cmd application\ BizTalkCheckmkPulse.exe BizTalkCheckmkPulse.exe.config ``` Format-Self-Test ohne WMI, SQL oder Event Log: ```cmd artifacts\BizTalkCheckmkPulse-deploy\application\BizTalkCheckmkPulse.exe --self-test ``` Erwartet werden exakt neun `OK`-Zeilen. Die Regressionstests pruefen zusaetzlich Snapshot-Roundtrip, atomaren Ersatz, SHA-256-Manipulation, Stale-Erkennung, stabile Fallbacks und die bestehenden BizTalk-WMI-Diagnosen. Ein Mono-Build ist eine hilfreiche Quellcodepruefung, ersetzt aber nicht die Windows-/BizTalk-Laufzeitvalidierung. ## Berechtigung vorbereiten Die exakte Read-Only-Gruppe wird in der BizTalk Administration Console unter den Eigenschaften der BizTalk-Gruppe abgelesen. Ein bereits berechtigtes Konto kann sie alternativ ermitteln: ```powershell Get-CimInstance ` -Namespace root/MicrosoftBizTalkServer ` -ClassName MSBTS_GroupSetting | Select-Object Name, BizTalkReadOnlyUserGroup, BizTalkOperatorGroup, MgmtDbServerName, MgmtDbName ``` Ein AD-Administrator nimmt das neue Provider-Konto in `BizTalkReadOnlyUserGroup` auf. Nach AD-Replikation muss das Servicekonto durch einen neuen Tasklauf einen neuen Anmeldetoken erhalten. Die BizTalk-Konfiguration muss die Domain-Gruppe bereits als Windows-Login und in `BizTalkMgmtDb`, `BizTalkMsgBoxDb`, `BizTalkDTADb`, `BizTalkRuleEngineDb` sowie gegebenenfalls `BAMPrimaryImport` mit `BTS_READONLY_USERS` abbilden. Eine fehlende Abbildung wird durch BizTalk- und SQL-Administration fuer die Gruppe repariert, nicht als Einzelberechtigung fuer das Provider-Konto. ## Installation mit normalem Servicekonto ```powershell Set-Location C:\Temp\BizTalkCheckmkPulse-deploy .\Install-BizTalkCheckmkPulse.ps1 ` -CollectorAccount 'BEW\svc_biztalk_cmk' ` -EnvironmentName ACC ``` Der Installer fragt das Kennwort ueber `Get-Credential` ab und speichert es durch die Windows-Aufgabenplanung. Das Kennwort steht weder in der Konfigurationsdatei noch in den Logs. Wenn das Kennwort rotiert oder ablaeuft, muss es im Scheduled Task aktualisiert werden. Bis dahin wird der Snapshot nach 180 Sekunden stale und Checkmk zeigt alle neun Services als `UNKNOWN`. Ein gMSA kann weiterhin optional mit `-Gmsa` installiert werden; die produktive Standardbeschreibung geht vom normalen Servicekonto aus. Der Installer: 1. kopiert EXE und Config nach `%ProgramFiles%\BizTalkCheckmkPulse`, 2. erstellt `%ProgramData%\BizTalkCheckmkPulse\data` und `logs`, 3. setzt explizite ACLs fuer Administratoren, Provider und `LocalSystem`, 4. installiert nur den kleinen `.cmd`-Consumer unter `%ProgramData%\checkmk\agent\local`, 5. registriert `BizTalk Checkmk Pulse Provider` minuetlich mit `IgnoreNew`, fuenf Minuten Laufzeitlimit und zwei Wiederholungen, 6. fuehrt den Self-Test aus und startet den Provider einmalig. PowerShell wird nur fuer Installation und Betriebsdiagnose verwendet. Der minuetliche Provider und der Checkmk-Consumer sind .NET-/CMD-Laufzeitcode und haengen nicht von der PowerShell Execution Policy ab. ## Verifikation auf dem Server Task und letzter Lauf: ```powershell Get-ScheduledTask -TaskName 'BizTalk Checkmk Pulse Provider' | Select-Object TaskName, State Get-ScheduledTaskInfo -TaskName 'BizTalk Checkmk Pulse Provider' | Select-Object LastRunTime, LastTaskResult, NextRunTime ``` Provider-Log: ```powershell Get-ChildItem "$env:ProgramData\BizTalkCheckmkPulse\logs" | Sort-Object LastWriteTime -Descending | Select-Object -First 3 Name, Length, LastWriteTime Get-Content ` "$env:ProgramData\BizTalkCheckmkPulse\logs\biztalk-checkmk-pulse-*.log" ` -Tail 100 ``` Snapshot und Consumer: ```powershell Get-Item ` "$env:ProgramData\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot" | Select-Object FullName, Length, LastWriteTimeUtc & "$env:ProgramFiles\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume ``` Verbindlicher Test im echten `LocalSystem`-Kontext: ```powershell & "C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump | Select-String -Pattern "BizTalk|UNKNOWN|Snapshot|Permission" -Context 0,1 ``` Danach in Checkmk eine Service Discovery ausfuehren, die neun Services aufnehmen und Changes aktivieren. Ein zusaetzlicher Checkmk-Async-Cache ist nicht erforderlich: Der Consumer liest nur eine kleine lokale Datei und der Provider besitzt bereits seinen eigenen Minutentakt. ## Dateisystem und Sicherheitsgrenzen ```text %ProgramFiles%\BizTalkCheckmkPulse\ BizTalkCheckmkPulse.exe BizTalkCheckmkPulse.exe.config %ProgramData%\BizTalkCheckmkPulse\ data\ biztalk-checkmk-pulse.snapshot biztalk-checkmk-pulse.snapshot.provider.lock endpoints.xml logs\ biztalk-checkmk-pulse-YYYYMMDD.log %ProgramData%\checkmk\agent\local\ biztalk_checkmk_pulse.cmd ``` ACL-Soll: | Pfad | Provider | LocalSystem | Administratoren | | --- | --- | --- | --- | | Programm | Lesen/Ausfuehren | Lesen/Ausfuehren | Vollzugriff | | `data` | Aendern | Lesen/Ausfuehren | Vollzugriff | | `logs` | Aendern | Aendern | Vollzugriff | Der Snapshot enthaelt Monitoringzustand und kompakte Fehlerdetails, aber keine Passwoerter oder Nachrichteninhalte. Der Consumer validiert die Datei trotzdem vollstaendig, bevor er sie an Checkmk weitergibt. ## Konfiguration Datei: ```text %ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe.config ``` Wichtige Werte: | Key | Default | Bedeutung | | --- | --- | --- | | `EnvironmentName` | leer | Optional `ACC`, `DEV`, `TST`, `PRD`. | | `SnapshotPath` | `%ProgramData%\BizTalkCheckmkPulse\data\...` | Gemeinsame Provider-/Consumer-Datei. | | `SnapshotMaxAgeSeconds` | `180` | Ab diesem Alter liefert der Consumer `UNKNOWN`. | | `SnapshotMaxBytes` | `1048576` | Harte Eingabegroesse fuer den Consumer. | | `LogDirectory` | `%ProgramData%\BizTalkCheckmkPulse\logs` | Tageslogs. | | `LogRetentionDays` | `30` | Provider bereinigt aeltere Logs. | | `ProbeEndpointConnectivity` | `true` | Aktiviert den aggregierten TCP-/UDP-Netzwerkcheck. | | `EndpointCatalogPath` | `%ProgramData%\BizTalkCheckmkPulse\data\endpoints.xml` | Lokal gepflegte Endpoint-Konfiguration ohne vollstaendige URIs/Secrets. | | `EndpointDiscoveryIntervalHours` | `168` | Intervall fuer den vollstaendigen Umgebungsabgleich. | | `EndpointProbeTimeoutMilliseconds` | `3000` | Timeout je dedupliziertem Host/Port-Ziel. | | `EndpointProbeMaxConcurrency` | `12` | Begrenzte parallele Socket-Probes. | | `EndpointMaxCount` | `500` | Harte Obergrenze gegen fehlerhafte/uebergrosse Konfiguration. | | `QueryTimeoutSeconds` | `25` | WMI-Timeout je Query. | | `SqlConnectionTimeoutSeconds` | `5` | SQL-Timeout je Ziel. | | `WarnResumableThreshold` | `1` | WARN ab n resumable Suspensions. | | `CritNonResumableThreshold` | `1` | CRIT ab n non-resumable Suspensions. | | `CritRoutingFailureThreshold` | `1` | CRIT ab n Routing Failure Reports. | | `AlertOnArtifactRuntimeIssues` | `true` | Unerwartet deaktivierte Receive Locations bzw. inaktive Send Ports werden CRIT. | | `ExpectedDisabledReceiveLocations` | leer | Pipe-getrennte exakte Allowlist: `Name` oder `Anwendung\Name`. | | `ExpectedInactiveSendPorts` | leer | Pipe-getrennte exakte Allowlist: `Name` oder `Anwendung\Name`. | | `AlertOnInactiveOrchestrations` | `false` | Optional WARN fuer stopped/bound/unbound Orchestrations. | | `MaxSummaryItems` | `5` | Maximal angezeigte betroffene Artefakte je Service. | | `MaxDetailCharacters` | `1600` | Harte Obergrenze fuer Checkmk-Summary. | | `EmitPerApplicationSuspensionServices` | `false` | Zusaetzliche Anwendungsservices. | | `EventLogLookbackMinutes` | `60` | Event-Log-Zeitfenster des Providers. | Nach einer Config-Aenderung den Scheduled Task manuell starten. Der Consumer liest den naechsten atomar publizierten Snapshot. ## Fehlerbilder | Beobachtung | Ursache / Massnahme | | --- | --- | | Alle neun Services melden fehlenden Snapshot | Task, Provider-Log, Task-Konto/Kennwort und ACL pruefen. | | Snapshot ist `stale` | `LastTaskResult`, Laufzeit, WMI-/SQL-Timeout und Log pruefen. | | SHA-256 oder Format ungueltig | Datei nicht manuell bearbeiten; Datentraeger/AV und Schreibpfad pruefen, Task neu starten. | | Provider meldet `Login failed` | Provider-Konto und exakt konfigurierte Read-Only-Gruppe sowie `BTS_READONLY_USERS` pruefen. | | Receive Locations / Send Ports sind CRIT | `affected=` pruefen; nur fachlich bewusst inaktive Namen exakt in die jeweilige Allowlist aufnehmen. | | Endpoint Reachability ist CRIT | Nur `unavailable=` pruefen; DNS, Zielport, Firewall und externen Dienst kontrollieren. | | Endpoint Reachability ist UNKNOWN | WMI-Vollstaendigkeit, `endpoints.xml`, woechentlichen Refresh und nicht automatisch aufloesbare externe Adapteradresse pruefen. | | `Wmi/Schema` | Klasse/Properties gegen BizTalk-2020-Schema pruefen; keine Rechte ausweiten. | | Nur Event Log `UNKNOWN` | lokalen Application-Log-Zugriff des Provider-Kontos pruefen. | | Task-Result `2` | Parallelstart oder Snapshot-I/O; Log und Lock/ACL pruefen. | Ausfuehrliche Betriebs- und Architekturdetails stehen in [Dokumentation.md](Dokumentation.md). ## Deinstallation ```powershell .\Uninstall-BizTalkCheckmkPulse.ps1 ``` Das Skript fragt vor dem Entfernen. Mit `-KeepRuntimeData` bleiben Snapshot und Logs erhalten: ```powershell .\Uninstall-BizTalkCheckmkPulse.ps1 -KeepRuntimeData ``` Die AD-Gruppenmitgliedschaft des Provider-Kontos wird bewusst nicht automatisch geaendert und muss separat durch AD-/BizTalk-Administration entfernt werden. ## Certutil-Transport Zu jeder Uebergabe wird ein Source-ZIP und eine certutil-kompatible Base64-Textdatei erzeugt. Auf Windows: ```cmd certutil -decode biztalk-checkmk-pulse-source--.zip.b64.txt biztalk-checkmk-pulse-source.zip certutil -hashfile biztalk-checkmk-pulse-source.zip SHA256 tar -xf biztalk-checkmk-pulse-source.zip ``` Die konkrete Datei und SHA-256-Summe werden bei der Uebergabe genannt. ## Quellen - Microsoft: BizTalk `MSBTS_GroupSetting.BizTalkReadOnlyUserGroup` - Microsoft: Windows Groups and User Accounts in BizTalk Server - Microsoft: Managing BizTalk Server Security - Microsoft: [`MSBTS_SendPort` (WMI)](https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-sendport-wmi) - Microsoft: [`MSBTS_ReceiveLocation` (WMI)](https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-receivelocation-wmi) - Checkmk: Windows Agent und Local Checks Die genauen Links stehen in [Dokumentation.md](Dokumentation.md).