Помилка Powershell v3 Invoke-WebRequest HTTPS


126

Використовуючи Invoke-WebRequest та Invoke-RestMethod Powershell v3, я успішно використав метод POST для розміщення файлу json на веб-сайті https.

Я використовую команду

 $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

Однак, коли я намагаюся використовувати метод GET, наприклад:

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

Повертається наступна помилка

 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

Я намагався використовувати наступний код, щоб ігнорувати SSL cert, але я не впевнений, чи він насправді робить щось.

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

Чи може хтось надати якісь вказівки щодо того, що може піти не так і як це виправити?

Дякую


Отже, який ви використовуєте? Invoke-RestMethodабо Invoke-WebRequest?
svick

Invoke-WebRequest. Я використовую його, оскільки він повертає заголовки запиту / resposne на відміну від Invoke-RestMethod. Однак я спробував Invoke-RestMethod, який приймає ідентичні параметри.
floyd

Оскільки це варте, річ ServerValidationCallback майже напевно - це червона оселедець, оскільки помилка, яку ви повинні отримати, коли у вас є проблема перевірки SSL, слід сказати, що: Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. Ви можете спробувати вивчити $ Error [0] .Exception.InnerException для отримання додаткової інформації .. .
Джейкуль

Відповіді:


179

Ця обробка працювала для мене: http://connect.microsoft.com/PowerShell/feedback/details/419466/new-webserviceproxy-needs-force-parameter-to-ignore-ssl-errors

В основному, у вашому сценарії 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
Зауважте, ця відповідь правильна; однак пункт, зроблений на іншій відповіді ( stackoverflow.com/a/25163476/68432 ), також є дійсним. Це рішення не працюватиме, якщо ви попередньо зробили "[System.Net.ServicePointManager] :: ServerCertificateValidationCallback = {$ true}".
Пол Суарт

Вам потрібно додати перевірку стану типу відповідно до відповіді Артура Струтценберга нижче, або ви отримаєте помилку про те, що тип уже існує
Ральф Вілгосс

Чи існує ризик безпеки для використання цього у виробництві?
Амджад

13
Через 5 років це все ще рішення для PowerShell 5.1 (повна .NET Framework). Для PowerShell Core є -SkipCertificateCheckтепер.
evilSnobu

МС зняли Connect, це посилання недійсне. Чи є ще одне посилання?
Марк Хіт

71

Відповідь Лі чудова, але у мене також були проблеми з підтримкою протоколів веб-сервера.
Після додавання наступних рядків я міг отримати https-запит. Як зазначено у цій відповіді https://stackoverflow.com/a/36266735

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

Моє повне рішення з кодом Лі.

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

Ви знайшли краще рішення, тому що у вас є 40 сценаріїв, тоді ви повинні додати його до кожного? Здається, це не має сенсу. Btw, дякую за відповідь
Ender

1
Відповідь Лі не працювала для мене. Я повинен був додати біти, на які ви посилалися, і ЦІ РОБОТИ!
Пат К

Дуже дякую, уточнивши, що протоколи допомогли вирішити проблему
Алекс

1
Дякую, дякую, дякую, що показали мені SecurityProtocolглобальну статичну властивість. Христе, я щойно втратив ДНІ на перевірку сертифікатів, трестів, мережі, маршрутів, дозволів та іншої роботи, намагаючись вирішити невиразну endpoint does not respondпомилку під час доступу до одного конкретного сервера через https (усі інші працюють), тільки тому, що ця чортова повноважність 5.1 по замовчуванням SSL3, TLS , і він просто БЛОКІВ прокляту TLS11 і TLS12 BY DEFAULT бог , скільки я ненавиджу це лайно я написав , що сценарій в C # / рубін / C ++, або що - то ще , що ні PowerShell
Кетцалькоатль

1
@StanTastic: Я думаю, що неможливо назавжди змінити параметри за замовчуванням. Я думаю, що це в кодовому коді у вихідному коді ServicePointManager. Я ніколи не перевіряв, тому, можливо, є спосіб.
quetzalcoatl

10

Ви спробували використовувати 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)

Сонячно, я отримую таке використання при використанні цього коду: Виняток викликає "DownloadString" з аргументом "1": "Віддалений сервер повернув помилку: (406) Неприйнятно." У рядку: 4 char: 1 + $ wc.DownloadString ($ url) + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: NotSpecified: (:) [ ], MethodInvocationException + FullyQualifiedErrorId: WebException
floyd

На підставі документації API служби REST im із використанням 406 вказує "що заголовок прийняття, включений у запит, не дозволяє відповідь XML або JSON"
floyd

Які типи відповідей дозволені, якщо відповіді XML / JSON не дозволено?
Сонячний Чакраборті

Це користувацька веб-служба, яку ви використовуєте? Чи є публічно доступна документація для API REST?
Сонячний Чакраборті

Це система квитків під назвою EM7. Я не вірю, що вони мають публічні документи. Сервіс приймає відповідь JSON / XML (працює чудово, якщо я використовую cURL) Я вважаю, що помилка вказує на те, що System.Net.WebClient не є?
floyd

10

Альтернативна реалізація в чистому вигляді (Без Add-Typeз джерело):

#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

Наступне працювало для мене (і використовує найновіші непридатні засоби для взаємодії з функціями SSL Certs / функція зворотного виклику), і не намагається завантажити один і той же код кілька разів протягом одного сеансу оболонки повноважень:

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

Це було адаптовано з наступної статті https://d-fens.ch/2013/12/20/nobrainer-ssl-connection-error-when-using-powershell/


5

Я виявив, що використовуючи цю функцію зворотного дзвінка, щоб ігнорувати SSL-сертифікати [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

Я завжди отримував повідомлення про помилку, Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.яке звучить як результати, які у вас є.

Я знайшов цей форум, який привів мене до функції нижче. Я запускаю це один раз у межах мого іншого коду, і він працює для мене.

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

Я спробував шукати документацію на EM7 OpenSource REST API. Поки не пощастило.

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

Про API OpenSource REST багато говорять, але немає посилання на власний API чи будь-яку документацію. Можливо, я був нетерплячим.

Ось кілька речей, які можна спробувати

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

Спробуйте це, щоб побачити, чи можете ви відфільтрувати стовпці, які ви отримуєте з API

$a.Results | ft

або, ви можете також спробувати використовувати це

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

Заголовки стилю Curl

$b.Headers

Я тестував IRM / IWR за допомогою twitter JSON api.

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

Сподіваюся, це допомагає.


Дякую за всю допомогу. Однак перша команда $ a = Invoke-RestMethod (...) - це та, яка наразі не працює для мене. Добре працює для HTTP-сайту, але коли ви вводите HTTPS, який робить EM7, він повертає описану помилку. Це для Invoke-RestMethod та Invoke-WebRequest. Я зараз просто використовую командлет Invoke-Command та працює curl.
floyd

1

Invoke-WebRequest "DomainName" -SkipCertificateCheck

Ви можете використовувати параметр -SkipCertificateCheck, щоб досягти цього як однолінійна команда (ЦИЙ ПАРАМЕТР ТІЛЬКИ ПІДТРИМУЄТЬСЯ НА СКЛАДНІЙ ПСЕДИЦІЇ)


0
  1. Виконайте цю команду

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

в повноваженнях, використовуючи права адміністратора , Це генерує всі сертифікати в Особистій директорії

  1. Щоб позбутися помилки конфіденційності, виберіть ці сертифікати, клацніть правою кнопкою миші → Копіювати. І вставити в довірений кореневий орган сертифікації / сертифікати.
  2. Останнім кроком є ​​вибір правильних прив’язок в IIS. Перейдіть на веб-сайт IIS, виберіть Прив'язки, встановіть прапорець SNI та встановіть індивідуальні сертифікати для кожного веб-сайту.

Переконайтесь, що ім'я хоста веб-сайту та dns-ім'я сертифіката повинні точно збігатися


0

Ці параметри реєстру впливають на .NET Framework 4+ і, отже, PowerShell. Встановіть їх і перезапустіть будь-які сеанси PowerShell, щоб використовувати останню TLS, не потрібно перезавантажувати.

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 

Дивіться https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls#schusestrongcrypto


Для всіх, хто бачить цю відповідь, наш досвід полягає в тому, що цей патч реєстру насправді вимагає перезавантаження, щоб гарантувати належну функціональність. При спробі забезпечити з'єднання TLS 1.2 між вікном Windows, на якому працює додаток .NET, SSL 3 відображався через мережевий слід, який буде використаний із цим значенням реєстру на місці, але перед перезавантаженням; TLS 1.2 викликався лише після перезавантаження.
David W

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.