简体   繁体   English

在Invoke-WebRequest调用中信任自签名证书

[英]Trusting self-signed certificate in Invoke-WebRequest call

Question

Is there a way I can call Invoke-WebRequest and for example expect a given public key of the certificate to validate that I trust the connection? 有没有一种方法可以调用Invoke-WebRequest ,例如,期望证书的给定公钥来验证我是否信任连接?

If not, is there another way to invoke the webrequest and only trust the webpage without trusting the issuer or ignoring the certificate check? 如果不是,是否还有另一种方法可以调用webrequest并仅信任网页而不信任发行者或忽略证书检查?

Problem 问题

I want to load an webpage with Invoke-WebRequest . 我想使用Invoke-WebRequest加载网页。 I try to connect to the Webpage over https and the server offers an self-signed certificate. 我尝试通过https连接到网页,并且服务器提供了自签名证书。

Since I dont't have the Issuer-Certificate in my certificate-store Invoke-WebRequest will throw the error: 由于我的证书存储区中没有颁发者证书,因此Invoke-WebRequest将引发错误:

Invoke-WebRequest : The remote certificate is invalid according to the validation procedure. Invoke-WebRequest:根据验证过程,远程证书无效。

Known workarounds 已知的解决方法

  1. Using the -SkipCertificateCheck -Switch added in Powershell v6.0.0 ref 使用Powershell v6.0.0 参考中添加的-SkipCertificateCheck -Switch
  2. Adding a new Certificatepolicy to trust all Certificates ref 添加新Certificatepolicy信任所有证书裁判
  3. Trusting the Issuer-Certificate 信任发行人证书

What I tried but didn't work out 我尝试过但没有解决的问题

  1. Adding the Webpage-Certificate to the certificate-store without trusting the Issuer-Certificate 在不信任颁发者证书的情况下将网页证书添加到证书库
  2. Adding the Webpage-Certificate to the certificate-store and using the -Certificate -Parameter of Invoke-WebRequest to specify this certificate 添加网页证书的证书存储和使用-Certificate的-参数Invoke-WebRequest指定此证书

PS: Since this problem appears in both Powershell <5 and Powershell Core, I am tagging both. PS:由于此问题同时出现在Powershell <5和Powershell Core中,因此我将两者都标记出来。

Short answer, No you can't get around it, and when it comes to certificates, don't even try. 简短的回答,不,您无法解决它,并且在证书方面,甚至不要尝试。 The client will first look at the certificate, and the whole certificate chain to see if it is trusted. 客户端将首先查看证书以及整个证书链,以查看其是否受信任。 If any part of that chain (eg issuer) is not trusted, then it is not trusted. 如果该链的任何部分(例如发行者)不受信任,则它不受信任。 If this fundamental fact didn't happen, then there would be no way to revoke certificates. 如果这个基本事实没有发生,那么将没有办法撤销证书。

For self signed certificates, since they are not trusted, you are right, there are really only 2 options that the client has: 对于自签名证书,由于它们是不可信的,所以您是对的,客户端实际上只有两种选择:

  1. Ignore the certificate origin and blindly connect using the -SkipCertificateCheck switch. 忽略证书来源,并使用-SkipCertificateCheck开关盲目连接。
  2. Accept that the issuer and full chain can be trusted and Import the certificate 接受可以信任发行者和完整链并导入证书

You can't get around this fundamental fact. 您无法绕开这个基本事实。 I like to use the example: Self signed certificates are like delivering a bomb shaped object to a client with a sticker on it saying "Not a Bomb - Trust me, I'm @Paxz". 我喜欢使用示例:自签名证书就像将炸弹状的对象交付给客户端,并在其上贴有“不是炸弹-相信我,我是@Paxz”的贴纸。 Certificate chains are like while holding the bomb shaped object, you look at the delivery driver, and they look very shady, and at the same time don't look at all like @Paxz. 证书链就像拿着炸弹状的物体一样,您看着交付驱动程序,它们看起来非常阴暗,同时看起来完全不像@Paxz。 You then have the choice of either ignoring the sticker, or accept that I can Trust @Paxz, and the shady delivery driver. 然后,您可以选择忽略标签,或者接受我可以信任@Paxz和可疑的传递驱动程序。 You can't just shove the package through the front door without explicit consent. 未经明确同意,您不能只是将包裹推过前门。 When you trust the whole chain, the sticker will say "Not a Bomb - Trust me, I've been verified by Bomb Experts", since you trust Bomb Experts, the client will accept the package without question. 当您信任整个链时,标贴上会显示“不是炸弹-相信我,我已被炸弹专家验证”,因为您信任炸弹专家,因此客户将毫无疑问地接受该包裹。

I need a trusted connection to my Icinga2 server and found a way to compare a single certificate. 我需要一个与Icinga2服务器的可信连接,并找到了一种比较单个证书的方法。

This is the main code which stores a [X509Certificate2] certificate for comparison and set a callback function to validate the certificate. 这是存储[X509Certificate2]证书以进行比较并设置回调函数以验证证书的主要代码。

function set-SSLCertificate {
    param(
        $Cert
    )

    if (-not("validateCert" -as [type])) {
        add-type -TypeDefinition @"
            using System.Net.Security;
            using System.Security.Cryptography.X509Certificates;

            public static class ValidateCert {
                static X509Certificate2 MyCert;

                public static bool Validate(object sender,
                    X509Certificate cert,
                    X509Chain chain,
                    SslPolicyErrors sslPolicyErrors) {
                        if (MyCert.Equals(cert)) {
                            return true;
                        } else {
                            return false;
                        }
                }

                public static RemoteCertificateValidationCallback GetDelegate(X509Certificate2 Cert) {
                    MyCert = Cert;
                    return new RemoteCertificateValidationCallback(ValidateCert.Validate);
                }
            }
"@
    }
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [validateCert]::GetDelegate($Cert)
}

You need a certificate as [X509Certificate2]. 您需要一个证书[X509Certificate2]。

I use this function to convert a Base64 formatted certificate which is easy to store inside variables. 我使用此函数来转换Base64格式的证书,该证书易于存储在变量中。

function get-x509 {
    param(
        [string]
            $Cert64
    )

    $CertBin=[System.Convert]::FromBase64String(($Cert64.Trim(" ") -replace "-.*-",""))

    [System.Security.Cryptography.X509Certificates.X509Certificate2]$CertBin
}

The whole thing to connect the SSL server: 连接SSL服务器的整个过程:

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

$SecPass = ConvertTo-SecureString $Pass -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential($User, $SecPass)

$Cert = get-x509 $Cert64
set-SSLCertificate $Cert

Invoke-RestMethod -Uri $URL -Credential $Cred

To get the old behavior: 要获得旧的行为:

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM