Sometimes we run web services internally that don’t use a trusted SSL certificate. It’s not good practice, but in the real world this will be encountered.
In PowerShell, we often see this error come up when using Invoke-WebRequest
or Invoke-RestMethod
or even the [System.Net.WebClient]
class. All of these rely on the .Net framework which is set up to validate SSL certificates, so an exception gets thrown when we try to connect to a site over SSL that isn’t trusted.
For a while, a lot of people created a class that implemented the ICertificatePolicy
interface, provided a method that always returned true, and then set System.Net.ServicePointManager.CertificatePolicy
to an instance of the new class. This is also the method I have used for a while, and in PowerShell it didn’t seem to complain. But I’ve recently found that this method is in fact deprecated .
It seems the correct way is to set the ServicePointManager.ServerCertificateValidationCallback
property to a callback function. Ok, no problem. It’s almost the same thing.
Writing a Module
I started to think about this more while writing a module that I planned to use internally, primarily against a web service that we run with an invalid certificate. But I didn’t like the idea of turning off SSL validation for the entire PowerShell session, which could affect other calls made by the scripts using the modules (without it being obvious that SSL validation was being skipped), so I sought a solution where I could set and unset the validation at will, and preserve whatever existing setting was in place.
The idea was to export module functions that include a switch parameter like -SkipSslValidation
and the function could turn off validation, make its calls, then restore validation (or whatever the previous value was).
I started with this answer from Dan Hunex , which allows for the override, and modified it a bit so that it keeps track of the previous value and lets you restore it just as easily.
Here is the class definition in C#:
Now when you call OverrideValidation()
it stores the existing value in a stack. When you call RestoreValidation()
it simply pops the last value off the stack and sets the callback again. Using a stack makes it easier to nest calls in the client code without worrying about whether you’re restoring validation when a previous call expects it to be off.
Using it in PowerShell
Adding a C# class definition is very straightforward in PowerShell using the Add-Type
cmdlet, so in this example, $definition
is a string consisting of the above code:
To use the new object:
And in the context I was describing (a function):