.netpowershelladd-typepowershell-7.2

PowerShell - Add-Type Issue trying to do REST call without self-signed cert issue


I'm trying to better understand Add-Type in PowerShell after running into an issue of trying to do a REST API call and avoiding a self-signed cert issue. Code is as follows.

add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;

    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("InternalApiKey", "d472f0e9-23c9-4fff-aec9-cc1f2d5d6a85")

$response = Invoke-RestMethod 'https://localhost:9443/api/GetStats/' -Method 'GET' -Headers $headers
$response | ConvertTo-Json

When I run this it breaks with the error.

"New-Object: Cannot find type [TrustAllCertsPolicy]: verify that the assembly containing this type is loaded." And then, because that failed I get the error, "Invoke-RestMethod: The remote certificate is invalid because of errors in the certificate chain: PartialChain"

Just stumbled upon the fact it works as expected in PowerShell 5.1.22000.282 and does not in PowerShell 7.2.1. What changes can I make to make it work in both version of PowerShell?

Update: this link has some code to get it running in both versions of PowerShell. I accepted the answer I did because it was the most helpful and because I'm sharing this other answer. https://github.com/PowerShell/PowerShell/issues/7092


Solution

  • In PowerShell 7.x, the web cmdlets have a -SkipCertificateCheck switch you can use instead:

    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add("InternalApiKey", "d472f0e9-23c9-4fff-aec9-cc1f2d5d6a85")
    
    $response = Invoke-RestMethod 'https://localhost:9443/api/GetStats/' -SkipCertificateCheck -Method 'GET' -Headers $headers
    

    If the endpoint is already sending JSON, you might as well use Invoke-WebRequest instead (rather than letting Invoke-RestMethod convert from JSON to objects and then back again with ConvertTo-Json):

    $response = Invoke-WebRequest 'https://localhost:9443/api/GetStats/' -SkipCertificateCheck -Method 'GET' -Headers $headers
    $response.Content # this now contains the body of the raw response from the API, eg. JSON/XML/whatever