Private/InitTLS.ps1

# The version of Invoke-RestMethod included with PowerShell Core 6 now has a
# native -SkipCertificateCheck parameter. So we don't always need to mess around with
# ServicePointManager anymore. But rather than checking $PSVersionTable.PSEdition,
# we're going to explicitly check the parameter list of Invoke-RestMethod.
if ('SkipCertificateCheck' -notin (Get-Command Invoke-RestMethod).Parameters.Keys) {

    $script:SkipCertSupported = $false

    # Add our custom type for manipulating .NET cert validation
    if (-not ([System.Management.Automation.PSTypeName]'CertValidation').Type)
    {
        Add-Type @"
            using System.Net;
            using System.Net.Security;
            using System.Security.Cryptography.X509Certificates;
            public class CertValidation
            {
                static bool IgnoreValidation(object o, X509Certificate c, X509Chain ch, SslPolicyErrors e) {
                    return true;
                }
                public static void Ignore() {
                    ServicePointManager.ServerCertificateValidationCallback += IgnoreValidation;
                }
                public static void Restore() {
                    ServicePointManager.ServerCertificateValidationCallback -= IgnoreValidation;
                }
            }
"@

    }

} else {
    # remember that we can use SkipCertificateCheck
    $script:SkipCertSupported = $true
}

# add a function so it's easier to mock enable/disable
function Set-CertValidation {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory,Position=0)]
        [bool]$Skip
    )

    if ($Skip) {
        Write-Debug "Disabling cert validation"
        if ($script:SkipCertSupported) {
            $script:UseBasic.SkipCertificateCheck = $true
        } elseif (-not [Net.ServicePointManager]::ServerCertificateValidationCallback) {
            [CertValidation]::Ignore()
        }
    } else {
        Write-Debug "Enabling cert validation"
        if ($script:SkipCertSupported) {
            $script:UseBasic.SkipCertificateCheck = $false
        } elseif ([Net.ServicePointManager]::ServerCertificateValidationCallback) {
            [CertValidation]::Restore()
        }
    }
}

# The version of Invoke-RestMethod included with PowerShell Core 6 now has a native
# -SslProtocol parameter. According to the docs, it defaults to supporting all
# protocols "supported by the system". So we shouldn't need to tweak the supported
# protocols in [Net.ServicePointManager] like we do for the Desktop edition.
if ('SslProtocol' -notin (Get-Command Invoke-RestMethod).Parameters.Keys) {

    # In all of the PowerShell environments tested so far, the set of supported TLS protocols
    # configured by default in .NET seem to only include SSLv3 and TLSv1.0. So even if .NET
    # supports using things like TLS 1.1 or 1.2, cmdlets like Invoke-RestMethod will be limited
    # to TLS 1.0 unless the setting is overridden (per session).
    #
    # To give users a more secure default when using this module and try to prevent potential errors
    # when running against servers that have disabled TLS 1.0, we will change the default set
    # of protocols to include all protocol types beyond 1.0 (or currently configured max level)
    # supported in the current installed .NET framework.
    $currentMaxTls = [Math]::Max([Net.ServicePointManager]::SecurityProtocol.value__,[Net.SecurityProtocolType]::Tls.value__)
    $newTlsTypes = [enum]::GetValues('Net.SecurityProtocolType') | Where-Object { $_ -gt $currentMaxTls }
    $newTlsTypes | ForEach-Object {
        [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor $_
    }

}