Skip to content

Instantly share code, notes, and snippets.

@jmassardo
Created February 26, 2019 15:19
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save jmassardo/2e0dd7cce292f16ff8f6945b8b3752b5 to your computer and use it in GitHub Desktop.
Save jmassardo/2e0dd7cce292f16ff8f6945b8b3752b5 to your computer and use it in GitHub Desktop.
PowerShell hack to ignore ssl certificates when using Invoke-WebRequest
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
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Ssl3, [Net.SecurityProtocolType]::Tls, [Net.SecurityProtocolType]::Tls11, [Net.SecurityProtocolType]::Tls12
$Header = @{"api-token"="1234567890"}
$Request = Invoke-WebRequest -Uri "https://api.example.com" -Headers $Header -Method Get -ContentType "Application/Json"
@deaduncledave
Copy link

Dandy, thanks for finding this work-around.

@barronandersonmongo
Copy link

Thanks for the work-around. Any pointers on how to reverse/revert the applied definitions back to original state?

@LeonS13
Copy link

LeonS13 commented Sep 26, 2022

Does not work anymore in Powershell 7, while it does work in Powershell 5 on the same machine.
| (3,40): error CS0246: The type or namespace name 'ICertificatePolicy' could not be found (are you
| missing a using directive or an assembly reference?) public class TrustAllCertsPolicy :
| ICertificatePolicy {

@deaduncledave
Copy link

Does not work anymore in Powershell 7, while it does work in Powershell 5 on the same machine. | (3,40): error CS0246: The type or namespace name 'ICertificatePolicy' could not be found (are you | missing a using directive or an assembly reference?) public class TrustAllCertsPolicy : | ICertificatePolicy {

According to this, ICertificatePolicy is deprecated. PWSH 7.2 implementation of invoke-webrequest has an explicit parameter called -SkipCertificateCheck that should be used instead.

@LeonS13
Copy link

LeonS13 commented Sep 27, 2022

That one cmdlet has parameter is not a replacement for the old solution. The old solution did ignore certificates for everything in powershell, i used it to ignore missing certificate on a self hosted S3 storage when using the AWS modules. In short i did not use invoke-webrequest so what is a parameter for that going to do for me? But the links you provided did indeed help. When you just want everything to ignore certificates again you can just do this.
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} ;

@pandieme
Copy link

Today I figured out that you can define this class using PowerShell code, and it has worked the same for me, but without being the only C# code in my PowerShell project.

if ($PSEdition -eq 'Desktop') {
    class TrustAllCertsPolicy : System.Net.ICertificatePolicy {
        [bool] CheckValidationResult (
            [System.Net.ServicePoint]$srvPoint,
            [System.Security.Cryptography.X509Certificates.X509Certificate]$certificate,
            [System.Net.WebRequest]$request,
            [int]$certificateProblem
        ) {
            return $true
        }
    }

    [System.Net.ServicePointManager]::CertificatePolicy = New-Object -TypeName TrustAllCertsPolicy
}

I gate it behind a $PSEdition check, as this is only needed in Windows PowerShell. The -SkipCertificateCheck switch has been around since PowerShell 6.

@scarson
Copy link

scarson commented Jan 9, 2024

@pandieme how are you using that edition check in practice? I found it will fail to execute at all in PowerShell Core due to the ParserError issue for class references described in PowerShell: Unable to find type when using PS 5 classes and Defining a PowerShell class in a script causes a parser error if the class references external types that aren't currently loaded

ParserError:
Line |
   3 |  class TrustAllCertsPolicy : System.Net.ICertificatePolicy {
     |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Unable to find type [System.Net.ICertificatePolicy].

@pandieme
Copy link

pandieme commented Jan 9, 2024

@pandieme how are you using that edition check in practice? I found it will fail to execute at all in PowerShell Core due to the ParserError issue for class references described in PowerShell: Unable to find type when using PS 5 classes and Defining a PowerShell class in a script causes a parser error if the class references external types that aren't currently loaded

ParserError:
Line |
   3 |  class TrustAllCertsPolicy : System.Net.ICertificatePolicy {
     |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Unable to find type [System.Net.ICertificatePolicy].

@scarson - Aha yeah, so in practice it's kind of a pain, as the System.Net.ICertificatePolicy class does not exist at all for new age PowerShell, and code will not run at all if it's present in your script. In my particular case, I was using it in a module that is imported dynamically, so... here's how I'm using it, but I would suggest a good TLDR is don't bother, just use the C# snippet, it aint that bad 😅

My module has a tree something like this

-- MyModule/
---- private/
------ PrivateFunction.ps1
----public/
------ PublicFunction.ps1
-- MyModule.psm1
-- MyModule.psd1

The, in PowerShell Core, errornous code is inside the PrivateModule.ps1 file.

using namespace System.Net
using namespace System.Security.Cryptography.X509Certificates
using namespace System.Management.Automation

#Requires -PSEdition Desktop

function Set-TrustAllCertsPolicy {
    if (-not ([PSTypeName]'TrustAllCertsPolicy').Type) {
        class TrustAllCertsPolicy : ICertificatePolicy {
            [bool] CheckValidationResult(
                [ServicePoint]$srvPoint,
                [X509Certificate]$certificate,
                [WebRequest]$request,
                [int]$certificateProblem
            ) {
                return $true
            }
        }
    }

    [ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}

The Public function that would use this Private function is in PublicFunction.ps1

using namespace System.Net

function Set-BypassCertificatePolicy {
    if ($PSVersionTable.PSEdition -eq 'Desktop') {
        Set-TrustAllCertsPolicy
    }

    [ServicePointManager]::SecurityProtocol = [SecurityProtocolType]::Tls12
}

And the import logic for this dynamic module is governed by the MyModule.psm1 file

using namespace System.Collections.Generic

[List[string]]$PublicFunctions = @()

[array]$WindowsPowerShellOnly = @(
    'Set-TrustAllCertsPolicy'
)

"$PSScriptRoot\public", "$PSScriptRoot\private" | ForEach-Object {
    if (Test-Path -Path $_) {
        Get-ChildItem -Path $_ -Filter "*.ps1" -Recurse | ForEach-Object {
            if (($_.BaseName -in $WindowsPowerShellOnly) -and ($PSEdition -ne 'Desktop')) { return }
            if ($_.FullName -match 'public') {$PublicFunctions.Add($_.BaseName)}
            . $_.FullName
        }
    }
}

Export-ModuleMember -Function $PublicFunctions

Because the private function's name that won't execute in PowerShell Core is in the $WindowsPowerShellOnly array, when it gets to the check if (($_.BaseName -in $WindowsPowerShellOnly)... it won't be imported if it's not PSEdition Desktop.

At the time I put that together I was determined to keep my codebase purely PowerShell, but having had time to think about it over time, I would in future simply do the PSEdition check and if it's Desktop, import the type using the C# snippet. But regardless, this code here is in use and working fine, it's just a level of complexity that isn't necessary and I think really only satisfied my curiosity and former stubbornness, but hey it's all part of the journey I guess.

Anyway, that's my answer to how I'm using that check in practice. Good luck and have fun!

@FixRM
Copy link

FixRM commented Apr 9, 2024

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } works on Windows + PS 5.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment