问题
有没有一种方法可以调用Invoke-WebRequest
,例如,期望证书的给定公共密钥可以验证我信任连接吗?
如果没有,是否有另一种方式调用WebRequest并仅信任网页而不信任发行人或忽略证书检查?
问题
我想加载一个用Invoke-WebRequest
加载网页。我尝试通过HTTPS连接到网页,服务器提供自签名证书。
由于我没有证书店里的发行人认证Invoke-WebRequest
会引发错误:
Invoke-webrequest:根据验证过程,远程证书无效。
已知的解决方法
- 使用powershell v6.0.0 Ref 中添加的
- 添加一个新的证书人员来信任所有证书ref
- 信任发行人认证
-SkipCertificateCheck
-Switch我尝试过但没有奏效
- 将网页认证添加到证书存储中,而不信任发行人认证
- 将网页认证添加到证书店,并使用
-Certificate
参数Invoke-WebRequest
指定此证书
ps:由于此问题出现在PowerShell< 5和PowerShell Core中,所以我都在标记。
简短的答案,不,您无法绕过它,当涉及证书时,甚至不要尝试。客户将首先查看证书,以及整个证书链,以查看是否受到信任。如果该链的任何部分(例如发行人(不信任,则不信任它。如果这个基本事实没有发生,那么将无法撤销证书。
对于自签名的证书,由于他们不信任,您是对的,实际上只有2个选项:
- 忽略证书来源并使用
-SkipCertificateCheck
开关盲目连接。 - 接受可以信任发行人和完整的链条,并导入证书
您无法解决这个基本事实。我喜欢使用以下示例:自签名的证书就像将炸弹形状的物体交付给贴纸上的客户说"不是炸弹 - 相信我,我是@paxz"。证书链就像握住炸弹形对象时一样,您看着送货驱动程序,它们看起来很阴暗,与此同时,看起来不像@paxz那样。然后,您可以选择忽略贴纸,或者接受我可以信任@paxz和阴暗的送货驱动程序。未经明确的同意,您不能仅仅将包裹穿过前门。当您相信整个链条时,贴纸会说"不是炸弹 - 相信我,我已经得到炸弹专家的验证",因为您相信炸弹专家,客户将毫无疑问接受包裹。
我需要与我的icinga2服务器的可信连接,并找到了一种比较单个证书的方法。
这是存储[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)
}
您需要证书为[x509certificate2]。
我使用此功能将base64格式的证书转换为易于存储在变量中。
function get-x509 {
param(
[string]
$Cert64
)
$CertBin=[System.Convert]::FromBase64String(($Cert64.Trim(" ") -replace "-.*-",""))
[System.Security.Cryptography.X509Certificates.X509Certificate2]$CertBin
}
连接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
获得旧行为:
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null