GraphValidation/Microsoft.AzureStack.GraphValidation.psm1

function Invoke-AzsGraphValidation {
    <#
    .SYNOPSIS
        Performs Graph Validation before DC Integration with Azure Stack
    .DESCRIPTION
        A tool that can be run standalone or as part Graph integration for Azure Stack.
        Gives operators pre-validation before attempting integration, to ensure all prerequisites are met.
        Calls into Graph functions to provide validation of readiness for graph integration.
        Validation:
            Test Domain
            - should be resolvable and forest root.
            Test AD Credentials
            - test graph credentials have appropriate rights to query AD
            - as per https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-integrate-identity#create-user-account-in-the-existing-active-directory-optional
            Test Global Catalog
            - should be resolvable and contactable.
            Test KDC
            - should be resolvable
            Test Network Connectivity
            - as per https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-integrate-identity#graph-protocols-and-ports
    .EXAMPLE
        PS C:\> Invoke-AzureStackGraphValidation -ForestFQDN contoso.com -Credential $cred
        Validates contoso.com forest can be queried with credential $cred and above validations are performed.
    .PARAMETER ForestFQDN
        ForestFQDN - UriHostNameType.Dns - Forest Root with which to integrate Graph.
    .PARAMETER Credential
        Credential - PSCredential - Service Account with read rights to integrate Graph. Username must be in domain\username format.
    .PARAMETER ForceTLS12
        Force the use of TLS 1.2, true by default
    .PARAMETER OutputPath
        Specifies custom path to save Readiness JSON report and Verbose log file.
    .PARAMETER CleanReport
        Specifies whether to purge the existing report and start again with a clean report. Execution history and validation data is lost for all Readiness Checker validations.
    .PARAMETER PassThru
        switch - Return output results PSObject
    .OUTPUTS
        Output (if any)
    .NOTES
        Graph Integration - https://aka.ms/AzsGraphIntegration
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "Enter Forest FQDN", ParameterSetName = "ValidateGraph")]
        [ValidateScript( {[System.Uri]::CheckHostName($_) -eq 'dns' <#ForestFQDN must be valid DNSHostName#>})]
        [string]
        $ForestFQDN,

        [Parameter(Mandatory = $true, HelpMessage = "Enter Credential with rights to query Forest", ParameterSetName = "ValidateGraph")]
        [ValidateScript( {$_.UserName -notlike '*@*' <#Username should not be upn#>})]
        [PSCredential]
        $Credential,

        [Parameter(Mandatory=$false,HelpMessage="Force the use of TLS 1.2, true by default")]
        [bool]$ForceTLS12 = $true,

        [Parameter(Mandatory = $false, HelpMessage = "Return output results PSObject")]
        [switch]
        $PassThru

    )
    $thisFunction = $MyInvocation.MyCommand.Name
    $GLOBAL:OutputPath = $OutputPath
    Import-Module $PSScriptRoot\..\Microsoft.AzureStack.ReadinessChecker.Reporting.psm1 -Force

    # Import localization strings
    Import-LocalizedData LocalizedData -BaseDirectory $PSScriptRoot -Filename Microsoft.AzureStack.GraphValidation.Strings.psd1

    # Load helper Modules
    Import-Module $PSScriptRoot\..\Microsoft.AzureStack.ReadinessChecker.Utilities.psm1 -Force

    # Check ActiveDirectory Module exist and prompt to install if not
    if (-not (Get-Module ActiveDirectory -ListAvailable)) {
        Write-AzsReadinessLog -message ($LocalizedData.MissingADPSModules) -function $thisFunction -type Error -ToScreen
        break
    }
    Import-Module ActiveDirectory -Force -WarningAction SilentlyContinue

    Write-Header -invocation $MyInvocation -params $PSBoundParameters

    # detect if this is on ercs machine or standalone.
    if ($ENV:COMPUTERNAME -notlike '*-ercs0') {
        $standalone = $true
        Write-AzsReadinessLog ("Running in standalone/offstamp mode") -Type Info -Function $thisFunction
    }

    if (-not (Resolve-DnsName -Name $ForestFQDN -QuickTimeout -ErrorAction SilentlyContinue)) {
        throw "Unable to resolve forest $forestFQDN in DNS"
    }

    if ($credential.Password)
    {
        Write-AzsReadinessLog -Message 'Checking password length and complexity' -Type Info -Function $thisFunction
        Test-PasswordLength -MinimumCharactersInPassword 8 -Password $Credential.Password -CredentialDescription 'Graph Password'
        Test-PasswordComplexity -Password $Credential.Password -CredentialDescription 'Graph Password'
        Write-AzsReadinessLog -Message 'Password length & complexity. Success' -Type Info -Function $thisFunction
    }
    else
    {
        Write-AzsReadinessLog -Message 'Password length and complexity checking skipped' -Type Info -Function $thisFunction
    }

    # Get/Clean Existing Report
    $readinessReport = Get-AzsReadinessProgress -clean:$CleanReport
    $readinessReport = Add-AzsReadinessCheckerJob -report $readinessReport

    # Force Security Profile to TLS1.2
    if ($ForceTLS12)
    {
        # Change Security Protocol to TLS1.2 for the session and track for clean up later.
        $restoreSecurityProtocol = [Net.ServicePointManager]::SecurityProtocol
        $tempSecurityProtocol = [Net.SecurityProtocolType]::Tls12
        Set-SecurityProtocol -securityProtocol $tempSecurityProtocol
    }

    # Start Checks
    $results = @()
    $DomainResult = Test-Domain -ForestFQDN $ForestFQDN
    Write-Result -in $DomainResult
    $results += $DomainResult

    $AdCredResult = Test-ADCredential -credential $credential -ForestFQDN $ForestFQDN
    Write-Result -in $AdCredResult
    $results += $AdCredResult


    if ($DomainResult.result -eq 'OK') {
        $GCResult = Test-GlobalCatalog -ForestFQDN $ForestFQDN
        Write-Result -in $GCResult
        $results += $GCResult

        $KDCResult = Test-KDC -ForestFQDN $ForestFQDN
        Write-Result -in $KDCResult
        $results += $KDCResult

        $LdapPath = ConvertTo-LdapPath -FQDN $ForestFQDN
        $ldapSearchResult = Test-LDAPSearch -LdapPath $LdapPath -Credential $Credential
        Write-Result -in $ldapSearchResult
        $results += $ldapSearchResult
    }
    else {
        Write-AzsReadinessLog "Domain test failed. Skipping GC and KDC tests." -Type Info -Function $thisFunction
    }

    if ($GCResult.outputObject) {
        $ConnectivityResult = Test-NetworkConnectivity -forestFQDN $ForestFQDN -GlobalCatalog $GCResult.outputObject.Hostname
        Write-Result -in $ConnectivityResult
        $results += $ConnectivityResult
    }

    # Restore TLS back to default
    if ($ForceTLS12)
    {
        Set-SecurityProtocol -securityProtocol $restoreSecurityProtocol
    }

    if ($standalone) {
        $hash = @{'Test' = 'Standalone'; 'Result' = 'Warning'; 'FailureDetail' = $LocalizedData.StandaloneWarning; 'outputObject' = $null}
        $object = New-Object PSObject -Property $hash
        $results += $object
    }

    if ($results.result -match "Fail|Warning" -or $standalone) {
        Write-Result -in $results.failureDetail
    }

    # Write results to readiness report
    $readinessReport.GraphValidation = $results
    $readinessReport = Close-AzsReadinessCheckerJob -report $readinessReport
    Write-AzsReadinessProgress -report $readinessReport
    Write-AzsReadinessReport -report $readinessReport

    Write-Footer -invocation $MyInvocation

    if ($PassThru){
        Write-Output $results
    }
}

function Test-Domain {
    param ([string]$ForestFQDN)
    $thisFunction = $MyInvocation.MyCommand.Name

    $test = 'Test Forest Root'
    Write-AzsReadinessLog -Message "Test Domain: $ForestFQDN" -Type Info -Function $thisFunction

    try {
        $domain = Get-ADDomainController -DomainName $ForestFQDN -ForceDiscover -Discover -ErrorAction SilentlyContinue
    }
    catch {
        if ($_.exception.errorcode -eq '1355') {
            $failureDetail = $LocalizedData.CannotResolveForestFQDN -f $ForestFQDN
            Write-AzsReadinessLog -Message $failureDetail -Type Error -Function $thisFunction
        }
        else {
            $failureDetail = $LocalizedData.TestFailed -f $thisFunction, $_.Exception.Message
            Write-AzsReadinessLog -Message $failureDetail -Type Error -Function $thisFunction
        }
    }

    if (-not $domain) {
        $failureDetail = $LocalizedData.DomainNotFound -f $ForestFQDN
        $result = 'Fail'
        Write-AzsReadinessLog -Message $failureDetail -Type Warning -Function $thisFunction
    }
    elseif ($domain.domain -ne $domain.forest) {
        # This can only be a warning, but need to inform that searches will be limited to child domain.
        $failureDetail = $LocalizedData.NotForestRoot -f $ForestFQDN, $domain.forest
        $result = 'Warning'
        Write-AzsReadinessLog -Message $failureDetail -Type Warning -Function $thisFunction
    }
    else {
        $result = 'OK'
        Write-AzsReadinessLog -Message "Domain Controller found:" -Type Info -Function $thisFunction
        $domain.psbase.PropertyNames | ForEach-Object {Write-AzsReadinessLog -Message ("{0} : {1}" -f $PSITEM, $domain.$PSITEM) -Type Info -Function $thisFunction}
    }

    $hash = @{'Test' = $test; 'Result' = $result; 'FailureDetail' = $failureDetail; 'outputObject' = $domain}
    $object = New-Object PSObject -Property $hash
    $object
}

function Test-ADCredential {
    param ([PSCredential]$credential, [string]$ForestFQDN)
    $thisFunction = $MyInvocation.MyCommand.Name

    $test = 'Test Graph Credential'
    Write-AzsReadinessLog -Message ("Attempting to logon to forest {0} with AD Credential {1}..." -f $forestFQDN, $Credential.Username) -Type Info -Function $thisFunction

    try {
        $rootDSE = Get-ADRootDSE -Server $ForestFQDN -Credential $Credential -ErrorAction stop
        Write-AzsReadinessLog -Message ("AD Credential {0} verified." -f $credential.username) -Type Info -Function $thisFunction
        Write-AzsReadinessLog -Message ("AD Root {0} found." -f $rootDSE.rootDomainNamingContext) -Type Info -Function $thisFunction
        $rootDSE.psbase.PropertyNames | ForEach-Object {Write-AzsReadinessLog -Message ("{0} : {1}" -f $PSITEM, $rootDSE.$PSITEM) -Type Info -Function $thisFunction}
        # Check for supported forest and domain modes
        $supportedADDomainMode = 'Windows2012Domain', 'Windows2012R2Domain', 'Windows2016Domain'
        $supportedForestMode = 'Windows2012Forest', 'Windows2012R2Forest', 'Windows2016Forest'
        if ($rootDSE.domainFunctionality -notin $supportedADDomainMode -or $rootDSE.forestFunctionality -notin $supportedForestMode) {
            $failureDetail = $LocalizedData.FunctionalLevelNotSupport -f $ForestFQDN, $rootDSE.domainFunctionality, $rootDSE.forestFunctionality
            $result = 'Fail'
            Write-AzsReadinessLog -Message $failureDetail -Type Warning -Function $thisFunction
        }
        else {
            $result = 'OK'
            Write-AzsReadinessLog -Message "Forest/Domain functional levels are supported." -Type Info -Function $thisFunction
        }
    }
    catch {
        if ($_.Exception.InnerException.InnerException.InnerException.Message -match 'The logon attempt failed') {
            $failureDetail = $LocalizedData.ServerRejectedCreds -f $credential.UserName, $ForestFQDN
            $result = 'Fail'
            Write-AzsReadinessLog -Message $failureDetail -Type Warning -Function $thisFunction
        }
        else {
            $failureDetail = $LocalizedData.TestFailed -f $thisFunction, $_.Exception.Message
            $result = 'Fail'
            Write-AzsReadinessLog -Message $failureDetail -Type Warning -Function $thisFunction
        }
    }

    $hash = @{'Test' = $test; 'Result' = $result; 'FailureDetail' = $failureDetail; 'outputObject' = $null}
    $object = New-Object PSObject -Property $hash
    $object
}

function Test-GlobalCatalog {
    param ([PSCredential]$credential, [string]$ForestFQDN)
    $thisFunction = $MyInvocation.MyCommand.Name

    $test = 'Test Global Catalog'
    Write-AzsReadinessLog -Message ("Getting Global Catalog for forest: {0}" -f $ForestFQDN) -Type Info -Function $thisFunction
    try {
        $GlobalCatalog = Get-ADDomainController -DomainName $forestFQDN -ForceDiscover -Discover -Service GlobalCatalog -ErrorAction SilentlyContinue
    }
    catch {
        $failureDetail = $LocalizedData.TestFailed -f $thisFunction, $_.Exception.Message
        $result = 'Fail'
        Write-AzsReadinessLog -Message $failureDetail -Type Error -Function $thisFunction
    }

    if (-not $GlobalCatalog) {
        $failureDetail = $LocalizedData.GCNotFound
        $result = 'Fail'
        Write-AzsReadinessLog -Message $failureDetail -Type Error -Function $thisFunction
    }
    else {
        $result = 'OK'
        Write-AzsReadinessLog -Message "Global Catalog found:" -Type Info -Function $thisFunction
        $GlobalCatalog.psbase.PropertyNames | ForEach-Object {Write-AzsReadinessLog -Message ("{0} : {1}" -f $PSITEM, $GlobalCatalog.$PSITEM) -Type Info -Function $thisFunction}
    }

    $hash = @{'Test' = $test; 'Result' = $result; 'FailureDetail' = $failureDetail; 'outputObject' = $GlobalCatalog}
    $object = New-Object PSObject -Property $hash
    $object
}

function Test-KDC {
    param ([PSCredential]$credential, [string]$ForestFQDN)
    $thisFunction = $MyInvocation.MyCommand.Name

    $test = 'Test KDC'
    Write-AzsReadinessLog -Message ("Getting KDC for forest: {0}" -f $ForestFQDN) -Type Info -Function $thisFunction
    try {
        $KDC = Get-ADDomainController -DomainName $forestFQDN -ForceDiscover -Discover -Service KDC -ErrorAction SilentlyContinue
    }
    catch {
        $failureDetail = $LocalizedData.TestFailed -f $thisFunction, $_.Exception.Message
        $result = 'Fail'
        Write-AzsReadinessLog -Message $failureDetail -Type Error -Function $thisFunction
    }

    if (-not $KDC) {
        $failureDetail = $LocalizedData.KDCNotFound
        $result = 'Fail'
        Write-AzsReadinessLog -Message $failureDetail -Type Error -Function $thisFunction
    }
    else {
        $result = 'OK'
        Write-AzsReadinessLog -Message "KDC resolved:" -Type Info -Function $thisFunction
        $KDC.psbase.PropertyNames | ForEach-Object {Write-AzsReadinessLog -Message ("{0} : {1}" -f $PSITEM, $KDC.$PSITEM) -Type Info -Function $thisFunction}
    }

    $hash = @{'Test' = $test; 'Result' = $result; 'FailureDetail' = $failureDetail; 'outputObject' = $null}
    $object = New-Object PSObject -Property $hash
    $object
}

function Test-NetworkConnectivity {
    # on stamp only operation (help:https://aka.ms/AzsADFSIntegrationOffline)
    param ([string]$forestFQDN, [string]$GlobalCatalog, [string]$ADFSServer)

    $thisFunction = $MyInvocation.MyCommand.Name
    $test = 'Test Network Connectivity'

    $connectivityTests = @{
        'LDAP'      = @{
            'port'   = 389
            'target' = $ForestFQDN
            'source' = $null
            'result' = $null
        }
        'LDAPSSL'   = @{
            'port'   = 636
            'target' = $ForestFQDN
            'source' = $null
            'result' = $null
        }
        'LDAPGC'    = @{
            'port'   = 3268
            'target' = $GlobalCatalog
            'source' = $null
            'result' = $null
        }
        'LDAPGCSSL' = @{
            'port'   = 3269
            'target' = $GlobalCatalog
            'source' = $null
            'result' = $null
        }
    }

    if ($ADFSServers) {
        foreach ($key in $connectivityTests.keys) {
            $probe = $connectivityTests[$key]
            $result = Test-NetworkConnectivityInternal -source $ADFSServer -destination $probe.target -port $probe.port
            $connectivityTests[$key].Result = $result
        }
    }
    else {
        foreach ($key in $connectivityTests.keys) {
            $probe = $connectivityTests[$key]
            $result = Test-NetworkConnectivityInternal -destination $probe.target -port $probe.port
            $connectivityTests[$key].Result = $result
        }
    }

    # Analyse connectivity Result, success on a single encrypted/unencrypted is a pass
    $failureDetail = @()
    if (-not ($connectivityTests.LDAPGCSSL.Result.TcpTestSucceeded -or $connectivityTests.LDAPGC.Result.TcpTestSucceeded)) {
        $failureDetail += $LocalizedData.LDAPGCConnectivityFailure
    }

    if (-not ($connectivityTests.LDAPSSL.Result.TcpTestSucceeded -or $connectivityTests.LDAP.Result.TcpTestSucceeded)) {
        $failureDetail += $LocalizedData.LDAPConnectivityFailure
    }

    if ($failureDetail) {
        #switch severity depending on the scenario onstamp = fail, offstamp = warning
        switch ($standalone) {
            $true {$result = 'Warning'}
            $false {$result = 'Fail'}
        }
    }
    else {
        $result = 'OK'
    }
    $hash = @{'Test' = $test; 'Result' = $result; 'FailureDetail' = $failureDetail; 'outputObject' = $null}
    $object = New-Object PSObject -Property $hash
    $object
}

function Test-NetworkConnectivityInternal {
    param ($source, $destination, $port)
    $thisFunction = $MyInvocation.MyCommand.Name

    try {
        if ($source) {
            $result = Invoke-Command -ComputerName $source {Test-NetConnection -ComputerName $destination -Port $port -WarningAction SilentlyContinue}
        }
        else {
            $result = Test-NetConnection -ComputerName $destination -Port $port -WarningAction SilentlyContinue
            $source = $ENV:COMPUTERNAME
        }
        # write result to log file
        switch ($result.TcpTestSucceeded) {
            $true {$logLevel = 'Info'}
            $false {$logLevel = 'Warning'}
        }
        Write-AzsReadinessLog -Message ("Connectivity test source = {0}; destination {1}; port = {2}; TcpTestSucceeded = {3}" -f $source, $destination, $port, $result.TcpTestSucceeded) -Type $logLevel -Function $thisFunction
    }
    catch {
        $result = $_.exception
        Write-AzsReadinessLog -Message ("Connectivity test source = {0}; destination {1}; port = {2} failed with error {3}" -f $source, $destination, $port, $result) -Type Error -Function $thisFunction
    }
    $result
}

function Test-LDAPSearch{
    param ($Credential,$LdapPath)
    $thisFunction = $MyInvocation.MyCommand.Name
    $test = 'Test LDAP Search'
    try{
        # Create an ADSI Search for 5 users
        Write-AzsReadinessLog -Message ("Starting user search in {0}, limited to 5 users." -f $LdapPath) -Type Info -Function $thisFunction
        $Searcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher
        $Searcher.Filter = "(objectCategory=User)"
        $Searcher.SizeLimit = '5'
        $Domain = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $LdapPath ,$($Credential.UserName),$($Credential.GetNetworkCredential().password)
        $Searcher.SearchRoot = $Domain
        $searchResult = $Searcher.FindAll()
    }
    catch{
        $failureDetail = $localizedData.TestFailed -f $thisFunction,$_.Exception.Message
        Write-AzsReadinessLog -Message $failureDetail -Type Error -Function $thisFunction
        $result = 'Fail'
    }
    if ($searchResult)
    {
        Write-AzsReadinessLog -Message ("Finished user search in {0}. {1} users found" -f $LdapPath,$searchResult.count) -Type Info -Function $thisFunction
        $result = 'OK'
    }
    $hash = @{'Test' = $test; 'Result' = $result; 'FailureDetail' = $failureDetail; 'outputObject' = $null}
    $object = New-Object PSObject -Property $hash
    $object
}

function ConvertTo-LdapPath{
    param ($FQDN)
    $distinguishedName = $ForestFQDN.split('.') | ForEach-Object {"DC=$PSITEM"}
    $ldapPath = "GC://{0}/{1}" -f ($FQDN,($distinguishedName -join ','))
    $ldapPath
}
function Write-Result {
    param([psobject]$in)
    if ($in.test) {
        Write-Host ("`t{0}: " -f $($in.Test)).PadRight(30) -noNewLine
        if ($in.Result -eq 'OK') {
            Write-Host 'OK' -foregroundcolor Green
        }
        elseif ($in.Result -eq 'WARNING') {
            Write-Host 'Warning' -foregroundcolor Yellow
        }
        elseif ($in.Result -eq 'Skipped') {
            Write-Host 'Skipped' -foregroundcolor White
        }
        else {
            Write-Host 'Fail' -foregroundcolor Red
        }
    }
    else {
        Write-Host "`Details:"
        $in | ForEach-Object {if ($_) {Write-Host "[-] $_" -foregroundcolor Yellow}}
        Write-Host ("Additional help URL: {0}" -f "https://aka.ms/AzsGraphIntegration")
    }
}
# SIG # Begin signature block
# MIInygYJKoZIhvcNAQcCoIInuzCCJ7cCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCATR2QpYkz6b4+X
# XATyFz+aNOSTGGi9qknzVeq3rHFy+KCCDYEwggX/MIID56ADAgECAhMzAAACzI61
# lqa90clOAAAAAALMMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAxWhcNMjMwNTExMjA0NjAxWjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQCiTbHs68bADvNud97NzcdP0zh0mRr4VpDv68KobjQFybVAuVgiINf9aG2zQtWK
# No6+2X2Ix65KGcBXuZyEi0oBUAAGnIe5O5q/Y0Ij0WwDyMWaVad2Te4r1Eic3HWH
# UfiiNjF0ETHKg3qa7DCyUqwsR9q5SaXuHlYCwM+m59Nl3jKnYnKLLfzhl13wImV9
# DF8N76ANkRyK6BYoc9I6hHF2MCTQYWbQ4fXgzKhgzj4zeabWgfu+ZJCiFLkogvc0
# RVb0x3DtyxMbl/3e45Eu+sn/x6EVwbJZVvtQYcmdGF1yAYht+JnNmWwAxL8MgHMz
# xEcoY1Q1JtstiY3+u3ulGMvhAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUiLhHjTKWzIqVIp+sM2rOHH11rfQw
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDcwNTI5MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAeA8D
# sOAHS53MTIHYu8bbXrO6yQtRD6JfyMWeXaLu3Nc8PDnFc1efYq/F3MGx/aiwNbcs
# J2MU7BKNWTP5JQVBA2GNIeR3mScXqnOsv1XqXPvZeISDVWLaBQzceItdIwgo6B13
# vxlkkSYMvB0Dr3Yw7/W9U4Wk5K/RDOnIGvmKqKi3AwyxlV1mpefy729FKaWT7edB
# d3I4+hldMY8sdfDPjWRtJzjMjXZs41OUOwtHccPazjjC7KndzvZHx/0VWL8n0NT/
# 404vftnXKifMZkS4p2sB3oK+6kCcsyWsgS/3eYGw1Fe4MOnin1RhgrW1rHPODJTG
# AUOmW4wc3Q6KKr2zve7sMDZe9tfylonPwhk971rX8qGw6LkrGFv31IJeJSe/aUbG
# dUDPkbrABbVvPElgoj5eP3REqx5jdfkQw7tOdWkhn0jDUh2uQen9Atj3RkJyHuR0
# GUsJVMWFJdkIO/gFwzoOGlHNsmxvpANV86/1qgb1oZXdrURpzJp53MsDaBY/pxOc
# J0Cvg6uWs3kQWgKk5aBzvsX95BzdItHTpVMtVPW4q41XEvbFmUP1n6oL5rdNdrTM
# j/HXMRk1KCksax1Vxo3qv+13cCsZAaQNaIAvt5LvkshZkDZIP//0Hnq7NnWeYR3z
# 4oFiw9N2n3bb9baQWuWPswG0Dq9YT9kb+Cs4qIIwggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZnzCCGZsCAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAsyOtZamvdHJTgAAAAACzDAN
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgic+XJtio
# NO7waKF2wDRRFKl1SPpl4UzssMiPODQziC4wQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
# BgkqhkiG9w0BAQEFAASCAQBq9qdfZUf7IdLimCU4aMU7uQW7gLRz2XrTkrJzbSGx
# EWWn/Tsb7dFEekyawZqhb81XpEze4Q6EKZpNsqX7UG3cIofBu2cYnl+/c28rqe3N
# lFYU+u23I9zg3mZhoS9R6RXhYPAXWJmFPr9Su95iGdqMeudH+xoudNCq1Oq1Hjtb
# SRJFGvshncCR/i0SIEGdb/PSMOHa7Yd5XEZW8NRNOtS9S+59mc4W3s1H0Orp+Wd0
# V+Yevb8UPUWkvJ0/wNT/V9pK/fU/UkrAkh3dVtvsguVVqeYFJDQsvi0MR99bvgDG
# JY9zD/RISRm52WOaZWoTJIW+XC83FHAKIuFHqoto+jogoYIXKTCCFyUGCisGAQQB
# gjcDAwExghcVMIIXEQYJKoZIhvcNAQcCoIIXAjCCFv4CAQMxDzANBglghkgBZQME
# AgEFADCCAVkGCyqGSIb3DQEJEAEEoIIBSASCAUQwggFAAgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEIAS0XPnxKCJiseZ2fKY1yUv6IWfqXlM3dajVgg8g
# chccAgZjYtTzouYYEzIwMjIxMTExMjE1MzMwLjI5MlowBIACAfSggdikgdUwgdIx
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1p
# Y3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhh
# bGVzIFRTUyBFU046MDg0Mi00QkU2LUMyOUExJTAjBgNVBAMTHE1pY3Jvc29mdCBU
# aW1lLVN0YW1wIFNlcnZpY2WgghF4MIIHJzCCBQ+gAwIBAgITMwAAAbJuQAN/bqmU
# kgABAAABsjANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg
# MjAxMDAeFw0yMjA5MjAyMDIyMDFaFw0yMzEyMTQyMDIyMDFaMIHSMQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQg
# SXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg
# RVNOOjA4NDItNEJFNi1DMjlBMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt
# cCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyqJlMh17
# +VDisL4GaXl/9a6r/EpPGt9sbbceh+ZD6pkA3gbI7vc8XfL04B+m3tB/aNyV1Y4Z
# QH4fMG7CWVjI/d/HgxjzO+4C4HfsW+jK2c0LYMqdWtWUc5VwZQv0KeaEM0wDb+ey
# SMh/YiiIb0nSotivx268d1An0uLY+r2C7JJv2a9QvrSiCyUI72CSHoWIQPAyvBSv
# xaNrqMWlROfLy2DQ3RycI3bDh8qSnmplxtRgViJwtJv/oDukcK1frGeOrCGYmiJv
# e+QonJXFu4UtGFVfEf3lvQsd42GJ+feO+jaP7/hBXXSMSldVb6IL0GxO1Hr3G9ON
# TnVmA/sFHhgMRarsmzKVI6/kHlMdMNdF/XzhRHMWFPJvw5lApjuaoyHtzwnzDWwQ
# zhcNQXZRk3Lzb01ULMba190RdlofEXxGbGlBgHHKFnBjWui24hL6B83Z6r6GQBPe
# Kkafz8qYPAO3MBud+5eMCmB5mrCBxgnykMn7L/FTqi7MnPUG97lNOKGSIDvBCxB7
# pHrRmT10903PDQwrmeJHO5BkC3gYj3oWGOGVRZxRk4KS/8lcz84a7+uBKmVjB2Y8
# vPN8O1fK7L8YJTkjiXTyDqKJ9fKkyChiSRx44ADPi/HXHQE6dlZ8jd9LCo1S+g3u
# dxNP4wHhWm9/VAGmmMEBBS6+6Lp4IbQwJU0CAwEAAaOCAUkwggFFMB0GA1UdDgQW
# BBSZ8ieAXNkRmU+SMM5WW4FIMNpqcTAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJl
# pxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAx
# MCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3Rh
# bXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM
# MAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEA
# 3Ee27cXMhptoNtaqzB0oGUCEpdEI37kJIyK/ZNhriLZC5Yib732mLACEOEAN9uqi
# vXPIuL3ljoZCe8hZSB14LugvVm1nJ73bNgr4Qh/BhmaFL4IfiKd8DNS+xwdkXfCW
# slR89QgMZU/SUJhWx72aC68bR2qRjhrJA8Qc68m5uBllo52D83x0id3p8Z45z7QO
# gbMH4uJ45snZDQC0S3dc3eJfwKnr51lNfzHAT8u+FHA+lv/6cqyE7tNW696fB1PC
# oH8tPoI09oSXAV4rEqupFM8xsd6D6L4qcEt/CaERewyDazVBfskjF+9P3qZ3R6Iy
# OIwQ7bYts7OYsw13csg2jACdEEAm1f7f97f3QH2wwYwen5rVX6GCzrYCikGXSn/T
# SWLfQM3nARDkh/flmTtv9PqkTHqslQNgK2LvMJuKSMpNqcGc5z33MYyV6Plf58L+
# TkTFQKs6zf9XMZEJm3ku9VBJ1aqr9AzNMSaKbixvMBIr2KYSSM21lnK8LUKxRwPW
# +gWS2V3iYoyMT64MRXch10P4OtGT3idXM09K5ld7B9U6dcdJ6obvEzdXt+XZovi/
# U6Evb4nA7VPHcHSKs7U72ps10mTfnlue13VFJUqAzbYoUEeegvsmzulGEGJoqZVN
# Aag5v6PVBrur5yLEajjxWH2TfkEOwlL8MuhcVI8OXiYwggdxMIIFWaADAgECAhMz
# AAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9v
# dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0z
# MDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIICIjAN
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7VgtP9
# 7pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeFRiMM
# tY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gm
# U3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl3GoPz130
# /o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP
# 3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7
# vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+A
# utuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz
# 1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy16cg8ML6
# EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y1BzFa/Zc
# UlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6HXtqPnhZy
# acaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJ
# KwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSfpxVd
# AF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8G
# CCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3Mv
# UmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQC
# BAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYD
# VR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZF
# aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9v
# Q2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcw
# AoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJB
# dXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1VffwqreEsH2cB
# MSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27DzHkwo/7
# bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pvvinLbtg/
# SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2
# EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2Fz
# Lixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0
# /fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9
# swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJ
# Xk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+
# pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW
# 4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N
# 7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIC1DCCAj0CAQEwggEAoYHYpIHVMIHSMQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNy
# b3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxl
# cyBUU1MgRVNOOjA4NDItNEJFNi1DMjlBMSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt
# ZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQCOEn4R7JJF+fYoI2yOf1wX
# 0BRJOqCBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqG
# SIb3DQEBBQUAAgUA5xkwmzAiGA8yMDIyMTExMjA0MzUzOVoYDzIwMjIxMTEzMDQz
# NTM5WjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDnGTCbAgEAMAcCAQACAhZKMAcC
# AQACAhF5MAoCBQDnGoIbAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkK
# AwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQADgYEAQQnp
# xmAEnNhSBvp4MGM/Qk7ctE5BAA/CKKCNtWMXMGNd2lEQgYy2OfzDtjlG/OPP7Cyz
# pggR8SsyZG2OcpBiH2AFL6PFdVSer+DLj5RmVDIILKI5W7huG9cO8m7+27ue9WlH
# Vy6J0NbBxqVfVYINhww4uXMc7UrJ4jE1JoGHaNsxggQNMIIECQIBATCBkzB8MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy
# b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAbJuQAN/bqmUkgABAAABsjAN
# BglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8G
# CSqGSIb3DQEJBDEiBCB30WlEUV04v3p9YB+uwtr5CcDOnZJHOBYh9kPxs6s+vjCB
# +gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIFN4zjzn4T63g8RWJ5SgUpfs9XIu
# j+fO76G0k8IbTj41MIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
# MTACEzMAAAGybkADf26plJIAAQAAAbIwIgQg+dXoK77m+XnycffE6pBTfFve9DQh
# M6PPpalM4C9qpewwDQYJKoZIhvcNAQELBQAEggIAtTzN5f8tjuJ7Ksf8dYKUmkyq
# 92b5r8SxneQLAYwg4uUa2q1Gag3la4m0IQn6kb6X458ww4gzroSrDrDO/a9MZMxY
# +DEaJmq6vdUgHkBSuCpPXHrkqWzsWkoghNgKPf8yeIzyoNMvy0fzs5t7+PG+UZu1
# SAFlufizF1a/uEvqUUlhKe3QmLnkX4QhpdWCYAMbVaKeWbJ3+6G3ySLBMNAjt6g7
# Gde9QkdRuur0/U1cAeg4jr3ZPsXAvDngUMfjiMp4URiA4F1M8br6zB6NzH8YON74
# LDS9v7zykv5e1F0t7hnbzyR5fuG6OIlprDLfgN2mpvIb6sM34k5SlsER3IbW9eaF
# 1u7AnwEN3KULcsfTk9Sh/X239EjjEBNL5CLRbSGRxbZQ0VUOqPvFp2DBvuqBXwQ9
# crpyYGDnBt2Y5iSbQIRU/kTsJzSohVNUjiZfClzqFJ4df+cet0E0s3Ppm68dYvnw
# 1dHD0QLYry2nQ84RRmWckwjrbhu4ouf+yMBBsO7Pt72LMAAfj5hYFoNktsmlefjS
# tJUOoogAwTXLgZrG4gP4FAJpfd0rTkHUpFyLipLaFf8pJxSn8K0b+7aFx0BQ8ire
# HTBBNm5lGRrbDIAipX1+dX0/Sx0TfitV03lK6GTzm2Vl3m8psfbd7lspC8HSbNvp
# LEpsy6tV120Yl7pokqw=
# SIG # End signature block