lordmilko / PrtgAPI

C#/PowerShell interface for PRTG Network Monitor
MIT License
305 stars 38 forks source link

Using Powershell API behind a proxy #41

Closed Z3nto closed 6 years ago

Z3nto commented 6 years ago

I'm trying to use the Powershell Api behind a Proxy. I've already set the winhttp proxy, but this didn't solve it. How can i use the API behind a proxy?

Error message: get-probe : The remote server returned an error: (407) Proxy Authentication Required.

Thanks.

lordmilko commented 6 years ago

I feel like I may need to implement support for using a proxy.

Does your proxy actually require authentication? If so, is that authentication separate from your Windows authentication?

In addition, do you ever have any issues with any other web based cmdlets interacting with your proxy, and if so how do you overcome your issues with those?

lordmilko commented 6 years ago

Can you also potentially try one of the following workarounds?

Z3nto commented 6 years ago

Yes, my proxy needs to authenticate with my windows credentials. simple pass through. Other powershell cmdlets working fine with my proxy.

Based on your suggested links I've added two lines to my script.

[System.Net.WebRequest]::DefaultWebProxy = [System.Net.WebRequest]::GetSystemWebProxy()
[System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials

Now it's working. Maybe you can add a simple switch for this at connect-prtgserver?

Thank you for your help

lordmilko commented 6 years ago

Thanks @Z3nto,

I will look into adding parameters for configuring the proxy via Connect-PrtgServer and Set-PrtgClient to PrtgAPI 0.9.2 or 0.9.3. I will update this issue when this feature has been implemented

Regards, lordmilko

lordmilko commented 6 years ago

Hi @Z3nto,

Can you please run the following code and advise what the output is? If you are not already connected to your PRTG Server you will be prompted to enter in your server address and password.

The code below represents a simple test designed to gauge how much infrastructure is required to support automatic proxy authentication. As the DefaultWebProxy is a global resource utilized by the application, it is important as little is changed as possible to prevent issues in more complex usage scenarios.

In the event any sensitive information is emitted from the output, please replace this information with something else (e.g. a bogus server/username/password) without disrupting the general information included in the output

if(!(Get-PrtgClient))
{
    Connect-PrtgServer
}

$prtgClient = Get-PrtgClient

Add-Type -AssemblyName System.Net.Http

$handler = New-Object System.Net.Http.HttpClientHandler
$defaultProxy = [System.Net.WebRequest]::DefaultWebProxy

if($defaultProxy.Credentials)
{
    Write-Host "Default credentials are $($defaultProxy.Credentials)"
}
else
{
    Write-Host "Default proxy doesn't have any credentials"
}

$systemProxy = [System.Net.WebRequest]::GetSystemWebProxy()

if($defaultProxy -eq $systemProxy)
{
    Write-Host "System and default proxy were the same"
}
else
{
    Write-Host "System and default proxy were different"
}

if($defaultProxy.Credentials -eq $null)
{
    Write-Host "Setting default proxy to default network credentials"
    [System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
}

$httpClient = New-Object System.Net.Http.HttpClient -ArgumentList @($handler)

$url = "$($prtgClient.Server)/api/table.xml?content=sensors&columns=name,id&username=$($prtgClient.UserName)&count=1&passhash=$($prtgClient.Passhash)"

if(!($url.StartsWith("http")))
{
    $url = "https://$url"
}

$httpClient.GetStringAsync($url)
Z3nto commented 6 years ago

Hi @lordmilko

there you go. I've execute the script 2 times in the same powershell session to show the changes:

PS C:\temp> .\testPrtgAPI.ps1

cmdlet Connect-PrtgServer at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
Credential
Connect-PrtgServer : The remote server returned an error: (407) Proxy Authentication Required.
At C:\temp\testPrtgAPI.ps1:4 char:5
+     Connect-PrtgServer https://foo.bar.de
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Connect-PrtgServer], WebException
    + FullyQualifiedErrorId : System.Net.WebException,PrtgAPI.PowerShell.Cmdlets.ConnectPrtgServer

Default proxy doesn't have any credentials
System and default proxy were different
Setting default proxy to default network credentials
Exception calling "GetStringAsync" with "1" argument(s): "Invalid URI: The hostname could not be parsed."
At C:\temp\testPrtgAPI.ps1:49 char:1
+ $httpClient.GetStringAsync($url)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : UriFormatException

PS C:\temp> .\testPrtgAPI.ps1

cmdlet Connect-PrtgServer at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
Credential
Default credentials are System.Net.SystemNetworkCredential
System and default proxy were different

Result                 : <?xml version="1.0" encoding="UTF-8"?>
                           <sensors totalcount="465" listend="0">
                            <prtg-version>18.3.42.1748</prtg-version>
                            <item>
                             <name> br0</name>
                            </item>
                           </sensors>
Id                     : 117
Exception              :
Status                 : RanToCompletion
IsCanceled             : False
IsCompleted            : True
CreationOptions        : None
AsyncState             :
IsFaulted              : False
AsyncWaitHandle        : System.Threading.ManualResetEvent
CompletedSynchronously : False
lordmilko commented 6 years ago

Thanks @Z3nto,

I realized you were going to get that error and was in the middle of amending my message, however it appears running it twice works around that issue :P

This tells us that in your case, you don't actually need to replace the DefaultWebProxy with the SystemWebProxy, and that is sufficient to simply instruct the DefaultWebProxy to utilize the DefaultNetworkCredentials if the server asks for them. That's great, as I believe my proposed resolution (applying the DefaultNetworkCredentials if no credentials have otherwise been specified) is the least risky solution to this issue.

Can you potentially also confirm for me how your proxy has been configured on your system? If you open Internet Explorer Properties and navigate to Connections -> LAN Settings, is your proxy manually specified under Proxy server or is automatically detected via having the Automatically detect settings box ticked?

Z3nto commented 6 years ago

@lordmilko my proxy is set manually, but this is configured via Group Policy :)

lordmilko commented 6 years ago

That's fine; my research shows that when the proxy settings are detected via automatic detection/PAC scripts the DefaultWebProxy may not necessarily be equal to the SystemWebProxy. The implication of this is that users requiring PAC scripts may have issues with this fix, thereby requiring some sort of infrastructure be put in place to determine which proxy to use in a given scenario, and given I don't even have a proxy server to mess with I certainly don't want to go down that path.

As such, for now I will implement a solution sufficient for this issue and revisit proxy configurations at a later date in the event anyone requires additional functionality.

I will update this issue when PrtgAPI 0.9.2 is ready for distribution to confirm with you the implemented solution does in fact resolve the issue.

lordmilko commented 6 years ago

Hi @Z3nto,

I have compiled a release candiate for PrtgAPI 0.9.2. Can you please perform the following steps and confirm whether the issue has been resolved?

  1. Download the release candidate
  2. Right click PrtgAPI.zip -> Properties
  3. On the General tab, under Security select Unblock
  4. Unzip the file
  5. Inside the extracted folder, double click the file PrtgAPI.cmd to open a PowerShell prompt with the release candidate loaded in it
  6. Run the command Connect-PrtgServer and attempt to connect using your server's details, and then confirm you can run a cmdlet like Get-Probe

Regards, lordmilko

Z3nto commented 6 years ago

Hi @lordmilko , with the release candidate the issue has been resolved. Thanks :)

lordmilko commented 6 years ago

Thanks @Z3nto,

PrtgAPI 0.9.2 has now been released. To update, simply run

Update-Module PrtgAPI

and reopen your PowerShell. For a full list of changes please see the release notes

Regards, lordmilko