PureStorage.AzureNative.Tools.psm1

. $PSScriptRoot/PureStorage.AzureNative.Util.ps1

$PluginPrivileges = @(
    'Datastore.AllocateSpace',
    'Datastore.Browse',
    'Datastore.Config',
    'Datastore.Delete',
    'Datastore.DeleteFile',
    'Datastore.FileManagement',
    'Datastore.Move',
    'Datastore.Rename',
    'Datastore.UpdateVirtualMachineFiles',
    'Datastore.UpdateVirtualMachineMetadata',
    'Extension.Register',
    'Extension.Unregister',
    'Extension.Update',
    'Folder.Create',
    'Folder.Delete',
    'Folder.Move',
    'Folder.Rename',
    'Global.CancelTask',
    'Global.ManageCustomFields',
    'Global.SetCustomField',
    'Host.Config.Storage',
    'ScheduledTask.Create',
    'ScheduledTask.Delete',
    'ScheduledTask.Edit',
    'ScheduledTask.Run',
    'Sessions.ValidateSession',
    'StorageProfile.Update',
    'StorageProfile.View',
    'StorageViews.View',
    'StorageViews.ConfigureService',
    'Task.Create',
    'Task.Update',
    'VirtualMachine.Config.AddExistingDisk',
    'VirtualMachine.Config.AddNewDisk',
    'VirtualMachine.Config.AddRemoveDevice',
    'VirtualMachine.Config.RemoveDisk',
    'VirtualMachine.Interact.PowerOff',
    'VirtualMachine.Interact.PowerOn',
    'VirtualMachine.Inventory.Create',
    'VirtualMachine.Inventory.CreateFromExisting',
    'VirtualMachine.Inventory.Delete',
    'VirtualMachine.Inventory.Move',
    'VirtualMachine.Inventory.Register',
    'VirtualMachine.Inventory.Unregister',
    'VirtualMachine.Provisioning.Clone',
    'VirtualMachine.Provisioning.CloneTemplate',
    'VirtualMachine.Provisioning.CreateTemplateFromVM',
    'VirtualMachine.Provisioning.GetVmFiles',
    'VirtualMachine.State.CreateSnapshot',
    'VirtualMachine.State.RemoveSnapshot',
    'VirtualMachine.State.RenameSnapshot',
    'VirtualMachine.State.RevertToSnapshot'
)

# AVS resource ID for the dev environment
$AvsResourceIdDev = "/subscriptions/96798833-9949-4913-a555-b0f2de70a444/resourceGroups/rg-krypton-sddc-network-dev-eastus/providers/Microsoft.AVS/privateClouds/krypton-private-cloud-dev"
$AvsResourceIdQA = "/subscriptions/de8f0119-1ff4-4aa1-b5ee-7be650f2d750/resourceGroups/rg-krypton-avs-qa-eastus/providers/Microsoft.AVS/privateClouds/krypton-avs-qa-eastus"

# Time window for the request (set to 60 minutes for now, can be adjusted as discussed)
$TimeWindowInMinutes = 60

# Service account name prefix
$AccountNamePrefix = "psserviceaccount"

# Service account role name
$RoleName = "PureStorageService"

Function Get-SSLThumbprintFromCertString {
    param (
        [String]$CertString
    )

    $CertString = $CertString -replace '-----BEGIN CERTIFICATE-----', ''
    $CertString = $CertString -replace '-----END CERTIFICATE-----', ''
    $CertString = $CertString -replace '\s', ''

    $certificate = [Security.Cryptography.X509Certificates.X509Certificate2]::new([Convert]::FromBase64String($CertString))

    $thumbprint = $certificate.Thumbprint
    $thumbprint = $thumbprint -replace '(.{2})', '$1:'
    $thumbprint = $thumbprint.TrimEnd(':')

    return $thumbprint
}

Function Register-RemotePlugin {
    param(
        [parameter(Mandatory = $true)]
        [VMware.Vim.ExtensionManager]$ExtensionMgr,
        [parameter(Mandatory = $true)]
        [String]$RegistrationUrl,
        [parameter(Mandatory = $true)]
        [String]$PluginVersion,
        [parameter(Mandatory = $true)]
        [String]$PluginThumbprint,
        [parameter(Mandatory = $false)]
        [String]$PluginCertificate
    )

    #build extension to register. Will pull the SSL thumprint from the target address
    $description = New-Object VMware.Vim.Description
    $description.label = "Pure Storage Manager"
    $description.summary = "Pure Storage Management Plugin for the vSphere Client"

    $extensionClientInfo = New-Object VMware.Vim.ExtensionClientInfo
    $extensionClientInfo.Company = "Pure Storage, Inc."
    $extensionClientInfo.Description = $description
    $extensionClientInfo.Type = "vsphere-client-remote"
    $extensionClientInfo.Version = $PluginVersion
    $extensionClientInfo.Url = $RegistrationUrl

    $extensionServerInfo = New-Object VMware.Vim.ExtensionServerInfo
    $extensionServerInfo.AdminEmail = "noreply@purestorage.com"
    $extensionServerInfo.Company = "Pure Storage, Inc."
    $extensionServerInfo.Description = $description
    $extensionServerInfo.Url = $RegistrationUrl
    $extensionServerInfo.Type = "HTTPS"
    $extensionServerInfo.ServerThumbprint = $PluginThumbprint
    if ($PluginCertificate) {
        $extensionServerInfo.ServerCertificate = $PluginCertificate
    }

    $extensionSpec = New-Object VMware.Vim.Extension
    $extensionSpec.key = "com.purestorage.integrations.vmware.pureplugin"
    $extensionSpec.version = $PluginVersion
    $extensionSpec.Description = $description
    $extensionSpec.Client += $extensionClientInfo
    $extensionSpec.Server += $extensionServerInfo
    $extensionSpec.LastHeartbeatTime = get-date

    Write-Verbose "Registering new plugin"
    $ExtensionMgr.RegisterExtension($extensionSpec)
}

<#
    .SYNOPSIS
     This function unregisters the vSphere remote plugin extension from AVS

    .EXAMPLE
     Unregister-PureStorageAvsRemotePlugin

    .INPUTS
     No inputs are required

    .OUTPUTS
     None
#>

Function Unregister-PureStorageAvsRemotePlugin {
    [CmdletBinding()]
    [AVSAttribute(10, UpdatesSDDC = $false, AutomationOnly = $true)]
    param()

    $services = Get-View 'ServiceInstance'
    $extensionMgr = Get-View $services.Content.ExtensionManager
    $extensionMgr.UnregisterExtension("com.purestorage.integrations.vmware.pureplugin")

    Write-Host "PureStorage Remote Plugin un-registered successfully"
}

<#
    .SYNOPSIS
     This function registers the vSphere remote plugin extension with AVS

    .PARAMETER RegistrationUrl
     vSphere remote plugin registration URL

    .PARAMETER PluginVersion
     The version of the plugin that is being registered

    .PARAMETER PluginCertificate
     The full SSL certificate of the vSphere remote plugin being registered, in pem format. i.e.
     -----BEGIN CERTIFICATE-----
     Base64–encoded certificate
     -----END CERTIFICATE-----

    .EXAMPLE
     Register-PureStorageAvsRemotePlugin -PluginHost 'https://10.20.30.40/plugin-manifest-location.zip' -PluginVersion '1.0.0' -PluginCertificate @"
       -----BEGIN CERTIFICATE-----
       Base64–encoded certificate
       -----END CERTIFICATE-----
       "@

    .INPUTS
     vSphere remote plugin registration URL, version, and SSL certificate

    .OUTPUTS
     None
#>

Function Register-PureStorageAvsRemotePlugin {
    [CmdletBinding()]
    [AVSAttribute(10, UpdatesSDDC = $false, AutomationOnly = $true)]
    param(
        [Parameter(
            Mandatory = $true,
            HelpMessage = 'vSphere remote plugin registration URL')]
        [ValidateNotNull()]
        [String]$RegistrationUrl,

        [Parameter(
            Mandatory = $true,
            HelpMessage = 'version of the vSphere remote plugin being registered')]
        [ValidateNotNull()]
        [String]$PluginVersion,

        [Parameter(
            Mandatory = $true,
            HelpMessage = 'full SSL certificate of the vSphere remote plugin being registered')]
        [ValidateNotNull()]
        [String]$PluginCertificate
    )
    $services = Get-View 'ServiceInstance'
    $extensionMgr = Get-View $services.Content.ExtensionManager
    $serverVersion = $services.Content.About.Version

    $CERT_SUPPORTED_VCENTER_VERSION = "8.0.2";
    $thumbprint = Get-SSLThumbprintFromCertString -CertString $PluginCertificate
    if ([System.Version]$ServerVersion -ge [System.Version]$CERT_SUPPORTED_VCENTER_VERSION) {
        Write-Host "Host Version $serverVersion, registering using Remote Plugin public certificate"
        Register-RemotePlugin -ExtensionMgr $extensionMgr -RegistrationUrl $RegistrationUrl -PluginVersion $PluginVersion -PluginThumbprint $thumbprint -PluginCertificate $PluginCertificate
    }
    else {
        Write-Host "Host Version $serverVersion, registering using Remote Plugin thumbprint"
        Register-RemotePlugin -ExtensionMgr $extensionMgr -RegistrationUrl $RegistrationUrl -PluginVersion $PluginVersion -PluginThumbprint $thumbprint
    }

    Write-Host "PureStorage Remote Plugin (Version: $PluginVersion) registered successfully"
}

<#
    .SYNOPSIS
     This function get the version of vSphere remote plugin extension with AVS

    .EXAMPLE
     Get-PureStorageAvsRemotePluginVersion

    .INPUTS
     No inputs are required

     .OUTPUTS
     Named Plugin Version stored under Key "PureStorageAvsPluginVersion" in NamedOutput if Plugin is registered
#>

Function Get-PureStorageAvsRemotePluginVersion {
    [CmdletBinding()]
    [AVSAttribute(10, UpdatesSDDC = $false, AutomationOnly = $true)]
    param()

    $services = Get-View 'ServiceInstance'
    $extensionMgr = Get-View $services.Content.ExtensionManager
    $version = ($extensionMgr.FindExtension("com.purestorage.integrations.vmware.pureplugin")).version

    if ($null -eq $version) {
        Write-Warning "No Pure Storage Avs Remote Plugin Installed $version"
    }
    else {
        Write-Host "Pure Storage Avs Remote Plugin Version $version is currently installed"
    }

    $NamedOutputs = @{}
    $NamedOutputs["PureStorageAvsPluginVersion"] = $version
    Set-Variable -Name NamedOutputs -Value $NamedOutputs -Scope Global
}

<#
.SYNOPSIS
Creates a new service account and assigns it a role with specific privileges.

.DESCRIPTION
The New-ServiceAccount function creates a new service account with the specified name and password. It then creates a role named 'PureStorageService'
if it doesn't already exist, and assigns the role to the service account. The function also adds permissions for the service account on all VM hosts.

.PARAMETER InitializationHandle
The InitializationHandle is a base64 encoded JSON object that contains the following fields:
{
     "data": "<Base64 encoded InitializationHandle>",
     "signature": "<Signature>"
}

.EXAMPLE
$InitializationDataEnc = New-ServiceAccount -InitializationHandle "eyJkYXRh"

This example decodes the InitializationHandle and validates the signature first.
It then creates a new service account with the name defined in data.serviceAccountUsername wiht random password.
It assigns the 'PureStorageService' role to the service account and adds permissions for the service account on all VM hosts.
It returns an encrypted initialization data which is base64 encoded that contains the service account username, password and vSphere IP.

#>


function New-AvsServiceAccount {
    [CmdletBinding()]
    [AVSAttribute(10, UpdatesSDDC = $false, AutomationOnly = $true)]
    param(
        [Parameter(Mandatory = $true)]
        [string]$InitializationHandle
    )

    # Convert the InitializationHandle to a JSON object
    $DecodedInitializationHandle = ConvertFrom-Base64 -Base64Text $InitializationHandle | ConvertFrom-Json
    $Data = $DecodedInitializationHandle.data
    $Signature = $DecodedInitializationHandle.signature

    # Convert the data to a JSON object
    $DecodedData = ConvertFrom-Base64 -Base64Text $Data | ConvertFrom-Json

    # The data is a JSON object with the following structure:
    # {
    # "sddcResourceId": "string",
    # "requestDatetime": "string",
    # "ephemeralPublicKey": "string",
    # "serviceAccountUserame": "string"
    # }
    $SddcResourceId = $DecodedData.sddcResourceId
    $RequestDatetime = $DecodedData.requestDatetime
    $EphemeralPublicKey = $DecodedData.ephemeralPublicKey
    $AccountName = $DecodedData.serviceAccountUsername

    # Validate the prefix of the account name
    if (-not $AccountName.StartsWith($AccountNamePrefix)) {
        throw "The account name must start with '$AccountNamePrefix'"
    }

    # Make sure user doesn't try to use the data with a different SDDC
    if ($env:SddcResourceId -and $env:SddcResourceId -ne $SddcResourceId) {
        throw "The SDDC resource ID in the request does not match the current SDDC resource ID"
    }

    if ($SddcResourceId -eq $AvsResourceIdDev -or $SddcResourceId -eq $AvsResourceIdQA)
    {
        $AVS_PUBLIC_KEY_PATH = "$PSScriptRoot/avs_public_key_dev.pem"
    } elseif (-not [string]::IsNullOrEmpty($SddcResourceId)) {
        $AVS_PUBLIC_KEY_PATH = "$PSScriptRoot/avs_public_key_prod.pem"
    } else {
        # Default to local test environment when AVS is not set
        $AVS_PUBLIC_KEY_PATH = "$PSScriptRoot/avs_public_key_test.pem"
    }

    $publicKey = Get-Content $AVS_PUBLIC_KEY_PATH -Raw
    # Validate the signature
    $IsValidSignature = Test-TextSignarure -Text $Data -Signature $Signature -PublicKey $publicKey
    if (-not $IsValidSignature) {
        throw "The data signature is not valid"
    }

    # Make sure the request date is in UTC
    if ($RequestDatetime.Kind -ne [System.DateTimeKind]::Utc) {
        throw "Request datetime must be in UTC"
    }
    # Validate the request datetime is within the time window
    Test-RequestDatetimeInUTC -RequestDatetime $RequestDatetime -TimeWindowInMinutes $TimeWindowInMinutes

    # Generate a random password for the service account
    $AccountPassword = New-RandomPassword

    # If the user already exists, update the password
    $User = Get-SsoPersonUser -Domain 'vsphere.local' | Where-Object { $_.Name -eq $AccountName }
    if ($User) {
        Write-Warning "User $AccountName already exists, updating the password"
        Set-SsoPersonUser -User $User -NewPassword $AccountPassword -ErrorAction Stop
    } else {
        $User = New-SsoPersonUser -UserName $AccountName -Password $AccountPassword -Description "Pure Storage Service Account" -ErrorAction Stop
    }
    # Create Role and assign Role to user
    $Role = Get-VIRole -Name $RoleName -ErrorAction SilentlyContinue
    if ($Role) {
        Write-Warning "Role $RoleName already exists"
    }
    else {
        $Privileges = @()
        foreach ($priv in $PluginPrivileges) {
            Write-Debug "Adding privilege: $priv"
            $Privileges += Get-VIPrivilege -Id $priv
        }

        $Role = New-VIRole -Name $RoleName -Privilege $Privileges
    }

    $Account = Get-VIAccount -Domain $User.Domain | Where-Object { $_.Id -eq $AccountName }
    if (-not $Account) {
        throw "Failed to create account for user $User"
    }

    $RootFolder = Get-Folder -NoRecursion
    if (-not $RootFolder) {
        throw "Failed to retrieve root folder"
    }

    Write-Host "Adding permissions for Account $AccountName on $($RootFolder.Name) with Role $RoleName"
    New-VIPermission -Entity $RootFolder -Principal $Account -Role $Role -Propagate $true

    $vSphereIP = $Account.Server.ServiceUri.Host

    $InitializationData= @{
        "serviceAccountUsername" = $AccountName
        "serviceAccountPassword" = $AccountPassword
        "vSphereIP" = $vSphereIP
    } | ConvertTo-Json

    try {
        $InitializationDataEnc = ConvertTo-EncryptedText -Text $InitializationData -PublicKey $EphemeralPublicKey
    }
    catch {
        throw "Failed to encrypt the initialization data with error: $_"
    }

    $NamedOutputs = @{}
    $NamedOutputs["InitializationDataEnc"] = $InitializationDataEnc
    Set-Variable -Name NamedOutputs -Value $NamedOutputs -Scope Global
}

<#
.SYNOPSIS
Removes a service account and the role assigned to it.

.DESCRIPTION
The Remove-AvsServiceAccount function removes the service account with "psserviceaccount" as the name prefix and an optional suffix in dev enviroment.
It removes the account only when it has the "PureStorageService" role assigned to it.
It also removes the role "PureStorageService" after the removal of the account.

.PARAMETER Suffix
The suffix of the account name which is only needed in dev enviroment and is empty in production.

.EXAMPLE
Remove-AvsServiceAccount -Suffix "1234"

This example tries to remove a service account named "psserviceaccount1234".
It checks if the account has the "PureStorageService" role assigned to it and removes the account and the role if it does.

#>


function Remove-AvsServiceAccount
{
    [CmdletBinding()]
    [AVSAttribute(10, UpdatesSDDC = $false, AutomationOnly = $true)]
    param(
        [Parameter(Mandatory = $false)]
        [string]$Suffix
    )

    $AccountName = $AccountNamePrefix + $Suffix

    $User = Get-SsoPersonUser -Domain 'vsphere.local' | Where-Object { $_.Name -eq $AccountName }
    if ($User) {
        # Get the roles assigned to the user
        $name = "VSPHERE.LOCAL\" + $User.Name
        $accountPermissions = Get-VIPermission -Principal $name
        # Check if the user has the PureStorageService role
        $hasRole = $false
        foreach ($permission in $accountPermissions) {
            if ($permission.Role -eq $RoleName) {
                $hasRole = $true
                break
            }
        }
        if ($hasRole) {
            Write-Host "Removing user $AccountName"
            try {
                Remove-SsoPersonUser -User $User
                # Removes the permission (user and role association)
                Remove-VIPermission -Permission $accountPermissions -Confirm:$false
                Write-Output "Removed user $name from the role $RoleName."
            }
            catch {
                throw "Failed to remove user $AccountName with error: $_"
            }

            $Role = Get-VIRole -Name $RoleName
            if ($Role) {
                # Filter permissions by role name
                $Permissions = Get-VIPermission
                $accountWithRole = $Permissions | Where-Object { $_.Role -eq $RoleName }
                # Remove the PureStorageService role if there is no account assigned to it
                if ($accountWithRole.Count -eq 0) {
                    Write-Host "Removing role $Role "
                    try {
                        Remove-VIRole -Role $Role -Force -Confirm:$false
                    }
                    catch {
                        throw "Failed to remove role $Role with error: $_"
                    }
                } else {
                    Write-Warning "Role $RoleName still has other accounts assigned to it"
                }
            }
            else {
                Write-Warning "Failed to find role $Role"
            }

        } else {
            Write-Warning "This command is only supposed to remove the account with the role $RoleName"
        }
    }
    else {
        Write-Warning "Failed to find user $AccountName"
    }
}

# SIG # Begin signature block
# MIIugwYJKoZIhvcNAQcCoIIudDCCLnACAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDrKjX16VZMa17H
# /qSxw4/6fQ3bwAqcSuwXbn+gWLaSmKCCE2gwggVyMIIDWqADAgECAhB2U/6sdUZI
# k/Xl10pIOk74MA0GCSqGSIb3DQEBDAUAMFMxCzAJBgNVBAYTAkJFMRkwFwYDVQQK
# ExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWduIENvZGUgU2ln
# bmluZyBSb290IFI0NTAeFw0yMDAzMTgwMDAwMDBaFw00NTAzMTgwMDAwMDBaMFMx
# CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQD
# EyBHbG9iYWxTaWduIENvZGUgU2lnbmluZyBSb290IFI0NTCCAiIwDQYJKoZIhvcN
# AQEBBQADggIPADCCAgoCggIBALYtxTDdeuirkD0DcrA6S5kWYbLl/6VnHTcc5X7s
# k4OqhPWjQ5uYRYq4Y1ddmwCIBCXp+GiSS4LYS8lKA/Oof2qPimEnvaFE0P31PyLC
# o0+RjbMFsiiCkV37WYgFC5cGwpj4LKczJO5QOkHM8KCwex1N0qhYOJbp3/kbkbuL
# ECzSx0Mdogl0oYCve+YzCgxZa4689Ktal3t/rlX7hPCA/oRM1+K6vcR1oW+9YRB0
# RLKYB+J0q/9o3GwmPukf5eAEh60w0wyNA3xVuBZwXCR4ICXrZ2eIq7pONJhrcBHe
# OMrUvqHAnOHfHgIB2DvhZ0OEts/8dLcvhKO/ugk3PWdssUVcGWGrQYP1rB3rdw1G
# R3POv72Vle2dK4gQ/vpY6KdX4bPPqFrpByWbEsSegHI9k9yMlN87ROYmgPzSwwPw
# jAzSRdYu54+YnuYE7kJuZ35CFnFi5wT5YMZkobacgSFOK8ZtaJSGxpl0c2cxepHy
# 1Ix5bnymu35Gb03FhRIrz5oiRAiohTfOB2FXBhcSJMDEMXOhmDVXR34QOkXZLaRR
# kJipoAc3xGUaqhxrFnf3p5fsPxkwmW8x++pAsufSxPrJ0PBQdnRZ+o1tFzK++Ol+
# A/Tnh3Wa1EqRLIUDEwIrQoDyiWo2z8hMoM6e+MuNrRan097VmxinxpI68YJj8S4O
# JGTfAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G
# A1UdDgQWBBQfAL9GgAr8eDm3pbRD2VZQu86WOzANBgkqhkiG9w0BAQwFAAOCAgEA
# Xiu6dJc0RF92SChAhJPuAW7pobPWgCXme+S8CZE9D/x2rdfUMCC7j2DQkdYc8pzv
# eBorlDICwSSWUlIC0PPR/PKbOW6Z4R+OQ0F9mh5byV2ahPwm5ofzdHImraQb2T07
# alKgPAkeLx57szO0Rcf3rLGvk2Ctdq64shV464Nq6//bRqsk5e4C+pAfWcAvXda3
# XaRcELdyU/hBTsz6eBolSsr+hWJDYcO0N6qB0vTWOg+9jVl+MEfeK2vnIVAzX9Rn
# m9S4Z588J5kD/4VDjnMSyiDN6GHVsWbcF9Y5bQ/bzyM3oYKJThxrP9agzaoHnT5C
# JqrXDO76R78aUn7RdYHTyYpiF21PiKAhoCY+r23ZYjAf6Zgorm6N1Y5McmaTgI0q
# 41XHYGeQQlZcIlEPs9xOOe5N3dkdeBBUO27Ql28DtR6yI3PGErKaZND8lYUkqP/f
# obDckUCu3wkzq7ndkrfxzJF0O2nrZ5cbkL/nx6BvcbtXv7ePWu16QGoWzYCELS/h
# AtQklEOzFfwMKxv9cW/8y7x1Fzpeg9LJsy8b1ZyNf1T+fn7kVqOHp53hWVKUQY9t
# W76GlZr/GnbdQNJRSnC0HzNjI3c/7CceWeQIh+00gkoPP/6gHcH1Z3NFhnj0qinp
# J4fGGdvGExTDOUmHTaCX4GUT9Z13Vunas1jHOvLAzYIwggbmMIIEzqADAgECAhB3
# vQ4DobcI+FSrBnIQ2QRHMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAkJFMRkw
# FwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWduIENv
# ZGUgU2lnbmluZyBSb290IFI0NTAeFw0yMDA3MjgwMDAwMDBaFw0zMDA3MjgwMDAw
# MDBaMFkxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS8w
# LQYDVQQDEyZHbG9iYWxTaWduIEdDQyBSNDUgQ29kZVNpZ25pbmcgQ0EgMjAyMDCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANZCTfnjT8Yj9GwdgaYw90g9
# z9DljeUgIpYHRDVdBs8PHXBg5iZU+lMjYAKoXwIC947Jbj2peAW9jvVPGSSZfM8R
# Fpsfe2vSo3toZXer2LEsP9NyBjJcW6xQZywlTVYGNvzBYkx9fYYWlZpdVLpQ0LB/
# okQZ6dZubD4Twp8R1F80W1FoMWMK+FvQ3rpZXzGviWg4QD4I6FNnTmO2IY7v3Y2F
# QVWeHLw33JWgxHGnHxulSW4KIFl+iaNYFZcAJWnf3sJqUGVOU/troZ8YHooOX1Re
# veBbz/IMBNLeCKEQJvey83ouwo6WwT/Opdr0WSiMN2WhMZYLjqR2dxVJhGaCJedD
# CndSsZlRQv+hst2c0twY2cGGqUAdQZdihryo/6LHYxcG/WZ6NpQBIIl4H5D0e6lS
# TmpPVAYqgK+ex1BC+mUK4wH0sW6sDqjjgRmoOMieAyiGpHSnR5V+cloqexVqHMRp
# 5rC+QBmZy9J9VU4inBDgoVvDsy56i8Te8UsfjCh5MEV/bBO2PSz/LUqKKuwoDy3K
# 1JyYikptWjYsL9+6y+JBSgh3GIitNWGUEvOkcuvuNp6nUSeRPPeiGsz8h+WX4VGH
# aekizIPAtw9FbAfhQ0/UjErOz2OxtaQQevkNDCiwazT+IWgnb+z4+iaEW3VCzYkm
# eVmda6tjcWKQJQ0IIPH/AgMBAAGjggGuMIIBqjAOBgNVHQ8BAf8EBAMCAYYwEwYD
# VR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU
# 2rONwCSQo2t30wygWd0hZ2R2C3gwHwYDVR0jBBgwFoAUHwC/RoAK/Hg5t6W0Q9lW
# ULvOljswgZMGCCsGAQUFBwEBBIGGMIGDMDkGCCsGAQUFBzABhi1odHRwOi8vb2Nz
# cC5nbG9iYWxzaWduLmNvbS9jb2Rlc2lnbmluZ3Jvb3RyNDUwRgYIKwYBBQUHMAKG
# Omh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2NvZGVzaWduaW5n
# cm9vdHI0NS5jcnQwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2NybC5nbG9iYWxz
# aWduLmNvbS9jb2Rlc2lnbmluZ3Jvb3RyNDUuY3JsMFYGA1UdIARPME0wQQYJKwYB
# BAGgMgEyMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29t
# L3JlcG9zaXRvcnkvMAgGBmeBDAEEATANBgkqhkiG9w0BAQsFAAOCAgEACIhyJsav
# +qxfBsCqjJDa0LLAopf/bhMyFlT9PvQwEZ+PmPmbUt3yohbu2XiVppp8YbgEtfjr
# y/RhETP2ZSW3EUKL2Glux/+VtIFDqX6uv4LWTcwRo4NxahBeGQWn52x/VvSoXMNO
# Ca1Za7j5fqUuuPzeDsKg+7AE1BMbxyepuaotMTvPRkyd60zsvC6c8YejfzhpX0FA
# Z/ZTfepB7449+6nUEThG3zzr9s0ivRPN8OHm5TOgvjzkeNUbzCDyMHOwIhz2hNab
# XAAC4ShSS/8SS0Dq7rAaBgaehObn8NuERvtz2StCtslXNMcWwKbrIbmqDvf+28rr
# vBfLuGfr4z5P26mUhmRVyQkKwNkEcUoRS1pkw7x4eK1MRyZlB5nVzTZgoTNTs/Z7
# KtWJQDxxpav4mVn945uSS90FvQsMeAYrz1PYvRKaWyeGhT+RvuB4gHNU36cdZytq
# tq5NiYAkCFJwUPMB/0SuL5rg4UkI4eFb1zjRngqKnZQnm8qjudviNmrjb7lYYuA2
# eDYB+sGniXomU6Ncu9Ky64rLYwgv/h7zViniNZvY/+mlvW1LWSyJLC9Su7UpkNpD
# R7xy3bzZv4DB3LCrtEsdWDY3ZOub4YUXmimi/eYI0pL/oPh84emn0TCOXyZQK8ei
# 4pd3iu/YTT4m65lAYPM8Zwy2CHIpNVOBNNwwggcEMIIE7KADAgECAgxcuW61kTkv
# +4t8zgQwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEds
# b2JhbFNpZ24gbnYtc2ExLzAtBgNVBAMTJkdsb2JhbFNpZ24gR0NDIFI0NSBDb2Rl
# U2lnbmluZyBDQSAyMDIwMB4XDTI0MDMxMTE0MDQxMloXDTI3MDMxMjE0MDQxMlow
# cjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNVBAcTC1Nh
# bnRhIENsYXJhMRswGQYDVQQKExJQdXJlIFN0b3JhZ2UsIEluYy4xGzAZBgNVBAMT
# ElB1cmUgU3RvcmFnZSwgSW5jLjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAMCQrioSn48IvHpTg5dofsUYj/pNTDidwjYUrcxVu78NoyhSweG8FhcxDi/S
# I40+8Fccl3D5ZoqpjkFnGhzSwmpxU3J4AP7+fdTZht9eWD1I5qKY07esYwdPDV4y
# g+csPfdGPqI2XjRfT5UC3YkXQeUrX8KQZldD4KqvgxzpYcuBwsgHbTb/eArpi68Y
# gFR2jgZGyZigfy8RuJMrL1thcBOe/VWjUyK21wVT8cuunBYFaStLHhsRBRMDcZBD
# uTSGC4evE6oaCqlQbdMl9YFJ64mDQsKlCxrr7rmLVtcVzKGwmjp4b2xRwE+RmTh6
# JtrUL9Wx/3a3UzgAnDNimfwp85zoL48kyLtHqQ3FI8tVKGm+aBOgBZfmURoy7fbp
# 4zKhGgqFbpOmILO16i4f999YsEEJQgIF3CtyH1R60/ZZWlDmoeeEgjAGrnd14muU
# 5Hk3Cksr43uPUAg+fV78Y0fDV85ibm42ZwwPuz6MI4HhYNUlGzRwIQ31vjaGuAMW
# HNqFKkcO0JuIeHQ/gFKPnYIxnGC9H9R4Kw/uMezqtnYJwGU2epB/ABl/w7U4NgU2
# ZOxWB5BFy4frZ3f+hNgbjFUjMaXnVFotOJxXntzjdSl4znw8DaKiC5ooChteZMIT
# G9p078p/TUsOJQbUtFADSY1hsfCfB7t+gJSNt5peS9GOZIMVAgMBAAGjggGxMIIB
# rTAOBgNVHQ8BAf8EBAMCB4AwgZsGCCsGAQUFBwEBBIGOMIGLMEoGCCsGAQUFBzAC
# hj5odHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC9nc2djY3I0NWNv
# ZGVzaWduY2EyMDIwLmNydDA9BggrBgEFBQcwAYYxaHR0cDovL29jc3AuZ2xvYmFs
# c2lnbi5jb20vZ3NnY2NyNDVjb2Rlc2lnbmNhMjAyMDBWBgNVHSAETzBNMEEGCSsG
# AQQBoDIBMjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNv
# bS9yZXBvc2l0b3J5LzAIBgZngQwBBAEwCQYDVR0TBAIwADBFBgNVHR8EPjA8MDqg
# OKA2hjRodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2dzZ2NjcjQ1Y29kZXNpZ25j
# YTIwMjAuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQYMBaAFNqzjcAk
# kKNrd9MMoFndIWdkdgt4MB0GA1UdDgQWBBSzJ9KiDCa3UBiAajy+Iioj5kQjzDAN
# BgkqhkiG9w0BAQsFAAOCAgEAHsFQixeQEcoHurq9NWSUt4S39Q+UGP6crmVq3Wwy
# 9g23YbdWg+SgMxoLUqdoDfA4k4B6Dyoo0jEQzn2kxnsnT9lNHKrcZHH88dv0hjfi
# H2qAiQWazPjS3LhK2J6nhpyipJPpyRaSQG4x4aG0NB2D4WUfUz9CGAYsERJGww/w
# kTaaxMipttKDTaI1C49u1igDfRzIO+Q8vuyyBFLiYTno/df97xtjNC+KxxFhDhl/
# 4tawK6kwxaVzCMAfj48I67Wbo4DMH6pM1s19as7c3qp92i3MylGKsB6+u+o7UkbS
# dLNkS4ALI33CJOUc+GoK3Nt5IXXCFJTQFHBXkBdAur3gmlXEm8vlNG/1Sbxr0H7T
# 1e7ABGH/48o/+PeMLuCc72EeK5dJ4cX9NEQ3QnTsZHwGnYzjEOvOvP0s1c7yNsDb
# cUHoIqQvb5xS5aqMU5G+8sdPQ1nwpPf7gGaEEbAVW4w51Pam42qeN9HIPa+ZinXn
# sN02Kk1Qw0QwUqzaQy9W/gIquI0KOjw0LmoW9M/8S0lrjpEq2eEeUw9WQLhhUEIi
# rFxGPtjqiCLiiS9CZ+kf2vWLJKUspkYv+OHT3q805Zg1dJsBFAzEYUFLb1mhmigD
# EO9bsMorjECIL2ijE5zHtbGkalrrsPWu8tiDT/B7P9GSYzKfOOy4PoOIfWSK0Ixl
# S7IxghpxMIIabQIBATBpMFkxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxT
# aWduIG52LXNhMS8wLQYDVQQDEyZHbG9iYWxTaWduIEdDQyBSNDUgQ29kZVNpZ25p
# bmcgQ0EgMjAyMAIMXLlutZE5L/uLfM4EMA0GCWCGSAFlAwQCAQUAoIGcMBkGCSqG
# SIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3
# AgEVMC8GCSqGSIb3DQEJBDEiBCCTR64+x0BaOUwfCZBG9UZOIIvimSOrJuVczlbx
# Fq47izAwBgorBgEEAYI3AgEMMSIwIKACgAChGoAYaHR0cHM6Ly9wdXJlc3RvcmFn
# ZS5jb20gMA0GCSqGSIb3DQEBAQUABIICACWwOIBQFBYtR4hR+GxU9/aeNGJF8YuX
# qD4302EkzcLWONJKOBqJmaLWq+otPJsw7skW1ram4JmiqsWaIvBzc3AI3E8yMWNA
# ojNaiGZ7i5GMaoqClkI2eYM8327Tq/01Sv2cyB1O2s/Tfrv6Mzx4gqqyifGv5l6F
# cwMiqG3z78fsjAdolSjdGORhcsmtj+UjKHGnXG9NIucytppi2h+il2+a6GArsX/J
# 0fzy26wb7RIZ7iDV863r0MGtEclT1waOwAhksANUlRzA+F9wBPxHfOjPDE2BuQKy
# Hf8/GrM0sEagHVT9C0rmbE95a7lTkySaX5XJ5v//LycklJtqzN++54DM884uyGUy
# TpV5wk83w4TS5n07xKTslhvFtih5JK64gjyffIbZpMtIegRn8sIX4ssUJggFS04j
# qtgF8vOEg0CBGzenjWEeNMZDA5Eh0hUwJyncHsbsN/LL3LTKKX4HbwB0HWcbA67O
# qrBXSfRibu8N6I/wh+yWOOrW4zLv2UZgzsgkoLSWpsVj95BKeGg92DuXffzbpz46
# Xj7H+e7532tGE6DYNQWp4f6hjJUx5CpJv5UMQhcjmO+R/VL+kZiWb1yAW28Cvrr2
# wI22YX19uYUKtZIrbEJPdfSv3XtVeHneGf3MRMYDPnryIXYCqt8QNhL2raoZBEhM
# 8NmA+ASLMpXeoYIXOjCCFzYGCisGAQQBgjcDAwExghcmMIIXIgYJKoZIhvcNAQcC
# oIIXEzCCFw8CAQMxDzANBglghkgBZQMEAgEFADB4BgsqhkiG9w0BCRABBKBpBGcw
# ZQIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIKwOgE0LY2vR1DNKokct
# qbYqV0cynFt6eowwFUUl/9S2AhEAiM2neGgwDgfgJR36dDMXGBgPMjAyNDEyMDMw
# MTA5NThaoIITAzCCBrwwggSkoAMCAQICEAuuZrxaun+Vh8b56QTjMwQwDQYJKoZI
# hvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu
# MTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRp
# bWVTdGFtcGluZyBDQTAeFw0yNDA5MjYwMDAwMDBaFw0zNTExMjUyMzU5NTlaMEIx
# CzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDEgMB4GA1UEAxMXRGlnaUNl
# cnQgVGltZXN0YW1wIDIwMjQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
# AQC+anOf9pUhq5Ywultt5lmjtej9kR8YxIg7apnjpcH9CjAgQxK+CMR0Rne/i+ut
# MeV5bUlYYSuuM4vQngvQepVHVzNLO9RDnEXvPghCaft0djvKKO+hDu6ObS7rJcXa
# /UKvNminKQPTv/1+kBPgHGlP28mgmoCw/xi6FG9+Un1h4eN6zh926SxMe6We2r1Z
# 6VFZj75MU/HNmtsgtFjKfITLutLWUdAoWle+jYZ49+wxGE1/UXjWfISDmHuI5e/6
# +NfQrxGFSKx+rDdNMsePW6FLrphfYtk/FLihp/feun0eV+pIF496OVh4R1TvjQYp
# AztJpVIfdNsEvxHofBf1BWkadc+Up0Th8EifkEEWdX4rA/FE1Q0rqViTbLVZIqi6
# viEk3RIySho1XyHLIAOJfXG5PEppc3XYeBH7xa6VTZ3rOHNeiYnY+V4j1XbJ+Z9d
# I8ZhqcaDHOoj5KGg4YuiYx3eYm33aebsyF6eD9MF5IDbPgjvwmnAalNEeJPvIeoG
# JXaeBQjIK13SlnzODdLtuThALhGtyconcVuPI8AaiCaiJnfdzUcb3dWnqUnjXkRF
# wLtsVAxFvGqsxUA2Jq/WTjbnNjIUzIs3ITVC6VBKAOlb2u29Vwgfta8b2ypi6n2P
# zP0nVepsFk8nlcuWfyZLzBaZ0MucEdeBiXL+nUOGhCjl+QIDAQABo4IBizCCAYcw
# DgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYB
# BQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMB8GA1UdIwQY
# MBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSfVywDdw4oFZBmpWNe
# 7k+SH3agWzBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0Eu
# Y3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au
# ZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0cy5kaWdpY2Vy
# dC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5n
# Q0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQA9rR4fdplb4ziEEkfZQ5H2EdubTggd
# 0ShPz9Pce4FLJl6reNKLkZd5Y/vEIqFWKt4oKcKz7wZmXa5VgW9B76k9NJxUl4Jl
# KwyjUkKhk3aYx7D8vi2mpU1tKlY71AYXB8wTLrQeh83pXnWwwsxc1Mt+FWqz57yF
# q6laICtKjPICYYf/qgxACHTvypGHrC8k1TqCeHk6u4I/VBQC9VK7iSpU5wlWjNlH
# lFFv/M93748YTeoXU/fFa9hWJQkuzG2+B7+bMDvmgF8VlJt1qQcl7YFUMYgZU1WM
# 6nyw23vT6QSgwX5Pq2m0xQ2V6FJHu8z4LXe/371k5QrN9FQBhLLISZi2yemW0P8Z
# Zfx4zvSWzVXpAb9k4Hpvpi6bUe8iK6WonUSV6yPlMwerwJZP/Gtbu3CKldMnn+Lm
# mRTkTXpFIEB06nXZrDwhCGED+8RsWQSIXZpuG4WLFQOhtloDRWGoCwwc6ZpPddOF
# kM2LlTbMcqFSzm4cd0boGhBq7vkqI1uHRz6Fq1IX7TaRQuR+0BGOzISkcqwXu7nM
# pFu3mgrlgbAW+BzikRVQ3K2YHcGkiKjA4gi4OA/kz1YCsdhIBHXqBzR0/Zd2QwQ/
# l4Gxftt/8wY3grcc/nS//TVkej9nmUYu83BDtccHHXKibMs/yXHhDXNkoPIdynhV
# Aku7aRZOwqw6pDCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZI
# hvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
# MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1
# c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzEL
# MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE
# aWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBD
# QTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVccl
# A8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9Q
# Ewsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDW
# VtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0
# UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huo
# wWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZw
# mCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rn
# H1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC
# 3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jz
# RWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEm
# CPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4w
# Er1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/
# AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs
# 1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYI
# KwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
# cC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2lj
# ZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2
# oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290
# RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG
# 9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3i
# Syn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKo
# Fr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9
# jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JE
# rpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOA
# CcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9r
# p/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvE
# lXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2
# uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRi
# CQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlH
# K+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwggWN
# MIIEdaADAgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJ
# BgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
# aWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBD
# QTAeFw0yMjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVT
# MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
# b20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZI
# hvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK
# 2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/G
# nhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJ
# IB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4M
# K7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN
# 2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I
# 11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KIS
# G2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9
# HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4
# pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpy
# FiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS31
# 2amyHeUbAgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs
# 1+OC0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd
# 823IDzAOBgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzAB
# hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9j
# YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQw
# RQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lD
# ZXJ0QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZI
# hvcNAQEMBQADggEBAHCgv0NcVec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4
# hxppVCLtpIh3bb0aFPQTSnovLbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3
# rDB6mouyXtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs
# 9wPHh6jSTEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K
# 2yCNNWAcAgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0n
# ftg62fC2h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggN2MIIDcgIBATB3MGMxCzAJ
# BgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGln
# aUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EC
# EAuuZrxaun+Vh8b56QTjMwQwDQYJYIZIAWUDBAIBBQCggdEwGgYJKoZIhvcNAQkD
# MQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNDEyMDMwMTA5NThaMCsG
# CyqGSIb3DQEJEAIMMRwwGjAYMBYEFNvThe5i29I+e+T2cUhQhyTVhltFMC8GCSqG
# SIb3DQEJBDEiBCB2p2Rr3PZzYYkErjLUjw1E9nV33OulU166qbty4rdrMDA3Bgsq
# hkiG9w0BCRACLzEoMCYwJDAiBCB2dp+o8mMvH0MLOiMwrtZWdf7Xc9sF1mW5BZOY
# Q4+a2zANBgkqhkiG9w0BAQEFAASCAgA/sqpj5A8hJbxbEqUKjat24oxZWGRQfO5o
# ODEGjsWdyBc/1Ti79cG/1zzxEnjNvyGQjp3FsqnOYOlYS7K+C7aOlRLmJI2R0Kfh
# 0X62fY7GSAntHPZhlCTvZnBrGzIdmOZWZWzJAcZh1gtmuPkNlOUzag20LVyNxr1N
# 6QGI8QVSI7CeGbBfI9L8hHWfPFlOKVtbsKpT3bjswZwA50Ely4XXFhSoKGlvOL6k
# CQCK9LifXsCECr4lib/wk8EnAH47AJOcdBrVoPAks6hCvxW0F4xFNaZR//ZLHpRX
# LynUFnKsVmVB7nV5em1llXGTs23vOoT53pyy9GpWYxCzr4SvwC9AQnKTOJdfxP5W
# 6gg1tH0TWzGAfuf8IDzfDkx45bFUQdjnPOhszmAszERisUzEQlXrvT0PBQlH7m5A
# dqm6l7CWgoB8SV+lkl8LejEpmpFOROIdrjkcIbYYczw4Q+QOLrBVLeo+8BOPpSNf
# sFTnpDIcobvoOqYM3/IOeev9UK3U2TkLKc+IE5FHxbMPRmn1qVCE5DoWBGpDcDS4
# jvPb8PSe43aYss5ZB0AO5sZ9BzWjZNMD/KJORvtulw6V+j/pZTDaL+PtT8+y8qMg
# MEAD5+iFB17OB5HGsQITNrwgZD9kDnWEFC+bN/QG1bUUV3zEnxJDtMXUutIIiecn
# +VygFuC2SA==
# SIG # End signature block