<# .SYNOPSIS Downloads ConfigWinRM.ps1 and ConfigWinRM.xml to C:\WinRM and optionally sets the Zabbix Proxy IP address as the WinRM firewall trusted host. .DESCRIPTION Downloads ConfigWinRM.ps1 and ConfigWinRM.xml from the internal Git server (git.totalservice.cz, WindowsServer repo) into C:\WinRM, creating that folder if it does not already exist. After the download, it asks for the Zabbix Proxy IP address: if one is entered, it is written into the element of the downloaded ConfigWinRM.xml; if the prompt is left empty (Enter only), ConfigWinRM.xml is left unchanged. The IP address can also be supplied directly via the -ZabbixProxyIPAddress parameter to run the script non-interactively. .PARAMETER ZabbixProxyIPAddress Zabbix Proxy IP address to allow through the WinRM firewall rule (FWWinRMTrustedHosts in ConfigWinRM.xml). Omit this parameter to be prompted interactively (or to fall back to $env:ZabbixProxyIPAddress if that is set); pass an empty string to skip the prompt and leave the existing value in ConfigWinRM.xml unchanged. .EXAMPLE PS> .\Download-WinRMConfigScript.ps1 Downloads both files to C:\WinRM and interactively prompts for the Zabbix Proxy IP address. .EXAMPLE PS> .\Download-WinRMConfigScript.ps1 -ZabbixProxyIPAddress '192.168.10.50' Downloads both files and sets FWWinRMTrustedHosts to 192.168.10.50 without prompting. .EXAMPLE PS> irm https://s.tslab.cz/ZBXWinRM | iex Shortest way to run the script directly from the repo without saving it locally first; prompts interactively for the Zabbix Proxy IP address. .NOTES Author: Petr Štěpán Created: 2026-07-21 Version: 1.1.0 Changelog: 1.0.0 - Initial version 1.1.0 - Added $env:ZabbixProxyIPAddress fallback so a plain "irm | iex" one-liner can supply the IP address without "& { ... } -Param" wrapping #> [CmdletBinding()] param( [Parameter(Mandatory = $false, HelpMessage = 'Zabbix Proxy IP address to allow through the WinRM firewall rule. Leave empty to keep the existing value.')] [string] $ZabbixProxyIPAddress ) # --- Safety preamble ------------------------------------------------------- Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' # Older Windows Server releases don't enable TLS 1.2 by default, which would make the # download below fail silently against a TLS-1.2-only server. [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 $SourceBaseUri = 'https://git.totalservice.cz/PSScripts/WindowsServer/raw/branch/main/ConfigWinRMForZabbix' $DestinationPath = 'C:\WinRM' $ScriptFile = Join-Path -Path $DestinationPath -ChildPath 'ConfigWinRM.ps1' $ConfigFile = Join-Path -Path $DestinationPath -ChildPath 'ConfigWinRM.xml' # --- Functions --------------------------------------------------------- function Invoke-RemoteFileDownload { <# .SYNOPSIS Downloads a single file from a URI to a local path. .PARAMETER Uri Source URI to download from. .PARAMETER OutFile Local destination file path. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $Uri, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $OutFile ) try { Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing Write-Host "Downloaded '$Uri' to '$OutFile'." } catch { Write-Error "Failed to download '$Uri' to '$OutFile': $_" throw } } function Update-WinRMTrustedHostConfig { <# .SYNOPSIS Sets the element of a ConfigWinRM.xml file. .PARAMETER Path Path to the ConfigWinRM.xml file to update. .PARAMETER TrustedHost Value to write into . #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateScript({ Test-Path -Path $_ -PathType Leaf })] [string] $Path, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $TrustedHost ) try { # PreserveWhitespace keeps the original file's indentation/comments intact - # without it, XmlDocument.Save() would reformat the whole file. $xml = New-Object -TypeName System.Xml.XmlDocument $xml.PreserveWhitespace = $true $xml.Load($Path) $node = $xml.ConfigWinRM.Options.FWWinRMTrustedHosts if ($null -eq $node) { throw "Element was not found in '$Path'." } $xml.ConfigWinRM.Options.FWWinRMTrustedHosts = $TrustedHost $xml.Save($Path) Write-Host "FWWinRMTrustedHosts set to '$TrustedHost' in '$Path'." } catch { Write-Error "Failed to update '$Path': $_" throw } } # --- Main -------------------------------------------------------------- try { if (-not (Test-Path -Path $DestinationPath)) { New-Item -Path $DestinationPath -ItemType Directory -Force | Out-Null Write-Host "Created directory '$DestinationPath'." } Invoke-RemoteFileDownload -Uri "$SourceBaseUri/ConfigWinRM.ps1" -OutFile $ScriptFile Invoke-RemoteFileDownload -Uri "$SourceBaseUri/ConfigWinRM.xml" -OutFile $ConfigFile # Only fall back to the environment variable / prompt when the caller did not pass # the parameter at all - an explicit empty string ("") means "skip the prompt, # leave ConfigWinRM.xml unchanged". $env:ZabbixProxyIPAddress lets a plain # "irm | iex" one-liner supply a value without needing "& { ... } -Param" - # piping into iex runs the downloaded param() block as a plain statement with no # bound arguments, so -ZabbixProxyIPAddress itself can only be set that way when # the script is invoked as a real command (locally or via "& { ... }"). if (-not $PSBoundParameters.ContainsKey('ZabbixProxyIPAddress')) { if ($env:ZabbixProxyIPAddress) { $ZabbixProxyIPAddress = $env:ZabbixProxyIPAddress } else { $ZabbixProxyIPAddress = Read-Host -Prompt 'Enter Zabbix Proxy IP address (press Enter to keep the current value)' } } if ([string]::IsNullOrWhiteSpace($ZabbixProxyIPAddress)) { Write-Host 'No Zabbix Proxy IP address provided - ConfigWinRM.xml left unchanged.' } else { $parsedIp = $null if (-not [System.Net.IPAddress]::TryParse($ZabbixProxyIPAddress, [ref] $parsedIp)) { throw "'$ZabbixProxyIPAddress' is not a valid IP address." } Update-WinRMTrustedHostConfig -Path $ConfigFile -TrustedHost $ZabbixProxyIPAddress } } catch { Write-Error "Script failed: $_" exit 1 } exit 0