[NoBrainer] SSL connection error when using PowerShell

When using https request (directly or indirectly) with PowerShell you might run into different errors when using non-standard (i.e. not trusted, expired, self-signed etc) certificates:

  1. The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
  2. The underlying connection was closed: An unexpected error occurred on a send.

In either case you will find plenty of information on the web on how you might workaround to this. If you happen to use PowerCLI I found the most reliable method to use the ‘Set-PowerCLIConfiguration’ cmdlet as this seems to be some kind of silver bullet working in all environments (although loading the PSSnapin is rather slow).

Add-PSSnapin VMware.VimAutomation.Core;
# set it to local session only
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore
  -Scope:Session -Confirm:$false;
# set it system wide
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore

[UPDATE 2013-12-29] when you search you will come across many different workarounds for this such as setting and modifying the ServiceEndpointManager in different variations:

[System.Net.ServicePointManager]::CheckCertificateRevocationList = $false;

# see update from 2016-06-27 below in case this does not work for you
[System.Net.ServicePointManager]::ServerCertificateValidationCallback += { $true; };

Add-Type @"
  using System.Net;
  using System.Security.Cryptography.X509Certificates;
  public class TrustAllCertificatesPolicy : ICertificatePolicy 
  {
     public bool CheckValidationResult
     (
       ServicePoint srvPoint, X509Certificate certificate
       ,
       WebRequest request, int certificateProblem
     ) 
     {
       return true;
     }
  }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertificatesPolicy

These also seem to work in different cases, however I made the following observations:
1. In combination with the aforementioned this might give you strange results when connecting to SSL endpoints (maybe the VMware implementation also overwrites this class).
2. At various customers either setting the ValidationCallback or adding the CertificatePolicy does not work when using self-signed certificates (and I honestly do not know why).
3. Once the behaviour is ‘broken’ you sometimes really have to close all existing PowerShell sessions and open a new one (again I do not know why).
4. (not really an observation) the property ‘CertificatePolicy’ is marked as obsolete by Microsoft and should not be used any more.

[UPDATE 2016-06-27] After setting [System.Net.ServicePointManager]::ServerCertificateValidationCallback += { $true; } and invoking a WebRequest you might receive a PowerShell ErrorRecord which gives you the following information when investigating the InnerException:

PS > $result = Invoke-RestMethod http://www.d-fens.ch
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
At line:1 char:11
+ $result = Invoke-RestMethod http://www.d-fens.ch
+           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

PS > $error[0].Exception.InnerException
There is no Runspace available to run scripts in this thread. You can provide one in the DefaultRunspace property of
the System.Management.Automation.Runspaces.Runspace type. The script block you attempted to invoke was: return $true;

If you come across this error, I would recommend to set the certitivate revocation callback directly from C# code like this:

Add-Type @"
    using System;
    using System.Net;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;
    public class ServerCertificateValidationCallback
    {
        public static void Ignore()
        {
            ServicePointManager.ServerCertificateValidationCallback += 
                delegate
                (
                    Object obj, 
                    X509Certificate certificate, 
                    X509Chain chain, 
                    SslPolicyErrors errors
                )
                {
                    return true;
                };
        }
    }
"@

[ServerCertificateValidationCallback]::Ignore();

If you happen to work in a VMware based environment this is all not necessary as you can utilise the ‘Set-PowerCLIConfiguration’ cmdlet (as described above).

Otherwise you can always use Set-SslSecurityPolicy from our biz.dfch.PS.System.Utilities PowerShell module which is avalailable at NuGet.

Comments

  1. Justin says:

    So I just ran into this same problem, and spent 4 hours looking for a solution. If you get the ‘unexpected error occurred on a send’, and the inner exception contains “Authentication failed because the remote party has closed the transport stream.” the issue turns out to be that the webserver does not like the TLS protocols being presented by PowerShell (or .NET apps for that matter). Adding this to my script fixed the problem:

    [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 -bor [System.Net.SecurityProtocolType]::Tls11

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: