AzStackHciExternalActiveDirectory/AzStackHci.ExternalActiveDirectory.Tests.psm1

Import-LocalizedData -BindingVariable lcAdTxt -FileName AzStackHci.ExternalActiveDirectory.Strings.psd1

class ExternalADTest
{
    [string]$TestName
    [scriptblock]$ExecutionBlock
}

$ExternalAdTestInitializors = @(
)

$ExternalAdTests = @(
    (New-Object -Type ExternalADTest -Property @{
        TestName = "RequiredOrgUnitsExist"
        ExecutionBlock = {
            Param ([hashtable]$testContext)

            $serverParams = @{}
            if ($testContext["AdServer"])
            {
                $serverParams += @{Server = $testContext["AdServer"]}
            }
            if ($testContext["AdCredentials"])
            {
                $serverParams += @{Credential = $testContext["AdCredentials"]}
            }

            $requiredOU = $testContext["ADOUPath"]

            Log-Info -Message (" Checking for the existance of OU: {0}" -f $requiredOU) -Type Info -Function "RequiredOrgUnitsExist"

            try {
                $resultingOU = Get-ADOrganizationalUnit -Identity $requiredOU -ErrorAction SilentlyContinue @serverParams
            }
            catch {
            }

            return @{
                Resource    = $_
                Status      = if ($resultingOU) { 'SUCCESS' } else { 'FAILURE' }
                TimeStamp   = [datetime]::UtcNow
                Source      = $ENV:COMPUTERNAME
                Detail = ($testContext["LcAdTxt"].MissingOURemediation -f $_)
           }
        }
    }),
    (New-Object -Type ExternalADTest -Property @{
        TestName = "LogPhysicalMachineObjectsIfExist"
        ExecutionBlock = {
            Param ([hashtable]$testContext)

            $serverParams = @{}
            if ($testContext["AdServer"])
            {
                $serverParams += @{Server = $testContext["AdServer"]}
            }
            if ($testContext["AdCredentials"])
            {
                $serverParams += @{Credential = $testContext["AdCredentials"]}
            }

            $adOUPath = $testContext["ADOUPath"]
            $domainFQDN = $testContext["DomainFQDN"]
            $seedNode = $ENV:COMPUTERNAME

            Log-Info -Message (" Validating seednode : {0} is part of a domain or not " -f $seedNode) -Type Info -Function "PhysicalMachineObjectsExist"
            $domainStatus = (gwmi win32_computersystem).partofdomain 
            if ($domainStatus)
            {
                
                Log-Info -Message (" Seed node {0} joined to the domain. Disconnect the seed node from the domain and proceed with the deployment" -f $seedNode) -Type Error -Function "PhysicalMachineObjectsExist"
                $results += @{
                    Resource    = "SeedNodePartofDomain"
                    Status      = "FAILURE"
                    TimeStamp   = [datetime]::UtcNow
                    Source      = $ENV:COMPUTERNAME
                    Detail = ("Seed joined to the domain. Disconnect the seed node from the domain and proceed with the deployment")
                }
            }
            else
            {
                $physicalHostsSetting = @($testContext["PhysicalMachineNames"] | Where-Object { -not [string]::IsNullOrEmpty($_) })
                Log-Info -Message (" Validating settings for physical hosts: {0}" -f ($physicalHostsSetting -join ", ")) -Type Info -Function "PhysicalMachineObjectsExist"

                try {
                    $allComputerObjects = Get-ADComputer -SearchBase $adOUPath -Filter "*" @serverParams
                }
                catch {
                    Log-Info -Message (" Failed to find any computer objects in ActiveDirectory. Inner exception: {0}" -f $_) -Type Error -Function "PhysicalMachineObjectsExist"
                    $allComputerObjects = @()
                }

                $foundPhysicalHosts = @($allComputerObjects | Where-Object {$_.Name -in $physicalHostsSetting})
                $missingPhysicalHostEntries = @($physicalHostsSetting | Where-Object {$_ -notin $allComputerObjects.Name})

                Log-Info -Message (" Found {0} entries in AD : {1}" -f $foundPhysicalHosts.Count,($foundPhysicalHosts.Name -join ", ")) -Type Info -Function "PhysicalMachineObjectsExist"

                $results = @()

                $results += @{
                    Resource    = "PhysicalHostAdComputerEntries"
                    Status      = "SUCCESS"
                    TimeStamp   = [datetime]::UtcNow
                    Source      = $ENV:COMPUTERNAME
                    Detail = ($testContext["LcAdTxt"].HostsMissingRemediation -f ($missingPhysicalHostEntries -join ", "),$adOUPath)
                }
            }
            return $results
        }
    }),
    (New-Object -Type ExternalADTest -Property @{
        TestName = "GpoInheritanceIsBlocked"
        ExecutionBlock = {
            Param ([hashtable]$testContext)

            $serverParams = @{}
            if ($TestContext["AdServer"])
            {
                $serverParams += @{Server = $TestContext["AdServer"]}
            }
            $ouPath = $testContext["ADOUPath"]

            $ousWithoutGpoInheritanceBlocked = @()

            $accessWasDenied = $false

            try
            {
                    try
                    {
                        $gpInheritance = Get-GPInheritance -Target $ouPath @serverParams
                    }
                    catch
                    {
                        if ($_.Exception -is [System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException]) { throw }
                    }

                    if ((-not $gpInheritance) -or (-not $gpInheritance.GpoInheritanceBlocked))
                    {
                        $statusValue = 'FAILURE'
                    }
            }
            catch [System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException]
            {
                $accessWasDenied = $true
            }

            if ($accessWasDenied)
            {
                return $null
            }

            return @{
                Resource    = "OuGpoInheritance"
                Status      = $statusValue
                TimeStamp   = [datetime]::UtcNow
                Source      = $ENV:COMPUTERNAME
                Detail = $testContext["LcAdTxt"].OuInheritanceBlockedMissingRemediation
            }
        }
    }),
    (New-Object -Type ExternalADTest -Property @{
        TestName = "ExecutingAsDeploymentUser"
        ExecutionBlock = {

            Param ([hashtable]$testContext)

            # Values retrieved from the test context
            $adOuPath = $testContext["ADOUPath"]
            [pscredential]$credentials = $testContext["AdCredentials"]
            $credentialName = $null
            $statusValue = 'FAILURE'
            $userHasOuPermissions = $false
            if ($credentials)
            {
                # Get the user SID so we can find it in the ACL
                $credentialParts = $credentials.UserName.Split("\\")
                $credentialName = $credentialParts[$credentialParts.Length-1]
            }
            else
            {
                $credentialName = $env:USERNAME
            }

            $serverParams = @{}
            if ($TestContext["AdServer"])
            {
                $serverParams += @{Server = $TestContext["AdServer"]}
            }
            if ($TestContext["AdCredentials"])
            {
                $serverParams += @{Credential = $TestContext["AdCredentials"]}
            }
            $deploymentUserIdentifier = Get-ADUser -Filter {Name -eq $credentialName} -SearchBase $adOuPath @serverParams
            if ($deploymentUserIdentifier)
            {

                Log-Info -Message (" Found user '{0}' in Active Directory" -f $credentialName) -Type Info -Function "ExecutingAsDeploymentUser"

                # Test whether the AdCredentials user has all access rights to the OU
                try {

                    $adDriveName = "AD"
                    $tempDriveName = "hciad"
                    $adDriveObject = $null

                    try
                    {
                        $adProvider = Get-PSProvider -PSProvider ActiveDirectory
                        if ($adProvider -and $adProvider.Drives.Count -gt 0)
                        {
                            $adDriveObject = $adProvider.Drives | Where-Object {$_.Name -eq $adDriveName -or $_.Name -eq $tempDriveName}
                        }
                    }
                    catch {
                        Log-Info -Message (" Error while trying to access active directory PS drive. Will fall back to creating a new PS drive. Inner exception: {0}" -f $_) -Type Warning -Function "ExecutingAsDeploymentUser"
                    }

                    if (-not $adDriveObject)
                    {
                        try {
                            # Add a new drive
                            $adDriveObject = New-PSDrive -Name $tempDriveName -PSProvider ActiveDirectory -Root '' @serverParams
                        }
                        catch {
                            Log-Info -Message (" Error while trying to create active directory PS drive. Inner exception: {0}" -f $_) -Type Error -Function "ExecutingAsDeploymentUser"
                        }
                    }

                    $ouAcl = $null

                    if ($adDriveObject)
                    {
                        $adDriveName = $adDriveObject.Name

                        try
                        {
                            $ouPath = ("{0}:\{1}" -f $adDriveName,$adOuPath)
                            $ouAcl = Get-Acl $ouPath
                        }
                        catch
                        {
                            Log-Info -Message (" Can't get acls from {0}. Inner exception: {1}" -f $ouPath,$_) -Type Error -Function "ExecutingAsDeploymentUser"
                        }
                        finally {
                            # best effort cleanup if we had added the temp drive
                            try
                            {
                                if ($adDriveName -eq $tempDriveName)
                                {
                                    $adDriveObject | Remove-PSDrive
                                }
                            }
                            catch {}
                        }
                    }

                    if ($ouAcl) {
                        try {
                            # must specify the type to retrieve -- need to get something comparable to the userSID
                             $accessRule = $ouAcl.Access | Where-Object { `
                                $_.IdentityReference -eq $deploymentUserIdentifier.SID -and `
                                $_.ActiveDirectoryRights -bor [System.DirectoryServices.ActiveDirectoryRights]::CreateChild -bor [System.DirectoryServices.ActiveDirectoryRights]::DeleteChild -and `
                                $_.ObjectType -eq ([System.Guid]::New('bf967a86-0de6-11d0-a285-00aa003049e2'))
                                }
                            if ($accessRule)
                            {
                                $userHasOuPermissions = $true
                                Log-Info -Message (" For AD OU ({0}) found active directory rights ({1}) and object type ({2}) " -f $ouPath, $accessRule.ActiveDirectoryRights, $accessRule.ObjectType ) -Type Warning -Function "ExecutingAsDeploymentUser"
                            }
                            else
                            {
                                Log-Info -Message (" Found ACLs for AD OU ({0}), but user ({1})'s didn't have access rights to create/delete computer objects. " -f $ouPath,$credentialName) -Type Error -Function "ExecutingAsDeploymentUser"
                            }
                        }
                        catch {
                            Log-Info -Message (" Error while trying to get access rules for OU. Inner exception: {0}" -f $_) -Type Error -Function "ExecutingAsDeploymentUser"
                        }

                    }
                }
                catch {
                    Log-Info -Message (" FAILED to look up ACL for AD OU ({0}) and search for GenericAll ACE for user ({1}). Inner exception: {2}" -f $ouPath,$credentialName,$_) -Type Error -Function "ExecutingAsDeploymentUser"
                }
            }
            # If the deployment user is not available in the OUPath then customer may be using the same user for multiple deployments. On a large AD environments we observed that get-aduser is taking long time and timed out hence skipping the rights permission check.
            else
            {
                Log-Info -Message (" User '{0} not found in {1} ' hence skipping the rights permission check. This may cause deployment failure during domain join phase if the user doesn't have the permissions to create or delete computer objects" -f $credentialName, $outPath) -Type Warning -Function "ExecutingAsDeploymentUser"
                #Assuming user has the permissions to create / delete computer objects.
                $userHasOuPermissions = $true
            }

            $failureReasons = @()

            # Summarize detail based on what failed
            if (-not $userHasOuPermissions) {
                $failureReasons += ($testContext["LcAdTxt"].CurrentUserMissingOUAccess -f $adOuPath)
            }

            if ($failureReasons.Count -gt 0) {
                $allFailureReasons = $failureReasons -join "; "
                $detail = ($testContext["LcAdTxt"].CurrentUserFailureSummary -f $credentials.UserName,$allFailureReasons)
            }
            else
            {
                $statusValue = 'SUCCESS'
                $detail = ""
            }
            return @{
                Resource    = "ExecutingAsDeploymentUser"
                Status      = $statusValue
                TimeStamp   = [datetime]::UtcNow
                Source      = $ENV:COMPUTERNAME
                Detail      = $detail
            }
        }
    })
)

function Test-OrganizationalUnitOnSession {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string]
        $ADOUPath,

        [Parameter(Mandatory=$true)]
        [string]
        $DomainFQDN,

        [Parameter(Mandatory=$true)]
        [string]
        $NamingPrefix,

        [Parameter(Mandatory=$true)]
        [string]
        $ClusterName,

        [Parameter(Mandatory)]
        [array]
        $PhysicalMachineNames,

        [Parameter(Mandatory=$false)]
        [System.Management.Automation.Runspaces.PSSession]
        $Session,

        [Parameter(Mandatory=$false)]
        [string]
        $ActiveDirectoryServer,

        [Parameter(Mandatory=$false)]
        [pscredential]
        $ActiveDirectoryCredentials
    )

    $testContext = @{
        ADOUPath = $ADOUPath
        ComputersADOUPath = "OU=Computers,$ADOUPath"
        UsersADOUPath = "OU=Users,$ADOUPath"
        DomainFQDN = $DomainFQDN
        NamingPrefix = $NamingPrefix
        ClusterName = $ClusterName
        LcAdTxt = $lcAdTxt
        AdServer = $ActiveDirectoryServer
        AdCredentials = $ActiveDirectoryCredentials
        AdCredentialsUserName = if ($ActiveDirectoryCredentials) { $ActiveDirectoryCredentials.UserName } else { "" }
        PhysicalMachineNames = $PhysicalMachineNames
    }

    $computerName = if ($Session) { $Session.ComputerName } else { $ENV:COMPUTERNAME }

    Log-Info -Message "Executing test on $computerName" -Type Info

    # Reuse the parameters for Invoke-Command so that we only have to set up context and session data once
    $invokeParams = @{
        ScriptBlock = $null
        ArgumentList = $testContext
    }
    if ($Session) {
        $invokeParams += @{Session = $Session}
    }

    # If provided, verify the AD server and credentials are reachable
    if ($ActiveDirectoryServer -or $ActiveDirectoryCredentials)
    {
        $params = @{}
        if ($ActiveDirectoryServer)
        {
            $params["Server"] = $ActiveDirectoryServer
        }
        if ($ActiveDirectoryCredentials)
        {
            $params["Credential"] = $ActiveDirectoryCredentials
        }
        try {
            $null = Get-ADDomain @params
        }
        catch {
            if (-not $ActiveDirectoryServer) {
                $ActiveDirectoryServer = "default"
            }
            $userName = "default"
            if ($ActiveDirectoryCredentials) {
                $userName = $ActiveDirectoryCredentials.UserName
            }
            throw ("Unable to contact AD server {0} using {1} credentials. Internal exception: {2}" -f $ActiveDirectoryServer,$userName,$_)
        }
    }

    # Initialize the array of detailed results
    $detailedResults = @()

    # Test preparation -- fill in more of the test context that needs to be executed remotely
    $ExternalAdTestInitializors | ForEach-Object {
        $invokeParams.ScriptBlock = $_.ExecutionBlock
        $testName = $_.TestName

        Log-Info -Message "Executing test initializer $testName" -Type Info

        try
        {
            $results = Invoke-Command @invokeParams

            if ($results)
            {
                $testContext += $results
            }
        }
        catch {
            throw ("Unable to execute test {0} on {1}. Inner exception: {2}" -f $testName,$computerName,$_)
        }
    }

    Log-Info -Message "Executing tests with parameters: " -Type Info
    foreach ($key in $testContext.Keys)
    {
        if ($key -ne "LcAdTxt")
        {
            Log-Info -Message " $key : $($testContext[$key])" -Type Info
        }
    }

    # Update InvokeParams with the full context
    $invokeParams.ArgumentList = $testContext

    # For each test, call the test execution block and append the results
    $ExternalAdTests | ForEach-Object {
        # override ScriptBlock with the particular test execution block
        $invokeParams.ScriptBlock = $_.ExecutionBlock
        $testName = $_.TestName

        Log-Info -Message "Executing test $testName" -Type Info

        try
        {
            $results = Invoke-Command @invokeParams

            Log-Info -Message ("Test $testName completed with: {0}" -f $results) -Type Info

            $detailedResults += $results
        }
        catch {
            Log-Info -Message ("Test $testName FAILED. Inner exception: {0}" -f $_) -Type Info
        }
    }

    return $detailedResults
}

function Test-OrganizationalUnit {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string]
        $ADOUPath,

        [Parameter(Mandatory=$true)]
        [string]
        $DomainFQDN,

        [Parameter(Mandatory=$true)]
        [string]
        $NamingPrefix,

        [Parameter(Mandatory=$true)]
        [string]
        $ClusterName,

        [Parameter(Mandatory=$true)]
        [array]
        $PhysicalMachineNames,

        [Parameter(Mandatory=$false)]
        [System.Management.Automation.Runspaces.PSSession]
        $PsSession,

        [Parameter(Mandatory=$false)]
        [string]
        $ActiveDirectoryServer = $null,

        [Parameter(Mandatory=$false)]
        [pscredential]
        $ActiveDirectoryCredentials = $null
    )

    $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop

    Log-Info -Message "Executing Test-OrganizationalUnit"
    $fullTestResults = Test-OrganizationalUnitOnSession -ADOUPath $ADOUPath -DomainFQDN $DomainFQDN -NamingPrefix $NamingPrefix -ClusterName $ClusterName -Session $PsSession -ActiveDirectoryServer $ActiveDirectoryServer -ActiveDirectoryCredentials $ActiveDirectoryCredentials -PhysicalMachineNames $PhysicalMachineNames

    # Build the results
    $TargetComputerName = if ($PsSession.PSComputerName) { $PsSession.PSComputerName } else { $ENV:COMPUTERNAME }
    $remediationValues = $fullTestResults | Where-Object -Property Status -NE 'SUCCESS' | Select-Object $Remediation
    $remediationValues = $remediationValues -join "`r`n"
    if (-not $remediationValues)
    {
        $remediationValues = ''
    }

    $testOuResult = @()
    foreach ($result in $fullTestResults)
    {
        $params = @{
            Name               = "AzStackHci_ExternalActiveDirectory_Test_OrganizationalUnit_$($result.Resource)"
            Title              = "Test AD Organizational Unit - $($result.Resource)"
            DisplayName        = "Test AD Organizational Unit - $($result.Resource)"
            Severity           = 'CRITICAL'
            Description        = 'Tests that the specified organizational unit exists and contains the proper OUs'
            Tags               = @{}
            Remediation        = 'https://learn.microsoft.com/en-us/azure-stack/hci/deploy/deployment-tool-prerequisites'
            TargetResourceID   = "Test_AD_OU_$TargetComputerName"
            TargetResourceName = "Test_AD_OU_$TargetComputerName"
            TargetResourceType = 'ActiveDirectory'
            Timestamp          = [datetime]::UtcNow
            Status             = $result.Status
            AdditionalData     = $result
            HealthCheckSource  = $ENV:EnvChkrId
        }
        $testOuResult += New-AzStackHciResultObject @params
    }

    return $testOuResult
}
# SIG # Begin signature block
# MIInzgYJKoZIhvcNAQcCoIInvzCCJ7sCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDAPZA28EbUc2SL
# lkUQ++7bIMpREw0veQ+cPH3hgZZFs6CCDYUwggYDMIID66ADAgECAhMzAAADri01
# UchTj1UdAAAAAAOuMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjMxMTE2MTkwODU5WhcNMjQxMTE0MTkwODU5WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQD0IPymNjfDEKg+YyE6SjDvJwKW1+pieqTjAY0CnOHZ1Nj5irGjNZPMlQ4HfxXG
# yAVCZcEWE4x2sZgam872R1s0+TAelOtbqFmoW4suJHAYoTHhkznNVKpscm5fZ899
# QnReZv5WtWwbD8HAFXbPPStW2JKCqPcZ54Y6wbuWV9bKtKPImqbkMcTejTgEAj82
# 6GQc6/Th66Koka8cUIvz59e/IP04DGrh9wkq2jIFvQ8EDegw1B4KyJTIs76+hmpV
# M5SwBZjRs3liOQrierkNVo11WuujB3kBf2CbPoP9MlOyyezqkMIbTRj4OHeKlamd
# WaSFhwHLJRIQpfc8sLwOSIBBAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhx/vdKmXhwc4WiWXbsf0I53h8T8w
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMTgzNjAfBgNVHSMEGDAW
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
# AGrJYDUS7s8o0yNprGXRXuAnRcHKxSjFmW4wclcUTYsQZkhnbMwthWM6cAYb/h2W
# 5GNKtlmj/y/CThe3y/o0EH2h+jwfU/9eJ0fK1ZO/2WD0xi777qU+a7l8KjMPdwjY
# 0tk9bYEGEZfYPRHy1AGPQVuZlG4i5ymJDsMrcIcqV8pxzsw/yk/O4y/nlOjHz4oV
# APU0br5t9tgD8E08GSDi3I6H57Ftod9w26h0MlQiOr10Xqhr5iPLS7SlQwj8HW37
# ybqsmjQpKhmWul6xiXSNGGm36GarHy4Q1egYlxhlUnk3ZKSr3QtWIo1GGL03hT57
# xzjL25fKiZQX/q+II8nuG5M0Qmjvl6Egltr4hZ3e3FQRzRHfLoNPq3ELpxbWdH8t
# Nuj0j/x9Crnfwbki8n57mJKI5JVWRWTSLmbTcDDLkTZlJLg9V1BIJwXGY3i2kR9i
# 5HsADL8YlW0gMWVSlKB1eiSlK6LmFi0rVH16dde+j5T/EaQtFz6qngN7d1lvO7uk
# 6rtX+MLKG4LDRsQgBTi6sIYiKntMjoYFHMPvI/OMUip5ljtLitVbkFGfagSqmbxK
# 7rJMhC8wiTzHanBg1Rrbff1niBbnFbbV4UDmYumjs1FIpFCazk6AADXxoKCo5TsO
# zSHqr9gHgGYQC2hMyX9MGLIpowYCURx3L7kUiGbOiMwaMIIHejCCBWKgAwIBAgIK
# YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
# aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
# OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
# VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
# UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
# 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
# dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
# lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
# kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
# A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
# X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
# 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
# sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
# T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
# 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
# bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
# uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
# cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
# YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
# 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
# v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
# pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
# KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
# CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
# mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
# hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
# BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
# oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
# gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
# cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAOuLTVRyFOPVR0AAAAA
# A64wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIHBu
# 22aXHSL5wZYIB+LU2M+1kpzgU/O4jPFvnXFzkN/1MEIGCisGAQQBgjcCAQwxNDAy
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20wDQYJKoZIhvcNAQEBBQAEggEAEyutU95thkqgjtyErYz9AlWS+Ubbcx45bKfp
# LnPYJQgTElxT9p0pTzHEmqz7eYzMEqZ5/KOZTaGqaxUU+SSCV1xZpsEcPEEqNqaj
# /hJfM/9VJIX2mqURrsJsQ8zuRr1TA5sgvtjoCGVNZQB5+B0Mi9ps5q9xi2KeDmPg
# Kthd4JqDYgKDOx0du2P4P7Xc8pHIXPVGuIxfKi+Eump8mLmiLQsbmhZIc12gWj/A
# wLE4GwPfF2Wzx3u3rG2IffroPqTiBr+BITXJ8sVs8Ve4RziTeGT2v4EhDSa5UZ0B
# SZ7ZBQ76xv09gPgykH9c0zmP+0x4msWaFNNfTCuX/Hf9wVz4HaGCFykwghclBgor
# BgEEAYI3AwMBMYIXFTCCFxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZI
# AWUDBAIBBQAwggFZBgsqhkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGE
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCDT0z5W4mrBcUsuLZ7PMYLg2tork2VYjqWx
# FBsWBAOvWAIGZdZD5kFvGBMyMDI0MDMxMTE4MTcxNC4yNzdaMASAAgH0oIHYpIHV
# MIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL
# EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsT
# HVRoYWxlcyBUU1MgRVNOOkQwODItNEJGRC1FRUJBMSUwIwYDVQQDExxNaWNyb3Nv
# ZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAHcweCM
# wl9YXo4AAQAAAdwwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg
# UENBIDIwMTAwHhcNMjMxMDEyMTkwNzA2WhcNMjUwMTEwMTkwNzA2WjCB0jELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z
# b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMg
# VFNTIEVTTjpEMDgyLTRCRkQtRUVCQTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvI
# syA1sjg9kSKJzelrUWF5ShqYWL83amn3SE5JyIVPUC7F6qTcLphhHZ9idf21f0Ra
# GrU8EHydF8NxPMR2KVNiAtCGPJa8kV1CGvn3beGB2m2ltmqJanG71mAywrkKATYn
# iwKLPQLJ00EkXw5TSwfmJXbdgQLFlHyfA5Kg+pUsJXzqumkIvEr0DXPvptAGqkdF
# LKwo4BTlEgnvzeTfXukzX8vQtTALfVJuTUgRU7zoP/RFWt3WagahZ6UloI0FC8Xl
# BQDVDX5JeMEsx7jgJDdEnK44Y8gHuEWRDq+SG9Xo0GIOjiuTWD5uv3vlEmIAyR/7
# rSFvcLnwAqMdqcy/iqQPMlDOcd0AbniP8ia1BQEUnfZT3UxyK9rLB/SRiKPyHDlg
# 8oWwXyiv3+bGB6dmdM61ur6nUtfDf51lPcKhK4Vo83pOE1/niWlVnEHQV9NJ5/Db
# USqW2RqTUa2O2KuvsyRGMEgjGJA12/SqrRqlvE2fiN5ZmZVtqSPWaIasx7a0GB+f
# dTw+geRn6Mo2S6+/bZEwS/0IJ5gcKGinNbfyQ1xrvWXPtXzKOfjkh75iRuXourGV
# PRqkmz5UYz+R5ybMJWj+mfcGqz2hXV8iZnCZDBrrnZivnErCMh5Flfg8496pT0ph
# jUTH2GChHIvE4SDSk2hwWP/uHB9gEs8p/9Pe/mt9AgMBAAGjggFJMIIBRTAdBgNV
# HQ4EFgQU6HPSBd0OfEX3uNWsdkSraUGe3dswHwYDVR0jBBgwFoAUn6cVXQBeYl2D
# 9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3Nv
# ZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy
# MDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1l
# LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUB
# Af8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQAD
# ggIBANnrb8Ewr8eX/H1sKt3rnwTDx4AqgHbkMNQo+kUGwCINXS3y1GUcdqsK/R1g
# 6Tf7tNx1q0NpKk1JTupUJfHdExKtkuhHA+82lT7yISp/Y74dqJ03RCT4Q+8ooQXT
# MzxiewfErVLt8WefebncST0i6ypKv87pCYkxM24bbqbM/V+M5VBppCUs7R+cETiz
# /zEA1AbZL/viXtHmryA0CGd+Pt9c+adsYfm7qe5UMnS0f/YJmEEMkEqGXCzyLK+d
# h+UsFi0d4lkdcE+Zq5JNjIHesX1wztGVAtvX0DYDZdN2WZ1kk+hOMblUV/L8n1YW
# zhP/5XQnYl03AfXErn+1Eatylifzd3ChJ1xuGG76YbWgiRXnDvCiwDqvUJevVRY1
# qy4y4vlVKaShtbdfgPyGeeJ/YcSBONOc0DNTWbjMbL50qeIEC0lHSpL2rRYNVu3h
# sHzG8n5u5CQajPwx9PzpsZIeFTNHyVF6kujI4Vo9NvO/zF8Ot44IMj4M7UX9Za4Q
# wGf5B71x57OjaX53gxT4vzoHvEBXF9qCmHRgXBLbRomJfDn60alzv7dpCVQIuQ06
# 2nyIZKnsXxzuKFb0TjXWw6OFpG1bsjXpOo5DMHkysribxHor4Yz5dZjVyHANyKo0
# bSrAlVeihcaG5F74SZT8FtyHAW6IgLc5w/3D+R1obDhKZ21WMIIHcTCCBVmgAwIB
# AgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0
# IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1
# WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O
# 1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZn
# hUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t
# 1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxq
# D89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmP
# frVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSW
# rAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv
# 231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zb
# r17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYcten
# IPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQc
# xWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17a
# j54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQAB
# MCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQU
# n6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEw
# QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E
# b2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQB
# gjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/
# MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJ
# oEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01p
# Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYB
# BQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v
# Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3h
# LB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x
# 5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74p
# y27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1A
# oL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbC
# HcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB
# 9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNt
# yo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3
# rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcV
# v7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A24
# 5oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lw
# Y1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB
# 0jELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMk
# TWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1U
# aGFsZXMgVFNTIEVTTjpEMDgyLTRCRkQtRUVCQTElMCMGA1UEAxMcTWljcm9zb2Z0
# IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAHDn/cz+3yRkIUCJf
# SbL3djnQEqaggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN
# BgkqhkiG9w0BAQUFAAIFAOmZJPIwIhgPMjAyNDAzMTExNDM2MzRaGA8yMDI0MDMx
# MjE0MzYzNFowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA6Zkk8gIBADAHAgEAAgIP
# 5jAHAgEAAgISBTAKAgUA6Zp2cgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEE
# AYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GB
# AEnp5IEb3Yf3GB5/uVjS4xo4JZEx2KfJ6LX11vwW4T9ViD7bWIN8NsqHuJX96IBA
# D/2YNah18Midhe38BMtmYPtQNoEd+FdYxfcZN97swDTFR14W1qGOCWdftv3MsK8+
# QkthEeNbLfNnrXPsXmvCqpb2f9UCsXRvK3M1y+cAiH4GMYIEDTCCBAkCAQEwgZMw
# fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd
# TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAHcweCMwl9YXo4AAQAA
# AdwwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRAB
# BDAvBgkqhkiG9w0BCQQxIgQggsMNNziz2y8RG3uAUUoon8YcoUTOvXSVIjHURfTp
# VTgwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCBTpxeKatlEP4y8qZzjuWL0
# Ou0IqxELDhX2TLylxIINNzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
# QSAyMDEwAhMzAAAB3MHgjMJfWF6OAAEAAAHcMCIEIIryvC4+0V7RzAR/kEzt6v8L
# CncFnPLA8Eyd0hpkqbWjMA0GCSqGSIb3DQEBCwUABIICAFuQzpKJhf2xhzcqWj4T
# M01uQvsAu29CMKgiMtxbeBucSIKCzQs9f1B7DJLltm0MlKYDx1ZuS3jBxYJCQWJ9
# u4Aw48T59tDSZoYA1d42rluLxBOlr1br4AUErfUAF+cvDi3U9v2Xm13voKd+hxgm
# 9b2GyhOeos79ajI66ibx3QX9kkI9UqyBwQEDHhA2m4yHJqb+QA0qf91rhAfK7l33
# VF6rJRwZ6NL4J8KYNrqAdLcYoiVHd2f3hrzrNkleQw9M4nyrcYC+FYQkpuw8LKoh
# Gw1TFgGRrpEXYm1F+EF7idrlf1S/nfO90F+jd9tvNDogOxudPOzuvTy5Nnkm9iaU
# mcThr9chDqouxOxuwv5M+FR9OBEiag1MRnzeg7vPJkkKMLlYcVSKUZARh6cEoJW/
# nM/PVEJST9QPsonQtuQAjYjr7FD2sXidMzsQpo9rjhN9ALR8vBB+dXUX+M74gY9n
# YKca5ydD3Ey78l1Nu1wCUXf9RCkcY9ip7CgvcDmc48Jut6lS0Ek5aBRKvxiVJ6aG
# 78cJVwd6Ie7stWCQoX30VrJJGg8xm6V2Lvb4yxk8qeXxhU+roVpdk+gMJoHevaPp
# dtjCUnXn/xYPJf3kDdhCXTRSraDXGPUTSY1VNUneVr52vzp8uaIgC60NIyXo613a
# SbIOTAWXSt5EHWFtd+JslQR6
# SIG # End signature block