-
-
Save jmassardo/2e0dd7cce292f16ff8f6945b8b3752b5 to your computer and use it in GitHub Desktop.
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" |
Thanks for the work-around. Any pointers on how to reverse/revert the applied definitions back to original state?
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 {
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.
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} ;
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.
@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 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!
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
works on Windows + PS 5.1
If you just need to access some address, like running some sort of webhook, you can use curl:
$response = & curl.exe --insecure -X GET "$TriggerURL"
if ($response -notmatch "ok") {
...
Dandy, thanks for finding this work-around.