Private/AuthenticationOperations.ps1

<#
SAMPLE CODE NOTICE
 
THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
#>


function Connect-Azure {
    param(
        [Parameter(Mandatory, ParameterSetName = 'ByEndpoint')]
        [ValidateNotNullOrEmpty()]
        [BAPEndpoint]$Endpoint,
        [Parameter(Mandatory, ParameterSetName = 'ByEnvironment')]
        [ValidateNotNullOrEmpty()]
        [AzureEnvironment] $AzureEnvironment,
        [Parameter(Mandatory=$false, ParameterSetName = 'ByEndpoint')]
        [Parameter(Mandatory=$false, ParameterSetName = 'ByEnvironment')]
        [string]$TenantId = $null,
        [Parameter(Mandatory=$false, ParameterSetName = 'ByEndpoint')]
        [Parameter(Mandatory=$false, ParameterSetName = 'ByEnvironment')]
        [string]$AuthScope = $null,
        [Parameter(Mandatory=$false, ParameterSetName = 'ByEndpoint')]
        [Parameter(Mandatory=$false, ParameterSetName = 'ByEnvironment')]
        [switch]$Force
    )

    if($PSCmdlet.ParameterSetName -eq 'ByEndpoint') {
        $AzureEnvironment = switch ($Endpoint) {
            ([BAPEndpoint]::china) { "AzureChinaCloud" }
            ([BAPEndpoint]::dod) { "AzureUSGovernment" }
            ([BAPEndpoint]::usgovhigh) { "AzureUSGovernment" }
            Default { "AzureCloud" }
        }
    }

    $context = Get-AzContext -ListAvailable
    $foundContext = $false

    if(-not($Force) -and [string]::IsNullOrWhiteSpace($AuthScope) -and $null -ne $context) {
        if([string]::IsNullOrWhiteSpace($TenantId)) {
            $matchedContext = $context | Where-Object { $_.Environment.Name -eq $AzureEnvironment } | Select-Object -First 1
            if($matchedContext) {
                Set-AzContext -Context $matchedContext
                Write-Host "Already connected to Azure environment: $AzureEnvironment with account $($matchedContext.Account.Id) with tenants [$($matchedContext.Account.Tenants -join ",")]" -ForegroundColor Yellow
                $foundContext = $true
            }
        }
        else {
            # Prioritize the home tenant if it exists
            $homeTenantContext = $context | Where-Object { $_.Environment.Name -eq $AzureEnvironment -and $_.Tenant.TenantCategory -eq "Home" -and $_.Tenant.Id -eq $TenantId } | Select-Object -First 1
            if($homeTenantContext) {
                Set-AzContext -Context $homeTenantContext
                Write-Host "Already connected to Azure environment: $AzureEnvironment with account $($homeTenantContext.Account.Id) with home tenant Id $TenantId" -ForegroundColor Yellow
                $foundContext = $true
            }
            else {
                $tenantContext = $context | Where-Object { $_.Environment.Name -eq $AzureEnvironment -and $_.Account.Tenants -contains $TenantId } | Select-Object -First 1
                if ($tenantContext) {
                    Set-AzContext -Context $tenantContext
                    Write-Host "Already connected to Azure environment: $AzureEnvironment with account $($tenantContext.Account.Id) with tenant Id $TenantId" -ForegroundColor Yellow
                    $foundContext = $true
                }
            }
        }
    }

    if ($foundContext) {
        return $true
    }

    Write-Host "Logging In..." -ForegroundColor Green
    $connectParameters = @{
        Environment = $AzureEnvironment        
    }
    if(-not([string]::IsNullOrWhiteSpace($TenantId))) {
        $connectParameters['Tenant'] = $TenantId
    }
    if(-not([string]::IsNullOrWhiteSpace($AuthScope))) {
        $connectParameters['AuthScope'] = $AuthScope
    }

    $connect = Connect-AzAccount @connectParameters

    if ($null -eq $connect)
    {
        Write-Host "Error connecting to Azure Account" -ForegroundColor Red
        return $false
    }

    Write-Host "Logged In..." -ForegroundColor Green
    return $true
}

function Get-AccessToken {
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [BAPEndpoint]$Endpoint,

        [Parameter(Mandatory=$false)]
        [string]$TenantId = $null
    )

    $resourceUrl = Get-APIResourceUrl -Endpoint $Endpoint

    $token = Get-AzAccessToken -ResourceUrl $resourceUrl -AsSecureString -ErrorAction SilentlyContinue
    if ($null -eq $token) {
        $tokenError = $global:Error[0]
        if($tokenError.Exception.AuthenticationErrorCode -eq "failed_to_acquire_token_silently_from_broker")
        {
            Write-Host "Failed to acquire token silently. Please log in interactively." -ForegroundColor Red
            Connect-Azure -AuthScope $resourceUrl -Endpoint $Endpoint -TenantId $TenantId
            $token = Get-AzAccessToken -ResourceUrl $resourceUrl -AsSecureString
        }
        else
        {
            Write-Host "Failed to acquire access token: $($tokenError.Exception.AuthenticationErrorCode)" -ForegroundColor Red
            Connect-Azure -AuthScope $resourceUrl -Endpoint $Endpoint -TenantId $TenantId -Force
        }

        if($null -eq $token) {
            throw "Failed to acquire access token. Please check your Azure login and try again."
        }
    }
    return $token.Token
}

function ConvertFrom-SecureStringInternal {
    param (
        [Parameter(Mandatory)]
        [System.Security.SecureString]$SecureString
    )

    try{
        $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
        $plainText = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
        return $plainText
    }
    catch {
        throw "Failed to convert SecureString to plain text: $_"
    }
    finally {
        if ($ptr) {
            [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr)
        }
    }   
}
# SIG # Begin signature block
# MIIoDAYJKoZIhvcNAQcCoIIn/TCCJ/kCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBmAuRVYVXf7Iai
# tpVRBwPeU4cRIpcYy6te6c4DbdWOvaCCDXYwggX0MIID3KADAgECAhMzAAAEhV6Z
# 7A5ZL83XAAAAAASFMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM3WhcNMjYwNjE3MTgyMTM3WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDASkh1cpvuUqfbqxele7LCSHEamVNBfFE4uY1FkGsAdUF/vnjpE1dnAD9vMOqy
# 5ZO49ILhP4jiP/P2Pn9ao+5TDtKmcQ+pZdzbG7t43yRXJC3nXvTGQroodPi9USQi
# 9rI+0gwuXRKBII7L+k3kMkKLmFrsWUjzgXVCLYa6ZH7BCALAcJWZTwWPoiT4HpqQ
# hJcYLB7pfetAVCeBEVZD8itKQ6QA5/LQR+9X6dlSj4Vxta4JnpxvgSrkjXCz+tlJ
# 67ABZ551lw23RWU1uyfgCfEFhBfiyPR2WSjskPl9ap6qrf8fNQ1sGYun2p4JdXxe
# UAKf1hVa/3TQXjvPTiRXCnJPAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUuCZyGiCuLYE0aU7j5TFqY05kko0w
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
# MBQGA1UEBRMNMjMwMDEyKzUwNTM1OTAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBACjmqAp2Ci4sTHZci+qk
# tEAKsFk5HNVGKyWR2rFGXsd7cggZ04H5U4SV0fAL6fOE9dLvt4I7HBHLhpGdE5Uj
# Ly4NxLTG2bDAkeAVmxmd2uKWVGKym1aarDxXfv3GCN4mRX+Pn4c+py3S/6Kkt5eS
# DAIIsrzKw3Kh2SW1hCwXX/k1v4b+NH1Fjl+i/xPJspXCFuZB4aC5FLT5fgbRKqns
# WeAdn8DsrYQhT3QXLt6Nv3/dMzv7G/Cdpbdcoul8FYl+t3dmXM+SIClC3l2ae0wO
# lNrQ42yQEycuPU5OoqLT85jsZ7+4CaScfFINlO7l7Y7r/xauqHbSPQ1r3oIC+e71
# 5s2G3ClZa3y99aYx2lnXYe1srcrIx8NAXTViiypXVn9ZGmEkfNcfDiqGQwkml5z9
# nm3pWiBZ69adaBBbAFEjyJG4y0a76bel/4sDCVvaZzLM3TFbxVO9BQrjZRtbJZbk
# C3XArpLqZSfx53SuYdddxPX8pvcqFuEu8wcUeD05t9xNbJ4TtdAECJlEi0vvBxlm
# M5tzFXy2qZeqPMXHSQYqPgZ9jvScZ6NwznFD0+33kbzyhOSz/WuGbAu4cHZG8gKn
# lQVT4uA2Diex9DMs2WHiokNknYlLoUeWXW1QrJLpqO82TLyKTbBM/oZHAdIc0kzo
# STro9b3+vjn2809D0+SOOCVZMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg
# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03
# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr
# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg
# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy
# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9
# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh
# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k
# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB
# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn
# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90
# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w
# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o
# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa
# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG
# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV
# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG
# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl
# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb
# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l
# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6
# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0
# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560
# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam
# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa
# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah
# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA
# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt
# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr
# /Xmfwb1tbWrJUnMTDXpQzTGCGewwghnoAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAASFXpnsDlkvzdcAAAAABIUwDQYJYIZIAWUDBAIB
# BQCggZAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwLwYJKoZIhvcNAQkEMSIE
# IDG2y6sn7v3Sp8P7n3r/kDRfw0yTiIUr4NIka6H2x9mvMEIGCisGAQQBgjcCAQwx
# NDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29m
# dC5jb20wDQYJKoZIhvcNAQEBBQAEggEAjKLYrNztbM3USx/Q0JOAujemyYlW2bhB
# VKUrPENmUZi8QNYTrSTrrsUo2ZgprBzX23ff5Rqa6vtfI7UznGECj+U7UJzSG4YF
# aw/MScLeWOM6nTydluw5ME9VuWsej6v0E3ViY4rGcH+6rTo0dUwl8pP7eBVlkdnf
# ZAM/NhAVEdK52mume8olyDbqP1iHuotjK3tW0t+FqbVLlzHdcr+cS3xc2GSn3Y2r
# Y9Q3cfO9ILcMAE39iyz9u0QYc3xw1i3Mvf66bVe1fTgym8H+ezWbFeJz7Z4VgpmQ
# Iv+zk1RWb4zRRA2DAJFGdy5xDXE0zC8BiBky0dFcF1Hj35YiTVwkFaGCF5QwgheQ
# BgorBgEEAYI3AwMBMYIXgDCCF3wGCSqGSIb3DQEHAqCCF20wghdpAgEDMQ8wDQYJ
# YIZIAWUDBAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYB
# BAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCASmbZxnDJPcCzLtAyRGgbku/1raW38
# sJWUlL46RSGrsgIGaRXGJS7hGBMyMDI1MTEyMDAwMjMyMS4xMDdaMASAAgH0oIHR
# pIHOMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYD
# VQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hp
# ZWxkIFRTUyBFU046QTQwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBU
# aW1lLVN0YW1wIFNlcnZpY2WgghHqMIIHIDCCBQigAwIBAgITMwAAAgJ5UHQhFH24
# oQABAAACAjANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg
# MjAxMDAeFw0yNTAxMzAxOTQyNDRaFw0yNjA0MjIxOTQyNDRaMIHLMQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQg
# QW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046QTQw
# MC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZp
# Y2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC3eSp6cucUGOkcPg4v
# KWKJfEQeshK2ZBsYU1tDWvQu6L9lp+dnqrajIdNeH1HN3oz3iiGoJWuN2HVNZkcO
# t38aWGebM0gUUOtPjuLhuO5d67YpQsHBJAWhcve/MVdoQPj1njiAjSiOrL8xFarF
# LI46RH8NeDhAPXcJpWn7AIzCyIjZOaJ2DWA+6QwNzwqjBgIpf1hWFwqHvPEedy0n
# otXbtWfT9vCSL9sdDK6K/HH9HsaY5wLmUUB7SfuLGo1OWEm6MJyG2jixqi9NyRoy
# pdF8dRyjWxKRl2JxwvbetlDTio66XliTOckq2RgM+ZocZEb6EoOdtd0XKh3Lzx29
# AhHxlk+6eIwavlHYuOLZDKodPOVN6j1IJ9brolY6mZboQ51Oqe5nEM5h/WJX28GL
# ZioEkJN8qOe5P5P2Yx9HoOqLugX00qCzxq4BDm8xH85HKxvKCO5KikopaRGGtQlX
# jDyusMWlrHcySt56DhL4dcVnn7dFvL50zvQlFZMhVoehWSQkkWuUlCCqIOrTe7Rb
# mnbdJosH+7lC+n53gnKy4OoZzuUeqzCnSB1JNXPKnJojP3De5xwspi5tUvQFNflf
# GTsjZgQAgDBdg/DO0TGgLRDKvZQCZ5qIuXpQRyg37yc51e95z8U2mysU0XnSpWei
# gHqkyOAtDfcIpq5Gv7HV+da2RwIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFNoGubUP
# jP2f8ifkIKvwy1rlSHTZMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1Gely
# MF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv
# cHMvY3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNy
# bDBsBggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9z
# b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBD
# QSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYB
# BQUHAwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQCD83aFQUxN
# 37HkOoJDM1maHFZVUGcqTQcPnOD6UoYRMmDKv0GabHlE82AYgLPuVlukn7HtJPF2
# z0jnTgAfRMn26JFLPG7O/XbKK25hrBPJ30lBuwjATVt58UA1BWo7lsmnyrur/6h8
# AFzrXyrXtlvzQYqaRYY9k0UFY5GM+n9YaEEK2D268e+a+HDmWe+tYL2H+9O4Q1MQ
# Lag+ciNwLkj/+QlxpXiWou9KvAP0tIk+fH8F3ww5VOTi9aZ9+qPjszw31H4ndtiv
# BZaH5s5boJmH2JbtMuf2y7hSdJdE0UW2B0FEZPLImemlKhslJNVqEO7RPgl7c81Q
# uVSO58ffpmbwtSxhYrES3VsPglXn9ODF7DqmPMG/GysB4o/QkpNUq+wS7bORTNzq
# HMtH+ord2YSma+1byWBr/izIKggOCdEzaZDfym12GM6a4S+Iy6AUIp7/KIpAmfWf
# XrcMK7V7EBzxoezkLREEWI4XtPwpEBntOa1oDH3Z/+dRxsxL0vgya7jNfrO7oizT
# Aln/2ZBYB9ioUeobj5AGL45m2mcKSk7HE5zUReVkILpYKBQ5+X/8jFO1/pZyqzQe
# I1/oJ/RLoic1SieLXfET9EWZIBjZMZ846mDbp1ynK9UbNiCjSwmTF509Yn9M47VQ
# sxsv1olQu51rVVHkSNm+rTrLwK1tvhv0mTCCB3EwggVZoAMCAQICEzMAAAAVxedr
# ngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp
# ZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4
# MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG
# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3
# DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qls
# TnXIyjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLA
# EBjoYH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrE
# qv1yaa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyF
# Vk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1o
# O5pGve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg
# 3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2
# TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07B
# MzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJ
# NmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6
# r1AFemzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+
# auIurQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3
# FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl
# 0mWnG1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUH
# AgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0
# b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMA
# dQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAW
# gBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8v
# Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRf
# MjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEw
# LTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL
# /Klv6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu
# 6WZnOlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5t
# ggz1bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfg
# QJY4rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8s
# CXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCr
# dTDFNLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZ
# c9d/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2
# tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8C
# wYKiexcdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9
# JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDB
# cQZqELQdVTNYs6FwZvKhggNNMIICNQIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFt
# ZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOkE0MDAt
# MDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl
# oiMKAQEwBwYFKw4DAhoDFQBJiUhpCWA/3X/jZyIy0ye6RJwLzqCBgzCBgKR+MHwx
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA7MjV
# fjAiGA8yMDI1MTExOTIzNDcxMFoYDzIwMjUxMTIwMjM0NzEwWjB0MDoGCisGAQQB
# hFkKBAExLDAqMAoCBQDsyNV+AgEAMAcCAQACAgkfMAcCAQACAhNOMAoCBQDsyib+
# AgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSCh
# CjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAH3D1b0zTKLI76vy1CrF4her
# k+FyLDa7uvD+bDI0E0o+pKUKJz+fAgwZZ1vHuzdVT7nur/9kN7FpGRxQQzWsil36
# u75Ghh7dRWHafS7JAsvE5rffJ+2Kq+YhEJnnckL113S7OmKTrfOdF7BUOLp+q7hv
# QT1VaNgrKY8icvkYkq3alOoSkAvwQVK5iWDPT9Ts8B/QYjGLGw+2YIuMFmuM6dIW
# PzAW13xDkI/w1zk2H0mZ0Yzvd5l/bXoKC+RANjACDqRR2iAcpnRclriuAGkJtoqR
# JZX0e/OyhBSSQAxzM8toAG0FxBHdIIA0lDg8cBB+UcHzUpLSLouK8JLJanzkOkkx
# ggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAA
# AgJ5UHQhFH24oQABAAACAjANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkD
# MQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCDl2WGTg+uhwKgzQuKLyncE
# 5AHS/4jwndSdvY6dVcZlUzCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIPON
# 6gEYB5bLzXLWuUmL8Zd8xXAsqXksedFyolfMlF/sMIGYMIGApH4wfDELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0
# IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAICeVB0IRR9uKEAAQAAAgIwIgQgAL6X
# nPGms3QL5v14lRGnGhnljmJxIaqI3nXjUCe8LIswDQYJKoZIhvcNAQELBQAEggIA
# g7Vj7/4+nIQzLJIF9DA0bTLM2Alyj7L0ea4moxxU2yRsO1XsxEN62dYMFhu5qEzk
# bjNNODnnf+kW+P9U7dWjUfITt5TPwXSpIIYYuxpuSx5GzL4mmcUhaGZvtEGoxjP8
# jHyb+LKFKZ0k//swJp4pVOunA5Kc6fkDah8nwH1W/lvG5PfvRCGq8tBg02n24Vy0
# Lv3CHozqz8vS2K5HUAVUGTijfh9/5+D6Zu8r1BbWZiqOh2KJL79I5sguUCwNPjPL
# mph2s4QlXiTe2p1iRCmsIiN86FayyU01wwKXEocCpxJwo3luoImhcUwO9lcJjnFV
# gnyBwx+BGIQS0JRlY04a+0ZE5rbNNcQrlBILbzwC6/+SctsPQXZY07OMAimDtMHG
# BD3yMgN1b4GlpFF8eazuI/oV7ANZ1hAoLuheyw4YkyI4gOqs2QeJafwMGfAnbaci
# Hd4bzIgwtmyCXZr5HqAiJ7oEDp54wUM3M6qqxPFGB+3eFw71NLIH9igWJURxQeut
# Awbd68wt/4OdZ1R8BTRGHj66vHJaMk/0KNOnUkrM42F3Xlh7HgUb1VQQt6fzj/6c
# eF/+9znhgtWonlZRkCQX89bqs5b6+O9BjjHCm1dRQMJnYDT6n1Ku1+9qiBSvVYY0
# xR9GHwI/+IAJgnXUMzJQNgJL4UwNqyIGsAVTwl/DmDs=
# SIG # End signature block