Merge origin/main into main
This commit is contained in:
@@ -6,6 +6,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizTalkCheckmkPulse", "src\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizTalkCheckmkPulse.Tests", "tests\BizTalkCheckmkPulse.Tests\BizTalkCheckmkPulse.Tests.csproj", "{E219C45A-CC95-4F45-9B6F-8244CBAEE35A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizTalkCheckmkPulse.Tests", "tests\BizTalkCheckmkPulse.Tests\BizTalkCheckmkPulse.Tests.csproj", "{E219C45A-CC95-4F45-9B6F-8244CBAEE35A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizTalkCheckmkPulse.Setup", "src\BizTalkCheckmkPulse.Setup\BizTalkCheckmkPulse.Setup.csproj", "{764AC43A-26D8-43C1-9121-13FC8A9CC8B1}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizTalkCheckmkPulse.Packager", "src\BizTalkCheckmkPulse.Packager\BizTalkCheckmkPulse.Packager.csproj", "{B35A04E0-253B-4CEB-9033-F5109F3B9F82}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -20,6 +24,14 @@ Global
|
|||||||
{E219C45A-CC95-4F45-9B6F-8244CBAEE35A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{E219C45A-CC95-4F45-9B6F-8244CBAEE35A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{E219C45A-CC95-4F45-9B6F-8244CBAEE35A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{E219C45A-CC95-4F45-9B6F-8244CBAEE35A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{E219C45A-CC95-4F45-9B6F-8244CBAEE35A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{E219C45A-CC95-4F45-9B6F-8244CBAEE35A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{764AC43A-26D8-43C1-9121-13FC8A9CC8B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{764AC43A-26D8-43C1-9121-13FC8A9CC8B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{764AC43A-26D8-43C1-9121-13FC8A9CC8B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{764AC43A-26D8-43C1-9121-13FC8A9CC8B1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B35A04E0-253B-4CEB-9033-F5109F3B9F82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B35A04E0-253B-4CEB-9033-F5109F3B9F82}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B35A04E0-253B-4CEB-9033-F5109F3B9F82}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B35A04E0-253B-4CEB-9033-F5109F3B9F82}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
+26
-40
@@ -16,7 +16,7 @@ Verbindliche Randbedingungen:
|
|||||||
- Der Agentpfad fuehrt niemals WMI- oder SQL-Abfragen aus.
|
- Der Agentpfad fuehrt niemals WMI- oder SQL-Abfragen aus.
|
||||||
- Fehler muessen als gueltige Checkmk-`UNKNOWN`-Services sichtbar werden.
|
- Fehler muessen als gueltige Checkmk-`UNKNOWN`-Services sichtbar werden.
|
||||||
- Schreiben und Lesen duerfen nie einen halben Snapshot exponieren.
|
- Schreiben und Lesen duerfen nie einen halben Snapshot exponieren.
|
||||||
- Laufzeitcode benoetigt keine PowerShell und keine BizTalk-DLL-Referenz.
|
- Installation und Laufzeit benoetigen keine PowerShell und keine BizTalk-DLL-Referenz.
|
||||||
- Installation, ACL und Scheduled Task muessen reproduzierbar sein.
|
- Installation, ACL und Scheduled Task muessen reproduzierbar sein.
|
||||||
|
|
||||||
## 2. Ausloeser der Architekturanderung
|
## 2. Ausloeser der Architekturanderung
|
||||||
@@ -377,29 +377,30 @@ scripts\test-release.cmd
|
|||||||
scripts\package-release.cmd
|
scripts\package-release.cmd
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Der Release-Build der Visual-Studio-2019-Solution baut Anwendung, grafischen
|
||||||
|
Installer und Packaging-Werkzeug. Danach liegen der Paketordner
|
||||||
|
`artifacts\BizTalkCheckmkPulse-Setup` und das direkt transportierbare
|
||||||
|
`artifacts\BizTalkCheckmkPulse-Setup.zip` bereit.
|
||||||
|
|
||||||
### 8.2 Normales Servicekonto
|
### 8.2 Normales Servicekonto
|
||||||
|
|
||||||
```powershell
|
Das ZIP wird auf dem Zielserver vollstaendig entpackt. Danach `Setup.exe` als
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
Administrator starten, Konto im Format `DOMAIN\Benutzer` (zum Beispiel
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk' `
|
`BEW\t231bizmon`), Kennwort und Umgebung eintragen und die Installation
|
||||||
-EnvironmentName ACC
|
starten.
|
||||||
```
|
|
||||||
|
|
||||||
Der Installer muss als lokaler Administrator laufen. Er vergibt keine
|
Der Installer muss als lokaler Administrator laufen. Er vergibt keine
|
||||||
AD-/BizTalk-/SQL-Rechte; diese bleiben getrennte administrative Freigaben.
|
AD-/BizTalk-/SQL-Rechte; diese bleiben getrennte administrative Freigaben.
|
||||||
|
|
||||||
Der installierte Task selbst laeuft mit `RunLevel Limited`. Der Installer fragt
|
Der installierte Task selbst laeuft mit `RunLevel Limited`. Der Installer
|
||||||
das Kennwort mit `Get-Credential` ab; es wird nicht in Config oder Log
|
uebergibt das Kennwort direkt an die Windows-Task-Scheduler-COM-Schnittstelle;
|
||||||
|
es wird weder in einer Prozesskommandozeile noch in Config oder Log
|
||||||
geschrieben. Das Konto benoetigt `Log on as a batch job`.
|
geschrieben. Das Konto benoetigt `Log on as a batch job`.
|
||||||
|
|
||||||
### 8.3 Optionales gMSA
|
### 8.3 Optionales gMSA
|
||||||
|
|
||||||
```powershell
|
Im Installer die gMSA-Checkbox aktivieren und ein auf `$` endendes Konto wie
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
`BEW\svc_biztalk_cmk$` eingeben. Ein Kennwort wird dann nicht abgefragt.
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk$' `
|
|
||||||
-Gmsa `
|
|
||||||
-EnvironmentName ACC
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.4 Checkmk
|
### 8.4 Checkmk
|
||||||
|
|
||||||
@@ -451,12 +452,12 @@ aelter als `LogRetentionDays`.
|
|||||||
|
|
||||||
### 10.1 Grundpruefung
|
### 10.1 Grundpruefung
|
||||||
|
|
||||||
```powershell
|
```cmd
|
||||||
Get-ScheduledTaskInfo -TaskName 'BizTalk Checkmk Pulse Provider'
|
schtasks.exe /query /tn "BizTalk Checkmk Pulse Provider" /v /fo list
|
||||||
Get-Item "$env:ProgramData\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot"
|
dir "%ProgramData%\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot"
|
||||||
Get-Content "$env:ProgramData\BizTalkCheckmkPulse\logs\*.log" -Tail 100
|
type "%ProgramData%\BizTalkCheckmkPulse\logs\biztalk-checkmk-pulse-*.log"
|
||||||
& "$env:ProgramFiles\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
|
"%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
|
||||||
& "C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump
|
"C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump
|
||||||
```
|
```
|
||||||
|
|
||||||
### 10.2 Kein Snapshot
|
### 10.2 Kein Snapshot
|
||||||
@@ -615,32 +616,17 @@ Erst nach ACC-Abnahme erfolgt der gestufte Rollout nach DEV/TST/PRD.
|
|||||||
|
|
||||||
## 13. Deinstallation und Rollback
|
## 13. Deinstallation und Rollback
|
||||||
|
|
||||||
```powershell
|
`Setup.exe` aus dem entpackten Paket erneut starten und **Deinstallieren**
|
||||||
.\Uninstall-BizTalkCheckmkPulse.ps1
|
waehlen. Der Installer entfernt Task, Wrapper und Programmdateien, behaelt
|
||||||
```
|
Logs und Snapshot aber absichtlich bei. Die AD-Gruppenmitgliedschaft wird
|
||||||
|
nicht geaendert und separat nach Change-Verfahren entzogen.
|
||||||
`-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.
|
Rollback auf die alte direkte `LocalSystem`-Architektur ist nicht empfohlen.
|
||||||
Falls kurzfristig notwendig, muss Security die Maschinenkonto-Berechtigung
|
Falls kurzfristig notwendig, muss Security die Maschinenkonto-Berechtigung
|
||||||
explizit freigeben; der Checkmk-Agentdienst selbst darf nicht auf das
|
explizit freigeben; der Checkmk-Agentdienst selbst darf nicht auf das
|
||||||
Collector-Konto umgestellt werden.
|
Collector-Konto umgestellt werden.
|
||||||
|
|
||||||
## 14. Transport per certutil
|
## 14. Referenzen
|
||||||
|
|
||||||
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/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/windows-groups-and-user-accounts-in-biztalk-server
|
||||||
|
|||||||
@@ -164,22 +164,29 @@ scripts\test-release.cmd
|
|||||||
scripts\package-release.cmd
|
scripts\package-release.cmd
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Paket wird unter `artifacts\BizTalkCheckmkPulse-deploy` erzeugt:
|
Jeder Release-Build der Solution erzeugt automatisch den fertigen Paketordner
|
||||||
|
und das transportierbare ZIP:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
BizTalkCheckmkPulse-deploy\
|
artifacts\
|
||||||
Install-BizTalkCheckmkPulse.ps1
|
BizTalkCheckmkPulse-Setup.zip
|
||||||
Uninstall-BizTalkCheckmkPulse.ps1
|
BizTalkCheckmkPulse-Setup\
|
||||||
biztalk_checkmk_pulse.cmd
|
Setup.exe
|
||||||
application\
|
INSTALLATION.md
|
||||||
BizTalkCheckmkPulse.exe
|
biztalk_checkmk_pulse.cmd
|
||||||
BizTalkCheckmkPulse.exe.config
|
application\
|
||||||
|
BizTalkCheckmkPulse.exe
|
||||||
|
BizTalkCheckmkPulse.exe.config
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Das Packaging-Projekt ist Teil von `BizTalkCheckmkPulse.sln`. Ein normaler
|
||||||
|
`Release`-Build in Visual Studio 2019 genuegt daher; ein separates
|
||||||
|
PowerShell-/WiX-/MSI-Tooling wird nicht benoetigt.
|
||||||
|
|
||||||
Format-Self-Test ohne WMI, SQL oder Event Log:
|
Format-Self-Test ohne WMI, SQL oder Event Log:
|
||||||
|
|
||||||
```cmd
|
```cmd
|
||||||
artifacts\BizTalkCheckmkPulse-deploy\application\BizTalkCheckmkPulse.exe --self-test
|
artifacts\BizTalkCheckmkPulse-Setup\application\BizTalkCheckmkPulse.exe --self-test
|
||||||
```
|
```
|
||||||
|
|
||||||
Erwartet werden exakt neun `OK`-Zeilen. Die Regressionstests pruefen
|
Erwartet werden exakt neun `OK`-Zeilen. Die Regressionstests pruefen
|
||||||
@@ -191,16 +198,7 @@ Windows-/BizTalk-Laufzeitvalidierung.
|
|||||||
## Berechtigung vorbereiten
|
## Berechtigung vorbereiten
|
||||||
|
|
||||||
Die exakte Read-Only-Gruppe wird in der BizTalk Administration Console unter
|
Die exakte Read-Only-Gruppe wird in der BizTalk Administration Console unter
|
||||||
den Eigenschaften der BizTalk-Gruppe abgelesen. Ein bereits berechtigtes Konto
|
den Eigenschaften der BizTalk-Gruppe abgelesen.
|
||||||
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
|
Ein AD-Administrator nimmt das neue Provider-Konto in
|
||||||
`BizTalkReadOnlyUserGroup` auf. Nach AD-Replikation muss das Servicekonto durch
|
`BizTalkReadOnlyUserGroup` auf. Nach AD-Replikation muss das Servicekonto durch
|
||||||
@@ -215,22 +213,23 @@ fuer das Provider-Konto.
|
|||||||
|
|
||||||
## Installation mit normalem Servicekonto
|
## Installation mit normalem Servicekonto
|
||||||
|
|
||||||
```powershell
|
1. `BizTalkCheckmkPulse-Setup.zip` auf dem Zielserver vollstaendig entpacken.
|
||||||
Set-Location C:\Temp\BizTalkCheckmkPulse-deploy
|
2. `Setup.exe` starten und die UAC-Abfrage bestaetigen.
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
3. Collector-Konto, zum Beispiel `BEW\t231bizmon`, Kennwort und Umgebung
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk' `
|
eingeben.
|
||||||
-EnvironmentName ACC
|
4. **Installieren / aktualisieren** waehlen.
|
||||||
```
|
|
||||||
|
|
||||||
Der Installer fragt das Kennwort ueber `Get-Credential` ab und speichert es
|
Der Installer uebergibt das Kennwort direkt ueber die Windows-Task-Scheduler-
|
||||||
durch die Windows-Aufgabenplanung. Das Kennwort steht weder in der
|
COM-Schnittstelle. Es steht weder in einer Prozesskommandozeile noch in der
|
||||||
Konfigurationsdatei noch in den Logs.
|
Konfigurationsdatei oder in Logs. Der Backslash in `DOMAIN\Benutzer` wird als
|
||||||
|
normaler Bestandteil des Kontonamens verarbeitet.
|
||||||
|
|
||||||
Wenn das Kennwort rotiert oder ablaeuft, muss es im Scheduled Task aktualisiert
|
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
|
werden. Dazu `Setup.exe` mit dem neuen Kennwort erneut ausfuehren. Bis dahin
|
||||||
alle neun Services als `UNKNOWN`.
|
wird der Snapshot nach 180 Sekunden stale und Checkmk zeigt alle acht Services
|
||||||
|
als `UNKNOWN`.
|
||||||
|
|
||||||
Ein gMSA kann weiterhin optional mit `-Gmsa` installiert werden; die
|
Ein gMSA kann ueber die Checkbox ohne Kennworteingabe installiert werden; die
|
||||||
produktive Standardbeschreibung geht vom normalen Servicekonto aus.
|
produktive Standardbeschreibung geht vom normalen Servicekonto aus.
|
||||||
|
|
||||||
Der Installer:
|
Der Installer:
|
||||||
@@ -245,48 +244,34 @@ Der Installer:
|
|||||||
`IgnoreNew`, fuenf Minuten Laufzeitlimit und zwei Wiederholungen,
|
`IgnoreNew`, fuenf Minuten Laufzeitlimit und zwei Wiederholungen,
|
||||||
6. fuehrt den Self-Test aus und startet den Provider einmalig.
|
6. fuehrt den Self-Test aus und startet den Provider einmalig.
|
||||||
|
|
||||||
PowerShell wird nur fuer Installation und Betriebsdiagnose verwendet. Der
|
Installation, Update, Deinstallation und Laufzeit verwenden keine PowerShell.
|
||||||
minuetliche Provider und der Checkmk-Consumer sind .NET-/CMD-Laufzeitcode und
|
|
||||||
haengen nicht von der PowerShell Execution Policy ab.
|
|
||||||
|
|
||||||
## Verifikation auf dem Server
|
## Verifikation auf dem Server
|
||||||
|
|
||||||
Task und letzter Lauf:
|
Task und letzter Lauf:
|
||||||
|
|
||||||
```powershell
|
```cmd
|
||||||
Get-ScheduledTask -TaskName 'BizTalk Checkmk Pulse Provider' |
|
schtasks.exe /query /tn "BizTalk Checkmk Pulse Provider" /v /fo list
|
||||||
Select-Object TaskName, State
|
|
||||||
Get-ScheduledTaskInfo -TaskName 'BizTalk Checkmk Pulse Provider' |
|
|
||||||
Select-Object LastRunTime, LastTaskResult, NextRunTime
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Provider-Log:
|
Provider-Log:
|
||||||
|
|
||||||
```powershell
|
```cmd
|
||||||
Get-ChildItem "$env:ProgramData\BizTalkCheckmkPulse\logs" |
|
dir /o-d "%ProgramData%\BizTalkCheckmkPulse\logs"
|
||||||
Sort-Object LastWriteTime -Descending |
|
type "%ProgramData%\BizTalkCheckmkPulse\logs\biztalk-checkmk-pulse-*.log"
|
||||||
Select-Object -First 3 Name, Length, LastWriteTime
|
|
||||||
|
|
||||||
Get-Content `
|
|
||||||
"$env:ProgramData\BizTalkCheckmkPulse\logs\biztalk-checkmk-pulse-*.log" `
|
|
||||||
-Tail 100
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Snapshot und Consumer:
|
Snapshot und Consumer:
|
||||||
|
|
||||||
```powershell
|
```cmd
|
||||||
Get-Item `
|
dir "%ProgramData%\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot"
|
||||||
"$env:ProgramData\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot" |
|
"%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
|
||||||
Select-Object FullName, Length, LastWriteTimeUtc
|
|
||||||
|
|
||||||
& "$env:ProgramFiles\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Verbindlicher Test im echten `LocalSystem`-Kontext:
|
Verbindlicher Test im echten `LocalSystem`-Kontext:
|
||||||
|
|
||||||
```powershell
|
```cmd
|
||||||
& "C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump |
|
"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
|
Danach in Checkmk eine Service Discovery ausfuehren, die neun Services
|
||||||
@@ -386,33 +371,12 @@ Ausfuehrliche Betriebs- und Architekturdetails stehen in
|
|||||||
|
|
||||||
## Deinstallation
|
## Deinstallation
|
||||||
|
|
||||||
```powershell
|
`Setup.exe` erneut starten und **Deinstallieren** waehlen. Snapshot und Logs
|
||||||
.\Uninstall-BizTalkCheckmkPulse.ps1
|
bleiben dabei unter `%ProgramData%\BizTalkCheckmkPulse` erhalten.
|
||||||
```
|
|
||||||
|
|
||||||
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
|
Die AD-Gruppenmitgliedschaft des Provider-Kontos wird bewusst nicht automatisch
|
||||||
geaendert und muss separat durch AD-/BizTalk-Administration entfernt werden.
|
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-<datum>-<commit>.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
|
## Quellen
|
||||||
|
|
||||||
- Microsoft: BizTalk `MSBTS_GroupSetting.BizTalkReadOnlyUserGroup`
|
- Microsoft: BizTalk `MSBTS_GroupSetting.BizTalkReadOnlyUserGroup`
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Installation auf dem BizTalk-Server
|
||||||
|
|
||||||
|
1. `BizTalkCheckmkPulse-Setup.zip` vollstaendig in ein lokales Verzeichnis entpacken.
|
||||||
|
2. `Setup.exe` als lokaler Administrator starten und die UAC-Abfrage bestaetigen.
|
||||||
|
3. Das Collector-Konto im Format `DOMAIN\Benutzer` eingeben, zum Beispiel
|
||||||
|
`BEW\t231bizmon`.
|
||||||
|
4. Kennwort und Umgebung eingeben und **Installieren / aktualisieren** waehlen.
|
||||||
|
5. Im Aufgabenplaner den Task `BizTalk Checkmk Pulse Provider` und danach den
|
||||||
|
Checkmk-Agent-Dump kontrollieren.
|
||||||
|
|
||||||
|
PowerShell wird fuer Installation, Update, Deinstallation und Laufzeit nicht
|
||||||
|
benoetigt. Das Kennwort wird direkt an die Windows-Aufgabenplanung uebergeben
|
||||||
|
und weder in einer Datei noch in einer Prozesskommandozeile abgelegt.
|
||||||
|
|
||||||
|
Der Installer vergibt keine AD-, BizTalk- oder SQL-Berechtigungen. Das Konto
|
||||||
|
muss separat Mitglied der fuer die BizTalk-Gruppe konfigurierten Read-Only-
|
||||||
|
Gruppe sein und lokal das Recht `Log on as a batch job` besitzen.
|
||||||
|
|
||||||
|
Bei einer Deinstallation bleiben Snapshot und Logs absichtlich unter
|
||||||
|
`%ProgramData%\BizTalkCheckmkPulse` erhalten. Sie koennen nach der
|
||||||
|
Betriebsfreigabe manuell entfernt werden.
|
||||||
@@ -1,171 +0,0 @@
|
|||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[string]$CollectorAccount,
|
|
||||||
|
|
||||||
[switch]$Gmsa,
|
|
||||||
|
|
||||||
[ValidateSet("", "ACC", "DEV", "TST", "PRD")]
|
|
||||||
[string]$EnvironmentName = "",
|
|
||||||
|
|
||||||
[string]$InstallDirectory = "$env:ProgramFiles\BizTalkCheckmkPulse",
|
|
||||||
|
|
||||||
[string]$CheckmkLocalDirectory = "$env:ProgramData\checkmk\agent\local"
|
|
||||||
)
|
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
|
||||||
Set-StrictMode -Version 2.0
|
|
||||||
|
|
||||||
$taskName = "BizTalk Checkmk Pulse Provider"
|
|
||||||
$runtimeRoot = Join-Path $env:ProgramData "BizTalkCheckmkPulse"
|
|
||||||
$dataDirectory = Join-Path $runtimeRoot "data"
|
|
||||||
$logDirectory = Join-Path $runtimeRoot "logs"
|
|
||||||
$sourceApplication = Join-Path $PSScriptRoot "application"
|
|
||||||
$sourceWrapper = Join-Path $PSScriptRoot "biztalk_checkmk_pulse.cmd"
|
|
||||||
$targetExe = Join-Path $InstallDirectory "BizTalkCheckmkPulse.exe"
|
|
||||||
$targetConfig = "$targetExe.config"
|
|
||||||
$targetWrapper = Join-Path $CheckmkLocalDirectory "biztalk_checkmk_pulse.cmd"
|
|
||||||
|
|
||||||
function Assert-Administrator {
|
|
||||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
|
||||||
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
|
|
||||||
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
||||||
throw "Die Installation muss in einer administrativen Windows PowerShell ausgefuehrt werden."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Invoke-Icacls {
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory = $true)][string]$Path,
|
|
||||||
[Parameter(Mandatory = $true)][string[]]$Arguments
|
|
||||||
)
|
|
||||||
|
|
||||||
& icacls.exe $Path @Arguments | Out-Host
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
|
||||||
throw "icacls ist fuer '$Path' mit Exitcode $LASTEXITCODE fehlgeschlagen."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert-Administrator
|
|
||||||
|
|
||||||
if (-not (Test-Path -LiteralPath $sourceApplication -PathType Container)) {
|
|
||||||
throw "Quellverzeichnis fehlt: $sourceApplication"
|
|
||||||
}
|
|
||||||
if (-not (Test-Path -LiteralPath $sourceWrapper -PathType Leaf)) {
|
|
||||||
throw "Checkmk-Wrapper fehlt: $sourceWrapper"
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Gmsa -and -not $CollectorAccount.EndsWith('$')) {
|
|
||||||
throw "Ein gMSA-Kontoname muss mit '$' enden, z.B. DOMAIN\svc_biztalk_cmk$."
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Installiere Programmdateien nach $InstallDirectory ..."
|
|
||||||
New-Item -ItemType Directory -Path $InstallDirectory -Force | Out-Null
|
|
||||||
Copy-Item -Path (Join-Path $sourceApplication "*") -Destination $InstallDirectory -Force
|
|
||||||
|
|
||||||
[xml]$configuration = Get-Content -LiteralPath $targetConfig
|
|
||||||
$environmentSetting = $configuration.configuration.appSettings.add |
|
|
||||||
Where-Object { $_.key -eq "EnvironmentName" } |
|
|
||||||
Select-Object -First 1
|
|
||||||
if ($null -eq $environmentSetting) {
|
|
||||||
throw "EnvironmentName fehlt in $targetConfig."
|
|
||||||
}
|
|
||||||
$environmentSetting.value = $EnvironmentName
|
|
||||||
$configuration.Save($targetConfig)
|
|
||||||
|
|
||||||
Write-Host "Erzeuge Runtime-Verzeichnisse und Least-Privilege-ACLs ..."
|
|
||||||
New-Item -ItemType Directory -Path $runtimeRoot, $dataDirectory, $logDirectory -Force | Out-Null
|
|
||||||
|
|
||||||
# Runtime-Root: Provider lesen, SYSTEM lesen, lokale Administratoren verwalten.
|
|
||||||
Invoke-Icacls -Path $runtimeRoot -Arguments @(
|
|
||||||
"/inheritance:r",
|
|
||||||
"/grant:r",
|
|
||||||
"*S-1-5-18:(OI)(CI)(RX)",
|
|
||||||
"*S-1-5-32-544:(OI)(CI)(F)",
|
|
||||||
"${CollectorAccount}:(OI)(CI)(RX)"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Daten: ausschliesslich Provider schreibt, LocalSystem liest den Snapshot.
|
|
||||||
Invoke-Icacls -Path $dataDirectory -Arguments @(
|
|
||||||
"/inheritance:r",
|
|
||||||
"/grant:r",
|
|
||||||
"*S-1-5-18:(OI)(CI)(RX)",
|
|
||||||
"*S-1-5-32-544:(OI)(CI)(F)",
|
|
||||||
"${CollectorAccount}:(OI)(CI)(M)"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Logs: Provider und LocalSystem-Consumer duerfen getrennte Diagnosezeilen anhaengen.
|
|
||||||
Invoke-Icacls -Path $logDirectory -Arguments @(
|
|
||||||
"/inheritance:r",
|
|
||||||
"/grant:r",
|
|
||||||
"*S-1-5-18:(OI)(CI)(M)",
|
|
||||||
"*S-1-5-32-544:(OI)(CI)(F)",
|
|
||||||
"${CollectorAccount}:(OI)(CI)(M)"
|
|
||||||
)
|
|
||||||
|
|
||||||
Write-Host "Installiere Checkmk Local Check nach $CheckmkLocalDirectory ..."
|
|
||||||
New-Item -ItemType Directory -Path $CheckmkLocalDirectory -Force | Out-Null
|
|
||||||
Copy-Item -LiteralPath $sourceWrapper -Destination $targetWrapper -Force
|
|
||||||
|
|
||||||
Write-Host "Registriere Scheduled Task '$taskName' ..."
|
|
||||||
$action = New-ScheduledTaskAction `
|
|
||||||
-Execute $targetExe `
|
|
||||||
-Argument "--collect" `
|
|
||||||
-WorkingDirectory $InstallDirectory
|
|
||||||
$trigger = New-ScheduledTaskTrigger `
|
|
||||||
-Once `
|
|
||||||
-At (Get-Date).AddMinutes(1) `
|
|
||||||
-RepetitionInterval (New-TimeSpan -Minutes 1)
|
|
||||||
$settings = New-ScheduledTaskSettingsSet `
|
|
||||||
-MultipleInstances IgnoreNew `
|
|
||||||
-ExecutionTimeLimit (New-TimeSpan -Minutes 5) `
|
|
||||||
-StartWhenAvailable `
|
|
||||||
-RestartCount 2 `
|
|
||||||
-RestartInterval (New-TimeSpan -Minutes 1)
|
|
||||||
|
|
||||||
if ($Gmsa) {
|
|
||||||
$principal = New-ScheduledTaskPrincipal `
|
|
||||||
-UserId $CollectorAccount `
|
|
||||||
-LogonType Password `
|
|
||||||
-RunLevel Limited
|
|
||||||
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal
|
|
||||||
Register-ScheduledTask -TaskName $taskName -InputObject $task -Force | Out-Null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$credential = Get-Credential `
|
|
||||||
-UserName $CollectorAccount `
|
|
||||||
-Message "Kennwort fuer das dedizierte BizTalk-Monitoringkonto eingeben"
|
|
||||||
if ($credential.UserName -ne $CollectorAccount) {
|
|
||||||
throw "Das eingegebene Konto stimmt nicht mit CollectorAccount ueberein."
|
|
||||||
}
|
|
||||||
|
|
||||||
$principal = New-ScheduledTaskPrincipal `
|
|
||||||
-UserId $CollectorAccount `
|
|
||||||
-LogonType Password `
|
|
||||||
-RunLevel Limited
|
|
||||||
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal
|
|
||||||
Register-ScheduledTask `
|
|
||||||
-TaskName $taskName `
|
|
||||||
-InputObject $task `
|
|
||||||
-User $CollectorAccount `
|
|
||||||
-Password $credential.GetNetworkCredential().Password `
|
|
||||||
-Force | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Fuehre formatseitigen Self-Test aus ..."
|
|
||||||
$selfTest = & $targetExe --self-test
|
|
||||||
if ($LASTEXITCODE -ne 0 -or @($selfTest).Count -ne 9) {
|
|
||||||
throw "Self-Test fehlgeschlagen. Erwartet wurden neun Checkmk-Zeilen."
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Starte den Provider einmalig ..."
|
|
||||||
Start-ScheduledTask -TaskName $taskName
|
|
||||||
|
|
||||||
Write-Host ""
|
|
||||||
Write-Host "Installation abgeschlossen."
|
|
||||||
Write-Host "Naechste Pruefungen:"
|
|
||||||
Write-Host " Get-ScheduledTaskInfo -TaskName '$taskName'"
|
|
||||||
Write-Host " Get-Content '$logDirectory\biztalk-checkmk-pulse-*.log' -Tail 50"
|
|
||||||
Write-Host " & '$targetExe' --consume"
|
|
||||||
Write-Host " & 'C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe' dump"
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "High")]
|
|
||||||
param(
|
|
||||||
[string]$InstallDirectory = "$env:ProgramFiles\BizTalkCheckmkPulse",
|
|
||||||
[string]$CheckmkLocalDirectory = "$env:ProgramData\checkmk\agent\local",
|
|
||||||
[switch]$KeepRuntimeData
|
|
||||||
)
|
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
|
||||||
$taskName = "BizTalk Checkmk Pulse Provider"
|
|
||||||
$runtimeRoot = Join-Path $env:ProgramData "BizTalkCheckmkPulse"
|
|
||||||
$wrapper = Join-Path $CheckmkLocalDirectory "biztalk_checkmk_pulse.cmd"
|
|
||||||
|
|
||||||
if ($PSCmdlet.ShouldProcess($taskName, "Scheduled Task entfernen")) {
|
|
||||||
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
if (Test-Path -LiteralPath $wrapper) {
|
|
||||||
if ($PSCmdlet.ShouldProcess($wrapper, "Checkmk Local Check entfernen")) {
|
|
||||||
Remove-Item -LiteralPath $wrapper -Force
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Test-Path -LiteralPath $InstallDirectory) {
|
|
||||||
if ($PSCmdlet.ShouldProcess($InstallDirectory, "Programmdateien entfernen")) {
|
|
||||||
Remove-Item -LiteralPath $InstallDirectory -Recurse -Force
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (-not $KeepRuntimeData -and (Test-Path -LiteralPath $runtimeRoot)) {
|
|
||||||
if ($PSCmdlet.ShouldProcess($runtimeRoot, "Snapshot und Logs entfernen")) {
|
|
||||||
Remove-Item -LiteralPath $runtimeRoot -Recurse -Force
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@ set "BASE=%ProgramFiles%\BizTalkCheckmkPulse"
|
|||||||
set "EXE=%BASE%\BizTalkCheckmkPulse.exe"
|
set "EXE=%BASE%\BizTalkCheckmkPulse.exe"
|
||||||
|
|
||||||
if not exist "%EXE%" (
|
if not exist "%EXE%" (
|
||||||
echo 3 "BizTalk Platform" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Install-BizTalkCheckmkPulse.ps1 erneut als Administrator ausfuehren und danach cmk-agent-ctl.exe dump erneut ausfuehren.
|
echo 3 "BizTalk Platform" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Setup.exe erneut als Administrator ausfuehren und danach cmk-agent-ctl.exe dump erneut ausfuehren.
|
||||||
echo 3 "BizTalk SQL Access" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
echo 3 "BizTalk SQL Access" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
echo 3 "BizTalk Suspended Instances" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
echo 3 "BizTalk Suspended Instances" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
echo 3 "BizTalk Host Instances" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
echo 3 "BizTalk Host Instances" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
|
|||||||
@@ -37,15 +37,10 @@ Bevorzugte Rolle fuer BizTalk Server 2020:
|
|||||||
BizTalk Server Read Only Users
|
BizTalk Server Read Only Users
|
||||||
SQL-Datenbankrolle: BTS_READONLY_USERS
|
SQL-Datenbankrolle: BTS_READONLY_USERS
|
||||||
|
|
||||||
Die exakt konfigurierte Gruppe mit einem bereits berechtigten Konto ermitteln:
|
Die exakt konfigurierte Gruppe in den Eigenschaften der BizTalk-Gruppe in der
|
||||||
|
BizTalk Administration Console ablesen. Das Provider-Konto durch
|
||||||
Get-CimInstance -Namespace root/MicrosoftBizTalkServer `
|
AD-Administration in BizTalkReadOnlyUserGroup aufnehmen. Nicht vom
|
||||||
-ClassName MSBTS_GroupSetting |
|
Standardnamen ausgehen.
|
||||||
Select-Object Name, BizTalkReadOnlyUserGroup, BizTalkOperatorGroup,
|
|
||||||
MgmtDbServerName, MgmtDbName
|
|
||||||
|
|
||||||
Das Provider-Konto durch AD-Administration in BizTalkReadOnlyUserGroup
|
|
||||||
aufnehmen. Nicht vom Standardnamen ausgehen.
|
|
||||||
|
|
||||||
Die Operator-Gruppe ist nur eine begruendungspflichtige Eskalation, falls eine
|
Die Operator-Gruppe ist nur eine begruendungspflichtige Eskalation, falls eine
|
||||||
konkret benoetigte WMI-Klasse trotz bestaetigter Read-Only-Zuordnung und neuem
|
konkret benoetigte WMI-Klasse trotz bestaetigter Read-Only-Zuordnung und neuem
|
||||||
@@ -64,28 +59,19 @@ NICHT DURCHFUEHREN
|
|||||||
INSTALLATION
|
INSTALLATION
|
||||||
============
|
============
|
||||||
|
|
||||||
Normales Servicekonto:
|
BizTalkCheckmkPulse-Setup.zip vollstaendig entpacken und Setup.exe als
|
||||||
|
Administrator starten. Konto im Format DOMAIN\Benutzer (zum Beispiel
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
BEW\t231bizmon), Kennwort und Umgebung eingeben. PowerShell wird nicht
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk' `
|
benoetigt.
|
||||||
-EnvironmentName ACC
|
|
||||||
|
|
||||||
VERIFIKATION
|
VERIFIKATION
|
||||||
============
|
============
|
||||||
|
|
||||||
Get-ScheduledTaskInfo -TaskName 'BizTalk Checkmk Pulse Provider'
|
schtasks.exe /query /tn "BizTalk Checkmk Pulse Provider" /v /fo list
|
||||||
|
dir "%ProgramData%\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot"
|
||||||
Get-Content `
|
type "%ProgramData%\BizTalkCheckmkPulse\logs\biztalk-checkmk-pulse-*.log"
|
||||||
"$env:ProgramData\BizTalkCheckmkPulse\logs\*.log" `
|
"%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
|
||||||
-Tail 100
|
"C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump
|
||||||
|
|
||||||
Get-Item `
|
|
||||||
"$env:ProgramData\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot"
|
|
||||||
|
|
||||||
& "$env:ProgramFiles\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
|
|
||||||
|
|
||||||
& "C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump |
|
|
||||||
Select-String -Pattern "BizTalk|UNKNOWN|Permission|snapshot" -Context 0,1
|
|
||||||
|
|
||||||
ERWARTET
|
ERWARTET
|
||||||
========
|
========
|
||||||
|
|||||||
+13
-17
@@ -15,13 +15,10 @@ Provider-Konto und publiziert einen validierbaren Snapshot.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Normales Servicekonto:
|
`BizTalkCheckmkPulse-Setup.zip` vollstaendig entpacken, `Setup.exe` als
|
||||||
|
Administrator starten und Konto, Kennwort sowie Umgebung eingeben. Konten wie
|
||||||
```powershell
|
`BEW\t231bizmon` werden direkt im Windows-Format `DOMAIN\Benutzer` verarbeitet.
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
Der Installer benoetigt keine PowerShell.
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk' `
|
|
||||||
-EnvironmentName ACC
|
|
||||||
```
|
|
||||||
|
|
||||||
Der Installer legt den Local Check hier ab:
|
Der Installer legt den Local Check hier ab:
|
||||||
|
|
||||||
@@ -44,15 +41,14 @@ Verzoegerung zum minuetlichen Provider.
|
|||||||
|
|
||||||
Aktive Agentkonfiguration pruefen:
|
Aktive Agentkonfiguration pruefen:
|
||||||
|
|
||||||
```powershell
|
```cmd
|
||||||
& "C:\Program Files (x86)\checkmk\service\check_mk_agent.exe" showconfig local
|
"C:\Program Files (x86)\checkmk\service\check_mk_agent.exe" showconfig local
|
||||||
```
|
```
|
||||||
|
|
||||||
Verbindlicher Agent-Dump:
|
Verbindlicher Agent-Dump:
|
||||||
|
|
||||||
```powershell
|
```cmd
|
||||||
& "C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump |
|
"C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe" dump
|
||||||
Select-String -Pattern "BizTalk|UNKNOWN|snapshot|Permission" -Context 0,1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Service Discovery
|
## Service Discovery
|
||||||
@@ -95,11 +91,11 @@ Installationsautomation die klarere Variante.
|
|||||||
|
|
||||||
## Healthchecks
|
## Healthchecks
|
||||||
|
|
||||||
```powershell
|
```cmd
|
||||||
Get-ScheduledTaskInfo -TaskName 'BizTalk Checkmk Pulse Provider'
|
schtasks.exe /query /tn "BizTalk Checkmk Pulse Provider" /v /fo list
|
||||||
Get-Item "$env:ProgramData\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot"
|
dir "%ProgramData%\BizTalkCheckmkPulse\data\biztalk-checkmk-pulse.snapshot"
|
||||||
Get-Content "$env:ProgramData\BizTalkCheckmkPulse\logs\*.log" -Tail 50
|
type "%ProgramData%\BizTalkCheckmkPulse\logs\biztalk-checkmk-pulse-*.log"
|
||||||
& "$env:ProgramFiles\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
|
"%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe" --consume
|
||||||
```
|
```
|
||||||
|
|
||||||
Soll:
|
Soll:
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ if errorlevel 1 (
|
|||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
msbuild BizTalkCheckmkPulse.sln /p:Configuration=Release /p:Platform="Any CPU" /m:1 /v:minimal
|
msbuild "%~dp0..\BizTalkCheckmkPulse.sln" /p:Configuration=Release /p:Platform="Any CPU" /m:1 /v:minimal
|
||||||
exit /b %ERRORLEVEL%
|
exit /b %ERRORLEVEL%
|
||||||
|
|||||||
@@ -4,18 +4,6 @@ setlocal
|
|||||||
call "%~dp0build-release.cmd"
|
call "%~dp0build-release.cmd"
|
||||||
if errorlevel 1 exit /b 1
|
if errorlevel 1 exit /b 1
|
||||||
|
|
||||||
set "ROOT=%~dp0.."
|
echo Install package written to artifacts\BizTalkCheckmkPulse-Setup
|
||||||
set "OUT=%ROOT%\artifacts\BizTalkCheckmkPulse-deploy"
|
echo Install ZIP written to artifacts\BizTalkCheckmkPulse-Setup.zip
|
||||||
set "APP=%OUT%\application"
|
|
||||||
|
|
||||||
if exist "%OUT%" rmdir /s /q "%OUT%"
|
|
||||||
mkdir "%APP%"
|
|
||||||
|
|
||||||
copy "%ROOT%\deployment\checkmk\biztalk_checkmk_pulse.cmd" "%OUT%\" >nul
|
|
||||||
copy "%ROOT%\deployment\Install-BizTalkCheckmkPulse.ps1" "%OUT%\" >nul
|
|
||||||
copy "%ROOT%\deployment\Uninstall-BizTalkCheckmkPulse.ps1" "%OUT%\" >nul
|
|
||||||
copy "%ROOT%\src\BizTalkCheckmkPulse\bin\Release\BizTalkCheckmkPulse.exe" "%APP%\" >nul
|
|
||||||
copy "%ROOT%\src\BizTalkCheckmkPulse\bin\Release\BizTalkCheckmkPulse.exe.config" "%APP%\" >nul
|
|
||||||
|
|
||||||
echo Deployment package written to %OUT%
|
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" Condition="false" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{B35A04E0-253B-4CEB-9033-F5109F3B9F82}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>BizTalkCheckmkPulse.Packager</RootNamespace>
|
||||||
|
<AssemblyName>BizTalkCheckmkPulse.Packager</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.IO.Compression" />
|
||||||
|
<Reference Include="System.IO.Compression.FileSystem" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\BizTalkCheckmkPulse\BizTalkCheckmkPulse.csproj">
|
||||||
|
<Project>{A4D4D050-9EA7-4A71-B510-7D9D699B9F38}</Project>
|
||||||
|
<Name>BizTalkCheckmkPulse</Name>
|
||||||
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\BizTalkCheckmkPulse.Setup\BizTalkCheckmkPulse.Setup.csproj">
|
||||||
|
<Project>{764AC43A-26D8-43C1-9121-13FC8A9CC8B1}</Project>
|
||||||
|
<Name>BizTalkCheckmkPulse.Setup</Name>
|
||||||
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Target Name="CreateInstallPackage" AfterTargets="Build" Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<Exec Command=""$(TargetPath)" "$(MSBuildProjectDirectory)\..\.." "$(Configuration)"" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
|
||||||
|
namespace BizTalkCheckmkPulse.Packager
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
private static int Main(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (args.Length != 2) throw new ArgumentException("Usage: BizTalkCheckmkPulse.Packager.exe <repository-root> <configuration>");
|
||||||
|
var root = Path.GetFullPath(args[0]);
|
||||||
|
var configuration = args[1];
|
||||||
|
var artifacts = Path.Combine(root, "artifacts");
|
||||||
|
var package = Path.Combine(artifacts, "BizTalkCheckmkPulse-Setup");
|
||||||
|
var application = Path.Combine(package, "application");
|
||||||
|
var zip = Path.Combine(artifacts, "BizTalkCheckmkPulse-Setup.zip");
|
||||||
|
|
||||||
|
if (Directory.Exists(package)) Directory.Delete(package, true);
|
||||||
|
Directory.CreateDirectory(application);
|
||||||
|
|
||||||
|
Copy(
|
||||||
|
Path.Combine(root, "src", "BizTalkCheckmkPulse.Setup", "bin", configuration, "BizTalkCheckmkPulse.Setup.exe"),
|
||||||
|
Path.Combine(package, "Setup.exe"));
|
||||||
|
Copy(
|
||||||
|
Path.Combine(root, "src", "BizTalkCheckmkPulse", "bin", configuration, "BizTalkCheckmkPulse.exe"),
|
||||||
|
Path.Combine(application, "BizTalkCheckmkPulse.exe"));
|
||||||
|
Copy(
|
||||||
|
Path.Combine(root, "src", "BizTalkCheckmkPulse", "bin", configuration, "BizTalkCheckmkPulse.exe.config"),
|
||||||
|
Path.Combine(application, "BizTalkCheckmkPulse.exe.config"));
|
||||||
|
Copy(
|
||||||
|
Path.Combine(root, "deployment", "checkmk", "biztalk_checkmk_pulse.cmd"),
|
||||||
|
Path.Combine(package, "biztalk_checkmk_pulse.cmd"));
|
||||||
|
Copy(
|
||||||
|
Path.Combine(root, "deployment", "INSTALLATION.md"),
|
||||||
|
Path.Combine(package, "INSTALLATION.md"));
|
||||||
|
|
||||||
|
if (File.Exists(zip)) File.Delete(zip);
|
||||||
|
ZipFile.CreateFromDirectory(package, zip, CompressionLevel.Optimal, false);
|
||||||
|
Console.WriteLine("Install package: " + package);
|
||||||
|
Console.WriteLine("Install ZIP: " + zip);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Packaging failed: " + ex.Message);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Copy(string source, string target)
|
||||||
|
{
|
||||||
|
if (!File.Exists(source)) throw new FileNotFoundException("Required package file missing: " + source, source);
|
||||||
|
File.Copy(source, target, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" Condition="false" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{764AC43A-26D8-43C1-9121-13FC8A9CC8B1}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<RootNamespace>BizTalkCheckmkPulse.Setup</RootNamespace>
|
||||||
|
<AssemblyName>BizTalkCheckmkPulse.Setup</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Security" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="InstallerEngine.cs" />
|
||||||
|
<Compile Include="MainForm.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="TaskSchedulerService.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="app.manifest" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.AccessControl;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace BizTalkCheckmkPulse.Setup
|
||||||
|
{
|
||||||
|
internal sealed class InstallerEngine
|
||||||
|
{
|
||||||
|
internal const string TaskName = "BizTalk Checkmk Pulse Provider";
|
||||||
|
private readonly string packageDirectory;
|
||||||
|
private readonly string installDirectory;
|
||||||
|
private readonly string runtimeDirectory;
|
||||||
|
private readonly string checkmkLocalDirectory;
|
||||||
|
|
||||||
|
public InstallerEngine(string packageDirectory)
|
||||||
|
{
|
||||||
|
this.packageDirectory = Path.GetFullPath(packageDirectory);
|
||||||
|
installDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "BizTalkCheckmkPulse");
|
||||||
|
runtimeDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "BizTalkCheckmkPulse");
|
||||||
|
checkmkLocalDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "checkmk", "agent", "local");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Install(string account, string password, bool isGmsa, string environmentName, Action<string> report)
|
||||||
|
{
|
||||||
|
Validate(account, password, isGmsa, environmentName);
|
||||||
|
var accountSid = (SecurityIdentifier)new NTAccount(account).Translate(typeof(SecurityIdentifier));
|
||||||
|
report("Konto aufgeloest: " + account + " (" + accountSid.Value + ")");
|
||||||
|
|
||||||
|
var sourceApplication = Path.Combine(packageDirectory, "application");
|
||||||
|
var sourceExe = Path.Combine(sourceApplication, "BizTalkCheckmkPulse.exe");
|
||||||
|
var sourceConfig = sourceExe + ".config";
|
||||||
|
var sourceWrapper = Path.Combine(packageDirectory, "biztalk_checkmk_pulse.cmd");
|
||||||
|
RequireFile(sourceExe);
|
||||||
|
RequireFile(sourceConfig);
|
||||||
|
RequireFile(sourceWrapper);
|
||||||
|
|
||||||
|
// Ein laufender Provider kann die installierte EXE waehrend eines Updates sperren.
|
||||||
|
new TaskSchedulerService().DeleteIfExists(TaskName);
|
||||||
|
report("Vorhandener Scheduled Task angehalten beziehungsweise fuer das Update entfernt.");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(installDirectory);
|
||||||
|
var targetExe = Path.Combine(installDirectory, "BizTalkCheckmkPulse.exe");
|
||||||
|
var targetConfig = targetExe + ".config";
|
||||||
|
File.Copy(sourceExe, targetExe, true);
|
||||||
|
File.Copy(sourceConfig, targetConfig, true);
|
||||||
|
SetEnvironment(targetConfig, environmentName);
|
||||||
|
report("Programmdateien installiert: " + installDirectory);
|
||||||
|
|
||||||
|
var dataDirectory = Path.Combine(runtimeDirectory, "data");
|
||||||
|
var logDirectory = Path.Combine(runtimeDirectory, "logs");
|
||||||
|
Directory.CreateDirectory(runtimeDirectory);
|
||||||
|
Directory.CreateDirectory(dataDirectory);
|
||||||
|
Directory.CreateDirectory(logDirectory);
|
||||||
|
|
||||||
|
ApplyDirectoryAcl(installDirectory, accountSid, FileSystemRights.ReadAndExecute, FileSystemRights.ReadAndExecute);
|
||||||
|
ApplyDirectoryAcl(runtimeDirectory, accountSid, FileSystemRights.ReadAndExecute, FileSystemRights.ReadAndExecute);
|
||||||
|
ApplyDirectoryAcl(dataDirectory, accountSid, FileSystemRights.Modify, FileSystemRights.ReadAndExecute);
|
||||||
|
ApplyDirectoryAcl(logDirectory, accountSid, FileSystemRights.Modify, FileSystemRights.Modify);
|
||||||
|
report("Least-Privilege-Verzeichnisrechte gesetzt.");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(checkmkLocalDirectory);
|
||||||
|
File.Copy(sourceWrapper, Path.Combine(checkmkLocalDirectory, "biztalk_checkmk_pulse.cmd"), true);
|
||||||
|
report("Checkmk Local Check installiert: " + checkmkLocalDirectory);
|
||||||
|
|
||||||
|
RunSelfTest(targetExe);
|
||||||
|
report("Self-Test erfolgreich: acht Checkmk-Services.");
|
||||||
|
|
||||||
|
new TaskSchedulerService().RegisterAndStart(
|
||||||
|
TaskName,
|
||||||
|
targetExe,
|
||||||
|
installDirectory,
|
||||||
|
account,
|
||||||
|
isGmsa ? null : password,
|
||||||
|
isGmsa);
|
||||||
|
report("Scheduled Task registriert: " + TaskName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Uninstall(bool keepRuntimeData, Action<string> report)
|
||||||
|
{
|
||||||
|
new TaskSchedulerService().DeleteIfExists(TaskName);
|
||||||
|
report("Scheduled Task entfernt.");
|
||||||
|
|
||||||
|
var wrapper = Path.Combine(checkmkLocalDirectory, "biztalk_checkmk_pulse.cmd");
|
||||||
|
if (File.Exists(wrapper)) File.Delete(wrapper);
|
||||||
|
if (Directory.Exists(installDirectory)) Directory.Delete(installDirectory, true);
|
||||||
|
if (!keepRuntimeData && Directory.Exists(runtimeDirectory)) Directory.Delete(runtimeDirectory, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Validate(string account, string password, bool isGmsa, string environmentName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(account)) throw new ArgumentException("Collector-Konto fehlt.");
|
||||||
|
if (account.IndexOf('\\') <= 0 || account.EndsWith("\\", StringComparison.Ordinal))
|
||||||
|
throw new ArgumentException(@"Collector-Konto im Format DOMAIN\Benutzer eingeben, z.B. BEW\t231bizmon.");
|
||||||
|
if (isGmsa && !account.EndsWith("$", StringComparison.Ordinal))
|
||||||
|
throw new ArgumentException(@"Ein gMSA-Konto muss mit '$' enden, z.B. BEW\svc_biztalk_cmk$.");
|
||||||
|
if (!isGmsa && string.IsNullOrEmpty(password)) throw new ArgumentException("Kennwort fehlt.");
|
||||||
|
if (!new[] { "", "ACC", "DEV", "TST", "PRD" }.Contains(environmentName))
|
||||||
|
throw new ArgumentException("Ungueltige Umgebung.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RequireFile(string path)
|
||||||
|
{
|
||||||
|
if (!File.Exists(path))
|
||||||
|
throw new FileNotFoundException("Installationspaket ist unvollstaendig. Datei fehlt: " + path, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetEnvironment(string configPath, string environmentName)
|
||||||
|
{
|
||||||
|
var document = new XmlDocument { PreserveWhitespace = true };
|
||||||
|
document.Load(configPath);
|
||||||
|
var setting = document.SelectSingleNode("/configuration/appSettings/add[@key='EnvironmentName']") as XmlElement;
|
||||||
|
if (setting == null) throw new InvalidDataException("EnvironmentName fehlt in " + configPath + ".");
|
||||||
|
setting.SetAttribute("value", environmentName);
|
||||||
|
document.Save(configPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ApplyDirectoryAcl(
|
||||||
|
string path,
|
||||||
|
SecurityIdentifier collectorSid,
|
||||||
|
FileSystemRights collectorRights,
|
||||||
|
FileSystemRights systemRights)
|
||||||
|
{
|
||||||
|
var inheritance = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
|
||||||
|
var security = new DirectorySecurity();
|
||||||
|
security.SetAccessRuleProtection(true, false);
|
||||||
|
security.AddAccessRule(new FileSystemAccessRule(
|
||||||
|
new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null),
|
||||||
|
FileSystemRights.FullControl,
|
||||||
|
inheritance,
|
||||||
|
PropagationFlags.None,
|
||||||
|
AccessControlType.Allow));
|
||||||
|
security.AddAccessRule(new FileSystemAccessRule(
|
||||||
|
new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null),
|
||||||
|
systemRights,
|
||||||
|
inheritance,
|
||||||
|
PropagationFlags.None,
|
||||||
|
AccessControlType.Allow));
|
||||||
|
security.AddAccessRule(new FileSystemAccessRule(
|
||||||
|
collectorSid,
|
||||||
|
collectorRights,
|
||||||
|
inheritance,
|
||||||
|
PropagationFlags.None,
|
||||||
|
AccessControlType.Allow));
|
||||||
|
new DirectoryInfo(path).SetAccessControl(security);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RunSelfTest(string executable)
|
||||||
|
{
|
||||||
|
var start = new ProcessStartInfo(executable, "--self-test")
|
||||||
|
{
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true
|
||||||
|
};
|
||||||
|
using (var process = Process.Start(start))
|
||||||
|
{
|
||||||
|
if (process == null) throw new InvalidOperationException("Self-Test konnte nicht gestartet werden.");
|
||||||
|
var output = process.StandardOutput.ReadToEnd();
|
||||||
|
var error = process.StandardError.ReadToEnd();
|
||||||
|
if (!process.WaitForExit(30000))
|
||||||
|
{
|
||||||
|
process.Kill();
|
||||||
|
throw new InvalidOperationException("Self-Test hat das Zeitlimit ueberschritten.");
|
||||||
|
}
|
||||||
|
var lines = output.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (process.ExitCode != 0 || lines.Length != 8 || lines.Any(x => !x.StartsWith("0 ", StringComparison.Ordinal)))
|
||||||
|
throw new InvalidOperationException("Self-Test fehlgeschlagen. Exitcode=" + process.ExitCode + ", Zeilen=" + lines.Length + ". " + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace BizTalkCheckmkPulse.Setup
|
||||||
|
{
|
||||||
|
internal sealed class MainForm : Form
|
||||||
|
{
|
||||||
|
private readonly InstallerEngine engine;
|
||||||
|
private readonly TextBox account = new TextBox();
|
||||||
|
private readonly TextBox password = new TextBox();
|
||||||
|
private readonly ComboBox environment = new ComboBox();
|
||||||
|
private readonly CheckBox gmsa = new CheckBox();
|
||||||
|
private readonly Button install = new Button();
|
||||||
|
private readonly Button uninstall = new Button();
|
||||||
|
private readonly TextBox status = new TextBox();
|
||||||
|
|
||||||
|
public MainForm(InstallerEngine engine)
|
||||||
|
{
|
||||||
|
this.engine = engine;
|
||||||
|
Text = "BizTalk Checkmk Pulse Setup";
|
||||||
|
ClientSize = new Size(650, 485);
|
||||||
|
MinimumSize = new Size(666, 524);
|
||||||
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
|
Font = new Font("Segoe UI", 9F);
|
||||||
|
|
||||||
|
var title = new Label
|
||||||
|
{
|
||||||
|
AutoSize = true,
|
||||||
|
Font = new Font(Font.FontFamily, 15F, FontStyle.Bold),
|
||||||
|
Location = new Point(20, 18),
|
||||||
|
Text = "BizTalk Checkmk Pulse installieren"
|
||||||
|
};
|
||||||
|
var description = new Label
|
||||||
|
{
|
||||||
|
AutoSize = false,
|
||||||
|
Location = new Point(22, 58),
|
||||||
|
Size = new Size(605, 48),
|
||||||
|
Text = "Installiert Anwendung, Checkmk Local Check, sichere Verzeichnisrechte und den minuetlichen Scheduled Task. PowerShell wird nicht verwendet."
|
||||||
|
};
|
||||||
|
|
||||||
|
AddLabel("Collector-Konto", 22, 120);
|
||||||
|
account.Location = new Point(190, 116);
|
||||||
|
account.Size = new Size(420, 23);
|
||||||
|
account.Text = @"BEW\t231bizmon";
|
||||||
|
|
||||||
|
AddLabel("Kennwort", 22, 158);
|
||||||
|
password.Location = new Point(190, 154);
|
||||||
|
password.Size = new Size(420, 23);
|
||||||
|
password.UseSystemPasswordChar = true;
|
||||||
|
|
||||||
|
AddLabel("Umgebung", 22, 196);
|
||||||
|
environment.Location = new Point(190, 192);
|
||||||
|
environment.Size = new Size(160, 23);
|
||||||
|
environment.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||||
|
environment.Items.AddRange(new object[] { "(keine)", "ACC", "DEV", "TST", "PRD" });
|
||||||
|
environment.SelectedIndex = 0;
|
||||||
|
|
||||||
|
gmsa.Location = new Point(190, 229);
|
||||||
|
gmsa.Size = new Size(420, 24);
|
||||||
|
gmsa.Text = "Konto ist ein gMSA (kein Kennwort erforderlich)";
|
||||||
|
gmsa.CheckedChanged += delegate
|
||||||
|
{
|
||||||
|
password.Enabled = !gmsa.Checked;
|
||||||
|
if (gmsa.Checked) password.Clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
install.Location = new Point(190, 267);
|
||||||
|
install.Size = new Size(200, 34);
|
||||||
|
install.Text = "Installieren / aktualisieren";
|
||||||
|
install.Click += async delegate { await InstallAsync(); };
|
||||||
|
|
||||||
|
uninstall.Location = new Point(410, 267);
|
||||||
|
uninstall.Size = new Size(200, 34);
|
||||||
|
uninstall.Text = "Deinstallieren";
|
||||||
|
uninstall.Click += async delegate { await UninstallAsync(); };
|
||||||
|
|
||||||
|
status.Location = new Point(22, 320);
|
||||||
|
status.Size = new Size(588, 135);
|
||||||
|
status.Multiline = true;
|
||||||
|
status.ReadOnly = true;
|
||||||
|
status.ScrollBars = ScrollBars.Vertical;
|
||||||
|
status.Text = "Bereit. Setup.exe muss aus dem vollstaendig entpackten Installationspaket gestartet werden.";
|
||||||
|
|
||||||
|
Controls.AddRange(new Control[]
|
||||||
|
{
|
||||||
|
title, description, account, password, environment, gmsa, install, uninstall, status
|
||||||
|
});
|
||||||
|
AcceptButton = install;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddLabel(string text, int left, int top)
|
||||||
|
{
|
||||||
|
Controls.Add(new Label { AutoSize = true, Location = new Point(left, top), Text = text });
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InstallAsync()
|
||||||
|
{
|
||||||
|
var collectorAccount = account.Text.Trim();
|
||||||
|
var collectorPassword = password.Text;
|
||||||
|
var environmentName = environment.SelectedIndex <= 0 ? string.Empty : environment.SelectedItem.ToString();
|
||||||
|
var collectorIsGmsa = gmsa.Checked;
|
||||||
|
|
||||||
|
SetBusy(true, "Installation laeuft ...");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Run(() => engine.Install(
|
||||||
|
collectorAccount,
|
||||||
|
collectorPassword,
|
||||||
|
collectorIsGmsa,
|
||||||
|
environmentName,
|
||||||
|
Report));
|
||||||
|
password.Clear();
|
||||||
|
Report("Installation abgeschlossen. Der Provider-Task wurde einmalig gestartet.");
|
||||||
|
MessageBox.Show(this, "Installation erfolgreich abgeschlossen.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
password.Clear();
|
||||||
|
Report("FEHLER: " + ex.Message);
|
||||||
|
MessageBox.Show(this, ex.Message, "Installation fehlgeschlagen", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SetBusy(false, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UninstallAsync()
|
||||||
|
{
|
||||||
|
var result = MessageBox.Show(
|
||||||
|
this,
|
||||||
|
"Scheduled Task, Checkmk-Wrapper und Programmdateien entfernen? Snapshot und Logs bleiben erhalten.",
|
||||||
|
"Deinstallation bestaetigen",
|
||||||
|
MessageBoxButtons.YesNo,
|
||||||
|
MessageBoxIcon.Warning);
|
||||||
|
if (result != DialogResult.Yes) return;
|
||||||
|
|
||||||
|
SetBusy(true, "Deinstallation laeuft ...");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Run(() => engine.Uninstall(true, Report));
|
||||||
|
Report("Deinstallation abgeschlossen. Runtime-Daten wurden beibehalten.");
|
||||||
|
MessageBox.Show(this, "Deinstallation erfolgreich abgeschlossen.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Report("FEHLER: " + ex.Message);
|
||||||
|
MessageBox.Show(this, ex.Message, "Deinstallation fehlgeschlagen", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SetBusy(false, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetBusy(bool busy, string message)
|
||||||
|
{
|
||||||
|
install.Enabled = !busy;
|
||||||
|
uninstall.Enabled = !busy;
|
||||||
|
account.Enabled = !busy;
|
||||||
|
environment.Enabled = !busy;
|
||||||
|
gmsa.Enabled = !busy;
|
||||||
|
password.Enabled = !busy && !gmsa.Checked;
|
||||||
|
UseWaitCursor = busy;
|
||||||
|
if (message != null) Report(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Report(string message)
|
||||||
|
{
|
||||||
|
if (InvokeRequired)
|
||||||
|
{
|
||||||
|
BeginInvoke(new Action<string>(Report), message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status.AppendText(Environment.NewLine + DateTime.Now.ToString("HH:mm:ss") + " " + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace BizTalkCheckmkPulse.Setup
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
private static void Main()
|
||||||
|
{
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.Run(new MainForm(new InstallerEngine(AppDomain.CurrentDomain.BaseDirectory)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace BizTalkCheckmkPulse.Setup
|
||||||
|
{
|
||||||
|
internal sealed class TaskSchedulerService
|
||||||
|
{
|
||||||
|
private const int TaskCreateOrUpdate = 6;
|
||||||
|
private const int TaskLogonPassword = 1;
|
||||||
|
private const int TaskTriggerTime = 1;
|
||||||
|
private const int TaskActionExecute = 0;
|
||||||
|
private const int TaskInstancesIgnoreNew = 2;
|
||||||
|
|
||||||
|
public void RegisterAndStart(
|
||||||
|
string taskName,
|
||||||
|
string executable,
|
||||||
|
string workingDirectory,
|
||||||
|
string account,
|
||||||
|
string password,
|
||||||
|
bool isGmsa)
|
||||||
|
{
|
||||||
|
dynamic service = null;
|
||||||
|
dynamic root = null;
|
||||||
|
dynamic definition = null;
|
||||||
|
dynamic registeredTask = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var schedulerType = Type.GetTypeFromProgID("Schedule.Service", true);
|
||||||
|
service = Activator.CreateInstance(schedulerType);
|
||||||
|
service.Connect();
|
||||||
|
root = service.GetFolder("\\");
|
||||||
|
definition = service.NewTask(0);
|
||||||
|
|
||||||
|
definition.RegistrationInfo.Description = "Collects BizTalk monitoring data for the Checkmk local check.";
|
||||||
|
definition.Principal.UserId = account;
|
||||||
|
// Auch gMSA werden als Password-Logon registriert. Nur das Kennwort
|
||||||
|
// bleibt leer; TASK_LOGON_SERVICE_ACCOUNT ist ausschliesslich fuer
|
||||||
|
// LocalSystem, LocalService und NetworkService vorgesehen.
|
||||||
|
definition.Principal.LogonType = TaskLogonPassword;
|
||||||
|
definition.Principal.RunLevel = 0;
|
||||||
|
|
||||||
|
definition.Settings.Enabled = true;
|
||||||
|
definition.Settings.StartWhenAvailable = true;
|
||||||
|
definition.Settings.MultipleInstances = TaskInstancesIgnoreNew;
|
||||||
|
definition.Settings.ExecutionTimeLimit = "PT5M";
|
||||||
|
definition.Settings.RestartCount = 2;
|
||||||
|
definition.Settings.RestartInterval = "PT1M";
|
||||||
|
definition.Settings.DisallowStartIfOnBatteries = false;
|
||||||
|
definition.Settings.StopIfGoingOnBatteries = false;
|
||||||
|
|
||||||
|
dynamic trigger = definition.Triggers.Create(TaskTriggerTime);
|
||||||
|
trigger.StartBoundary = DateTime.Now.AddMinutes(1).ToString("s");
|
||||||
|
trigger.Enabled = true;
|
||||||
|
trigger.Repetition.Interval = "PT1M";
|
||||||
|
|
||||||
|
dynamic action = definition.Actions.Create(TaskActionExecute);
|
||||||
|
action.Path = executable;
|
||||||
|
action.Arguments = "--collect";
|
||||||
|
action.WorkingDirectory = workingDirectory;
|
||||||
|
|
||||||
|
registeredTask = root.RegisterTaskDefinition(
|
||||||
|
taskName,
|
||||||
|
definition,
|
||||||
|
TaskCreateOrUpdate,
|
||||||
|
account,
|
||||||
|
isGmsa ? null : password,
|
||||||
|
TaskLogonPassword,
|
||||||
|
null);
|
||||||
|
registeredTask.Run(null);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Release(registeredTask);
|
||||||
|
Release(definition);
|
||||||
|
Release(root);
|
||||||
|
Release(service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteIfExists(string taskName)
|
||||||
|
{
|
||||||
|
dynamic service = null;
|
||||||
|
dynamic root = null;
|
||||||
|
dynamic task = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var schedulerType = Type.GetTypeFromProgID("Schedule.Service", true);
|
||||||
|
service = Activator.CreateInstance(schedulerType);
|
||||||
|
service.Connect();
|
||||||
|
root = service.GetFolder("\\");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
task = root.GetTask(taskName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
task.Stop(0);
|
||||||
|
}
|
||||||
|
catch (COMException)
|
||||||
|
{
|
||||||
|
// Ein nicht laufender Task muss vor dem Loeschen nicht gestoppt werden.
|
||||||
|
}
|
||||||
|
root.DeleteTask(taskName, 0);
|
||||||
|
}
|
||||||
|
catch (COMException ex)
|
||||||
|
{
|
||||||
|
const int FileNotFound = unchecked((int)0x80070002);
|
||||||
|
if (ex.ErrorCode != FileNotFound) throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Release(task);
|
||||||
|
Release(root);
|
||||||
|
Release(service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Release(object value)
|
||||||
|
{
|
||||||
|
if (value != null && Marshal.IsComObject(value)) Marshal.FinalReleaseComObject(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="BizTalkCheckmkPulse.Setup" />
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges>
|
||||||
|
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
</assembly>
|
||||||
Reference in New Issue
Block a user