如何使用 cacert 文件在 Powershell (Invoke-WebRequest) 中执行 cUrl 等效项?

Posted

技术标签:

【中文标题】如何使用 cacert 文件在 Powershell (Invoke-WebRequest) 中执行 cUrl 等效项?【英文标题】:How to execute a cUrl equivalent in Powershell (Invoke-WebRequest) using cacert file? 【发布时间】:2016-08-11 21:30:45 【问题描述】:

基本上我想将命令 curl 翻译为与当前在 linux 服务器中的参数相同,但在 Powershell 中,以便上传文件:

curl -v -T $file -u user:password http://myurl --cacert /opt/keystores/ca_cert.pem

我找到了执行此任务的等效命令:PowerShell 3.0+ 的“Invoke-WebRequest”,但问题是我不知道如何使用 CA 证书文件 (.pem) 调用它,而且我没有'在 Internet 上没有找到任何样本。

谢谢!

【问题讨论】:

这里的限制是证书必须cacert文件中的一个CA颁发,或者只是你不能将cacert导入到商店因此必须直接引用该文件?最后一个可行,第一个有点棘手 其次,我无法将 cacert 导入商店,我必须直接引用该文件。目前我已经从 Internet 下载了一个 Windows cURL 来执行此操作,但我希望能够在 Powershell 中完成所有操作(使用 .NET 库或其他),而无需引用外部可执行文件...... 【参考方案1】:

当您在 .NET 中建立 TLS 连接时,对等证书将根据 RemoteCertificateValidationCallback function 进行验证,由相关 AppDomain 的 ServicePointManager 管理。

大多数关于如何在 PowerShell 中覆盖默认验证的示例都会告诉您这样做:

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

不要这样做! - 它会完全绕过验证。

可以做的是实现一个适当的回调函数并手动调用链验证。在执行此操作之前,您可以将不在机器或用户证书存储中的证书添加到您可以验证的链列表中:

$callback = 
    param(
        $sender,
        [System.Security.Cryptography.X509Certificates.X509Certificate]$certificate,
        [System.Security.Cryptography.X509Certificates.X509Chain]$chain,
        [System.Net.Security.SslPolicyErrors]$sslPolicyErrors
    )

    # No need to retype this long type name
    $CertificateType = [System.Security.Cryptography.X509Certificates.X509Certificate2]

    # Read the CA cert from file
    $CACert = $CertificateType::CreateFromCertFile("C:\path\to\ca.crt") -as $CertificateType

    # Add the CA cert from the file to the ExtraStore on the Chain object
    $null = $chain.ChainPolicy.ExtraStore.Add($CACert)

    # return the result of chain validation
    return $chain.Build($certificate)


# Assign your delegate to the ServicePointManager callback
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $callback

# Do your Invoke-WebRequest or WebClient call here

我不知道如何从 PEM 文件中读取多个证书到证书集合中,所以你必须一个一个地添加每个 ca 证书,对不起

【讨论】:

谢谢@MathiasRJessen,会测试并告诉你。将回调分配给ServerCertificateValidationCallback后,原则上我不需要在Invoke-WebRequest中添加Certificate参数,对吧? 正确,它将适用于该进程/会话生命周期剩余时间内的所有 https 请求:-)【参考方案2】:

您正在寻找Invoke-RestMethod。

它有一个 Get-PfxCertificate 参数,它从文件中获取 PFX 证书。您可以通过检查此link

从 pem 转换为 PFX 文件

所以你的代码看起来像这样:

$cert = Get-PfxCertificate -FilePath c:\path\to\cert.pfx

$userPassB64 = [System.Convert]::ToBase64String([System.Text.ASCIIEncoding]::ASCII.GetBytes("username:password")

Invoke-WebRequest -Uri http://myurl -Method Post -Header @Authentication "Basic " + $userPassB64 -InFile 'c:\path\to\uploadfile.txt'

更新

正如 Mathias 指出的,命令中的证书选项是针对客户端证书的。 --cacert 选项的要点是在证书不在 curl 使用的默认证书包中时提供对等验证。有关此选项解决什么问题的相关问题,请参阅 here。

我建议按原样尝试该命令,以根据机器上安装的 CA 来查看 SSL 协商是否成功。 如果 SSL 协商失败,那么您可以尝试从目标站点下载证书文件并将其安装在本地证书存储中。执行此操作的步骤已在here 中列出。

【讨论】:

-Certificate 参数采用 客户端证书 来验证请求 - 不是 CA 证书来验证对等方 @MathiasR.Jessen,谢谢,你是正确的,所以没有使用 Invoke-RestMethod 的等价物。我相信正确的方法是将证书导入计算机商店中受信任的 CA。我会更新答案。 正确,虽然还有另一种方法,如果您必须针对 cacert 文件进行验证并且无法导入到商店 - 实现自定义 ICertificatePolicy 类并将其分配给 ServicePointManager 策略,也写一个答案 谢谢大家。事情是我需要从字面上翻译要在 Powershell 中执行的命令,所以我需要 100% 使用 CA 证书。不确定我是否对 ICertificatePolicy 类@MathiasR.Jessen 了解得很好,你能更深入地解释一下吗?谢谢! @javiaf 不用担心!可惜没有直译。等效于 curl 的 powershell 不支持此选项。您可以通过从 Windows 机器上的 Web 浏览器导入证书来实现相同的效果。 Mathias 通过代码提供了另一种方法。这些细节交给他。

以上是关于如何使用 cacert 文件在 Powershell (Invoke-WebRequest) 中执行 cUrl 等效项?的主要内容,如果未能解决你的问题,请参考以下文章

将 cacert 卷曲到 Java HttpClient 等效项

如何把安全证书导入到java中的cacerts证书库

powershell PowerShel便利ツール

如何把安全证书导入到java中的cacerts证书库(转)

Create AD Users by Powershel_v1.0

cacerts 和 keystore 有啥区别?