Ошибка HTTPS Powershell v3 Invoke-WebRequest


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, но я не уверен, что он действительно что-то делает.

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

Может ли кто-нибудь дать некоторое руководство о том, что здесь может быть не так и как это исправить?

Спасибо


Так какой из них вы используете? Invoke-RestMethodили Invoke-WebRequest?
svick

Invoke-WebRequest. Я использую его, поскольку он возвращает заголовки запроса / ответа, в отличие от 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 для получения дополнительной информации .. .
Jaykul

Ответы:


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 есть файл -SkipCertificateChecknow.
evilSnobu

MS отключила 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 скриптов, вам нужно добавить его в каждый? Кажется, в этом нет никакого смысла. Кстати, спасибо за ответ
Эндер

1
Ответ Ли не сработал для меня. Мне пришлось добавить фрагменты, на которые вы ссылались, и ЭТО РАБОТАЛО!
Pat K

Большое спасибо, указание протоколов помогло решить проблему
Alex

1
Спасибо, спасибо, спасибо, что показали мне SecurityProtocolглобальное статическое свойство. Господи, я только что потерял ДНИ на проверку сертификатов, доверительных отношений, сети, маршрутов, разрешений и кучу всего прочего, пытаясь решить неопределенную endpoint does not respondошибку при доступе к одному конкретному серверу через https (все остальные работают) только потому, что этот проклятый PowerShell 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 символа: 1 + $ wc.DownloadString ($ url) + ~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: NotSpecified: (:) [ ], MethodInvocationException + FullyQualifiedErrorId: WebException
ФЛОЙД

На основе документации API службы REST im using 406 указывает, что «заголовок accept, включенный в запрос, не допускает ответ XML или JSON»
floyd

Какие типы ответов разрешены, если ответы XML / JSON не разрешены?
Санни Чакраборти

Вы используете эту настраиваемую веб-службу? Есть ли общедоступная документация по REST API?
Санни Чакраборти

Это система продажи билетов под названием 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-сертификатами / функциями обратного вызова) и не пытается загружать один и тот же код несколько раз в одном сеансе 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();

Это было адаптировано из следующей статьи 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
}


2

Invoke-WebRequest "DomainName" -SkipCertificateCheck

Вы можете использовать параметр -SkipCertificateCheck для достижения этой цели как однострочную команду (ЭТОТ ПАРАМЕТР ПОДДЕРЖИВАЕТСЯ ТОЛЬКО В ОСНОВНОЙ ПЕРЕДАЧЕ)


1

Я попытался найти документацию по EM7 OpenSource REST API. Пока не повезло.

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

Об OpenSource REST API много говорят, но нет ссылки на фактический 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

Заголовки стиля завитка

$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

0
  1. Запустите эту команду

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

в PowerShell с использованием прав администратора. Это создаст все сертификаты в личном каталоге.

  1. Чтобы избавиться от ошибки конфиденциальности, выберите эти сертификаты, щелкните правой кнопкой мыши → Копировать. И вставьте Trusted Root Certification Authority / Certificates.
  2. Последний шаг - выбрать правильные привязки в IIS. Перейдите на сайт IIS, выберите Bindings, установите флажок SNI и установите индивидуальные сертификаты для каждого сайта.

Убедитесь, что имя хоста веб-сайта и dns-name сертификата должны точно совпадать


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 был вызван только после перезагрузки.
Дэвид В.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.