33

It seems like this question has been asked and answered, but so far every solution I come across does not help. I'm writing a PowerShell script to run some REST API's to get usage information. My script breaks immediately just trying to communicate to the server. For testing sake, I'm doing a very simplistic command:

Invoke-RestMethod 'https://server:4443/login' 

It returns with this error:

Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send. 

I can run the same command but with URL google.com and I get a valid return, so I know the command is working generally speaking.

If I run the curl equivalent on the server itself, things complete as expected. Here's a snippet of the verbose output of the curl command:

* SSLv3, TLS handshake, Client hello (1): * SSLv3, TLS handshake, Server hello (2): * SSLv3, TLS handshake, CERT (11): * SSLv3, TLS handshake, Server key exchange (12): * SSLv3, TLS handshake, Server finished (14): * SSLv3, TLS handshake, Client key exchange (16): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSL connection using TLSv1.0 / DHE-RSA-AES256-SHA * Server certificate: * subject: CN=localhost * start date: 2016-03-22 21:48:57 GMT * expire date: 2026-03-20 21:48:57 GMT * issuer: CN=localhost * SSL certificate verify result: self signed certificate (18), continuing anyway. 

I'm only assuming this is a self signed cert issue based upon searching the fairly generic error PowerShell returns.

I've tried:

[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} 

and other similar methods (complex functions) to help ignore certificate issues with no luck.

I'm running PowerShell 5 in case that helps.

I'm decent with PowerShell code but this is my first time trying Invoke-RestMethod, so maybe I'm missing something. Any insight is appreciated.

2
  • Maybe you miss your credentials if the webserver requires auth (-Credential). Or you need to specifiy -Method parameter post or` get. Its hard to tell if we don't know what your server is expecting. Commented Apr 6, 2016 at 18:54
  • My apologies for not giving full information upfront. I pass credentials via headers. I've tried to explicitly call the method too. Commented Apr 6, 2016 at 19:18

6 Answers 6

35

This will also work in later versions of powershell with invoke-restmethod/webrequest. It avoids the requirement for a runspace by implementing the handler as native .net:

if (-not("dummy" -as [type])) { add-type -TypeDefinition @" using System; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; public static class Dummy { public static bool ReturnTrue(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } public static RemoteCertificateValidationCallback GetDelegate() { return new RemoteCertificateValidationCallback(Dummy.ReturnTrue); } } "@ } [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [dummy]::GetDelegate() 

Hope this helps.

Sign up to request clarification or add additional context in comments.

4 Comments

Worked like a charm. The proposed answer is probably more complete, but a lot more code to maintain. Your solution worked prefectly. Thanks
The above worked great for me, but in addition I also had to add the code in this answer: stackoverflow.com/a/41618979/908316
Wow, it works. And this is so much easier than adding a "--insecure" to cURL. Thank you PowerShell for making our life this easy. Sorry did I say that out loud? ;p
lifesaving. actually lifesaving
15

i know this is old, but it still came up when i had this question with out actually checking. google first right?

Try this:

invoke-restMethod -SkipCertificateCheck -uri 'https://server:4443/login' -etc..etc..etc.. 

got it here via google: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-6

1 Comment

the question is marked for 5.0, the documentation you are referring to is for version 6.
15

If after @x0n answer, you still have the problem, try add before Request/Rest this

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

Working script for me:

if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type) { $certCallback = @" using System; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; public class ServerCertificateValidationCallback { public static void Ignore() { if(ServicePointManager.ServerCertificateValidationCallback ==null) { ServicePointManager.ServerCertificateValidationCallback += delegate ( Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors ) { return true; }; } } } "@ Add-Type $certCallback } [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; [ServerCertificateValidationCallback]::Ignore() Invoke-WebRequest https://*YOUR URI* 

3 Comments

this works for me on a Windows Server 2016 Box + PowerShell 5 (PSVersion 5.1.14393.693) For PowerShell 6+ use the -SkipCertificateCheck flag of Invoke-WebRequest
also look for stackoverflow.com/a/55246366/1358289 for a pure powershell solution to this problem
Thank you for adding a complete sample to know where to put the magic code.
2

I had a similar issue and my PS version was 5.1, I initially used [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12

But anything below Powershell6 please use the certificate policy from below link : https://gist.github.com/rchaganti/aae721ebccd25eaab0b8b3dd67ad4b9b

It works like charm. Thanks to Ravi Chaganti.

1 Comment

Works for me: [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 Powershel: 5.1.19041.2364
0

I have been fighting this same issue for awhile now. I tried several variations of such scripts as what's already been posted in this thread. I was surprised to discover that by taking the same script and running it on my own workstation instead of in my testing environment that it worked.

In the end, I found out that by simply running the script in my test environment using elevated credentials (Run as administrator) that it worked without the SSL/TLS error.

Comments

0

You don't need to hack in C# via Add-Type; powershell works fine.

$extra = @{} if ($PSVersionTable.PSVersion.Major -gt 5) { $extra['SkipCertificateCheck'] = $True } elseif (![System.Net.ServicePointManager]::ServerCertificateValidationCallback) { class ServerCertificateValidationCallback { static [bool] Ignore( [System.Object] $obj, [System.Security.Cryptography.X509Certificates.X509Certificate] $certificate, [System.Security.Cryptography.X509Certificates.X509Chain] $chain, [System.Net.Security.SslPolicyErrors] $errors ) { return $True } } [System.Net.ServicePointManager]::ServerCertificateValidationCallback += [System.Delegate]::CreateDelegate( [System.Net.Security.RemoteCertificateValidationCallback], [ServerCertificateValidationCallback], 'Ignore' ) } 

Now you can run regardless of whether you're PS5 or PS6/7

Invoke-RestMethod -Uri $uri -YourOther $arguments @extra 

The power of this answer over the others is that you can now modify whether you return $True based on whatever you want to write (maybe double-check that the cert is the self-signed one you're allowing as opposed to allowing everything..)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.