在 Invoke-WebRequest 调用中信任自签名证书
Trusting self-signed certificate in Invoke-WebRequest call
问题
有没有一种方法可以调用 Invoke-WebRequest
,例如期望证书的给定 public 密钥来验证我是否信任该连接?
如果不是,是否有另一种方法可以调用 webrequest 并且只信任网页而不信任颁发者或忽略证书检查?
问题
我想加载 Invoke-WebRequest
的网页。我尝试通过 https 连接到网页,服务器提供了一个自签名证书。
因为我的证书库中没有颁发者证书 Invoke-WebRequest
会抛出错误:
Invoke-WebRequest : The remote certificate is invalid according to the validation procedure.
已知解决方法
- 使用 Powershell v6.0.0 中添加的
-SkipCertificateCheck
-开关 ref
- 添加新的证书策略以信任所有证书ref
- 信任颁发者证书
我尝试过但没有成功的方法
- 在不信任颁发者证书的情况下将网页证书添加到证书库
- 将网页证书添加到证书存储并使用
Invoke-WebRequest
的 -Certificate
参数指定此证书
PS:由于这个问题出现在 Powershell <5 和 Powershell Core 中,我标记了两者。
简短的回答,不,你无法绕过它,当涉及到证书时,甚至不要尝试。客户端首先会查看证书和整个证书链,看它是否可信。如果该链的任何部分(例如发行者)不可信,那么它就是不可信的。如果这个基本事实没有发生,那么就没有办法吊销证书。
对于自签名证书,由于它们不受信任,您是对的,客户端实际上只有 2 个选项:
- 忽略证书来源并使用
-SkipCertificateCheck
开关盲目连接。
- 接受颁发者和全链可以信任并导入证书
你无法回避这个基本事实。我喜欢用这个例子:自签名证书就像把一个形状为 object 的炸弹交给客户,上面贴着 "Not a Bomb - Trust me, I'm @Paxz" 的标签。证书链就像拿着炸弹形状的object,你看看交付driver,看起来很黑,同时一点也不像@Paxz。然后你可以选择忽略这个标签,或者接受我可以信任@Paxz,以及不正当的交付 driver。未经明确同意,您不能直接将包裹推过前门。当您信任整个链条时,贴纸会显示 "Not a Bomb - Trust me, I've been verified by Bomb Experts",因为您信任 Bomb Experts,所以客户会毫无疑问地接受包裹。
我需要一个到我的 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
问题
有没有一种方法可以调用 Invoke-WebRequest
,例如期望证书的给定 public 密钥来验证我是否信任该连接?
如果不是,是否有另一种方法可以调用 webrequest 并且只信任网页而不信任颁发者或忽略证书检查?
问题
我想加载 Invoke-WebRequest
的网页。我尝试通过 https 连接到网页,服务器提供了一个自签名证书。
因为我的证书库中没有颁发者证书 Invoke-WebRequest
会抛出错误:
Invoke-WebRequest : The remote certificate is invalid according to the validation procedure.
已知解决方法
- 使用 Powershell v6.0.0 中添加的
-SkipCertificateCheck
-开关 ref - 添加新的证书策略以信任所有证书ref
- 信任颁发者证书
我尝试过但没有成功的方法
- 在不信任颁发者证书的情况下将网页证书添加到证书库
- 将网页证书添加到证书存储并使用
Invoke-WebRequest
的-Certificate
参数指定此证书
PS:由于这个问题出现在 Powershell <5 和 Powershell Core 中,我标记了两者。
简短的回答,不,你无法绕过它,当涉及到证书时,甚至不要尝试。客户端首先会查看证书和整个证书链,看它是否可信。如果该链的任何部分(例如发行者)不可信,那么它就是不可信的。如果这个基本事实没有发生,那么就没有办法吊销证书。
对于自签名证书,由于它们不受信任,您是对的,客户端实际上只有 2 个选项:
- 忽略证书来源并使用
-SkipCertificateCheck
开关盲目连接。 - 接受颁发者和全链可以信任并导入证书
你无法回避这个基本事实。我喜欢用这个例子:自签名证书就像把一个形状为 object 的炸弹交给客户,上面贴着 "Not a Bomb - Trust me, I'm @Paxz" 的标签。证书链就像拿着炸弹形状的object,你看看交付driver,看起来很黑,同时一点也不像@Paxz。然后你可以选择忽略这个标签,或者接受我可以信任@Paxz,以及不正当的交付 driver。未经明确同意,您不能直接将包裹推过前门。当您信任整个链条时,贴纸会显示 "Not a Bomb - Trust me, I've been verified by Bomb Experts",因为您信任 Bomb Experts,所以客户会毫无疑问地接受包裹。
我需要一个到我的 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