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)
            # This test is not working for cloud deployment (cloud deployment launches the environment checker under local system context which is not able to query the AD).
            # Still figuring out the solution till then I am commenting this test case.
            return $null
            $serverParams = @{}
            if ($TestContext["AdServer"])
            {
                $serverParams += @{Domain = $TestContext["AdServer"]}
            }

            $ouPath = $testContext["ADOUPath"]

            $ousWithoutGpoInheritanceBlocked = @()

            $accessWasDenied = $false
            $statusValue = 'SUCCESS'

            try
            {
                    try
                    {
                        $gpInheritance = Get-GPInheritance -Target $ouPath @serverParams | Select-Object GpoInheritanceBlocked
                    }
                    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

            $failureReasons = @()
            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 {
                            #Verify whether the user has generic all permissions or not.
                            $genericAllPermissions = $ouAcl.Access | Where-Object { `
                                $_.IdentityReference -eq $deploymentUserIdentifier.SID -and `
                                $_.ObjectType -eq [System.Guid]::Empty -and `
                                $_.InheritedObjectType -eq [System.Guid]::Empty -and `
                                $_.ActiveDirectoryRights -eq [System.DirectoryServices.ActiveDirectoryRights]::GenericAll 
                                }
                            if ($genericAllPermissions)
                            {
                                Log-Info -Message (" AD OU ({0}) has genericAll permissions to the SID {1}." -f $ouPath, $deploymentUserIdentifier.SID ) -Type Info -Function "ExecutingAsDeploymentUser"
                            }
                            else
                            {
                                $computerCreateAndDeleteChildPermissions = $ouAcl.Access | Where-Object { `
                                    $_.IdentityReference -eq $deploymentUserIdentifier.SID -and `
                                    $_.ActiveDirectoryRights -eq [System.DirectoryServices.ActiveDirectoryRights]::CreateChild -bor [System.DirectoryServices.ActiveDirectoryRights]::DeleteChild -and `
                                    $_.ObjectType -eq ([System.Guid]::New('bf967a86-0de6-11d0-a285-00aa003049e2'))
                                    }

                                $readPropertyPermissions = $ouAcl.Access | Where-Object { `
                                    $_.IdentityReference -eq $deploymentUserIdentifier.SID -and `
                                    $_.ActiveDirectoryRights -eq [System.DirectoryServices.ActiveDirectoryRights]::ReadProperty -and `
                                    $_.InheritedObjectType -eq [System.Guid]::Empty -and `
                                    $_.ObjectType -eq [System.Guid]::Empty
                                    }

                                $msfveRecoverInformationobjectsPermissions = $ouAcl.Access | Where-Object { `
                                    $_.IdentityReference -eq $deploymentUserIdentifier.SID -and `
                                    $_.ActiveDirectoryRights -eq [System.DirectoryServices.ActiveDirectoryRights]::GenericAll -and `
                                    $_.ObjectType -eq [System.Guid]::Empty -and `
                                    $_.InheritedObjectType -eq ([System.Guid]::New('ea715d30-8f53-40d0-bd1e-6109186d782c'))
                                    }

                                if ($computerCreateAndDeleteChildPermissions)
                                {
                                    Log-Info -Message (" For AD OU ({0}) found active directory rights ({1}) and object type ({2}) " -f $ouPath, $computerCreateAndDeleteChildPermissions.ActiveDirectoryRights, $computerCreateAndDeleteChildPermissions.ObjectType ) -Type Info -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"
                                    $failureReasons += ($testContext["LcAdTxt"].CurrentUserMissingCreateAndDeleteComputerObjectPermission -f $adOuPath)
                                }

                                if ($readPropertyPermissions)
                                {
                                    Log-Info -Message (" For AD OU ({0}) found active directory rights ({1}) and object type ({2}) " -f $ouPath, $readPropertyPermissions.ActiveDirectoryRights, $readPropertyPermissions.ObjectType ) -Type Info -Function "ExecutingAsDeploymentUser"
                                }
                                else
                                {
                                    Log-Info -Message (" Found ACLs for AD OU ({0}), but user ({1})'s didn't have access rights to read AD objects. " -f $ouPath,$credentialName) -Type Error -Function "ExecutingAsDeploymentUser"
                                    $failureReasons += ($testContext["LcAdTxt"].CurrentUserMissingReadObjectPermissions -f $adOuPath)
                                }

                                if ($msfveRecoverInformationobjectsPermissions)
                                {
                                    Log-Info -Message (" For AD OU ({0}) found active directory rights ({1}) and object type ({2}) " -f $ouPath, $msfveRecoverInformationobjectsPermissions.ActiveDirectoryRights, $msfveRecoverInformationobjectsPermissions.ObjectType ) -Type Info -Function "ExecutingAsDeploymentUser"
                                }
                                else
                                {
                                    Log-Info -Message (" Found ACLs for AD OU ({0}), but user ({1})'s didn't have access rights to msFVE-RecoverInformationobjects. " -f $ouPath,$credentialName) -Type Error -Function "ExecutingAsDeploymentUser"
                                    $failureReasons += ($testContext["LcAdTxt"].CurrentUserMissingMsfveRecoverInformationobjectsPermissions -f $adOuPath)
                                }

                            }
                        }
                        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.
            }

            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
# MIInvwYJKoZIhvcNAQcCoIInsDCCJ6wCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAb//qOEV90DIut
# OH/joWIStIoLcZTJOC0h8E6tJFM6tqCCDXYwggX0MIID3KADAgECAhMzAAADrzBA
# DkyjTQVBAAAAAAOvMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjMxMTE2MTkwOTAwWhcNMjQxMTE0MTkwOTAwWjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDOS8s1ra6f0YGtg0OhEaQa/t3Q+q1MEHhWJhqQVuO5amYXQpy8MDPNoJYk+FWA
# hePP5LxwcSge5aen+f5Q6WNPd6EDxGzotvVpNi5ve0H97S3F7C/axDfKxyNh21MG
# 0W8Sb0vxi/vorcLHOL9i+t2D6yvvDzLlEefUCbQV/zGCBjXGlYJcUj6RAzXyeNAN
# xSpKXAGd7Fh+ocGHPPphcD9LQTOJgG7Y7aYztHqBLJiQQ4eAgZNU4ac6+8LnEGAL
# go1ydC5BJEuJQjYKbNTy959HrKSu7LO3Ws0w8jw6pYdC1IMpdTkk2puTgY2PDNzB
# tLM4evG7FYer3WX+8t1UMYNTAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQURxxxNPIEPGSO8kqz+bgCAQWGXsEw
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
# MBQGA1UEBRMNMjMwMDEyKzUwMTgyNjAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAISxFt/zR2frTFPB45Yd
# mhZpB2nNJoOoi+qlgcTlnO4QwlYN1w/vYwbDy/oFJolD5r6FMJd0RGcgEM8q9TgQ
# 2OC7gQEmhweVJ7yuKJlQBH7P7Pg5RiqgV3cSonJ+OM4kFHbP3gPLiyzssSQdRuPY
# 1mIWoGg9i7Y4ZC8ST7WhpSyc0pns2XsUe1XsIjaUcGu7zd7gg97eCUiLRdVklPmp
# XobH9CEAWakRUGNICYN2AgjhRTC4j3KJfqMkU04R6Toyh4/Toswm1uoDcGr5laYn
# TfcX3u5WnJqJLhuPe8Uj9kGAOcyo0O1mNwDa+LhFEzB6CB32+wfJMumfr6degvLT
# e8x55urQLeTjimBQgS49BSUkhFN7ois3cZyNpnrMca5AZaC7pLI72vuqSsSlLalG
# OcZmPHZGYJqZ0BacN274OZ80Q8B11iNokns9Od348bMb5Z4fihxaBWebl8kWEi2O
# PvQImOAeq3nt7UWJBzJYLAGEpfasaA3ZQgIcEXdD+uwo6ymMzDY6UamFOfYqYWXk
# ntxDGu7ngD2ugKUuccYKJJRiiz+LAUcj90BVcSHRLQop9N8zoALr/1sJuwPrVAtx
# HNEgSW+AKBqIxYWM4Ev32l6agSUAezLMbq5f3d8x9qzT031jMDT+sUAoCw0M5wVt
# CUQcqINPuYjbS1WgJyZIiEkBMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
# 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
# /Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAAOvMEAOTKNNBUEAAAAAA68wDQYJYIZIAWUDBAIB
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIMmoS83d/g8L2Ww99h3RGU0t
# ylcI6UAfRznDdLeyYFAoMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
# BQAEggEAiWGj3sCgTwA/2xsejXD9AgVNk7Rd87lrmw5x3AiBcxytWxxK6bCHCbT3
# lpxz6wgZHyxvG933fTpZQ3bOm4Gx3yknyJ5q9EEJV6DL21ULl4VaPkcAyvHHPD6Y
# x0mverkCg3Zv4O0SVkM51eYmFxBRttvQy5uBzuwMRES12nytYIFCqKezDrwdWgUy
# AEW7/Havqdab+7fQeY0L1q2xY1Z7aOd6K+my/PgukMtLIPAON3DGi9qtD4UqLIRD
# 7VsW3nMWFmOXvTTxdUuUeOIhkgCxmRO3C+gOWWQRwCCYHJjs5af3HJowpZEseO5z
# n8+jEdleZwbgpCrTPbAqoeQkE6/0hKGCFykwghclBgorBgEEAYI3AwMBMYIXFTCC
# FxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq
# hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCCTif5ShwaInsHVBF1Ece5m1wYtnMmV2Gv6paXCb1laRQIGZpZiRdRH
# GBMyMDI0MDcxNjE2MjYzMi40MzVaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl
# bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO
# OjhENDEtNEJGNy1CM0I3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT
# ZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAHj372bmhxogyIAAQAAAeMwDQYJ
# KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjMx
# MDEyMTkwNzI5WhcNMjUwMTEwMTkwNzI5WjCB0jELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl
# cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4RDQxLTRC
# RjctQjNCNzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL6kDWgeRp+fxSBUD6N/yuEJ
# pXggzBeNG5KB8M9AbIWeEokJgOghlMg8JmqkNsB4Wl1NEXR7cL6vlPCsWGLMhyqm
# scQu36/8h2bx6TU4M8dVZEd6V4U+l9gpte+VF91kOI35fOqJ6eQDMwSBQ5c9ElPF
# UijTA7zV7Y5PRYrS4FL9p494TidCpBEH5N6AO5u8wNA/jKO94Zkfjgu7sLF8SUdr
# c1GRNEk2F91L3pxR+32FsuQTZi8hqtrFpEORxbySgiQBP3cH7fPleN1NynhMRf6T
# 7XC1L0PRyKy9MZ6TBWru2HeWivkxIue1nLQb/O/n0j2QVd42Zf0ArXB/Vq54gQ8J
# IvUH0cbvyWM8PomhFi6q2F7he43jhrxyvn1Xi1pwHOVsbH26YxDKTWxl20hfQLdz
# z4RVTo8cFRMdQCxlKkSnocPWqfV/4H5APSPXk0r8Cc/cMmva3g4EvupF4ErbSO0U
# NnCRv7UDxlSGiwiGkmny53mqtAZ7NLePhFtwfxp6ATIojl8JXjr3+bnQWUCDCd5O
# ap54fGeGYU8KxOohmz604BgT14e3sRWABpW+oXYSCyFQ3SZQ3/LNTVby9ENsuEh2
# UIQKWU7lv7chrBrHCDw0jM+WwOjYUS7YxMAhaSyOahpbudALvRUXpQhELFoO6tOx
# /66hzqgjSTOEY3pu46BFAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUsa4NZr41Fbeh
# Z8Y+ep2m2YiYqQMwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD
# VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG
# CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw
# MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD
# CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBALe+my6p1NPMEW1t
# 70a8Y2hGxj6siDSulGAs4UxmkfzxMAic4j0+GTPbHxk193mQ0FRPa9dtbRbaezV0
# GLkEsUWTGF2tP6WsDdl5/lD4wUQ76ArFOencCpK5svE0sO0FyhrJHZxMLCOclvd6
# vAIPOkZAYihBH/RXcxzbiliOCr//3w7REnsLuOp/7vlXJAsGzmJesBP/0ERqxjKu
# dPWuBGz/qdRlJtOl5nv9NZkyLig4D5hy9p2Ec1zaotiLiHnJ9mlsJEcUDhYj8PnY
# nJjjsCxv+yJzao2aUHiIQzMbFq+M08c8uBEf+s37YbZQ7XAFxwe2EVJAUwpWjmtJ
# 3b3zSWTMmFWunFr2aLk6vVeS0u1MyEfEv+0bDk+N3jmsCwbLkM9FaDi7q2HtUn3z
# 6k7AnETc28dAvLf/ioqUrVYTwBrbRH4XVFEvaIQ+i7esDQicWW1dCDA/J3xOoCEC
# V68611jriajfdVg8o0Wp+FCg5CAUtslgOFuiYULgcxnqzkmP2i58ZEa0rm4LZymH
# BzsIMU0yMmuVmAkYxbdEDi5XqlZIupPpqmD6/fLjD4ub0SEEttOpg0np0ra/MNCf
# v/tVhJtz5wgiEIKX+s4akawLfY+16xDB64Nm0HoGs/Gy823ulIm4GyrUcpNZxnXv
# E6OZMjI/V1AgSAg8U/heMWuZTWVUMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ
# mQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh
# dGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1
# WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEB
# BQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjK
# NVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhg
# fWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJp
# rx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/d
# vI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka9
# 7aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKR
# Hh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9itu
# qBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyO
# ArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItb
# oKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6
# bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6t
# AgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQW
# BBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacb
# UzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYz
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku
# aHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA
# QwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2
# VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwu
# bWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEw
# LTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93
# d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt
# MjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/q
# XBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6
# U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVt
# I1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis
# 9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTp
# kbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0
# sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138e
# W0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJ
# sWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7
# Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0
# dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQ
# tB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB0jELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxh
# bmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4
# RDQxLTRCRjctQjNCNzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
# dmljZaIjCgEBMAcGBSsOAwIaAxUAPYiXu8ORQ4hvKcuE7GK0COgxWnqggYMwgYCk
# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF
# AOpA4L4wIhgPMjAyNDA3MTYyMDA2MjJaGA8yMDI0MDcxNzIwMDYyMlowdDA6Bgor
# BgEEAYRZCgQBMSwwKjAKAgUA6kDgvgIBADAHAgEAAgIA4jAHAgEAAgIRQTAKAgUA
# 6kIyPgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID
# B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBABovXeYyjmm8c15r6i+k
# HXQTzOXhVG6P9FYEu7IMXFDNqIfD9GWGW4dNKveMeEOyCx5k4K+5ofO12fNr5Evb
# AQmbYIm9zGenqybwU3aW0UHuAC9nXQmIYzQlk4v8S7zkj7ewARmZm51OIQsJ/Cwz
# ivYZGKhLJcCZaykyZAM5ZSSoMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgUENBIDIwMTACEzMAAAHj372bmhxogyIAAQAAAeMwDQYJYIZIAWUDBAIB
# BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx
# IgQg77LLgCeuGTHwE+mJJz3RbGXJ/DanKX+nCtGM7oZdqE0wgfoGCyqGSIb3DQEJ
# EAIvMYHqMIHnMIHkMIG9BCAz1COr5bD+ZPdEgQjWvcIWuDJcQbdgq8Ndj0xyMuYm
# KjCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB49+9
# m5ocaIMiAAEAAAHjMCIEIINS+U670Mb2pz1BF3HBSD5lKZ+5Nkhf+iVkoyCO09e+
# MA0GCSqGSIb3DQEBCwUABIICAAwtof4PYYuxJ+5LD1MHwqF8Zuc7XyErWhxLVio5
# tkbF+CGlXy2WcPLBjMJJO3pB1Ch0mmxxlG0iRUyEqd1WvB/iG8j71o1SnpDjapsK
# FDaDJBu2ouIhE1i+O5PznzjICSXMBkoCScKttfo2rqb/Cyc0G6W2AnLsEQKAcuVI
# AMdkY7t0jhJIgI/H4JnCUfHZvtSuOuazTmn0+2fMGZmgsjJKmbHEGYkYwIH+JLix
# V4kRa312vEyqe1GISzPCV8dKpho2c7cYwn52AWu8qdlBM/2llvCCyp510dOWzCLp
# YxTZUHXzLiJ0u5C2i6aYSnP/KyFajf6MXmOfSHmLnyqD7f15Q3u0vbmMbVGhbey3
# Fg52fxV6jnGxZddxkpGHLvXXFpb3a+X3bhJwE+EhwFmV7ZG3a33Yw+EJbB6u++wC
# Tu+QL8Kur+jXYqEWGXFIBZzT9x+H28QMKQq3LuHxOQTuk2vMnudicl5sJZdFEFu3
# hOySaKTFpcbb6R3dMPdfEYMzS+J9BWiGhzbHrKN29qYgpYiyJgssPOkYwB9FGrG9
# +qhFqC8BlX+bG3G7Sx6H1uKMFnSTtbM8Tz7Tom7EiPUApx3RNVAKVTDCT6ejtqJb
# zQGJt3TprbjCweI0KhABHR5ClQLUwltRfxtF6N/xh6CTJB9F82jUV76K161NJbeq
# 7GIM
# SIG # End signature block