SqlVirtualMachine.Autorest/custom/Assert-AzSqlVMEntraAuth.ps1


# ----------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Code generated by Microsoft (R) AutoRest Code Generator.Changes may cause incorrect behavior and will be lost if the code
# is regenerated.
# ----------------------------------------------------------------------------------

<#
.Synopsis
Validates a SQL virtual machine Entra Authentication.
.Description
Validates a SQL virtual machine Entra Authentication.
.Example
{{ Add code here }}
.Example
{{ Add code here }}
 
.Inputs
Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Models.ISqlVirtualMachineIdentity
.Outputs
Boolean
.Notes
COMPLEX PARAMETER PROPERTIES
 
To create the parameters described below, construct a hash table containing the appropriate properties. For information on hash tables, run Get-Help about_Hash_Tables.
 
INPUTOBJECT <ISqlVirtualMachineIdentity>: Identity Parameter
  [AvailabilityGroupListenerName <String>]: Name of the availability group listener.
  [Id <String>]: Resource identity path
  [ResourceGroupName <String>]: Name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal.
  [SqlVirtualMachineGroupName <String>]: Name of the SQL virtual machine group.
  [SqlVirtualMachineName <String>]: Name of the SQL virtual machine.
  [SubscriptionId <String>]: Subscription ID that identifies an Azure subscription.
 
.Link
https://learn.microsoft.com/powershell/module/az.sqlvirtualmachine/Assert-AzSqlVMEntraAuth
#>

function Assert-AzSqlVMEntraAuth {
    [CmdletBinding(DefaultParameterSetName = 'AssertExpanded', PositionalBinding = $false, SupportsShouldProcess, ConfirmImpact = 'Medium')]
    [OutputType([bool])]
    param(
        [Parameter(ParameterSetName = 'AssertExpanded', Mandatory)]
        [Alias('SqlVirtualMachineName', 'SqlVMName')]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Path')]
        [System.String]
        # Name of the SQL virtual machine.
        ${Name},

        [Parameter(ParameterSetName = 'AssertExpanded', Mandatory)]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Path')]
        [System.String]
        # Name of the resource group that contains the resource.
        # You can obtain this value from the Azure Resource Manager API or the portal.
        ${ResourceGroupName},

        [Parameter(ParameterSetName = 'AssertExpanded')]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Path')]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Runtime.DefaultInfo(Script = '(Get-AzContext).Subscription.Id')]
        [System.String]
        # Subscription ID that identifies an Azure subscription.
        ${SubscriptionId},

        [Parameter(ParameterSetName = 'AssertViaIdentity', Mandatory, ValueFromPipeline)]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Path')]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Models.ISqlVirtualMachineIdentity]
        # Identity Parameter
        # To construct, see NOTES section for INPUTOBJECT properties and create a hash table.
        ${InputObject},
    
        [Parameter()]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Body')]
        [System.String]
        # The client Id of the Managed Identity to query Microsoft Graph API.
        ${ManagedIdentityClientId},

        [Parameter(Mandatory)]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Body')]
        [System.String]
        # Type of managed service identity (where both SystemAssigned and UserAssigned types are allowed).
        ${IdentityType},        

        [Parameter()]
        [Alias('AzureRMContext', 'AzureCredential')]
        [ValidateNotNull()]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Azure')]
        [System.Management.Automation.PSObject]
        # The credentials, account, tenant, and subscription used for communication with Azure.
        ${DefaultProfile},

        [Parameter()]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Runtime')]
        [System.Management.Automation.SwitchParameter]
        # Run the command as a job
        ${AsJob},

        [Parameter(DontShow)]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Runtime')]
        [System.Management.Automation.SwitchParameter]
        # Wait for .NET debugger to attach
        ${Break},

        [Parameter(DontShow)]
        [ValidateNotNull()]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Runtime')]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Runtime.SendAsyncStep[]]
        # SendAsync Pipeline Steps to be appended to the front of the pipeline
        ${HttpPipelineAppend},

        [Parameter(DontShow)]
        [ValidateNotNull()]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Runtime')]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Runtime.SendAsyncStep[]]
        # SendAsync Pipeline Steps to be prepended to the front of the pipeline
        ${HttpPipelinePrepend},

        [Parameter()]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Runtime')]
        [System.Management.Automation.SwitchParameter]
        # Run the command asynchronously
        ${NoWait},

        [Parameter(DontShow)]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Runtime')]
        [System.Uri]
        # The URI for the proxy server to use
        ${Proxy},

        [Parameter(DontShow)]
        [ValidateNotNull()]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Runtime')]
        [System.Management.Automation.PSCredential]
        # Credentials for a proxy server to use for the remote call
        ${ProxyCredential},

        [Parameter(DontShow)]
        [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.Category('Runtime')]
        [System.Management.Automation.SwitchParameter]
        # Use the default credentials for the proxy
        ${ProxyUseDefaultCredentials}
    )

    process {
        
        try {
            $hasInputObject = $PSBoundParameters.Remove('InputObject')

            $null = $PSBoundParameters.Remove('ManagedIdentityClientId')
            $null = $PSBoundParameters.Remove('IdentityType')
        
            $hasAsJob = $PSBoundParameters.Remove('AsJob')
            $null = $PSBoundParameters.Remove('WhatIf')
            $null = $PSBoundParameters.Remove('Confirm')

            if ($hasInputObject) {
                $sqlvm = Get-AzSqlVM -InputObject $InputObject @PSBoundParameters
            }
            else {
                $sqlvm = Get-AzSqlVM @PSBoundParameters
            }
            $null = $PSBoundParameters.Remove('InputObject')
            $null = $PSBoundParameters.Remove('ResourceGroupName')
            $null = $PSBoundParameters.Remove('Name')
            $null = $PSBoundParameters.Remove('SubscriptionId')        
        
            if ($hasAsJob) {
                $PSBoundParameters.Add('AsJob', $true)
            }                
        
            $resourceId = $sqlvm.Id
            $subId = ($resourceId -split '/')[2] #subscription id from vm object
            if ($PSCmdlet.ShouldProcess("SQL virtual machine $($sqlvm.Name)", "Assert")) {
                if ($IdentityType -ne 'SystemAssigned' -and $IdentityType -ne 'UserAssigned') {
                    # If the value is neither 'SystemAssigned' nor 'UserAssigned', throw an error
                    throw "IdentityType is invalid. The supported types are SystemAssigned or UserAssigned."
                }
                else { 
                    Assert-All -VmName $sqlvm.Name -ResourceGroup $sqlvm.ResourceGroupName -MsiClientId $ManagedIdentityClientId -IdentityType $IdentityType -SubscriptionId $subId
                    Write-Output $true
                    return
                }
            }
        }
        catch {
            throw
        }
    }
}

<#
    .SYNOPSIS
    Given a VM, check if it's eligible for Azure Entra authentication
     
    .Description
    Given a VM, check if it's eligible for Azure Entra authentication
 
    .PARAMETER VmName
    Name of the VM
 
    .PARAMETER ResourceGroup
    Name of the resource group
 
    .PARAMETER SubscriptionId
    Subscription Id
     
    .PARAMETER MsiClientId
    The client Id of the Managed Identity to query Microsoft Graph API.
     
    .PARAMETER IdentityType
    Type of managed service identity
 
    .OUTPUTS
    bool if the validation passed or not
#>

function Assert-All {    
    [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.DoNotExportAttribute()]
    param(
        [Parameter(Mandatory = $true)]
        [string] $VmName,
        [Parameter(Mandatory = $true)]
        [string] $ResourceGroup,
        [Parameter(Mandatory = $true)]
        [string] $SubscriptionId,
        [Parameter(Mandatory = $false)]
        [string] $MsiClientId,
        [Parameter(Mandatory = $false)]
        [string] $IdentityType)

    # All validations go here
    if ($IdentityType -eq 'SystemAssigned' -and -not($null -eq $MsiClientId -or $MsiClientId -eq '')) {
        Write-Error "Enable Azure Entra authentication with system-assigned managed identity, but the ManagedIdentityClientId is also provided." -ErrorAction Stop
    }
    if ($IdentityType -eq 'UserAssigned' -and ($null -eq $MsiClientId -or $MsiClientId -eq '')) {
        Write-Error "ManagedIdentityClientId should not be empty or null when using UserAssigned type." -ErrorAction Stop
    }

    # validate the SQL VM supports Azure Entra authentication, i.e. it is on Windows platform and is SQL 2022 or later
    $null = Assert-SqlVMversion -ResourceGroupName $ResourceGroup -SqlVirtualMachineName $VmName -SubscriptionId $SubscriptionId
    # validate the MSI is valid on the Azure virtual machine
    $PrincipalId = Assert-MsiValidity -ResourceGroupName $ResourceGroup -SqlVirtualMachineName $VmName -MsiClientId $MsiClientId -SubscriptionId $SubscriptionId
    # validate the MSI has appropriate permission to query Microsoft Graph API
    $null = Assert-MsiWithEnoughPermission -PrincipalId $PrincipalId
    Write-Host "Sql virtual machine $($sqlvm.Name) is valid for Azure Entra authentication."
}

<#
    .SYNOPSIS
    Check if SQL VM version is minimum SQL2022
     
    .Description
    Check if SQL VM version is minimum SQL2022
 
    .PARAMETER SqlVirtualMachineName
    Name of the VM
 
    .PARAMETER ResourceGroupName
    Name of the resource group
 
    .PARAMETER SubscriptionId
    Subscription Id
#>

function Assert-SqlVMversion {
    [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.DoNotExportAttribute()]
    param(
        [Parameter(Mandatory = $true)]
        [string] $SubscriptionId,
        [Parameter(Mandatory = $true)]
        [string] $ResourceGroupName,
        [Parameter(Mandatory = $true)]
        [string] $SqlVirtualMachineName
    )
    try {
    # Get the SQL VM instance
    $vmExtensionName = 'SqlIaasExtension'
    $path = "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Compute/virtualMachines/$SqlVirtualMachineName/extensions/$vmExtensionName" + "?`$expand=instanceView&api-version=2024-03-01"
    $jsonObject = Invoke-AzRestMethod -Method GET -Path $path | Select-Object -ExpandProperty Content | ConvertFrom-Json
    $resourceProviderPluginStatus = $jsonObject.properties.instanceView.substatuses | Where-Object { $_.code -like "*Resource Provider Plugin*"} 

    if ($resourceProviderPluginStatus) {
        $sqlVersion = $resourceProviderPluginStatus | Select-Object @{Name = 'SqlVersion'; Expression = { $_.Message | ConvertFrom-Json | Select-Object -ExpandProperty SqlVersion } }
        $osVersion = $resourceProviderPluginStatus | Select-Object @{Name = 'OSVersion'; Expression = { $_.Message | ConvertFrom-Json | Select-Object -ExpandProperty OSVersion } }
    } else {
        throw "Please make sure the VM is up and running."
    }
}
catch {
    throw "Unable to validate Azure Entra authentication due to an error: $_"
}

# Construct error message for unsupported SQL server version or OS platform.
$unsupportedError = "Azure Entra authentication requires SQL Server 2022 on Windows platform, but the current version of this SQL VM is $($sqlVersion.SqlVersion) - $($osVersion.OSVersion)"
    
if (-not $sqlVersion -or -not $osVersion) {
    throw $unsupportedError
}

try {
    $intVersion = [int]($sqlVersion.SqlVersion.Substring(3))
}
catch {
    throw $unsupportedError
}

if ($intVersion -lt 2022 -or -not $osVersion.OSVersion.StartsWith("WS")) {
    $unsupportedError += "`n Recommendation: Upgrade SQL Server to SQL Server 2022 or later."
    throw $unsupportedError
}
}

<#
    .SYNOPSIS
    Validate the provided MSI is associated with SQL VM or not
     
    .Description
    Validate the provided MSI is associated with SQL VM or not
 
    .PARAMETER SqlVirtualMachineName
    Name of the VM
 
    .PARAMETER ResourceGroupName
    Name of the resource group
     
    .PARAMETER MsiClientId
    Msi Client Id
 
    .PARAMETER SubscriptionId
    Subscription Id
#>

function Assert-MsiValidity {
    [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.DoNotExportAttribute()]
    param(
        [Parameter(Mandatory = $true)]
        [string] $SubscriptionId,
        [Parameter(Mandatory = $true)]
        [string] $ResourceGroupName,
        [Parameter(Mandatory = $true)]
        [string] $SqlVirtualMachineName,
        [Parameter(Mandatory = $false)]
        [string] $MsiClientId
    )

    try {
        # Get the VM instance
        $path = "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Compute/virtualMachines/$SqlVirtualMachineName/" + "?`$expand=instanceView&api-version=2024-03-01"
        $vm = Invoke-AzRestMethod -Method GET -Path $path | Select-Object -ExpandProperty Content | ConvertFrom-Json
    }
    catch {
        throw "Unable to validate Azure Entra authentication due to retrieving the Azure virtual machine instance encountering an error: $_"
    }

    # The system-assigned MSI case.
    if ($IdentityType -eq 'SystemAssigned') {
        if ($null -eq $vm.Identity -or $null -eq $vm.Identity.PrincipalId) {
            $azError = "Enable Azure Entra authentication with system-assigned managed identity, but the system-assigned managed identity is not enabled on this Azure virtual machine."
            $azError += "`n Recommendation: Enable the system-assigned managed identity on the Azure virtual machine: $SqlVirtualMachineName."
            throw $azError
        }

        return $vm.Identity.PrincipalId
    }

    # The user-assigned MSI case.
    if ($IdentityType -eq 'UserAssigned') {
    if ($null -eq $vm.Identity -or $null -eq $vm.Identity.UserAssignedIdentities) {
        $azError = "Enable Azure Entra authentication with user-assigned managed identity '$MsiClientId', but the managed identity is not attached to this Azure virtual machine."
        $azError += "`n Recommendation: Attach the user-assigned managed identity '$MsiClientId' to the Azure virtual machine $SqlVirtualMachineName."
        throw $azError
    }

    foreach ($key in $vm.identity.userAssignedIdentities.PSObject.Properties.Name) {
        $identity = $vm.identity.userAssignedIdentities.$key
        if ($identity.clientId -eq $MsiClientId) {
            return $identity.principalId
        }
    }
    
    $azError = "Enable Azure Entra authentication with user-assigned managed identity '$MsiClientId', but the managed identity is not attached to this Azure virtual machine."
    $azError += "`n Recommendation: Attach the user-assigned managed identity '$MsiClientId' to the Azure virtual machine $SqlVirtualMachineName."
    throw $azError
    }
}

<#
    .SYNOPSIS
    Validate the provided MSI has required permissions or not
     
    .Description
    Validate the provided MSI has required permissions or not
     
    .PARAMETER PrincipalId
    Msi Principal Id
#>

function Assert-MsiWithEnoughPermission {    
    [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.DoNotExportAttribute()]
    param(
        [Parameter(Mandatory = $true)]
        [string] $PrincipalId
    )    
        
    # Get directory roles assigned to the MSI
    $directoryRoles = Get-DirectoryRoleList -PrincipalId $PrincipalId

    # Check if the MSI has the "Directory Readers" role
    if ($directoryRoles.displayName -contains "Directory Readers") {
        return
    }

    # Retrieve app role IDs for required roles
    $appRoleIdMap = Find-RoleId

    # Retrieve all assigned app role IDs for the MSI
    $allAssignedRoleIds = Get-AssignedAppRoleList -PrincipalId $PrincipalId

    # Find missing roles
    $missingRoles = @("User.Read.All", "Application.Read.All", "GroupMember.Read.All") | Where-Object { $appRoleIdMap[$_] -notin $allAssignedRoleIds }

    if ($missingRoles.Count -gt 0) {
        $azError = "The managed identity is lacking the following roles for Azure Entra authentication: $($missingRoles -join ', ')."
        $azError += "`n Recommendation: Grant the managed identity EITHER the Directory.Readers role OR the three App roles 'User.Read.All', 'Application.Read.All', 'GroupMember.Read.All'"
        throw $azError
    }        
}

function Find-RoleId {
    [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.DoNotExportAttribute()]
    param()
    try {
        $graphurl = (Get-AzContext).Environment.ExtendedProperties.MicrosoftGraphUrl
        $uri = $graphurl + "/v1.0/servicePrincipals?" + "`$filter=displayName eq 'Microsoft Graph'"
        $result = Invoke-AzRestMethod -Method GET -Uri $uri | Select-Object -ExpandProperty Content | ConvertFrom-Json
        $servicePrincipals = $result.value

    }
    catch {
        throw "Querying Microsoft Graph API failed to find the service principal of Microsoft Graph Application: $_"
    }

    # If we failed to find the Microsoft Graph service application, fail the validation.
    if (!$servicePrincipals) {
        throw "Querying Microsoft Graph API failed to find the service principal of Microsoft Graph Application"
    }

    $appRoleIdMap = @{
        "User.Read.All"        = $null
        "Application.Read.All" = $null
        "GroupMember.Read.All" = $null
    }

    foreach ($appRole in $servicePrincipals.appRoles) {
        $roleName = $appRole.value
        if ($appRoleIdMap.ContainsKey($roleName)) {
            $appRoleIdMap[$roleName] = $appRole.id
        }
    }

    # If we failed to find all role definitions, fail the validation.
    $missingRoleDefs = $appRoleIdMap.Keys | Where-Object {$null -eq $appRoleIdMap[$_]}

    if ($missingRoleDefs) {
        $errorMessage = "Querying Microsoft Graph API failed to find the following roles: $($missingRoleDefs -join ', ')"
        Write-Warning $errorMessage
        throw $errorMessage
    }

    return $appRoleIdMap
}

function Get-DirectoryRoleList {        
    [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.DoNotExportAttribute()]
    param(
        [Parameter(Mandatory = $true)]
        [string] $PrincipalId
    )
    
    try {
        $graphurl = (Get-AzContext).Environment.ExtendedProperties.MicrosoftGraphUrl
        $uri = $graphurl + "/v1.0/servicePrincipals/$PrincipalId/transitiveMemberOf/microsoft.graph.directoryRole"
        $RoleList = Invoke-AzRestMethod -Method GET -Uri $uri | Select-Object -ExpandProperty Content | ConvertFrom-Json
        return $RoleList.value
    }
    catch {
        throw "Microsoft Graph API Error: $_"
    }
}

function Get-AssignedAppRoleList {        
    [Microsoft.Azure.PowerShell.Cmdlets.SqlVirtualMachine.DoNotExportAttribute()]
    param(
        [Parameter(Mandatory = $true)]
        [string] $PrincipalId
    )
    
    try {
        $graphurl = (Get-AzContext).Environment.ExtendedProperties.MicrosoftGraphUrl
        $uri = $graphurl + "/v1.0/servicePrincipals/$PrincipalId/appRoleAssignments"
        $RoleList = Invoke-AzRestMethod -Method GET -Uri $uri | Select-Object -ExpandProperty Content | ConvertFrom-Json
        return $RoleList.value.AppRoleId
    }
    catch {
        throw "Microsoft Graph API Error: $_"
    }
}
# SIG # Begin signature block
# MIInvwYJKoZIhvcNAQcCoIInsDCCJ6wCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDNQ7Q/60f3qHAI
# GOs1DeBVoyd6J6LnEBav2OgM8iWwg6CCDXYwggX0MIID3KADAgECAhMzAAADrzBA
# 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
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIBeZt1oXGJewaN5R50Ab/R08
# PQdOmacrpQ0v26qlF2YhMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
# BQAEggEAr19jXfhJk2feQGZj2hSu/woPfkjnB+9kG2mYSAqBSuq54CuEKd19NbjD
# PD3528wfLBrmsfLE0QL0Hcyu3+ZaovIe79B8q439qDGfedJ6TO1ObmP7Z7L+Vm65
# 8Qg4nDS7EPrkyGv2nyam514kPASw8XPfkM17tTjBolrpPT8FJRH4/MKXvsEqDHSa
# 6HX9VJY56/uEjkdL6y1JqtnHTxuPM9nN7SiiMwpKz9BmMsUOE0v+WERmAAf1NjVg
# PyGpgUp63zlC7zY1GmxIC6DTY40ipXh5hxaHE8RGGmF62lB5zNmwTp0v5J1g5SOn
# iF8uXttRG/AxjnKpvpEty0VbXaO1RqGCFykwghclBgorBgEEAYI3AwMBMYIXFTCC
# FxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq
# hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCBPFpDL0OwB30ck7NaxzMCiGfDN3w2Z5cHvlDEDM9bAagIGZnLU8zls
# GBMyMDI0MDcwNDA4MzA0OS42OTVaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl
# bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO
# OjNCRDQtNEI4MC02OUMzMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT
# ZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAHlj2rA8z20C6MAAQAAAeUwDQYJ
# KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjMx
# MDEyMTkwNzM1WhcNMjUwMTEwMTkwNzM1WjCB0jELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl
# cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozQkQ0LTRC
# ODAtNjlDMzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKl74Drau2O6LLrJO3HyTvO9
# aXai//eNyP5MLWZrmUGNOJMPwMI08V9zBfRPNcucreIYSyJHjkMIUGmuh0rPV5/2
# +UCLGrN1P77n9fq/mdzXMN1FzqaPHdKElKneJQ8R6cP4dru2Gymmt1rrGcNe800C
# cD6d/Ndoommkd196VqOtjZFA1XWu+GsFBeWHiez/PllqcM/eWntkQMs0lK0zmCfH
# +Bu7i1h+FDRR8F7WzUr/7M3jhVdPpAfq2zYCA8ZVLNgEizY+vFmgx+zDuuU/GChD
# K7klDcCw+/gVoEuSOl5clQsydWQjJJX7Z2yV+1KC6G1JVqpP3dpKPAP/4udNqpR5
# HIeb8Ta1JfjRUzSv3qSje5y9RYT/AjWNYQ7gsezuDWM/8cZ11kco1JvUyOQ8x/JD
# kMFqSRwj1v+mc6LKKlj//dWCG/Hw9ppdlWJX6psDesQuQR7FV7eCqV/lfajoLpPN
# x/9zF1dv8yXBdzmWJPeCie2XaQnrAKDqlG3zXux9tNQmz2L96TdxnIO2OGmYxBAA
# ZAWoKbmtYI+Ciz4CYyO0Fm5Z3T40a5d7KJuftF6CToccc/Up/jpFfQitLfjd71cS
# +cLCeoQ+q0n0IALvV+acbENouSOrjv/QtY4FIjHlI5zdJzJnGskVJ5ozhji0YRsc
# v1WwJFAuyyCMQvLdmPddAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQU3/+fh7tNczEi
# fEXlCQgFOXgMh6owHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD
# VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG
# CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw
# MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD
# CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBADP6whOFjD1ad8Gk
# EJ9oLBuvfjndMyGQ9R4HgBKSlPt3pa0XVLcimrJlDnKGgFBiWwI6XOgw82hdolDi
# MDBLLWRMTJHWVeUY1gU4XB8OOIxBc9/Q83zb1c0RWEupgC48I+b+2x2VNgGJUsQI
# yPR2PiXQhT5PyerMgag9OSodQjFwpNdGirna2rpV23EUwFeO5+3oSX4JeCNZvgyU
# OzKpyMvqVaubo+Glf/psfW5tIcMjZVt0elswfq0qJNQgoYipbaTvv7xmixUJGTbi
# xYifTwAivPcKNdeisZmtts7OHbAM795ZvKLSEqXiRUjDYZyeHyAysMEALbIhdXgH
# Eh60KoZyzlBXz3VxEirE7nhucNwM2tViOlwI7EkeU5hudctnXCG55JuMw/wb7c71
# RKimZA/KXlWpmBvkJkB0BZES8OCGDd+zY/T9BnTp8si36Tql84VfpYe9iHmy7Pqq
# xqMF2Cn4q2a0mEMnpBruDGE/gR9c8SVJ2ntkARy5SfluuJ/MB61yRvT1mUx3lypp
# O22ePjBjnwoEvVxbDjT1jhdMNdevOuDeJGzRLK9HNmTDC+TdZQlj+VMgIm8ZeEIR
# NF0oaviF+QZcUZLWzWbYq6yDok8EZKFiRR5otBoGLvaYFpxBZUE8mnLKuDlYobjr
# xh7lnwrxV/fMy0F9fSo2JxFmtLgtMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ
# 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
# bmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjoz
# QkQ0LTRCODAtNjlDMzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
# dmljZaIjCgEBMAcGBSsOAwIaAxUA942iGuYFrsE4wzWDd85EpM6RiwqggYMwgYCk
# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF
# AOowb6wwIhgPMjAyNDA3MDQwODQ3NDBaGA8yMDI0MDcwNTA4NDc0MFowdDA6Bgor
# BgEEAYRZCgQBMSwwKjAKAgUA6jBvrAIBADAHAgEAAgIDjTAHAgEAAgIS7DAKAgUA
# 6jHBLAIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID
# B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAFjqMfrR+15hqaKa0fQc
# uO46Lx3Vxgba3Lw/q0PL9ul/ubNj7ZveMa2Yt3grNK7G8M1zxOTNgpXclr1Fa2Ej
# +rt0h5/H5VoKEpQivohV5/OjfTufRK0dwDXZqLuIxi9G5jCWSY96KT1ngupUPwds
# 2/zEnKFjqm5OCMazixLERMJ2MYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgUENBIDIwMTACEzMAAAHlj2rA8z20C6MAAQAAAeUwDQYJYIZIAWUDBAIB
# BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx
# IgQgNfM6HADIvDDtC+nTJtQWc0NIBel/eAyRg7eLihkuWrwwgfoGCyqGSIb3DQEJ
# EAIvMYHqMIHnMIHkMIG9BCAVqdP//qjxGFhe2YboEXeb8I/pAof01CwhbxUH9U69
# 7TCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB5Y9q
# wPM9tAujAAEAAAHlMCIEID0JprgRwnDZv31CtiT5RFyADY9xhbnLbSoJaGtO5gOj
# MA0GCSqGSIb3DQEBCwUABIICAFT2itRH8hTq9tRktsML+FR+8Auzr6SuMVZ7YICR
# qbU6LqPcsUmKXBGghmwAMcfzVOBCAvDgBAH0jvKOgI+3qLolYTR4T41Vl0G5Eqrm
# kuOijsKLd+Cz6G3sRuwmBooDaJ6/o9XpyYI7qCMncSvF4/C7fJb3NHCskFRyv/o1
# SXuDbjphXtO8r7wyIBaH6KVmceNepLbXpapIukSBDyVzUgyloWrukIKmvQmwqF4A
# 8uAwlaFdAK5BkPJwd+RjmdDUaWpIMKxeCU7Aaote/6X6RBbTQjwEU6FSe/lA2xfc
# SV+YFYCyV8bvYSitQsws9cext5pScyfUKIPErOUvdRnlxC5sw+fYqr6+YHAO2aH5
# gueI+HlzJWK8anMKtG/IPcnaQeOuEIsLLkSrfV01QUDXK4DXUohJTVNnYZgaf3Y6
# cwKG3JxWYqJfApSG5Lm8sB9a7liHvoUpJZ5xfb/6scK0jRut0+0pHB2f0/UcqF8d
# wdmnASbBcIHTtoFx2mANujdvrHSmujtnW+HjAXEmzAVUDQkFItyLicNAloALYCml
# n4GXCKysQ0vpNC2AXinF+1OvUXjLT5aiyuH+X0U1TXMrS7Ea8PcJyvn9nzG1cuEa
# eH3tCASvOuERR2HiRtMjvPhmnFWcsgnWpXEuUtdFBFGZ46V+MqPTaTOAiC6hxFsW
# KjuM
# SIG # End signature block