Powershell 3.0 Invoke-WebRequest HTTPS shuts down for all requests

I am trying to work with our load balancer through Powershell 3.0 and the REST API. However, I am currently receiving a refusal no matter what I try, if it is an https request, be it our load balancer or any other https site. I feel like I'm missing something obvious.

Here is the code that does not work with https

try { #fails #$location='https://www.bing.com' #fails #$location='https://www.google.com' #fails #$location='https://www.facebook.com' #fails #$location='https://www.ebay.com' #works #$location='http://www.bing.com' #works #$location='http://www.google.com' #fails (looks like Facebook does a redirect to https://) $location='http://www.facebook.com' #works #$location='http://www.ebay.com' $response='' $response = Invoke-WebRequest -URI $location $response.StatusCode $response.Headers } catch { Write-Host StatusCode $response.StatusCode Write-Host $_.Exception } 

The error I get is:

 System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.Management.Automation.PSInvalidOperationException: 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.Runspa ce type. The script block you attempted to invoke was: $true at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult) at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar) --- End of inner exception stack trace --- at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request) at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord() 

I was hoping this page and proposals to the bottom, including from Aaron D.), would matter, but none of them changed the situation.

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

and

 function Ignore-SSLCertificates { $Provider = New-Object Microsoft.CSharp.CSharpCodeProvider $Compiler = $Provider.CreateCompiler() $Params = New-Object System.CodeDom.Compiler.CompilerParameters $Params.GenerateExecutable = $false $Params.GenerateInMemory = $true $Params.IncludeDebugInformation = $false $Params.ReferencedAssemblies.Add("System.DLL") > $null $TASource=@' namespace Local.ToolkitExtensions.Net.CertificatePolicy { public class TrustAll : System.Net.ICertificatePolicy { public bool CheckValidationResult(System.Net.ServicePoint sp,System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem) { return true; } } } '@ $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource) $TAAssembly=$TAResults.CompiledAssembly ## We create an instance of TrustAll and attach it to the ServicePointManager $TrustAll = $TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll") [System.Net.ServicePointManager]::CertificatePolicy = $TrustAll } 

and

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

I tried switching to Invoke-RestCommand, but to no avail, as I get the same answer.

It seems like this should be something eco-friendly, because I cannot believe that it does not work for anyone else, but I tried it on the workstation and on the server with the same results (not usually but I know that they were configured differently).

Any thoughts?

+14
Aug 05 '14 at 16:31
source share
4 answers

This worked great for me. The site uses TLS 1.0 by default, and apparently the PS does not work with this. I used this line:

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

My PS scripts (so far everything I've tested) worked fine.

+30
Sep 28 '16 at 1:34
source

The answer to this question does not solve the SSL problem:

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

If you do, your first https request will work (it seems), but there will be no subsequent ones. Also, at this point you need to close ISE Powershell and reopen it, then try again (without this line).

This is stated in the sentence here http://social.technet.microsoft.com/Forums/windowsserver/en-US/79958c6e-4763-4bd7-8b23-2c8dc5457131/sample-code-required-for-invokerestmethod-using-https -and-basic-authorization? forum = winserverpowershell - "And all subsequent runs raise this error:", but it was not clear which solution reset was.

+20
Aug 6 '14 at
source

I also suffered for a very long time from this. This even affected Visual Studio, since VS uploaded my $PROFILE to its domain when starting NuGet recovery.

Seeing your comment above, I realized that I had a custom callback script, because one of our suppliers sent a product with an invalid CN to ssl cert.

In short, I replaced the delegate script with a compiled C # object (removing the script space from the equation).

(separate block of code for C # allocation)

 using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; public static class CustomCertificateValidationCallback { public static void Install() { ServicePointManager.ServerCertificateValidationCallback += CustomCertificateValidationCallback.CheckValidationResult; } public static bool CheckValidationResult( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { // please don't do this. do some real validation with explicit exceptions. return true; } } 

In Powershell:

 Add-Type "" # C# Code [CustomCertificateValidationCallback]::Install() 
+6
Mar 10 '16 at 21:23
source

Combining and summarizing some of the above lessons, I took the following approach:

The syntax is colorized and commented out as C # of the past:

 // Piggyback in System.Net namespace to avoid using statement(s) namespace System.Net { // Static class to make the ps call easy // Uses a short name that is unlikely to clash with real stuff...YMMV public static class Util { // Static method for a static class public static void Init() { // [optionally] clear any cruft loaded into this static scope ServicePointManager.ServerCertificateValidationCallback = null; // Append a dangerously permissive validation callback // using lambda syntax for brevity. ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errs) => true; // Tell SPM to try protocols that have a chance // of working against modern servers. // Word on the street is that these will be tried from "most secure" // to least secure. Some people add em all! ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; } } } 

And now the real version of PowerShell with highlighting (no comment, but the same code)

 Add-Type -Language CSharp @" namespace System.Net { public static class Util { public static void Init() { ServicePointManager.ServerCertificateValidationCallback = null; ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errs) => true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; }}}"@ [System.Net.Util]::Init() 

Obviously, you can remove irrelevant spaces, but you should be able to add them to your session, and then Invoke-WebRequest as you wish.

note that

 # Do not use IMHO! [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} 
An approach

seems completely wrong for PS 5.1 (where I checked this). Not sure where it came from, but I would like to avoid it and save the heartache.

0
Aug 09 '19 at 2:11
source



All Articles