fix: ensure httpclient is able to bypass ssl check

HttpClient does not relay on global ServicePointManager to determine apply ssl policy
This change is extending the existing class used by WebClient and make it usable by HttpClient aswell

Introduce a new parameter switch on DownloadLowFile method allowing to disable ssl check

related to #3066
This commit is contained in:
Loïc LEUILLIOT 2023-05-24 21:56:46 +02:00
Родитель 41f31ad98f
Коммит 34cd2da801
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B3E9AC3003D80473
5 изменённых файлов: 113 добавлений и 157 удалений

Просмотреть файл

@ -391,25 +391,8 @@ try {
$devServerUrl = "$($protocol)$($containerName):$($customConfig.DeveloperServicesPort)/$ServerInstance"
}
$sslVerificationDisabled = ($protocol -eq "https://")
if ($sslVerificationDisabled) {
if (-not ([System.Management.Automation.PSTypeName]"SslVerification").Type)
{
Add-Type -TypeDefinition "
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class SslVerification
{
private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
public static void Disable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidationCallback; }
public static void Enable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; }
}"
}
Write-Host "Disabling SSL Verification"
[SslVerification]::Disable()
}
$timeout = 300000
$sslVerificationDisabled = ($protocol -eq "https://")
if ($customConfig.ClientServicesCredentialType -eq "Windows") {
$useDefaultCredentials = $true
}
@ -467,7 +450,7 @@ try {
}
Write-Host "Url : $Url"
try {
DownloadFileLow -sourceUrl $url -destinationFile $symbolsFile -timeout $timeout -useDefaultCredentials:$useDefaultCredentials -Headers $headers
DownloadFileLow -sourceUrl $url -destinationFile $symbolsFile -timeout $timeout -useDefaultCredentials:$useDefaultCredentials -Headers $headers -skipCertificateCheck:$sslVerificationDisabled
}
catch {
$throw = $true
@ -485,14 +468,6 @@ try {
}
if ($throw) {
Write-Host "ERROR $($_.Exception.Message)"
if ($_.Exception.InnerException)
{
Write-Host "ERROR $($_.Exception.InnerException.Message)"
if ($_.Exception.InnerException.InnerException)
{
Write-Host "ERROR $($_.Exception.InnerException.InnerException.Message)"
}
}
throw (GetExtendedErrorMessage $_)
}
}
@ -568,11 +543,6 @@ try {
}
$depidx++
}
if ($sslverificationdisabled) {
Write-Host "Re-enabling SSL Verification"
[SslVerification]::Enable()
}
$result = Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($appProjectFolder, $appSymbolsFolder, $appOutputFile, $EnableCodeCop, $EnableAppSourceCop, $EnablePerTenantExtensionCop, $EnableUICop, $CustomCodeCops, $rulesetFile, $assemblyProbingPaths, $nowarn, $GenerateCrossReferences, $ReportSuppressedDiagnostics, $generateReportLayoutParam, $features, $preProcessorSymbols, $platformversion, $updateDependencies )

Просмотреть файл

@ -64,23 +64,6 @@ try {
}
$sslVerificationDisabled = ($protocol -eq "https://")
if ($sslVerificationDisabled) {
if (-not ([System.Management.Automation.PSTypeName]"SslVerification").Type)
{
Add-Type -TypeDefinition "
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class SslVerification
{
private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
public static void Disable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidationCallback; }
public static void Enable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; }
}"
}
Write-Host "Disabling SSL Verification"
[SslVerification]::Disable()
}
$timeout = 300000
$useDefaultCredentials = $false
$headers = @{}
@ -104,18 +87,13 @@ try {
$url = "$devServerUrl/dev/packages?publisher=$([uri]::EscapeDataString($publisher))&appName=$([uri]::EscapeDataString($appName))&versionText=$($appVersion)&tenant=$tenant"
Write-Host "Url : $Url"
try {
DownloadFileLow -sourceUrl $url -destinationFile $appFile -timeout $timeout -useDefaultCredentials:$useDefaultCredentials -Headers $headers
DownloadFileLow -sourceUrl $url -destinationFile $appFile -timeout $timeout -useDefaultCredentials:$useDefaultCredentials -Headers $headers -skipCertificateCheck:$sslVerificationDisabled
}
catch [System.Net.WebException] {
Write-Host "ERROR $($_.Exception.Message)"
throw (GetExtendedErrorMessage $_)
}
if ($sslverificationdisabled) {
Write-Host "Re-enabling SSL Verification"
[SslVerification]::Enable()
}
$appFile
}
catch {

Просмотреть файл

@ -1243,16 +1243,18 @@ function Disable-SslVerification
{
if (-not ([System.Management.Automation.PSTypeName]"SslVerification").Type)
{
Add-Type -TypeDefinition @"
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class SslVerification
{
private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
public static void Disable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidationCallback; }
public static void Enable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; }
}
$sslCallbackCode = @"
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class SslVerification
{
public static bool DisabledServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
public static void Disable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = DisabledServerCertificateValidationCallback; }
public static void Enable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; }
}
"@
Add-Type -TypeDefinition $sslCallbackCode
}
[SslVerification]::Disable()
}

Просмотреть файл

@ -1,3 +1,21 @@
$sslCallbackCode = @"
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class SslVerification
{
public static bool DisabledServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
public static void Disable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = DisabledServerCertificateValidationCallback; }
public static void Enable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; }
}
"@
try {
if (-not ([System.Management.Automation.PSTypeName]"SslVerification").Type) {
Add-Type -TypeDefinition $sslCallbackCode -Language CSharp -WarningAction SilentlyContinue | Out-Null
}
}
catch {}
<#
.Synopsis
Publish App to a NAV/BC Container
@ -189,6 +207,17 @@ try {
}
else {
$handler = New-Object System.Net.Http.HttpClientHandler
if ($customConfig.DeveloperServicesSSLEnabled -eq "true") {
$protocol = "https://"
}
else {
$protocol = "http://"
}
$sslVerificationDisabled = ($protocol -eq "https://")
if ($sslVerificationDisabled) {
Write-Host "Disabling SSL Verification"
$handler.ServerCertificateCustomValidationCallback = [SslVerification]::DisabledServerCertificateValidationCallback
}
if ($customConfig.ClientServicesCredentialType -eq "Windows") {
$handler.UseDefaultCredentials = $true
}
@ -204,13 +233,6 @@ try {
}
$HttpClient.Timeout = [System.Threading.Timeout]::InfiniteTimeSpan
$HttpClient.DefaultRequestHeaders.ExpectContinue = $false
if ($customConfig.DeveloperServicesSSLEnabled -eq "true") {
$protocol = "https://"
}
else {
$protocol = "http://"
}
$ip = Get-BcContainerIpAddress -containerName $containerName
if ($ip) {
@ -219,24 +241,6 @@ try {
else {
$devServerUrl = "$($protocol)$($containerName):$($customConfig.DeveloperServicesPort)/$($customConfig.ServerInstance)"
}
$sslVerificationDisabled = ($protocol -eq "https://")
if ($sslVerificationDisabled) {
if (-not ([System.Management.Automation.PSTypeName]"SslVerification").Type)
{
Add-Type -TypeDefinition "
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class SslVerification
{
private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
public static void Disable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidationCallback; }
public static void Enable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; }
}"
}
Write-Host "Disabling SSL Verification"
[SslVerification]::Disable()
}
}
$schemaUpdateMode = "synchronize"
@ -289,8 +293,7 @@ try {
}
if ($sslverificationdisabled) {
Write-Host "Re-enablssing SSL Verification"
[SslVerification]::Enable()
Write-Host "Restoring SSL Verification" # no action required - only to enforce blocks consistency
}
if ($bcContainerHelperConfig.NoOfSecondsToSleepAfterPublishBcContainerApp -gt 0) {
# Avoid race condition

Просмотреть файл

@ -1,6 +1,6 @@
$useTimeOutWebClient = $false
$useTimeOutWebClient = $false
if ($PSVersionTable.PSVersion -lt "6.0.0" -and !$useTimeOutWebClient) {
$Source = @"
$timeoutWebClientCode = @"
using System.Net;
public class TimeoutWebClient : WebClient
@ -25,12 +25,30 @@ $Source = @"
"@;
try {
Add-Type -TypeDefinition $Source -Language CSharp -WarningAction SilentlyContinue | Out-Null
Add-Type -TypeDefinition $timeoutWebClientCode -Language CSharp -WarningAction SilentlyContinue | Out-Null
$useTimeOutWebClient = $true
}
catch {}
}
$sslCallbackCode = @"
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class SslVerification
{
public static bool DisabledServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
public static void Disable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = DisabledServerCertificateValidationCallback; }
public static void Enable() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; }
}
"@
try {
if (-not ([System.Management.Automation.PSTypeName]"SslVerification").Type) {
Add-Type -TypeDefinition $sslCallbackCode -Language CSharp -WarningAction SilentlyContinue | Out-Null
}
}
catch {}
function Get-DefaultCredential {
Param(
[string]$Message,
@ -432,11 +450,11 @@ function GetExtendedErrorMessage {
$message = $exception.Message
if ($errorRecord.ErrorDetails) {
try {
$errorDetails = $errorRecord.ErrorDetails | ConvertFrom-Json
$message += " $($errorDetails.error)`r`n$($errorDetails.error_description)"
}
catch {}
try {
$errorDetails = $errorRecord.ErrorDetails | ConvertFrom-Json
$message += " $($errorDetails.error)`r`n$($errorDetails.error_description)"
}
catch {}
}
try {
if ($exception -is [System.Management.Automation.MethodInvocationException]) {
@ -972,12 +990,17 @@ function DownloadFileLow {
[string] $destinationFile,
[switch] $dontOverwrite,
[switch] $useDefaultCredentials,
[switch] $skipCertificateCheck,
[hashtable] $headers = @{"UserAgent" = "BcContainerHelper $bcContainerHelperVersion" },
[int] $timeout = 100
)
if ($useTimeOutWebClient) {
Write-Host "Downloading using WebClient"
if ($skipCertificateCheck) {
Write-Host "Disabling SSL Verification"
[SslVerification]::Disable()
}
$webClient = New-Object TimeoutWebClient -ArgumentList (1000*$timeout)
$headers.Keys | ForEach-Object {
$webClient.Headers.Add($_, $headers."$_")
@ -994,71 +1017,51 @@ function DownloadFileLow {
}
finally {
$webClient.Dispose()
if ($skipCertificateCheck) {
Write-Host "Restoring SSL Verification"
[SslVerification]::Enable()
}
}
}
else {
if ($PSVersionTable.PSVersion -ge "7.0.0") {
Write-Host "Downloading using Invoke-WebRequest"
if ($useDefaultCredentials) {
$response = Invoke-WebRequest -UseDefaultCredentials -TimeoutSec $timeout -Headers $headers -Uri $sourceUrl -SkipCertificateCheck
}
else {
$response = Invoke-WebRequest -TimeoutSec $timeout -Headers $headers -Uri $sourceUrl -SkipCertificateCheck
}
$fileStream = $null
if ($dontOverwrite) {
$fileMode = [System.IO.FileMode]::CreateNew
}
else {
$fileMode = [System.IO.FileMode]::Create
}
try {
$fileStream = New-Object System.IO.Filestream($destinationFile, $fileMode)
$fileStream.Write($response.Content)
$fileStream.Close()
}
finally {
if ($fileStream) {
$fileStream.Dispose()
}
}
Write-Host "Downloading using HttpClient"
$handler = New-Object System.Net.Http.HttpClientHandler
if ($skipCertificateCheck) {
Write-Host "Disabling SSL Verification"
$handler.ServerCertificateCustomValidationCallback = [SslVerification]::DisabledServerCertificateValidationCallback
}
if ($useDefaultCredentials) {
$handler.UseDefaultCredentials = $true
}
$httpClient = New-Object System.Net.Http.HttpClient -ArgumentList $handler
$httpClient.Timeout = [Timespan]::FromSeconds($timeout)
$headers.Keys | ForEach-Object {
$httpClient.DefaultRequestHeaders.Add($_, $headers."$_")
}
$stream = $null
$fileStream = $null
if ($dontOverwrite) {
$fileMode = [System.IO.FileMode]::CreateNew
}
else {
Write-Host "Downloading using HttpClient"
if ($useDefaultCredentials) {
$handler = New-Object System.Net.Http.HttpClientHandler
$handler.UseDefaultCredentials = $true
$httpClient = New-Object System.Net.Http.HttpClient -ArgumentList $handler
$fileMode = [System.IO.FileMode]::Create
}
try {
$stream = $httpClient.GetStreamAsync($sourceUrl).GetAwaiter().GetResult()
$fileStream = New-Object System.IO.Filestream($destinationFile, $fileMode)
$stream.CopyToAsync($fileStream).GetAwaiter().GetResult() | Out-Null
$fileStream.Close()
}
finally {
if ($fileStream) {
$fileStream.Dispose()
}
else {
$httpClient = New-Object System.Net.Http.HttpClient
if ($stream) {
$stream.Dispose()
}
$httpClient.Timeout = [Timespan]::FromSeconds($timeout)
$headers.Keys | ForEach-Object {
$httpClient.DefaultRequestHeaders.Add($_, $headers."$_")
}
$stream = $null
$fileStream = $null
if ($dontOverwrite) {
$fileMode = [System.IO.FileMode]::CreateNew
}
else {
$fileMode = [System.IO.FileMode]::Create
}
try {
$stream = $httpClient.GetStreamAsync($sourceUrl).GetAwaiter().GetResult()
$fileStream = New-Object System.IO.Filestream($destinationFile, $fileMode)
$stream.CopyToAsync($fileStream).GetAwaiter().GetResult() | Out-Null
$fileStream.Close()
}
finally {
if ($fileStream) {
$fileStream.Dispose()
}
if ($stream) {
$stream.Dispose()
}
if ($skipCertificateCheck) {
Write-Host "Restoring SSL Verification" # no action required - only to enforce blocks consistency
}
}
}