Erreur HTTPS Powershell v3 Invoke-WebRequest

126

En utilisant Invoke-WebRequest et Invoke-RestMethod de Powershell v3, j'ai utilisé avec succès la méthode POST pour publier un fichier json sur un site Web https.

La commande que j'utilise est

 $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

Cependant, lorsque j'essaye d'utiliser la méthode GET comme:

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

L'erreur suivante est renvoyée

 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

J'ai essayé d'utiliser le code suivant pour ignorer le certificat SSL, mais je ne suis pas sûr qu'il fasse réellement quelque chose.

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

Quelqu'un peut-il donner des indications sur ce qui pourrait ne pas se passer ici et comment y remédier?

Merci

floyd
la source
Alors, lequel utilisez-vous? Invoke-RestMethodou Invoke-WebRequest?
svick
Invoke-WebRequest. Je l'utilise car il renvoie les en-têtes request / resposne contrairement à Invoke-RestMethod. Cependant, j'ai essayé Invoke-RestMethod qui prend également des paramètres identiques.
floyd
Pour ce que ça vaut, la chose ServerValidationCallback est presque certainement un hareng rouge, puisque l'erreur que vous devriez obtenir lorsque vous avez un problème de validation SSL doit DITES que: Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. Vous pouvez essayer d'explorer $ Error [0] .Exception.InnerException pour plus d'informations. .
Jaykul

Réponses:

179

Cette solution a fonctionné pour moi: http://connect.microsoft.com/PowerShell/feedback/details/419466/new-webserviceproxy-needs-force-parameter-to-ignore-ssl-errors

Fondamentalement, dans votre script PowerShell:

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
la source
9
Notez que cette réponse est correcte; cependant, le point soulevé sur une autre réponse ( stackoverflow.com/a/25163476/68432 ) est également valable. Cette solution ne fonctionnera pas si vous avez fait "[System.Net.ServicePointManager] :: ServerCertificateValidationCallback = {$ true}" au préalable.
Paul Suart
Vous devez ajouter la vérification de la condition de type selon la réponse d'Arthur Strutzenberg ci-dessous ou vous obtiendrez une erreur indiquant que le type existe déjà
Ralph Willgoss
Y a-t-il un risque de sécurité lié à son utilisation en production?
Amjad
13
5 ans plus tard, c'est toujours la solution pour PowerShell 5.1 (full .NET Framework). Pour PowerShell Core, il existe -SkipCertificateCheckmaintenant.
evilSnobu
MS a interrompu Connect, ce lien est invalide. Y a-t-il un autre lien?
Mark Heath le
71

La réponse de Lee est excellente, mais j'ai également eu des problèmes avec les protocoles pris en charge par le serveur Web.
Après avoir également ajouté les lignes suivantes, je pourrais obtenir la requête https. Comme indiqué dans cette réponse https://stackoverflow.com/a/36266735

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

Ma solution complète avec le code de Lee.

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
la source
avez-vous trouvé une meilleure solution, coz si vous avez 40 scripts alors vous devez l'ajouter à chacun ?. Cela n'a aucun sens. Btw, merci pour la réponse
Ender
1
La réponse de Lee n'a pas fonctionné pour moi. J'ai dû ajouter les bits que vous avez référencés et CELA A FONCTIONNÉ!
Pat K
Merci beaucoup, la spécification des protocoles a aidé à résoudre le problème
Alex
1
Merci merci merci de m'avoir montré la SecurityProtocolpropriété statique globale. Bon sang, je viens de perdre des JOURS en vérifiant les certificats, les approbations, le réseau, les routes, les autorisations et une foule d'autres choses en essayant de résoudre une endpoint does not responderreur vague lors de l'accès à un serveur spécifique via https (tous les autres fonctionnent), simplement parce que ce putain de PowerShell 5.1 par défaut SSL3, TLS et ce juste BLOCS GODDAMN TLS11 et TLS12 PAR dÉFAUT dieu à quel point je déteste cette merde je aurais dû écrire ce script en C # / Ruby / C ++, ou tout autre chose qui ne powershell
Quetzalcoatl
1
@StanTastic: Je pense qu'il est impossible de modifier définitivement les valeurs par défaut. Je pense qu'il est codé en dur dans le code source de ServicePointManager. Je n'ai jamais vérifié, alors peut-être qu'il y a un moyen.
quetzalcoatl
10

Avez-vous essayé d'utiliser 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)
Chakraborty ensoleillé
la source
Sunny, je reçois ce qui suit lors de l'utilisation de ce code: Exception appelant "DownloadString" avec "1" argument (s): "Le serveur distant a renvoyé une erreur: (406) Not Acceptable." À la ligne: 4 char: 1 + $ wc.DownloadString ($ url) + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: NotSpecified: (:) [ ], MethodInvocationException + FullyQualifiedErrorId: WebException
floyd
Basé sur la documentation de l'API du service REST, im using 406 indique "que l'en-tête d'acceptation inclus dans la demande ne permet pas une réponse XML ou JSON"
floyd
Quels types de réponse sont autorisés si les réponses XML / JSON ne sont pas autorisées?
Sunny Chakraborty
S'agit-il d'un service Web personnalisé que vous utilisez? Existe-t-il une documentation accessible au public pour l'API REST?
Sunny Chakraborty
C'est un système de billetterie appelé EM7. Je ne crois pas qu'ils aient des documents publics. Le service accepte la réponse JSON / XML (fonctionne très bien si j'utilise cURL) Je crois que l'erreur indique que System.Net.WebClient n'est pas?
floyd
10

Une implémentation alternative en pure (sans Add-Typede la source):

#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
la source
7

Ce qui suit a fonctionné pour moi (et utilise les derniers moyens non obsolètes pour interagir avec la fonctionnalité SSL Certs / callback) et n'essaye pas de charger le même code plusieurs fois dans la même session PowerShell:

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();

Cela a été adapté de l'article suivant https://d-fens.ch/2013/12/20/nobrainer-ssl-connection-error-when-using-powershell/

Arthur Strutzenberg
la source
5

J'ai constaté que lorsque j'ai utilisé cette fonction de rappel pour ignorer les certificats SSL [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

J'ai toujours reçu le message d'erreur Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.qui ressemble aux résultats que vous obtenez.

J'ai trouvé ce post de forum qui me conduit à la fonction ci-dessous. Je l'exécute une fois dans le cadre de mon autre code et cela fonctionne pour moi.

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
la source
1

J'ai essayé de rechercher de la documentation sur l'API REST EM7 OpenSource. Pas de chance pour l'instant.

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

On parle beaucoup de l'API REST OpenSource, mais pas de lien vers l'API réelle ou aucune documentation. J'étais peut-être impatient.

Voici quelques choses que vous pouvez essayer

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

Essayez ceci pour voir si vous pouvez filtrer les colonnes que vous obtenez de l'API

$a.Results | ft

ou, vous pouvez essayer d'utiliser ceci aussi

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

En-têtes de style Curl

$b.Headers

J'ai testé l'IRM / IWR avec l'API Twitter JSON.

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

J'espère que cela t'aides.

Chakraborty ensoleillé
la source
Merci pour toute votre assistance. Cependant, la première commande $ a = Invoke-RestMethod (...) est celle qui ne fonctionne pas actuellement pour moi. Fonctionne bien pour un site HTTP, mais lorsque vous introduisez HTTPS, ce que EM7 fait, il renvoie l'erreur décrite. C'est pour Invoke-RestMethod et Invoke-WebRequest. Je suis en train d'utiliser simplement une cmdlet Invoke-Command et d'exécuter curl.
floyd
1

Invoke-WebRequest "DomainName" -SkipCertificateCheck

Vous pouvez utiliser -SkipCertificateCheck Parameter pour y parvenir en tant que commande à une seule ligne (CE PARAMÈTRE EST UNIQUEMENT PRIS EN CHARGE SUR LA PSEDITION DE BASE)

Amar Helloween
la source
0
  1. Exécutez cette commande

Nouveau-SelfSignedCertificate -certstorelocation cert: \ localmachine \ my -dnsname {votre-site-hostname}

dans PowerShell en utilisant les droits d'administrateur , cela générera tous les certificats dans le répertoire personnel

  1. Pour supprimer l'erreur de confidentialité, sélectionnez ces certificats, cliquez avec le bouton droit de la souris → Copier. Et collez dans Trusted Root Certification Authority / Certificates.
  2. La dernière étape consiste à sélectionner les liaisons correctes dans IIS. Accédez au site Web IIS, sélectionnez Liaisons, sélectionnez la case à cocher SNI et définissez les certificats individuels pour chaque site Web.

Assurez-vous que le nom d'hôte du site Web et le nom DNS du certificat doivent correspondre exactement

Mohit Dharmadhikari
la source
0

Ces paramètres de registre affectent .NET Framework 4+ et donc PowerShell. Définissez-les et redémarrez toutes les sessions PowerShell pour utiliser le dernier TLS, aucun redémarrage nécessaire.

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 

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

Jeremy Cook
la source
Pour quiconque voit cette réponse, notre expérience est que ce correctif de registre nécessite en fait un redémarrage pour garantir une fonctionnalité appropriée. Lors de la tentative de garantir une connexion TLS 1.2 entre un boîtier Windows exécutant une application .NET, SSL 3 a été montré via la trace réseau à utiliser avec cette valeur de registre en place, mais avant un redémarrage; TLS 1.2 n'a été appelé qu'après un redémarrage.
David W
-1

Si vous exécutez ceci en tant qu'administrateur, cette erreur devrait disparaître

Autonome
la source