Files
biztalk-checkmk-pulse/Dokumentation.md
T

543 lines
19 KiB
Markdown

# Technische Dokumentation: BizTalk Checkmk Pulse
## 1. Ziel und Randbedingungen
Die Anwendung ueberwacht BizTalk Server 2020 auf Windows Server 2019 mit
Checkmk 2.4. Pro Umgebung (`ACC`, `DEV`, `TST`, `PRD`) wird lokal auf dem
BizTalk-Server gesammelt. Das Checkmk-MSSQL-Plugin bleibt fuer die allgemeine
SQL-Ueberwachung zustaendig; BizTalk Checkmk Pulse liefert die
BizTalk-spezifische Laufzeit- und Berechtigungssicht.
Verbindliche Randbedingungen:
- Der Checkmk Windows Agent bleibt `LocalSystem`.
- `LocalSystem` erhaelt keine BizTalk-/SQL-Gruppenmitgliedschaft.
- Ein separates Dienstkonto oder bevorzugt gMSA sammelt minuetlich.
- Der Agentpfad fuehrt niemals WMI- oder SQL-Abfragen aus.
- Fehler muessen als gueltige Checkmk-`UNKNOWN`-Services sichtbar werden.
- Schreiben und Lesen duerfen nie einen halben Snapshot exponieren.
- Laufzeitcode benoetigt keine PowerShell und keine BizTalk-DLL-Referenz.
- Installation, ACL und Scheduled Task muessen reproduzierbar sein.
## 2. Ausloeser der Architekturanderung
Der ACC-Agent-Dump vom 29.07.2026 bewies:
```text
Lokaler Prozess: NT AUTHORITY\SYSTEM
Netzwerkprincipal: BEW\AV23AGPWBIO1$
Providerfehler: COMException 0x80131904
Innerer Fehler: Login failed for user 'BEW\AV23AGPWBIO1$'
```
Lokales `root\MicrosoftBizTalkServer` war erreichbar. Die
datenbankgestuetzten BizTalk-WMI-Klassen scheiterten erst beim Zugriff des
Providers auf den getrennten SQL Server. DCOM-, Firewall- oder pauschale
WMI-ACL-Aenderungen beheben diesen Befund nicht.
Eine Berechtigung des Maschinenkontos haette die Netzwerkrolle allen
`LocalSystem`-Diensten des BizTalk-Servers vermittelt. Die jetzt implementierte
Producer/Consumer-Trennung beschraenkt sie stattdessen auf ein dediziertes
Konto.
## 3. Architektur
```text
Privilegierte Zone
┌──────────────────────────────────────────────────────────────┐
│ Task Scheduler: "BizTalk Checkmk Pulse Provider" │
│ Konto: DOMAIN\svc_biztalk_cmk$ (gMSA empfohlen) │
│ Intervall: 1 Minute, IgnoreNew, Laufzeitlimit 5 Minuten │
│ │
│ BizTalkCheckmkPulse.exe --collect │
│ ├─ WMI root\MicrosoftBizTalkServer │
│ ├─ integrierter SQL-Test an MgmtDb/MsgBoxDb │
│ ├─ lokales Windows Application Event Log │
│ ├─ Checkmk-Formatierung │
│ └─ atomare Snapshot-Publikation + Provider-Log │
└──────────────────────────────┬───────────────────────────────┘
│ Datei/ACL
v
%ProgramData%\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot
v
┌──────────────────────────────────────────────────────────────┐
│ Unprivilegierter Transportpfad │
│ Checkmk-Agent (LocalSystem) │
│ └─ local\biztalk_checkmk_pulse.cmd │
│ └─ BizTalkCheckmkPulse.exe --consume │
│ ├─ Format/Alter/Maschine/SHA-256 validieren │
│ └─ Payload unveraendert nach STDOUT │
└──────────────────────────────────────────────────────────────┘
```
Eine gemeinsame EXE implementiert beide Modi. Das reduziert
Versionsabweichungen. Die zentrale Config unter `%ProgramFiles%` gilt fuer
Provider und Consumer.
### 3.1 Provider-Modus
Aufruf:
```cmd
"%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --collect
```
Ablauf:
1. Config laden und absolute Runtimepfade validieren.
2. Tageslogs gemaess `LogRetentionDays` bereinigen.
3. exklusives Handle auf `<SnapshotPath>.provider.lock` halten.
4. WMI-, SQL- und Event-Log-Probes ausfuehren.
5. sechs stabile und optionale dynamische Checkmk-Zeilen formatieren.
6. Snapshot in einer eindeutigen Temporaerdatei desselben Verzeichnisses
schreiben.
7. `Flush(true)` ausfuehren und Temporaerdatei atomar publizieren.
8. Laufzeit, Zeilen- und Diagnosezahl loggen.
Exitcodes:
| Code | Bedeutung |
| --- | --- |
| `0` | Sammlung und Snapshot-Publikation erfolgreich. |
| `1` | unerwarteter Providerfehler; aktueller `UNKNOWN`-Snapshot wird versucht. |
| `2` | Parallelstart oder Snapshot-I/O-Fehler. |
Fachliche WMI-/SQL-Fehler werden strukturiert in den Snapshot geschrieben und
muessen nicht zwingend einen Prozessfehler verursachen. So bleibt die genaue
Fehlerkategorie in Checkmk sichtbar.
### 3.2 Consumer-Modus
Aufruf:
```cmd
"%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
```
Ohne Modusargument ist `--consume` der sichere Default. Der Checkmk-Wrapper
setzt es trotzdem explizit.
Der Consumer:
- oeffnet nur den Snapshot,
- begrenzt die Dateigroesse vor dem Einlesen,
- validiert striktes UTF-8,
- validiert Formatversion und Header,
- fordert die lokale Maschinenkennung,
- berechnet SHA-256 ueber den exakten Payload,
- prueft Zeilenanzahl und Checkmk-Zeilenform,
- verwirft Zeitstempel mehr als fuenf Minuten in der Zukunft,
- verwirft Snapshots nach `SnapshotMaxAgeSeconds`,
- gibt bei Erfolg ausschliesslich den validierten Payload aus.
Er gibt immer Exitcode `0` zurueck, damit ein Fehler die komplette
Checkmk-Agentsektion nicht zerstoert. Jede Ablehnung erzeugt sechs
`UNKNOWN`-Zeilen und einen Eintrag im Consumer-Log.
## 4. Snapshot-Vertrag
Version 1:
```text
BIZTALK_CHECKMK_PULSE_SNAPSHOT_V1
generatedUtc=2026-07-30T12:34:56.1234567Z
machineBase64=QVYyM0FHUFdCSU8x
identityBase64=QkVXXHN2Y19iaXp0YWxrX2NtayQ=
payloadLines=6
payloadSha256=<64 hex characters>
0 "BizTalk Platform" - ...
...
```
Maschine und Identitaet sind Base64-kodiert, um Zeilenumbrueche und
Trennzeichen im Header auszuschliessen. Base64 ist hier keine Verschluesselung.
Die SHA-256-Pruefung schuetzt vor unbemerkter Teil-/Fehlschreibung, nicht vor
einem lokalen Administrator.
### 4.1 Atomare Publikation
Die Temporaerdatei liegt zwingend im Snapshotverzeichnis. Dadurch findet der
Ersatz auf demselben Volume statt. Existiert bereits ein Snapshot, wird
`File.Replace` verwendet; beim ersten Lauf `File.Move`. Bis zum erfolgreichen
Ersatz bleibt der letzte vollstaendige Snapshot erhalten. Seine Alterspruefung
verhindert unbegrenztes Weiterreichen alter Daten.
### 4.2 Keine direkte Checkmk-Spooldatei
Checkmk kann zwar Dateien aus seinem Spoolverzeichnis direkt anhaengen, prueft
deren Inhalt aber laut eigener Dokumentation nicht. Ein fehlerhafter Spool kann
nachfolgende Agentsektionen beeinflussen. Deshalb liegt der Provider-Snapshot
in einem eigenen Verzeichnis und wird erst durch den validierenden Consumer in
die Local-Check-Ausgabe uebernommen.
## 5. Datenquellen
### 5.1 BizTalk WMI
Namespace:
```text
root\MicrosoftBizTalkServer
```
Pflichtklassen:
| Klasse | Zweck |
| --- | --- |
| `MSBTS_GroupSetting` | Gruppe, Read-Only-/Operator-Gruppe, Management- und Master-MessageBox-Ziel. |
| `MSBTS_HostInstance` | lokale Host-Instance-Zustaende. |
| `MSBTS_ServiceInstance` | suspendierte Instanzen. |
| `MSBTS_ReceiveLocation` | Receive-Location-Zustaende. |
| `MSBTS_SendPort` | Send-Port-Zustaende. |
| `MSBTS_Orchestration` | Orchestration-Zustaende. |
`MSBTS_GroupSetting` wird mit den dokumentierten Properties
`MgmtDbServerName`, `MgmtDbName`, `SubscriptionDBServerName`,
`SubscriptionDBName`, `BizTalkReadOnlyUserGroup` und
`BizTalkOperatorGroup` gelesen. Eine nicht dokumentierte
`MSBTS_MessageBoxSetting`-Klasse wird nicht abgefragt.
Hostnamen werden clientseitig verglichen. Sonderzeichen und FQDN-/Kurzname
gelangen nicht in dynamisch erzeugte WQL-Filter.
### 5.2 SQL-Zugriffsprobe
Der Provider oeffnet fuer Management- und Master-MessageBox-Datenbank eine
kurze `System.Data.SqlClient`-Verbindung mit integrierter
Windows-Authentifizierung, fuehrt `SELECT 1` aus und schliesst sie. Keine
BizTalk-Tabelle wird direkt gelesen oder veraendert.
Die Ausgabe `execution_identity=` zeigt deshalb das Provider-Konto, nicht mehr
`NT AUTHORITY\SYSTEM`. Der Check beweist, dass genau das Scheduled-Task-Konto
die Ziele erreichen kann.
### 5.3 Event Log
Der Provider liest das lokale Application Log im konfigurierten Zeitfenster
und filtert Quellen wie `BizTalk Server`, `XLANG/s`, `ENTSSO`,
`BizTalk Server Application` und `BizTalk Server EDI`.
## 6. Berechtigungsmodell
### 6.1 Bevorzugte BizTalk-Rolle
BizTalk Server 2020 fuehrte die `BizTalk Server Read Only Users`-Gruppe ein.
Sie darf Artefakte, Servicezustand, Message Flow und Trackinginformationen
lesen, aber keine administrativen Operationen ausfuehren. SQL-seitig wird sie
ueber `BTS_READONLY_USERS` vermittelt.
Soll:
```text
DOMAIN\svc_biztalk_cmk$
-> konfigurierte BizTalk Server Read Only Users-Domaingruppe
-> vorhandener Windows-Gruppenlogin am SQL Server
-> BTS_READONLY_USERS in den von BizTalk konfigurierten Datenbanken
```
Die genaue Gruppe ist aus
`MSBTS_GroupSetting.BizTalkReadOnlyUserGroup` beziehungsweise der
BizTalk-Administration zu lesen. Nicht vom Standardnamen ausgehen.
Die Operator-Gruppe (`BTS_OPERATORS`) wird erst geprueft, wenn eine konkret
benannte erforderliche WMI-Klasse trotz nachgewiesener Read-Only-Konfiguration
und neuem Anmeldetoken abgewiesen wird. Die Erweiterung muss mit Security,
BizTalk- und SQL-Administration begruendet werden.
Unzulaessig:
- Checkmk-Dienstkonto aendern,
- Maschinenkonto pauschal berechtigen,
- individueller SQL-Login fuer das Provider-Konto,
- direkte ad-hoc DB-Rollen,
- `db_owner` oder `sysadmin`,
- WMI-/DCOM-Vollzugriff als Reaktion auf einen SQL-Loginfehler.
### 6.2 Dateisystem-ACL
Der Installer entfernt die Vererbung an den Runtimeverzeichnissen und setzt
explizite Eintraege mit sprachneutralen Well-known-SIDs:
| Ziel | Collector | SYSTEM | lokale Administratoren |
| --- | --- | --- | --- |
| Runtime-Root | RX | RX | F |
| `data` | Modify | RX | F |
| `logs` | Modify | Modify | F |
`LocalSystem` kann deshalb den Snapshot lesen, aber im Datenverzeichnis nicht
schreiben. Schreibrecht im Logverzeichnis wird benoetigt, um abgelehnte
Snapshots aus dem Consumer-Kontext zu protokollieren.
## 7. Scheduled Task
Name:
```text
BizTalk Checkmk Pulse Provider
```
Sollkonfiguration:
| Einstellung | Wert |
| --- | --- |
| Trigger | einmalig, Wiederholung jede Minute ohne Enddatum |
| Programm | `%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe` |
| Argument | `--collect` |
| Arbeitsverzeichnis | `%ProgramFiles%\BizTalkCheckmkPulse` |
| Benutzer | dediziertes Dienstkonto oder gMSA |
| Mehrfachinstanzen | `IgnoreNew` |
| Laufzeitlimit | 5 Minuten |
| StartWhenAvailable | aktiv |
| Restart | zweimal im Minutenabstand |
Der Task wird mit gespeichertem Dienstkontokennwort beziehungsweise gMSA
ausgefuehrt, also unabhaengig von einer interaktiven Anmeldung.
## 8. Installation
### 8.1 Build
```cmd
scripts\test-release.cmd
scripts\package-release.cmd
```
### 8.2 gMSA
Voraussetzungen:
1. gMSA in AD erstellen und Abrufrecht auf den BizTalk-Server begrenzen.
2. Konto lokal installieren und mit `Test-ADServiceAccount` pruefen.
3. gMSA in die exakt konfigurierte BizTalk-Read-Only-Gruppe aufnehmen.
4. AD-Replikation abwarten.
Installation:
```powershell
.\Install-BizTalkCheckmkPulse.ps1 `
-CollectorAccount 'BEW\svc_biztalk_cmk$' `
-Gmsa `
-EnvironmentName ACC
```
### 8.3 regulaeres Dienstkonto
```powershell
.\Install-BizTalkCheckmkPulse.ps1 `
-CollectorAccount 'BEW\svc_biztalk_cmk' `
-EnvironmentName ACC
```
Der Installer muss als lokaler Administrator laufen. Er vergibt keine
AD-/BizTalk-/SQL-Rechte; diese bleiben getrennte administrative Freigaben.
### 8.4 Checkmk
Der installierte Wrapper liegt unter:
```text
%ProgramData%\checkmk\agent\local\biztalk_checkmk_pulse.cmd
```
Der Agent darf den Consumer synchron ausfuehren. Er liest nur maximal 1 MiB
lokale Daten; ein Checkmk-Async-Cache ist daher nicht notwendig. Falls alte
`check_mk.user.yml`-Regeln fuer den bisherigen 300-Sekunden-Cache existieren,
sollten sie entfernt werden, damit Checkmk den minuetlich aktualisierten
Snapshot nicht zusaetzlich verzoegert.
Nach dem Agent-Dump:
1. Service Discovery fuer den BizTalk-Host ausfuehren.
2. sechs stabile Services aufnehmen.
3. Changes aktivieren.
4. Views/Benachrichtigungen nach Umgebung konfigurieren.
## 9. Logging
Pfad:
```text
%ProgramData%\BizTalkCheckmkPulse\logs\
biztalk-checkmk-pulse-YYYYMMDD.log
```
Jede Zeile enthaelt UTC-Zeit, Level, Komponente, PID, Windows-Identitaet und
einzeilige Nachricht. Provider-Erfolge werden pro Lauf geloggt; der Consumer
loggt nur abgelehnte Snapshots. Exceptions werden mit Typ, Nachricht,
HRESULT-/Providerdetails und Stacktrace einzeilig gespeichert.
Logging ist best effort: Ein blockiertes Log darf Checkmk-Ausgabe oder
Snapshot-Publikation nicht zerstoeren. Der Provider entfernt beim Start Dateien
aelter als `LogRetentionDays`.
## 10. Diagnose und Runbook
### 10.1 Grundpruefung
```powershell
Get-ScheduledTaskInfo -TaskName 'BizTalk Checkmk Pulse Provider'
Get-Item "$env:ProgramData\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot"
Get-Content "$env:ProgramData\BizTalkCheckmkPulse\logs\*.log" -Tail 100
& "$env:ProgramFiles\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
& "C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump
```
### 10.2 Kein Snapshot
Pruefen:
1. Task existiert und ist aktiviert.
2. `LastTaskResult` und Provider-Log.
3. Dienstkonto kann sich als Batch anmelden.
4. gMSA ist lokal installiert und abrufbar.
5. Provider besitzt Modify auf `data` und `logs`.
6. EXE/Config sind ausfuehrbar.
### 10.3 Staler Snapshot
Der Consumer nennt Alter und Grenzwert. Ursachen:
- Task deaktiviert oder Konto/Kennwort ungueltig,
- vorheriger Lauf haengt,
- WMI-/SQL-Timeouts,
- Task Scheduler lief waehrend Wartung nicht,
- Snapshot-Publikation wird durch AV/EDR oder ACL blockiert.
Nicht einfach `SnapshotMaxAgeSeconds` stark erhoehen. Zuerst den minuetlichen
Lauf wiederherstellen. Bei geplanten Wartungen darf Checkmk bewusst `UNKNOWN`
anzeigen.
### 10.4 SHA-256-/Formatfehler
Snapshot nicht reparieren oder direkt an Checkmk kopieren. Task neu starten,
Datentraeger und AV/EDR pruefen. Wiederholt sich der Fehler, Temporaerdateien,
NTFS-Ereignisse und Schreibrechte untersuchen.
### 10.5 BizTalk-/SQL-Permission
1. Log zeigt `execution_identity` des Providers.
2. `BizTalkReadOnlyUserGroup` gegen BizTalk-Konfiguration abgleichen.
3. AD-Gruppenmitgliedschaft des Provider-Kontos pruefen.
4. neuen Logontoken durch neuen Tasklauf sicherstellen.
5. SQL-seitig Gruppenlogin und `BTS_READONLY_USERS` read-only pruefen.
6. keine Einzelrechte erteilen.
7. Nur wenn eine spezifische Klasse weiter abgewiesen wird, Read-Only-Umfang
mit Microsoft-Dokumentation und BizTalk-Betrieb abgleichen; Operator-Rolle
ist eine bewusste Eskalation.
### 10.6 WMI-Schema
`InvalidClass` oder `InvalidQuery` wird als `Wmi/Schema` klassifiziert.
Berechtigungserhoehung kann eine nicht vorhandene Klasse nicht erzeugen.
Installierte BizTalk-Version, WQL und Properties pruefen.
## 11. Konfiguration
Alle AppSettings befinden sich in:
```text
%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe.config
```
Runtime:
| Key | Default | Bereich |
| --- | --- | --- |
| `SnapshotPath` | `%ProgramData%\BizTalkCheckmkPulse\data\...` | absolut |
| `SnapshotMaxAgeSeconds` | `180` | 60 bis 86400 |
| `SnapshotMaxBytes` | `1048576` | 4096 bis 16777216 |
| `LogDirectory` | `%ProgramData%\BizTalkCheckmkPulse\logs` | absolut |
| `LogRetentionDays` | `30` | 1 bis 365 |
BizTalk-Probes:
| Key | Default |
| --- | --- |
| `Server` | `.` |
| `QueryTimeoutSeconds` | `25` |
| `ProbeSqlConnectivity` | `true` |
| `SqlConnectionTimeoutSeconds` | `5` |
| `ProbeEventLog` | `true` |
| `EventLogLookbackMinutes` | `60` |
Alarmierung:
| Key | Default |
| --- | --- |
| `WarnResumableThreshold` | `1` |
| `CritNonResumableThreshold` | `1` |
| `AlertOnArtifactRuntimeIssues` | `false` |
| `EmitPerApplicationSuspensionServices` | `false` |
| `EventLogWarnThreshold` | `1` |
| `EventLogCritThreshold` | `10` |
## 12. Tests und Abnahmekriterien
Automatisiert:
- Release-Build .NET Framework 4.7.2,
- exakt sechs Self-Test-Services,
- unbekannte Quellen werden `UNKNOWN`,
- dynamische Anwendungsservices nur bei bekannter Anwendung,
- WMI-Queryvertrag nutzt dokumentierte Properties,
- eingebetteter SQL-Loginfehler wird `Permission`,
- abgewiesener Principal wird extrahiert,
- Snapshot-Roundtrip und Ersatz,
- SHA-256-Manipulation wird verworfen,
- Stale-Snapshot wird verworfen,
- Consumer-Fallback enthaelt sechs `UNKNOWN`-Services.
Windows-/ACC-Abnahme:
1. `LastTaskResult=0`.
2. Snapshot wird mindestens dreimal minuetlich aktualisiert.
3. Provider-Log nennt das dedizierte Konto.
4. `BizTalk Platform` zeigt `read_only_group=`.
5. `BizTalk SQL Access`: `targets=2`, `available=2`.
6. keine Permission-`UNKNOWN`s.
7. ACL-Test: `LocalSystem` kann Snapshot lesen, nicht schreiben.
8. Task deaktivieren: nach 180 Sekunden sechs stale-`UNKNOWN`s.
9. Task wieder aktivieren: naechster Snapshot stellt Echtzustand her.
10. Agent-Dump und Checkmk Service Discovery erfolgreich.
Erst nach ACC-Abnahme erfolgt der gestufte Rollout nach DEV/TST/PRD.
## 13. Deinstallation und Rollback
```powershell
.\Uninstall-BizTalkCheckmkPulse.ps1
```
`-KeepRuntimeData` erhaelt Logs und Snapshot. Das Skript entfernt Task,
Wrapper und Programmdateien, aber keine AD-Gruppenmitgliedschaft. Die
Berechtigung wird separat nach Change-Verfahren entzogen.
Rollback auf die alte direkte `LocalSystem`-Architektur ist nicht empfohlen.
Falls kurzfristig notwendig, muss Security die Maschinenkonto-Berechtigung
explizit freigeben; der Checkmk-Agentdienst selbst darf nicht auf das
Collector-Konto umgestellt werden.
## 14. Transport per certutil
Die Source-Uebergabe besteht aus ZIP plus Base64-TXT:
```cmd
certutil -decode <datei>.zip.b64.txt <datei>.zip
certutil -hashfile <datei>.zip SHA256
tar -xf <datei>.zip
```
ZIP und Base64 werden erst nach dem Git-Commit aus genau diesem Commit erzeugt.
## 15. Referenzen
- https://learn.microsoft.com/en-us/biztalk/core/managing-biztalk-server-security
- https://learn.microsoft.com/en-us/biztalk/core/windows-groups-and-user-accounts-in-biztalk-server
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-groupsetting-biztalkreadonlyusergroup-property-wmi
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-groupsetting-wmi
- https://docs.checkmk.com/latest/en/agent_windows.html
- https://docs.checkmk.com/latest/en/localchecks.html
- https://docs.checkmk.com/latest/en/spool_directory.html