# # PRTG Pause # # Simple HTTP Listener to accept HTTP-GET from # # Must run as Administrator to create a HTTP Web Listener # http(s)://prtg_server_address/api/function?Username=uid&passhash=hash¶ms # # 20140611 Ver 1.0 Initiale public Version # 20140612 Ver 1.1 Sonderfall trailing? und favicon.ico # 20140612 Ver 1.2 Erweiterung um Template und Alert, Bugfix StatUsermittlung # Added ScanNow, errors in Red, Hyperlink to DeviceID # Errorausgabe im HTML addiert # 20140718 Ver 1.3 Abschalten der DNS Abfragen,da diese bei "nichtauflösbarkeit" zu lange brauchen. # Systeme müssen in PRTG über die IP-Adresse gepflegt werden # Funktioniert nicht sicher, wenn mehrere Systeme die gleiche IP-Adresse haben (z.B. mehrere Kunden) # Exclude von abruf des /favicon.ico addiert # 20140718 Ver 1.4 Try to match Hostname based on ReverseDNS # Additional Errorhandling if Lisatener Listener not bound param ( [string]$prtgserveruri="https://prtg.netatwork.de", # URL of PRTG Web Frontend [string]$prtgUsername="prtgpause", # Username [string]$prtgpasshash="2039135208" , # hash instead of password [string]$listenport = "81", [string]$htmltemplatefile = "./prtgpause-template.htm", [int]$devicecacheage = 10 # age of Device List Cache in seconds ) set-psdebug -strict # make sure that e throw an error für uninitialize variables etc [string]$script:lasterror="" # Emulate function on PowerShell 2.0 Systems function Invoke-WebRequest ([string]$uri) { $webclient = new-object System.Net.WebClient try { $webclient.downloadstring($uri) } catch { $script:lasterror = $_.Exception.Message write-host ("ERROR" + $script:lasterror) } } write-host "PRTGPause: Start" write-host "PRTGPause: Check HTML-Template" try { [string]$htmltemplate=get-content $htmltemplatefile } catch { write-error "Unable to load THML-Template: $htmltemplatefile " exit } write-host "PRTGPause: Check HTML-Template - SUCCESS" write-host "PRTGPause: Check PRTG Connectivity by reading Status" try { [xml]$data=Invoke-WebRequest -Uri ($prtgserveruri+"/api/getstatus.xml?id=0&Username="+$prtgUsername+"&passhash="+$prtgpasshash) write-host ("PRTG-Version:"+ $data.status.Version) write-host ("PRTG-Clock :"+ $data.status.Clock) } catch { write-error "Unable to load sensortree. Check PRTG URL, Username and Hash" exit } write-host "PRTGPause: Check PRTG Connectivity - SUCCESS" write-host "PRTGPause: Start HTTP listener on Port: $listenport" $listener = New-Object System.Net.HttpListener $listener.Prefixes.Add('http://+:'+$listenport+'/') # Must GENAU mit der Angabe in NETSH übereinstimmen $listener.Start() write-host "PRTGPause: Start HTTP listener on Port: $listenport SUCCESS" if ($error) { write-host "Error on starting Listener" exit } #$Host.UI.RawUI.FlushInputBuffer() #[console]::TreatControlCAsInput = $true #write-host "CTRL-C ist disabled" [datetime]$devicelistage = get-date "01.01.2014" # initialze Age [hashtable]$devicelist = @{} [bool]$quit=$false while ((!($quit))) { [string]$script:lasterror="" write-host ("Listening on " + $listener.Prefixes ) $context = $listener.GetContext() # Warte auf eingehende Anfragen write-host "------- New Request arrived ------------" $request = $context.Request write-host (" URL.AbsoluteUri:" + $request.URL.AbsoluteUri) write-host (" HttpMethod :" + $request.HttpMethod) [string]$remoteip = $Request.RemoteEndPoint.Address.IPAddressToString write-host (" RemoteIP :" + $remoteip) write-host (" Method :" + $Request.HttpMethod) write-host (" RAWURL :" + $Request.RawURL) #[System.Net.Dns]::GetHostByAddress($request.RemoteEndPoint.address).hostname if ($Request.RawURL -eq ("/")) { write-host "Statuspage Request found, Check für Cache Update" write-host ("Last Cache Update:" + $devicelistage.tostring()) write-host ("Now " + (Get-date).tostring()) if (((get-date) - $devicelistage).totalseconds -ge $devicecacheage) { write-host "---------- DeviceList to old. start Update --------------" [hashtable]$devicelist.clear() write-host " Loading Device XML" [xml]$data= Invoke-WebRequest -Uri ($prtgserveruri+"/api/table.xml?content=devices&output=xml&columns=device,host,objid&Username="+$prtgUsername+"&passhash="+$prtgpasshash) foreach ($device in ($data.devices.item)){ write-host ("found Device:"+$device.name+" Host:"+$device.host) -nonewline if ($device.host -eq "127.0.0.1") { write-host " Host is 127.0.0.1: SKIP" } elseif ($device.host -match "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") { write-host (" Host is IP-Address. Adding IP:" + $device.host) $devicelist.add($device.host,$device.objid) # DNS Queries take too long if name not resolvable. so i had to disable that # $hostname=[System.Net.Dns]::GetHostByAddress($device.host).hostname } else { write-host " Host is a DNS-Name. Adding Host " $device.host $devicelist.add($device.host,$device.objid) # foreach ($dnsanswer in ([System.Net.Dns]::GetHostAddresses($device.host))){ # write-host (" Resolved to IP-Address:" + $dnsanswer.IPAddressToString) # try { # $devicelist.add(($dnsanswer.IPAddressToString),$device.objid) # } # catch { # write-host (" Problem adding:" + $dnsanswer.IPAddressToString + " Maybe duplicate IP") # } # } } } [datetime]$devicelistage = get-date # Update DeviceList Age } else { write-host "Reusing existing device table" } } #$devicelist write-host "Loading HTMLTemplate" [string]$htmltemplate = get-content $htmltemplatefile # enable that to load template für every request [string]$htmlpage = $htmltemplate # use the templated loaded during startup $htmlpage = $htmlpage.replace("%IPADDRESS%",$remoteip) $htmlpage = $htmlpage.replace("%TIMESTAMP%",(get-date)) $deviceobjid="" write-host ("Searching für device in List: " + $remoteip) -nonewline if ($devicelist.containskey($remoteip)){ write-host " Found by IP" -nonewline $deviceobjid = $devicelist.item($remoteip) } else { try { $devicename = "" $devicename = [System.Net.Dns]::GetHostByAddress($remoteip).hostname } catch { $script:lasterror = $_.Exception.Message write-host ("ERROR Resolving Reverse DNS" + $script:lasterror) } if ($devicelist.containskey($devicename)){ write-host " Found by ReverseDNS" -nonewline $deviceobjid = $devicelist.item($devicename) } } if ($deviceobjid -ne ""){ write-host ".. Found System in Device List" if ($Request.RawURL.startswith("/pause")) { write-host "Pausing Device" $result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/pauseobjectfor.htm?id="+$deviceobjid+"&action=0&pausemsg=PausedbyPRTG-Pause&duration=15&Username="+$prtgUsername+"&passhash="+$prtgpasshash) } elseif ($Request.RawURL.startswith("/resume")) { write-host "Pausing Device" $result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/pause.htm?id="+$deviceobjid+"&action=1&Username="+$prtgUsername+"&passhash="+$prtgpasshash) } elseif ($Request.RawURL.startswith("/ackalarm")) { write-host "AckAlarm 15 Min" $result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/acknowledgealarm.htm?id="+$deviceobjid+"&ackmsg=AckAlarmByPRTGPause&duration=15&Username="+$prtgUsername+"&passhash="+$prtgpasshash) } elseif ($Request.RawURL.startswith("/scannow")) { write-host "AckAlarm 15 Min" $result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/scannow.htm?id="+$deviceobjid+"&Username="+$prtgUsername+"&passhash="+$prtgpasshash) } elseif ($Request.RawURL.startswith("/quit")) { write-host "Quit received" $quit = $true } else { write-host "No Special Command" } if ($true -or ($Request.RawURL -eq "/") -or ($Request.RawURL -eq "/?")) { write-host "------- Generating Response Page ------------" $htmlpage = $htmlpage.replace("%DEVICEID%",(""+$deviceobjid+"")) [xml]$status = Invoke-WebRequest -Uri ($prtgserveruri+"/api/getsensordetails.xml?columns=datetime,name,status,message&id="+$deviceobjid+"&Username="+$prtgUsername+"&passhash="+$prtgpasshash) if ($status.sensordata.statusid.'#cdata-section' -eq "12") { write-host " Found Status: 12" $htmlpage = $htmlpage.replace("%STATUS%",($status.sensordata.statustext.'#cdata-section')) $htmlpage = $htmlpage.replace("%BUTTON%","ResumeAckAlarm 15MinScanNow") } elseif ($status.sensordata.statusid.'#cdata-section' -eq "3") { write-host " Found Status: Ok" $htmlpage = $htmlpage.replace("%STATUS%","OK") $htmlpage = $htmlpage.replace("%BUTTON%","Pause 15MinAckAlarm 15MinScanNow") } else { write-host (" Found Status: unknown" + $status.sensordata.statustext.'#cdata-section') $htmlpage = $htmlpage.replace("%STATUS%",("unknown:"+$status.sensordata.statustext.'#cdata-section' + "XX")) $htmlpage = $htmlpage.replace("%BUTTON%","ScanNow") } [xml]$result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/table.xml?content=sensors&columns=objid,group,device,sensor,status,message,lastvalue,priority,favorite&id="+$deviceobjid+"&count=10&Username="+$prtgUsername+"&passhash="+$prtgpasshash) $htmlpage = $htmlpage.replace("%SENSORTABLE%",($result.sensors.item | select sensor,status,lastvalue | convertto-html -Fragment )) [xml]$result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/table.xml?content=messages&count=10&output=xml&columns=datetime,name,status,message&id="+$deviceobjid+"&count=10&Username="+$prtgUsername+"&passhash="+$prtgpasshash) $htmlpage = $htmlpage.replace("%MESAGETABLE%",($result.messages.item | select datetime,name,status,message_raw | convertto-html -Fragment )) } } else { write-host " NOT System in Device List" $htmlpage = $htmlpage.replace("%STATUS%","NOT IN DEVICE LIST") $htmlpage = $htmlpage.replace("%BUTTON%","") $htmlpage = $htmlpage.replace("%SENSORTABLE%","Device not found in List") $htmlpage = $htmlpage.replace("%MESAGETABLE%","Device not found in List") } write-host "Sending HTML Response" $response = $context.Response $response.ContentType = 'text/html' $response.ContentEncoding = [System.Text.Encoding]::UTF8; $htmlpage = $htmlpage.replace("%LASTERROR%",$script:lasterror.tostring()) [byte[]] $buffer = [System.Text.Encoding]::UTF8.GetBytes($htmlpage) $response.ContentLength64 = $buffer.length $response.OutputStream.Write($buffer, 0, $buffer.length) $response.OutputStream.close() write-host "--- DONE ---" } $listener.Stop() write-host "--- Normal End ---"