43

I have a rest endpoint that doesn't perform an authentication check. I can run a simple curl commmand from Linux:

curl -k https://application/api/about

This responds.

However if try the following on PowerShell it fails:

Invoke-RestMethod https://application/api/about

Then I get:

Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
At line:1 char:1
+ Invoke-RestMethod $Application
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Could some one please tell me how I can get around this problem ?

EDIT:

Trying with Invoke-WebRequest:

Invoke-WebRequest -Uri "https://application/api/about"

Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send. At line:1 char:1 + Invoke-WebRequest -Uri "https://application/api/a ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

dross
  • 1,719
  • 2
  • 14
  • 22

3 Answers3

91

Using:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Taken from Powershell 3.0 Invoke-WebRequest HTTPS Fails on All Requests.

JamesThomasMoon
  • 6,169
  • 7
  • 37
  • 63
dross
  • 1,719
  • 2
  • 14
  • 22
23

In my case the TLS trick was not the problem. It was due to certificate mismatch. Although you can use {$true} for the callback, this does not scale well. Eventually powershell will fail with an error indicated it failed to load a runspace. This seems to be a bug in powershell. Instead, you need to add the callback using .net code instead of a scriptblock.

#C# class to create callback
$code = @"
public class SSLHandler
{
    public static System.Net.Security.RemoteCertificateValidationCallback GetSSLHandler()
    {

        return new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });
    }
    
}
"@

#compile the class
Add-Type -TypeDefinition $code

#disable checks using new class
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLHandler]::GetSSLHandler()
#do the request
try
{
    invoke-WebRequest -Uri myurl -UseBasicParsing
} catch {
    # do something
} finally {
   #enable checks again
   [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
}
Justin
  • 1,303
  • 15
  • 30
  • 3
    This worked for me while setting `[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}` and `[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy` didn't. – Andy Arismendi Mar 10 '19 at 17:24
  • @justin I do not understand why this worked, but it did. Is it a powershell version issue? – MonaLisaOverdrive Jun 05 '19 at 16:48
  • @AndyArismendi using {$true} does work, but you can get yourself into trouble if there are too many calls to https. that is why you need a compiled class. – Justin Jun 13 '19 at 02:13
  • @MonaLisaOverdrive as far as i can tell it is a powershell issue, basically it keeps reloading the powershell runspace and eventually reaches a point where it can't. – Justin Jun 13 '19 at 02:13
2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12

Works in Windows server 2016

Major Minor Build Revision


5 1 17763 1007

ssilas777
  • 9,672
  • 4
  • 45
  • 68