Powershell v3 Invoke-WebRequest HTTPS 오류


126

Powershell v3의 Invoke-WebRequest 및 Invoke-RestMethod를 사용하여 성공적으로 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

SSL 유효성 검사 문제가있을 때 발생해야하는 오류는 다음과 같이 말합니다. Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. 자세한 내용은 $ Error [0] .Exception.InnerException을 탐색 해 볼 수 있기 때문에 ServerValidationCallback은 거의 확실하게 붉은 청어입니다 . .
Jaykul 2012-09-21

답변:


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}"를 미리 수행 한 경우 작동하지 않습니다.
Paul Suart 2015 년

아래 Arthur Strutzenberg 답변에 따라 유형 조건 검사를 추가해야합니다. 그렇지 않으면 유형이 이미 존재한다는 오류가 표시됩니다.
Ralph Willgoss

프로덕션에서 이것을 사용하면 보안 위험이 있습니까?
Amjad

13
5 년 후에도 여전히 PowerShell 5.1 (전체 .NET Framework)을위한 솔루션입니다. PowerShell Core의 경우 -SkipCertificateCheck지금이 있습니다.
evilSnobu

MS가 연결을 중단했습니다. 해당 링크는 유효하지 않습니다. 다른 링크가 있습니까?
Mark Heath

71

Lee의 대답은 훌륭하지만 웹 서버가 지원하는 프로토콜에 문제가있었습니다.
다음 줄도 추가 한 후 https 요청을받을 수 있습니다. 이 답변에서 지적했듯이 https://stackoverflow.com/a/36266735

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

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

더 나은 솔루션을 찾았습니까? 40 개의 스크립트가있는 경우 각 스크립트에 추가해야합니다. 말이 안되는 것 같습니다. Btw, 답변 주셔서 감사합니다
Ender

1
Lee의 대답은 저에게 효과가 없었습니다. 나는 당신이 참조한 비트를 추가해야했고 그것은 작동했습니다!
Pat K

문제를 해결하는 데 도움이 프로토콜 지정, 대단히 감사합니다
알렉스

1
SecurityProtocol전역 정적 속성을 보여 주셔서 감사합니다 . 맙소사, 나는 endpoint does not respondhttps를 통해 하나의 특정 서버에 액세스 할 때 모호한 오류 를 해결하려고 시도하는 인증서, 신뢰, 네트워크, 경로, 권한 및 기타 작업을 확인하는 데 며칠을 잃었습니다 (다른 모든 작업은 작동합니다). SSL3, TLS 기본값과 JUST BLOCKS 빌어 먹을 TLS11 및 TLS12 BY의 DEFAULT의 난이 쓰레기를 얼마나 싫어하는지 하나님은 내가 쓴 것이 PowerShell을하지 C #을 / 루비 / C ++, 또는 어떤 다른 사람의 스크립트
케찰코아틀

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)

Sunny, 해당 코드를 사용할 때 다음 메시지가 나타납니다. "1"인수를 사용하여 "DownloadString"을 호출하는 예외 : "원격 서버에서 오류를 반환했습니다 : (406) Not Acceptable." 줄 : 4 char : 1 + $ wc.DownloadString ($ url) + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified : (:) [ ] + MethodInvocationException FullyQualifiedErrorId : WebException이
플로이드

406을 사용하는 REST 서비스의 API 문서에 따르면 "요청에 포함 된 수락 헤더가 XML 또는 JSON 응답을 허용하지 않음"을 나타냅니다.
floyd

XML / JSON 응답이 허용되지 않는 경우 어떤 응답 유형이 허용됩니까?
Sunny Chakraborty

사용중인 사용자 지정 웹 서비스입니까? REST API에 대해 공개적으로 사용 가능한 문서가 있습니까?
Sunny Chakraborty

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
}


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

Twitter JSON API로 IRM / IWR을 테스트했습니다.

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

도움이 되었기를 바랍니다.


모든 도움에 감사드립니다. 그러나 첫 번째 명령 $ a = Invoke-RestMethod (...)는 현재 나를 위해 작동하지 않는 명령입니다. HTTP 사이트에서는 잘 작동하지만 EM7이 수행하는 HTTPS를 도입하면 설명 된 오류가 반환됩니다. Invoke-RestMethod 및 Invoke-WebRequest입니다. Invoke-Command cmdlet을 사용하고 curl을 실행하는 중입니다.
floyd

1

Invoke-WebRequest "DomainName"-SkipCertificateCheck

-SkipCertificateCheck Parameter를 사용 하여 한 줄짜리 명령으로이를 수행 할 수 있습니다 (이 매개 변수는 CORE PSEDITION에서만 지원됨).


0
  1. 이 명령 실행

New-SelfSignedCertificate -certstorelocation 인증서 : \ localmachine \ my -dnsname {your-site-hostname}

관리자 권한을 사용하는 powershell 에서 개인 디렉터리의 모든 인증서를 생성합니다.

  1. 프라이버시 오류를 제거하려면 해당 인증서를 선택하고 마우스 오른쪽 버튼으로 클릭 → 복사합니다. 그리고 신뢰할 수있는 루트 인증 기관 / 인증서에 붙여 넣습니다.
  2. 마지막 단계는 IIS에서 올바른 바인딩을 선택하는 것입니다. IIS 웹 사이트로 이동하여 바인딩, SNI 선택 확인란을 선택하고 각 웹 사이트에 대한 개별 인증서를 설정합니다.

웹 사이트 호스트 이름과 인증서 dns-name이 정확히 일치해야합니다.


0

이러한 레지스트리 설정은 .NET Framework 4 이상 및 따라서 PowerShell에 영향을줍니다. 최신 TLS를 사용하도록 설정하고 모든 PowerShell 세션을 다시 시작하면 재부팅 할 필요가 없습니다.

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를


이 답변을 보는 다른 사람에게는이 레지스트리 패치가 실제로 적절한 기능을 보장하기 위해 재부팅이 필요하다는 경험이 있습니다. .NET 앱을 실행하는 Windows 상자간에 TLS 1.2 연결을 확인하려고 할 때 SSL 3이 네트워크 추적을 통해이 레지스트리 값과 함께 사용되도록 표시되었지만 재부팅하기 전에 표시되었습니다. TLS 1.2는 재부팅 후에 만 ​​호출되었습니다.
David W

-1

관리자 권한으로 실행하면 해당 오류가 사라집니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.