Errore HTTPS Invoke-WebRequest di Powershell v3


126

Utilizzando Invoke-WebRequest e Invoke-RestMethod di Powershell v3, ho utilizzato con successo il metodo POST per pubblicare un file json su un sito Web https.

Il comando che sto usando è

 $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

Tuttavia, quando provo a utilizzare il metodo GET come:

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

Viene restituito il seguente errore

 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

Ho tentato di utilizzare il seguente codice per ignorare il certificato SSL, ma non sono sicuro che stia effettivamente facendo qualcosa.

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

Qualcuno può fornire qualche guida su cosa potrebbe andare storto qui e su come risolverlo?

Grazie


Allora quale stai usando? Invoke-RestMethodo Invoke-WebRequest?
svick

Invoke-WebRequest. Lo uso in quanto restituisce le intestazioni request / resposne a differenza di Invoke-RestMethod. Tuttavia ho provato Invoke-RestMethod che accetta anche parametri identici.
floyd

Per quello che vale, la cosa ServerValidationCallback è quasi certamente una falsa pista, poiché l'errore che dovresti ottenere quando hai un problema di convalida SSL dovrebbe DIRE che: Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. potresti provare a esplorare $ Error [0] .Exception.InnerException per maggiori informazioni .. .
Jaykul

Risposte:


179

Questa soluzione ha funzionato per me: http://connect.microsoft.com/PowerShell/feedback/details/419466/new-webserviceproxy-needs-force-parameter-to-ignore-ssl-errors

Fondamentalmente, nel tuo 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"

9
Nota, questa risposta è corretta; tuttavia, vale anche il punto fatto su un'altra risposta ( stackoverflow.com/a/25163476/68432 ). Questa soluzione non funzionerà se prima hai eseguito "[System.Net.ServicePointManager] :: ServerCertificateValidationCallback = {$ true}".
Paul Suart,

È necessario aggiungere il controllo della condizione del tipo come da risposta di Arthur Strutzenberg di seguito o verrà visualizzato un errore che
indica

C'è un rischio per la sicurezza per l'utilizzo di questo in produzione?
Amjad

13
5 anni dopo, questa è ancora la soluzione per PowerShell 5.1 (.NET Framework completo). Per PowerShell Core c'è -SkipCertificateCheckadesso.
evilSnobu

MS ha disattivato Connect, il collegamento non è valido. C'è un altro collegamento?
Mark Heath

71

La risposta di Lee è ottima, ma ho anche avuto problemi con i protocolli supportati dal server web.
Dopo aver aggiunto anche le seguenti righe, ho potuto ottenere la richiesta https. Come sottolineato in questa risposta https://stackoverflow.com/a/36266735

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

La mia soluzione completa con il codice di 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

hai trovato una soluzione migliore, perché se hai 40 script, devi aggiungerlo a ciascuno ?. Non sembra avere alcun senso. A proposito, grazie per la risposta
Ender

1
La risposta di Lee non ha funzionato per me. Ho dovuto aggiungere i bit a cui hai fatto riferimento e ha funzionato!
Pat K

Grazie mille, specificare i protocolli ha aiutato a risolvere il problema
Alex

1
Grazie grazie grazie per avermi mostrato la SecurityProtocolproprietà statica globale. Cristo, ho appena perso GIORNI controllando certificati, trust, rete, rotte, permessi e altre cose che cercavano di risolvere un vago endpoint does not responderrore quando si accede a un server specifico tramite https (tutti gli altri funzionano), solo perché quel maledetto PowerShell 5.1 default SSL3, TLS e semplicemente BLOCCHI GODDAMN TLS11 e TLS12 pER DIFETTO dio quanto odio questa merda avrei dovuto scrivere quello script in C # / rubino / C ++, o qualsiasi altra cosa che non sia PowerShell
Quetzalcoatl

1
@StanTastic: Penso che sia impossibile modificare in modo permanente le impostazioni predefinite. Penso che sia hardcoded nel codice sorgente di ServicePointManager. Non ho mai controllato, quindi forse c'è un modo.
quetzalcoatl

10

Hai provato a usare 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, ricevo quanto segue quando utilizzo quel codice: Eccezione durante la chiamata a "DownloadString" con argomenti "1": "Il server remoto ha restituito un errore: (406) Non accettabile". Alla riga: 4 caratteri: 1 + $ wc.DownloadString ($ url) + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: NotSpecified: (:) [ ], MethodInvocationException + FullyQualifiedErrorId: WebException
floyd

In base alla documentazione API del servizio REST, im utilizzando 406 indica "che l'intestazione di accettazione inclusa nella richiesta non consente una risposta XML o JSON"
floyd

Quali tipi di risposta sono consentiti se le risposte XML / JSON non sono consentite?
Sunny Chakraborty

È un servizio Web personalizzato che stai utilizzando? Esiste documentazione pubblicamente disponibile per l'API REST?
Sunny Chakraborty

È un sistema di biglietteria chiamato EM7 Non credo che abbiano documenti pubblici. Il servizio accetta la risposta JSON / XML (funziona perfettamente se uso cURL) Credo che l'errore stia indicando che System.Net.WebClient non lo è?
floyd

10

Un'implementazione alternativa in pure (senza Add-Typedi fonte):

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

7

Quanto segue ha funzionato per me (e utilizza i più recenti mezzi non deprecati per interagire con la funzionalità di callback / certificati SSL) e non tenta di caricare lo stesso codice più volte all'interno della stessa sessione di 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();

Questo è stato adattato dal seguente articolo https://d-fens.ch/2013/12/20/nobrainer-ssl-connection-error-when-using-powershell/


5

Ho scoperto che quando ho utilizzato la funzione di callback per ignorare i certificati SSL [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

Ho sempre ricevuto il messaggio di errore Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.che suona come i risultati che stai ottenendo.

Ho trovato questo post del forum che mi ha portato alla funzione sottostante. Lo eseguo una volta nell'ambito del mio altro codice e funziona per me.

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
}


1

Ho provato a cercare la documentazione sull'API REST EM7 OpenSource. Nessuna fortuna finora.

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

Si parla molto dell'API REST OpenSource, ma nessun collegamento all'API effettiva o alla documentazione. Forse ero impaziente.

Ecco alcune cose che puoi provare

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

Prova questo per vedere se riesci a filtrare le colonne che stai ottenendo dall'API

$a.Results | ft

oppure puoi provare a usare anche questo

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

Intestazioni stile ricciolo

$b.Headers

Ho testato IRM / IWR con l'API JSON di Twitter.

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

Spero che questo ti aiuti.


Grazie per tutta la tua assistenza. Tuttavia il primo comando $ a = Invoke-RestMethod (...) è quello che attualmente non funziona per me. Funziona bene per un sito HTTP ma quando si introduce HTTPS che EM7 fa, restituisce l'errore descritto. Questo è per Invoke-RestMethod e Invoke-WebRequest. Sto solo usando un cmdlet Invoke-Command e sto eseguendo curl.
floyd

1

Invoke-WebRequest "DomainName" -SkipCertificateCheck

È possibile utilizzare -SkipCertificateCheck Parameter per ottenere ciò come comando di una riga (QUESTO PARAMETRO È SUPPORTATO SOLO SU PEDIZIONE CORE)


0
  1. Esegui questo comando

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

in PowerShell utilizzando i diritti di amministratore , questo genererà tutti i certificati nella directory personale

  1. Per eliminare l'errore di privacy, selezionare questi certificati, fare clic con il tasto destro → Copia. E incolla Autorità di certificazione radice attendibile / Certificati.
  2. L'ultimo passaggio consiste nel selezionare le associazioni corrette in IIS. Vai al sito web IIS, seleziona Binding, seleziona la casella di controllo SNI e imposta i certificati individuali per ogni sito web.

Assicurati che il nome host del sito web e il nome dns del certificato corrispondano esattamente


0

Queste impostazioni del registro influiscono su .NET Framework 4+ e quindi su PowerShell. Impostali e riavvia tutte le sessioni di PowerShell per utilizzare l'ultimo TLS, non è necessario riavviare.

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 

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


Per chiunque altro veda questa risposta, la nostra esperienza è che questa patch del registro, infatti, richiede un riavvio per garantire la corretta funzionalità. Durante il tentativo di garantire una connessione TLS 1.2 tra una macchina Windows che esegue un'app .NET, SSL 3 è stato mostrato tramite traccia di rete da utilizzare con questo valore di registro in posizione, ma prima del riavvio; TLS 1.2 è stato richiamato solo dopo un riavvio.
David W

-1

Se lo esegui come amministratore, l'errore dovrebbe scomparire

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.