When you make a TLS
connection in .NET, the peer certificate is validated against a RemoteCertificateValidationCallback
function, governed by the ServicePointManager
for the AppDomain in question.
Most examples of how to override the default validation in PowerShell will tell you to just do:
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
Don't do that! - it will bypass validation completely.
What you can do, is implement a proper callback function and invoke chain validation manually. Before you do this, you can add certificates not in the machine or user certificate store to the list of chains you can validate against:
$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
I don't know how to read multiple certificates from a PEM file into a certificate collection, so you'll have to add each ca cert one by one, sorry