Files
biztalk-checkmk-pulse/deployment/Install-BizTalkCheckmkPulse.ps1
T

172 lines
6.1 KiB
PowerShell

[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 8) {
throw "Self-Test fehlgeschlagen. Erwartet wurden acht 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"