lordmilko / PrtgAPI

C#/PowerShell interface for PRTG Network Monitor
MIT License
301 stars 37 forks source link

Get-SensorTarget Error with new PRTG Version #181

Closed noaboa97 closed 3 years ago

noaboa97 commented 3 years ago

Describe the bug Clearly and concisely describe what you were trying to do, what happened and what you were expecting to happen

I've been using Get-SensorTarget to create some custom sensors. With version 20.3.62.1397 it works fine. With version 20.4.63.1427 I'm getting an Error, that my credentials where invalid. Even though both of them are authenticated with an AD Account where I made sure the creds a correct. I had it side by side and for the older version it worked and the newer one it didn‘t.

get-sensortarget : Could not authenticate to PRTG; the specified username and password were invalid.

Steps to reproduce Put the relevant code from your application that caused the issue to happen in the code block below

$device = get-device DEVICENAME
$device | get-sensortarget -rawType snmptraffic

What is the output of Get-PrtgClient -Diagnostic?

PSVersion      : 5.1.17763.1490
PSEdition      : Desktop
OS             : Microsoft Windows 10 Enterprise
PrtgAPIVersion : 0.9.13
Culture        : de-CH
CLRVersion     : .NET Framework 4.7.2 (461814)
PrtgVersion    : 20.3.62.1397
PrtgLanguage   : english.lng

PSVersion      : 5.1.17763.1490
PSEdition      : Desktop
OS             : Microsoft Windows 10 Enterprise
PrtgAPIVersion : 0.9.13
Culture        : de-CH
CLRVersion     : .NET Framework 4.7.2 (461814)
PrtgVersion    : 20.4.63.1427
PrtgLanguage   : english.lng

Additional context Anything else I should know to help solve the issue? Other command like Get-Device work.

lordmilko commented 3 years ago

Hi @noaboa97,

I just tested Get-SensorTarget on my copy of PRTG 20.4.63.1427 and it seems to work fine.

Are you experience the error, are you able to run $error[0].Exception.StackTrace and provide the output here?

What happens if you run Get-Device -Count 1 | Get-SensorTarget ExeXml; does this work?

noaboa97 commented 3 years ago

Hi @lordmilko

Thanks for answering so fast.

Here's the output:

PS C:\Scripts\PRTG\Functions> $error[0].Exception.StackTrace
   at PrtgAPI.Request.RequestEngine.ValidateHttpResponse(HttpResponseMessage responseMessage, PrtgResponse response)
   at PrtgAPI.Request.RequestEngine.ExecuteRequest(PrtgRequestMessage request, CancellationToken token, Func`2 responseParser)
   at PrtgAPI.Request.RequestEngine.ExecuteRequest(IJsonParameters parameters, Func`2 responseParser, CancellationToken token)
   at PrtgAPI.Request.ObjectEngine.GetObject[T](IJsonParameters parameters, Func`2 responseParser, CancellationToken token)
   at PrtgAPI.PrtgClient.WaitForSensorTargetResolution(Either`2 deviceOrId, Int32 tmpId, Func`2 progressCallback, Int32 timeout, CancellationToken token)
   at PrtgAPI.PrtgClient.GetSensorTargetsResponse(Either`2 deviceOrId, BeginAddSensorQueryParameters parameters, Func`2 progressCallback, Int32 timeout, CancellationToken token)
   at PrtgAPI.PrtgClient.ResolveSensorTargets[T](Either`2 deviceOrId, BeginAddSensorQueryParameters parameters, Func`2 progressCallback, Int32 timeout, CancellationToken token, Func`2 parser)
   at PrtgAPI.Request.PrtgTargetHelper.GetSensorTargets(Either`2 deviceOrId, String sensorType, String tableName, Func`2 progressCallback, Int32 timeout, ISensorQueryTargetParameters queryParameters, CancellationToken token)
   at PrtgAPI.PowerShell.Cmdlets.GetSensorTarget.<ProcessRecordEx>b__37_0(Either`2 d, Func`2 c, Int32 ti, CancellationToken to)
   at PrtgAPI.PowerShell.Cmdlets.GetSensorTarget.<>c__DisplayClass42_0`1.<GetTargets>b__0(Func`3 f)
   at PrtgAPI.PowerShell.Base.PrtgProgressCmdlet.WriteProcessProgressRecords(Func`2 getItems)
   at PrtgAPI.PowerShell.Cmdlets.GetSensorTarget.ProcessRecordEx()
   at PrtgAPI.PowerShell.Base.PrtgCmdlet.ExecuteWithCoreState(Action action)
   at System.Management.Automation.CommandProcessor.ProcessRecord()



If I run Get-Device -Count 1 | Get-SensorTarget ExeXml, I get the same error message.

PS C:\Scripts\PRTG\Functions> Get-Device -Count 1 | Get-SensorTarget ExeXml
Get-SensorTarget : Could not authenticate to PRTG; the specified username and password were invalid.
At line:1 char:23
+ Get-Device -Count 1 | Get-SensorTarget ExeXml
+                       ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-SensorTarget], HttpRequestException
    + FullyQualifiedErrorId : System.Net.Http.HttpRequestException,PrtgAPI.PowerShell.Cmdlets.GetSensorTarget
PS C:\Scripts\PRTG\Functions> $error[0].Exception.StackTrace
   at PrtgAPI.Request.RequestEngine.ValidateHttpResponse(HttpResponseMessage responseMessage, PrtgResponse response)
   at PrtgAPI.Request.RequestEngine.ExecuteRequest(PrtgRequestMessage request, CancellationToken token, Func`2 responseParser)
   at PrtgAPI.Request.RequestEngine.ExecuteRequest(IJsonParameters parameters, Func`2 responseParser, CancellationToken token)
   at PrtgAPI.Request.ObjectEngine.GetObject[T](IJsonParameters parameters, Func`2 responseParser, CancellationToken token)
   at PrtgAPI.PrtgClient.WaitForSensorTargetResolution(Either`2 deviceOrId, Int32 tmpId, Func`2 progressCallback, Int32 timeout, CancellationToken token)
   at PrtgAPI.PrtgClient.GetSensorTargetsResponse(Either`2 deviceOrId, BeginAddSensorQueryParameters parameters, Func`2 progressCallback, Int32 timeout, CancellationToken token)
   at PrtgAPI.PrtgClient.ResolveSensorTargets[T](Either`2 deviceOrId, BeginAddSensorQueryParameters parameters, Func`2 progressCallback, Int32 timeout, CancellationToken token, Func`2 parser)
   at PrtgAPI.Request.PrtgTargetHelper.GetExeXmlFiles(Either`2 deviceOrId, Func`2 progressCallback, Int32 timeout, CancellationToken token)
   at PrtgAPI.PowerShell.Cmdlets.GetSensorTarget.<>c__DisplayClass42_0`1.<GetTargets>b__0(Func`3 f)
   at PrtgAPI.PowerShell.Base.PrtgProgressCmdlet.WriteProcessProgressRecords(Func`2 getItems)
   at PrtgAPI.PowerShell.Cmdlets.GetSensorTarget.GetExeFile()
   at PrtgAPI.PowerShell.Base.PrtgCmdlet.ExecuteWithCoreState(Action action)
   at System.Management.Automation.CommandProcessor.ProcessRecord()
lordmilko commented 3 years ago

Hi @noaboa97,

The request that is failing is the request against getaddsensorprogress.htm. This is request requires specifying a cookie for authentication, rather than explicitly specifying a username and password. I can't actually see anywhere in the code where I'm explicitly utilizing a CookieContainer, so I believe I'm simply relying on the "default" behavior that the HttpClientHandler manages a CookieContainer for you, which is reused in every API request.

Are you able to install and run Fiddler and inspect the output of the API requests? Potentially you may need to enable HTTPS decryption by navigating to Tools -> Fiddler Options -> HTTPS -> Capture HTTPS CONNECTs and Decrypt HTTPS traffic

You should find that, in a fresh PowerShell session, on API requests like the one to addsensor2.htm, in the pane on the left it shows a username and passhash was specified, and on the pane on the right you don't see a cookie in the request

image

Down the bottom half of the right hand pane, if you select Cookies it should show you that a cookie was included in the response to addsensor2.htm

image

If you then inspect the requests for addsensor3.htm and getaddsensorprogress.htm you should find it specifies a cookie

image

image

Are you able to confirm that this is the case for all of these requests and that the addsensor3.htm and getaddsensorprogress.htm requests utilize the same cookie?

Also, are you running PrtgAPI on the PRTG Core Server itself, or on a remote computer? If a remote computer, does it work if you run the API request on the core server itself?

Finally, are you able to try and add an EXE/Script Advanced sensor in the PRTG UI (from the same system you've been having the issue on) and confirm you can load the page with the list of scripts to choose from and then add it successfully?

noaboa97 commented 3 years ago

Hi @lordmilko

Thank you so much for your help. I already rebooted my device and also the server. Also checked in diffrent PS Sessions. Today after I changed the webinterface from HTTPS to HTTP to check with Fiddler, the PRTG Service restarted and after that it's was working again.

So maybe because I was working 3 diffrent servers some how the cookie didn't got overwritten and it was using the wrong one. After I checked the cookie with both queries and they where diffrent.

Many thanks.

Best

Noah

lordmilko commented 3 years ago

Hi @noaboa97,

Glad to hear you figured it out, although I'm not too sure I understand what's gone on here. Each cookie should be identified by the .NET Framework as belonging to a specific URL, so it knows which cookies belong to which sites. When you switch between multiple servers, each server's PrtgClient would have its own internal HttpClientHandler, and thus by extension a CookieContainer that was used just for that particular server. Cross-cookie contamination therefore should not be possible

I tried switching between two PRTG servers and I couldn't reproduce this issue, if you could potentially advise how exactly you go about achieving this failure in the first place I can investigate whether it can be remediated

The following code demonstrates how you can inspect the contents of the internal CookieContainer. It shows the contents of the container before and after you invoke Get-SensorTarget

$client = get-prtgclient

$flags = [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic

$requestEngineInfo = $client.GetType().GetProperty("RequestEngine", $flags)
$requestEngine = $requestEngineInfo.GetValue($client)

$webClientInfo = $requestEngine.GetType().GetField("webClient", $flags)
$webClient = $webClientInfo.GetValue($requestEngine)

$handlerInfo = $webClient.GetType().GetField("handler", $flags)
$handler = $handlerInfo.GetValue($webClient)

$before = $handler.CookieContainer.GetCookies($client.Server)

$results = Get-Device -Count 1 | Get-SensorTarget ExeXml

$after = $handler.CookieContainer.GetCookies($client.Server)

Write-Host "Before" -ForegroundColor Yellow

$before

Write-Host "after" -ForegroundColor Yellow

$after

By inspecting the Domain property of the output you will see whether the cookie belongs to the correct PRTG server

Regards, lordmilko

noaboa97 commented 3 years ago

Hi @lordmilko

I further investigated today and I think it's about http and https. Because what you wrote, how it works, it would make sense to me. So my server is set to use SSL and I connect via the http url. Then of course the webserver will redirect me to https and I think thats the problem. So when it's looking for the cookie it searches it for https://...... and not http://......? Could that be?

I just tested this and was able to reproduce it and after I used https it worked.

So my conculsion it does matter for the PrtgAPI if its http or https for some cmdlets that use the cookie. But it doesn't for the PRTG Server because it redirects the traffic from http to https when you connect.

Thanks and best

Noah

lordmilko commented 3 years ago

Hi @noaboa97,

I've successfully managed to reproduce the issue.

When I connect to PRTG by specifying

Connect-PrtgServer https://prtg.example.com

on a server running HTTPS, there is no issue. But if I connect to the server running HTTPS via

Connect-PrtgServer http://prtg.example.com

The cookie container doesn't show anything when I run the PowerShell command in my previous response above, despite the fact cookies should be stored without a protocol prefix. Fiddler clearly shows thast addsensor2.htm did in fact return a cookie. On older versions of PRTG Get-SensorTarget does seem to work without issue when the HTTP/HTTPS protocol is mismatched.

By default, if you don't specify a protocol PrtgAPI will use HTTPS anyway. You should find that if you connect with HTTPS when your server is set to HTTPS it works without issues.

I will reopen this issue and investigate to what extent this issue can be worked around

JamesDolphin commented 2 years ago

I am experiencing this same issue with version 0.9.16 although 0.9.14 addressed this issue.

Error is thrown when getting ping sensor params.

I am connecting via HTTP with prtg setup to not use SSL

DynamicSensorParameters pingParams = client.GetDynamicSensorParameters(madeDevice, "Ping");

Error thrown is "Could not authenticate to PRTG; the specified username and password were invalid."

PRTG version is 22.3.78.1873

This has not been an issue on older versions of PRTG

lordmilko commented 2 years ago

Hi @JamesDolphin,

Issue #268 (which you are describing) is resolved in PrtgAPI 0.9.17

JamesDolphin commented 2 years ago

Thanks, all sorted