Powershell v3 HTTPS-Fehler Invoke-WebRequest

126

Mit Invoke-WebRequest und Invoke-RestMethod von Powershell v3 habe ich die POST-Methode erfolgreich verwendet, um eine JSON-Datei auf einer https-Website zu veröffentlichen.

Der Befehl, den ich benutze, ist

 $cert=New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("cert.crt")
 Invoke-WebRequest -Uri https://IPADDRESS/resource -Credential $cred -certificate $cert -Body $json -ContentType application/json -Method POST

Wenn ich jedoch versuche, die GET-Methode wie folgt zu verwenden:

 Invoke-WebRequest -Uri https://IPADDRESS/resource -Credential $cred -certificate $cert -Method GET

Der folgende Fehler wird zurückgegeben

 Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
 At line:8 char:11
 + $output = Invoke-RestMethod -Uri https://IPADDRESS/resource -Credential $cred
 +           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest)      [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Ich habe versucht, den folgenden Code zu verwenden, um das SSL-Zertifikat zu ignorieren, bin mir aber nicht sicher, ob es tatsächlich etwas bewirkt.

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

Kann jemand eine Anleitung geben, was hier möglicherweise schief geht und wie man es behebt?

Vielen Dank

Floyd
quelle
Also welches benutzt du? Invoke-RestMethododer Invoke-WebRequest?
Svick
Invoke-WebRequest. Ich benutze es, da es im Gegensatz zu Invoke-RestMethod die Request / Resposne-Header zurückgibt. Ich habe jedoch Invoke-RestMethod ausprobiert, das ebenfalls identische Parameter verwendet.
Floyd
Für das, was es wert ist, ist das ServerValidationCallback-Ding mit ziemlicher Sicherheit ein roter Hering, da der Fehler, den Sie erhalten sollten, wenn Sie ein SSL-Validierungsproblem haben, Folgendes aussagen sollte: Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. Sie könnten versuchen, $ Error [0] .Exception.InnerException zu untersuchen, um weitere Informationen zu erhalten. .
Jaykul

Antworten:

179

Diese Problemumgehung hat bei mir funktioniert: http://connect.microsoft.com/PowerShell/feedback/details/419466/new-webserviceproxy-needs-force-parameter-to-ignore-ssl-errors

Grundsätzlich in Ihrem PowerShell-Skript:

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

$result = Invoke-WebRequest -Uri "https://IpAddress/resource"
Lee Grissom
quelle
9
Beachten Sie, dass diese Antwort richtig ist. Der Punkt einer anderen Antwort ( stackoverflow.com/a/25163476/68432 ) ist jedoch ebenfalls gültig. Diese Lösung funktioniert nicht, wenn Sie zuvor "[System.Net.ServicePointManager] :: ServerCertificateValidationCallback = {$ true}" ausgeführt haben.
Paul Suart
Sie müssen die Typprüfungsprüfung gemäß der Antwort von Arthur Strutzenberg unten hinzufügen,
sonst
Gibt es ein Sicherheitsrisiko für die Verwendung in der Produktion?
Amjad
13
5 Jahre später ist dies immer noch die Lösung für PowerShell 5.1 (vollständiges .NET Framework). Für PowerShell Core gibt es ein -SkipCertificateCheckJetzt.
EvilSnobu
MS haben Connect heruntergefahren, dieser Link ist ungültig. Gibt es noch einen Link?
Mark Heath
71

Lees Antwort ist großartig, aber ich hatte auch Probleme mit den vom Webserver unterstützten Protokollen.
Nachdem ich auch die folgenden Zeilen hinzugefügt hatte, konnte ich die https-Anfrage durchstellen. Wie in dieser Antwort ausgeführt, https://stackoverflow.com/a/36266735

$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols

Meine vollständige Lösung mit Lees Code.

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;
    }
}
"@
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
AndOs
quelle
Haben Sie eine bessere Lösung gefunden, denn wenn Sie 40 Skripte haben, müssen Sie diese zu jedem hinzufügen? Scheint keinen Sinn zu ergeben. Übrigens, danke für die Antwort
Ender
1
Lees Antwort hat bei mir nicht funktioniert. Ich musste die Bits hinzufügen, auf die Sie verwiesen haben, und es hat funktioniert!
Pat K
Vielen Dank, die Angabe der Protokolle hat zur Lösung des Problems beigetragen
Alex
1
Danke, danke, danke, dass Sie mir die SecurityProtocolglobale statische Eigenschaft gezeigt haben. Gott, ich habe gerade TAGE verloren, als ich Zertifikate, Vertrauensstellungen, Netzwerke, Routen, Berechtigungen und eine Menge anderer Dinge überprüft habe, um vage endpoint does not respondFehler beim Zugriff auf einen bestimmten Server über https zu lösen (alle anderen funktionieren), nur weil diese verdammte Powershell 5.1 Standardwerte SSL3, TLS und es einfach BLOCKS Hippie - TLS11 und TLS12 Verzugs Gott , wie sehr ich diesen Mist hasse ich geschrieben haben , sollten das Skript in C # / Rubin / C ++, oder was sonst auch immer , die nicht Powershell ist
quetzalcoatl
1
@ StanTastic: Ich denke, es ist unmöglich, die Standardeinstellungen dauerhaft zu ändern. Ich denke, es ist im ServicePointManager-Quellcode fest codiert. Ich habe es aber nie überprüft, also gibt es vielleicht einen Weg.
Quetzalcoatl
10

Hast du es versucht System.Net.WebClient?

$url = 'https://IPADDRESS/resource'
$wc = New-Object System.Net.WebClient
$wc.Credentials = New-Object System.Net.NetworkCredential("username","password")
$wc.DownloadString($url)
Sunny Chakraborty
quelle
Sunny, ich erhalte Folgendes, wenn ich diesen Code verwende: Ausnahme beim Aufrufen von "DownloadString" mit "1" -Argumenten: "Der Remote-Server hat einen Fehler zurückgegeben: (406) Nicht akzeptabel." In Zeile: 4 Zeichen: 1 + $ wc.DownloadString ($ url) + ~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: NotSpecified: (:) [ ], MethodInvocationException + FullyQualifiedErrorId: WebException
FLOYD
Basierend auf der API-Dokumentation des REST-Dienstes gibt im using 406 an, "dass der in der Anforderung enthaltene Accept-Header keine XML- oder JSON-Antwort zulässt"
Floyd,
Welche Antworttypen sind zulässig, wenn XML / JSON-Antworten nicht zulässig sind?
Sunny Chakraborty
Ist dies ein benutzerdefinierter Webdienst, den Sie verwenden? Gibt es eine öffentlich verfügbare Dokumentation für die REST-API?
Sunny Chakraborty
Es ist ein Ticketingsystem namens EM7. Ich glaube nicht, dass sie öffentliche Dokumente haben. Der Dienst akzeptiert JSON / XML-Antworten (funktioniert einwandfrei, wenn ich cURL verwende). Ich glaube, der Fehler zeigt an, dass System.Net.WebClient nicht?
Floyd
9

Eine alternative Implementierung in rein (ohne Add-Typevon Quelle):

#requires -Version 5
#requires -PSEdition Desktop

class TrustAllCertsPolicy : System.Net.ICertificatePolicy {
    [bool] CheckValidationResult([System.Net.ServicePoint] $a,
                                 [System.Security.Cryptography.X509Certificates.X509Certificate] $b,
                                 [System.Net.WebRequest] $c,
                                 [int] $d) {
        return $true
    }
}
[System.Net.ServicePointManager]::CertificatePolicy = [TrustAllCertsPolicy]::new()
Maximilian Burszley
quelle
7

Das Folgende hat bei mir funktioniert (und verwendet die neuesten nicht veralteten Mittel, um mit der SSL-Zertifikat- / Rückruffunktion zu interagieren) und versucht nicht, denselben Code mehrmals in derselben Powershell-Sitzung zu laden:

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
 }
[ServerCertificateValidationCallback]::Ignore();

Dies wurde aus dem folgenden Artikel angepasst: https://d-fens.ch/2013/12/20/nobrainer-ssl-connection-error-when-using-powershell/

Arthur Strutzenberg
quelle
5

Ich fand das, als ich diese Rückruffunktion verwendete, um SSL-Zertifikate zu ignorieren [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

Ich habe immer die Fehlermeldung erhalten, Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.die nach den Ergebnissen klingt, die Sie haben.

Ich habe diesen Forumsbeitrag gefunden, der mich zu der folgenden Funktion führte. Ich führe dies einmal im Rahmen meines anderen Codes aus und es funktioniert für mich.

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
}

Aaron D.
quelle
1

Ich habe versucht, nach Dokumentation für die EM7 OpenSource REST-API zu suchen. Bisher kein Glück.

http://blog.sciencelogic.com/sciencelogic-em7-the-next-generation/05/2011

Es wird viel über die OpenSource REST-API gesprochen, aber kein Link zur eigentlichen API oder Dokumentation. Vielleicht war ich ungeduldig.

Hier sind einige Dinge, die Sie ausprobieren können

$a = Invoke-RestMethod -Uri https://IPADDRESS/resource -Credential $cred -certificate $cert 
$a.Results | ConvertFrom-Json

Versuchen Sie dies, um festzustellen, ob Sie die Spalten herausfiltern können, die Sie von der API erhalten

$a.Results | ft

oder Sie können dies auch versuchen

$b = Invoke-WebRequest -Uri https://IPADDRESS/resource -Credential $cred -certificate $cert 
$b.Content | ConvertFrom-Json

Curl Style Header

$b.Headers

Ich habe das IRM / IWR mit der Twitter JSON API getestet.

$a = Invoke-RestMethod http://search.twitter.com/search.json?q=PowerShell 

Hoffe das hilft.

Sunny Chakraborty
quelle
Vielen Dank für all Ihre Hilfe. Der erste Befehl $ a = Invoke-RestMethod (...) ist jedoch derjenige, der derzeit für mich nicht funktioniert. Funktioniert gut für eine HTTP-Site, aber wenn Sie HTTPS einführen, was EM7 tut, wird der beschriebene Fehler zurückgegeben. Dies gilt für Invoke-RestMethod und Invoke-WebRequest. Ich bin gerade dabei, ein Invoke-Command-Cmdlet zu verwenden und Curl auszuführen.
Floyd
1

Invoke-WebRequest "DomainName" -SkipCertificateCheck

Sie können den Parameter -SkipCertificateCheck verwenden , um dies als einzeiligen Befehl zu erreichen (DIESER PARAMETER WIRD NUR AUF KERN-PSEDITION UNTERSTÜTZT).

Amar Helloween
quelle
0
  1. Führen Sie diesen Befehl aus

New-SelfSignedCertificate -certstorelocation-Zertifikat: \ localmachine \ my -dnsname {your-site-hostname}

In Powershell mit Administratorrechten werden alle Zertifikate im persönlichen Verzeichnis generiert

  1. Um den Datenschutzfehler zu beseitigen, wählen Sie diese Zertifikate aus und klicken Sie mit der rechten Maustaste auf → Kopieren. Und fügen Sie Trusted Root Certification Authority / Zertifikate ein.
  2. Der letzte Schritt besteht darin, die richtigen Bindungen in IIS auszuwählen. Gehen Sie zur IIS-Website, wählen Sie Bindungen, aktivieren Sie das Kontrollkästchen SNI und legen Sie die einzelnen Zertifikate für jede Website fest.

Stellen Sie sicher, dass der Hostname der Website und der DNS-Name des Zertifikats genau übereinstimmen

Mohit Dharmadhikari
quelle
0

Diese Registrierungseinstellungen wirken sich auf .NET Framework 4+ und damit auf PowerShell aus. Legen Sie sie fest und starten Sie alle PowerShell-Sitzungen neu, um das neueste TLS zu verwenden. Ein Neustart ist nicht erforderlich.

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 

Siehe https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls#schusestrongcrypto

Jeremy Cook
quelle
Wir haben die Erfahrung gemacht, dass für diesen anderen Registrierungs-Patch tatsächlich ein Neustart erforderlich ist, um die ordnungsgemäße Funktionalität zu gewährleisten. Bei dem Versuch, eine TLS 1.2-Verbindung zwischen einer Windows-Box mit einer .NET-App sicherzustellen, wurde SSL 3 über die Netzwerkablaufverfolgung angezeigt, um mit diesem Registrierungswert verwendet zu werden, jedoch vor einem Neustart. TLS 1.2 wurde erst nach einem Neustart aufgerufen.
David W
-1

Wenn Sie dies als Administrator ausführen, sollte dieser Fehler behoben sein

Autonom
quelle