29

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.

briantist
  • 45,546
  • 6
  • 82
  • 127
firestarter247
  • 355
  • 1
  • 4
  • 7
  • 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. – Martin Brandl Apr 06 '16 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. – firestarter247 Apr 06 '16 at 19:18

5 Answers5

27

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.

x0n
  • 51,312
  • 7
  • 89
  • 111
  • Worked like a charm. The proposed answer is probably more complete, but a lot more code to maintain. Your solution worked prefectly. Thanks – spilote Oct 02 '18 at 14:02
  • 2
    The above worked great for me, but in addition I also had to add the code in this answer: https://stackoverflow.com/a/41618979/908316 – Freddie Oct 31 '18 at 17:42
  • 2
    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 – Wiebe Tijsma Apr 16 '19 at 16:26
  • lifesaving. actually lifesaving – qciccoretti Jul 26 '23 at 18:34
14

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*
Jamiker
  • 141
  • 1
  • 2
  • 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 – jgraglia Jan 29 '20 at 10:31
  • 1
    also look for https://stackoverflow.com/a/55246366/1358289 for a pure powershell solution to this problem – jgraglia Jan 29 '20 at 10:44
  • Thank you for adding a complete sample to know where to put the magic code. – granadaCoder Mar 27 '20 at 17:42
12

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

Sean
  • 6,873
  • 4
  • 21
  • 46
WilliamWyman
  • 161
  • 1
  • 3
1

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.

Aymen TAGHLISSIA
  • 1,675
  • 13
  • 30
DheerajG
  • 97
  • 2
  • 7
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.

James
  • 75
  • 2
  • 8