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
# MIIoLAYJKoZIhvcNAQcCoIIoHTCCKBkCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# 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
# /Xmfwb1tbWrJUnMTDXpQzTGCGgwwghoIAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAAOvMEAOTKNNBUEAAAAAA68wDQYJYIZIAWUDBAIB
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIMmoS83d/g8L2Ww99h3RGU0t
# ylcI6UAfRznDdLeyYFAoMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
# BQAEggEAiWGj3sCgTwA/2xsejXD9AgVNk7Rd87lrmw5x3AiBcxytWxxK6bCHCbT3
# lpxz6wgZHyxvG933fTpZQ3bOm4Gx3yknyJ5q9EEJV6DL21ULl4VaPkcAyvHHPD6Y
# x0mverkCg3Zv4O0SVkM51eYmFxBRttvQy5uBzuwMRES12nytYIFCqKezDrwdWgUy
# AEW7/Havqdab+7fQeY0L1q2xY1Z7aOd6K+my/PgukMtLIPAON3DGi9qtD4UqLIRD
# 7VsW3nMWFmOXvTTxdUuUeOIhkgCxmRO3C+gOWWQRwCCYHJjs5af3HJowpZEseO5z
# n8+jEdleZwbgpCrTPbAqoeQkE6/0hKGCF5YwgheSBgorBgEEAYI3AwMBMYIXgjCC
# F34GCSqGSIb3DQEHAqCCF28wghdrAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFRBgsq
# hkiG9w0BCRABBKCCAUAEggE8MIIBOAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCCTif5ShwaInsHVBF1Ece5m1wYtnMmV2Gv6paXCb1laRQIGZmsNwyKy
# GBIyMDI0MDcwOTA4NTM0MC4wM1owBIACAfSggdGkgc4wgcsxCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVy
# aWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo3RjAwLTA1
# RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCC
# Ee0wggcgMIIFCKADAgECAhMzAAAB8Cp8HVk75h+tAAEAAAHwMA0GCSqGSIb3DQEB
# CwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV
# BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTIzMTIwNjE4NDU1
# MVoXDTI1MDMwNTE4NDU1MVowgcsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMx
# JzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo3RjAwLTA1RTAtRDk0NzElMCMGA1UE
# AxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEB
# BQADggIPADCCAgoCggIBALUeLVOjOHc7RzMTzF9GevKaUk0JoZaiaY/LR4g1/7gQ
# mvut/y1LOWATwiXhmPjxPl9NM4CHqchNF/aUrv66lydn/GDQAqgNikFA5asv05sV
# KHKUgd+v8NDg+xFfwZG0ie4mwyTBKDrdt8HhDZSKQwQ/8K1keLzFble0Aqn3lyze
# a9QIy8gADzcmv9TIAMAIldVTiZpiKxzNTPsnXXV4PUqsb2ZD4hOCdFH9fbFMMwLP
# 6KjxlkUcbARmD5ze+Y+nzubg6o4pbKFyoxS6k+947+BAL1G/izMs0YNqh494rohT
# QmpwaNerFtwShL+zWEKA93tTHphZ5atRdrFtv4miyA5rNSBQazVqqmcuPPRgp9Sq
# fyLlNuZHV2oSVHhAD45l95WGlOiesziwT8yUnUkulHYXAAgdR4x+i1c1CLK1h9EF
# Q4kcV4lgR+VmBWTRfH/iRkF3OAVA85Z9V3Y2jNeULZ6ka1SNqW4Daiw69AdnMY6g
# pO9ZQ9f30yywY5s7TEkd3QPKA/8kBWn5tEYmpra7sCoubb60BPbrIjm95xwOY1my
# De8OHUdykIlr1ClFb8wPdr4AXbKBXWxGcZVRUbdU4NfcGEZPxMxT8aJTLeHsKVc7
# GZn7B4K4g7MKRMNsrk6UBLypI+mCn5caU4sQ9ozfUyB/phOmkBp4/SimHHfjmiG3
# AgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQU0IKyp1dHL8yaNkZVMC/HtgVamyUwHwYD
# VR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZO
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIw
# VGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBc
# BggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0
# cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYD
# VR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMC
# B4AwDQYJKoZIhvcNAQELBQADggIBADgi9JueviMQ+CjlbjGPf/7R0IbCzPzrdAZn
# aYH1nhLC0YYsy/B+xFSzc0iU8P8uxYDF1VgeSUDPAtPBDkz49F3L3YMZ+3IQ4Ywd
# +63sarwvdFRy+u+vQAv80218SlsASQIXOx57G1jmzeHOPetfbC+gFmbbK2HBwt5m
# YyAdAKaNmn/bR8dYmCuM9iOx7pEMm1ROW9SyOv7zvz+36+tAQiqWZ5sJ4SL5VBXF
# zvAXQu4xPD+AJZ1yoeiovnYmi3ErNjyNlJDtxw0eELh4cYVGlop6JJDQZe2VsYhs
# /iRbU7cnOUqN/AbrY0JK9+YzWI8P3RdiIWbv/yaBHXoCap58Ox+MEJbB/eqF4gx+
# BnNap4TPyVoWYzwN2ReO44JAT/YvRPGGuNS10yQBN9d1mNhGWxwEPKvzMYyWmsUL
# stzGoJeWHGG13YIz6alxNzxEHYPcSivRR2g/fpD2vhdYJVX/YqfQBe29bG8h/I4W
# blouXR4TOSF+/9eZSUF44ISVLuN111akGVCMm4cdQeM5UZeWslPtfiGJwXWjbfHl
# T6Puo8oFx6vI/b/WjF+Ydzq4FeVcEq6RX9AJkFUCIExgmGeS1qRYemj24h5KdhPp
# DHvB/ZFq5gcgRHxItGZuUzM86z4kdDOu+HvFK3HfXQs6n7QNo5ezzGNm+Gmf5a5m
# KPlGZmKMMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG
# 9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy
# MDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw
# MTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt
# ZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az
# /1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V2
# 9YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oa
# ezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkN
# yjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7K
# MtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRf
# NN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SU
# HDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoY
# WmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5
# C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8
# FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TAS
# BgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1
# Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUw
# UzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNy
# b3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoG
# CCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIB
# hjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fO
# mhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9w
# a2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr
# BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv
# bS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3
# DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEz
# tTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJW
# AAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G
# 82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/Aye
# ixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI9
# 5ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1j
# dEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZ
# KCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xB
# Zj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuP
# Ntq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvp
# e784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCA1Aw
# ggI4AgEBMIH5oYHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScw
# JQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0YwMC0wNUUwLUQ5NDcxJTAjBgNVBAMT
# HE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVAMIo
# Bkoq/mWx0LbKgwYpiJDLv2n/oIGDMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg
# UENBIDIwMTAwDQYJKoZIhvcNAQELBQACBQDqNyh6MCIYDzIwMjQwNzA5MDMwOTQ2
# WhgPMjAyNDA3MTAwMzA5NDZaMHcwPQYKKwYBBAGEWQoEATEvMC0wCgIFAOo3KHoC
# AQAwCgIBAAICIqgCAf8wBwIBAAICE5IwCgIFAOo4efoCAQAwNgYKKwYBBAGEWQoE
# AjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkq
# hkiG9w0BAQsFAAOCAQEAZckaPuqZmVdG4n3pfCTsXQt9N+eeizlYSRgIg2lyQPKq
# 4qyreaWRlN+a+7t8vRSK/ka3fMR4/Qsemq7K/f0rDtFJRNN4YPR0DnqIq1jOHtF1
# /+sPnMgpUcvt6S5eHF9pKcVyvsEL+HP7zw5HmoWJvzbKiyHNyI51C2cs26QEZ8uc
# sKcwCXTyiqPWhHIPTAZFNG36zg0U5oO9D8pcY9hhvfNxlr/KKaLcTrPxwrowpa9C
# pLJ2XXY3KaBWphGqnRdNPiPdS0su3z6hP5dApVgagIGNmsJpfhs4I3VuYXDCl3OF
# K8y3T9UB7Vk+G9jO0Ss02axu4VlFbDruT732PnaDIDGCBA0wggQJAgEBMIGTMHwx
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB8Cp8HVk75h+tAAEAAAHw
# MA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQw
# LwYJKoZIhvcNAQkEMSIEIMvo7yrrmFnc7q8A9JPnoRwRBM0bzLVDam67LBMbF3rZ
# MIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgXAGao6Vy/eRTuYAHmxZHvhAU
# CJLqZv4IzpqycUBlS4swgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg
# MjAxMAITMwAAAfAqfB1ZO+YfrQABAAAB8DAiBCDnmu/zCUiy9TOgvWsM3lvHcH0K
# PGSUv/4UkP6WWecfOTANBgkqhkiG9w0BAQsFAASCAgCK6LnRD30I/KTnlNlGT/UU
# V7uxGELwsAsnewXySu6JUNpHfbkYcIaEDkk+Rfgb9En2D9l8s7qBniKNEYN0cjDo
# KToFIyUfWi8SZkSe2aynMqrZYMOD+LQTwSGpC4jdrxiPDynKdGf7ZIMiabCrt/+l
# Kg7MY8djXzAcWvLwMfj16mNPE5p/Nyc7EHxssHVNLtG9eKH9uYQXH/gcwIqeRl2g
# 4WPSCog+fmKBmwIGgE4uQLDU1MNjWcNnwKTi8qS89/nOloKw9QdnMk9XBodz7zjr
# QL3e00UIOWy1RyAVroW6E33sJhau6giptggFa/zlQlMlVmUx/gPqsGK+HSMUy846
# rJ500I758SkgLVwuKC+L1pA3AJy+aTZPoV9V10vGojg8DXPRmw8RLHOamkwDcQom
# rBWHqkL2fXjO85LeWGNagRAiwLIC3x1hjx0cNKB3XVPuv3v8qRtsOQvJMnId1pQX
# +yrWE8oCqxjb4osRu4IB8C2uABWSpjUN4kCiVWj8KU8gJRqhV7btBRs5wfjwJiPC
# pzjJwuQ4xYByMdX7IPAEQSD/rD6kcVihLZ0SOuf4Dfw68ZvkoPZtsr6cOSArWab4
# 6jJ6vlPrxUYo9DIBKNKblb9D/SlO2mpQDhGPhG32dMF5Wwgors4bmZaDVzsBirSR
# lHXBeuRHSA4vehGStdOyJg==
# SIG # End signature block