modules/AzStack.Ece/AzStack.Ece.psm1

#################################################################
# #
# Copyright (C) Microsoft Corporation. All rights reserved. #
# #
#################################################################

#################################################################
# #
# STARTUP ACTIONS ON IMPORT #
# #
#################################################################

Import-LocalizedData -BindingVariable 'msg' -BaseDirectory "$PSScriptRoot\locale" -UICulture (Get-Culture) -WarningAction SilentlyContinue
Import-Module $PSScriptRoot\..\AzStack.Core\AzStack.Core.psm1 -WarningAction SilentlyContinue
Import-Module $PSScriptRoot\..\AzStack.Common\AzStack.Common.psm1 -WarningAction SilentlyContinue

# import the EceClient module if it is not already imported
if (-not (Get-Module -Name 'EceClient')) {
    Import-Module -Name 'EceClient' -Global -ErrorAction Continue 4> $null 3> $null
}

$configurationData = Import-PowerShellDataFile -Path "$PSScriptRoot\AzStack.Ece.Config.psd1"
New-Variable -Name 'CSSTools_AzStack_ECE' -Scope 'Global' -Force -Value @{
    Config = $configurationData
}

#################################################################
# #
# ENUMS AND CLASSES #
# #
#################################################################


#################################################################
# #
# FUNCTIONS #
# #
#################################################################

function Show-AzsSupportEceData {
    <#
    .SYNOPSIS
        Show ECE data for the current Azure Stack HCI cluster.
    .DESCRIPTION
        This function retrieves and displays information about the ECE deployment, including the deployment status, policy
    .EXAMPLE
        PS> Show-AzsSupportEceData
    .OUTPUTS
        None. This command writes formatted ECE deployment, WDAC policy, and action plan state information to the host.
    #>


    Confirm-AzsSupportOSVersion -MinimumVersion 23H2

    $clusterNodes = Get-ClusterNode
    $policyInfoJob = Start-DiagnosticCheck -ComputerNames $clusterNodes -DiagCheck {
        return @{
            "policyInfo" = Get-ASLocalWDACPolicyInfo
        }
    }

    # in some deployments there is no deployment xml - we will now output this information.
    if (Test-Path -Path $Global:CSSTools_AzStack_ECE.Config.EceStore.Files.Deployment) {
        $deploymentActionPlan = [xml](Get-Content -Raw -Path $Global:CSSTools_AzStack_ECE.Config.EceStore.Files.Deployment)
        $deploymentAction = $deploymentActionPlan.Action
    }
    else {
        $deploymentAction = @{"status" = "Unknown - Deployment file not found. You may not be on the Seed node." }
    }

    $policyInfo = Reconcile-DiagnosticCheck -jobs $policyInfoJob

    # 1. List Deployment information
    Write-Host "====[ $($msg.eceClusterOverview) ]====" -ForegroundColor White -BackgroundColor DarkGray
    Get-StampInformation | Select-Object DeploymentID, *version*, Hardware*, NumberOfNodes
    Write-Host "`n"

    # 2. Check if cluster is deployed
    Write-Host "====[ $($msg.eceClusterDeployment) ]====" -ForegroundColor White -BackgroundColor DarkGray
    if ($deploymentAction.status -eq "Error") {
        Trace-Output -Level:Exception -Message $msg.eceClusterDeploymentFail
    }
    else {
        Trace-Output -Level:Success -Message $msg.eceClusterDeploymentSuccess
    }
    Write-Host "`n"

    # 3. Check policy mode
    Write-Host "====[ $($msg.eceWdacState) ]====" -ForegroundColor White -BackgroundColor DarkGray

    foreach ($info in $policyInfo) {
        Trace-Output -Level:Information -Message ($msg.eceWdacStateNode -f $info.name)
        $info.output.policyInfo | Select-Object PolicyMode, PolicyName, PolicyVersion, Status, PolicyScope, MicrosoftProvided, IsSigned | Format-Table -AutoSize
    }

    # 3. Cluster Action Plan State
    Write-Host "====[ $($msg.eceActionPlanState) ]====" -ForegroundColor White -BackgroundColor DarkGray
    Get-ActionPlanInstances | Select-Object InstanceID, ActionPlanName, ActionTypeName, Status, StartDateTime, EndDateTime | Sort-Object -Property StartDateTime | Select-Object -Last 20 | Format-Table -AutoSize
    Write-Host "`n"
}

function Show-AzsSupportEceDeploymentDetail {
    <#
    .SYNOPSIS
        Show ECE deployment details for the current Azure Stack HCI cluster.
    .DESCRIPTION
        This function retrieves and displays detailed information about the ECE deployment action plan, including all steps and their statuses.
    .EXAMPLE
        PS> Show-AzsSupportEceDeploymentDetail
    #>

    Confirm-AzsSupportOSVersion -MinimumVersion 23H2

    $deploymentActionPlan = [xml](Get-Content -Raw -Path $Global:CSSTools_AzStack_ECE.Config.EceStore.Files.Deployment)
    $deploymentAction = $deploymentActionPlan.Action

    Write-Host "====[ $($msg.eceDeploymentOverview) ]====" -ForegroundColor White -BackgroundColor DarkGray
    Trace-Output -Level:Information -Message ($msg.eceDeploymentStart -f $deploymentAction.StartTimeUtc)
    Trace-Output -Level:Information -Message ($msg.eceDeploymentEnd -f $deploymentAction.EndTimeUtc)
    Trace-Output -Level:Information -Message ($msg.eceDeploymentState -f $deploymentAction.Status)

    # get all steps from the deployment
    Write-Host "====[ $($msg.eceActionplanAnalysis) ]====" -ForegroundColor White -BackgroundColor DarkGray
    Show-EceStep -obj $deploymentAction -showException $true
}

function Show-AzsSupportEceUpdateDetail {
    <#
        .SYNOPSIS
            Show ECE update action plan details for the current Azure Stack HCI cluster.
        .DESCRIPTION
            This function retrieves and displays detailed information about ECE update action plans, including all steps and their statuses. It lists the most recent update action plans and allows the user to select one for detailed viewing.
        .PARAMETER MaxUpdateRuns
            The maximum number of recent update action plans to display for selection. Defaults to 20.
        .EXAMPLE
            PS> Show-AzsSupportEceUpdateDetail
    #>

    [CmdletBinding()]
    param(
        $MaxUpdateRuns = 20
    )

    Confirm-AzsSupportOSVersion -MinimumVersion 23H2

    $actionPlanInstances = Get-ActionPlanInstances | Where-Object { $_.ActionPlanName -like "*MAS Update*" } | Select-Object InstanceID, ActionPlanName, ActionTypeName, Status, StartDateTime, EndDateTime
    if ($actionPlanInstances) {
        $actionPlanInstances | Sort-Object -Property StartDateTime | Select-Object -Last $MaxUpdateRuns | Format-Table -AutoSize

        $actionPlanInstanceID = Read-Host -Prompt $msg.eceUpdateActionPlan
        if (-not [string]::IsNullOrEmpty($actionPlanInstanceID)) {
            $actionPlanObj = Get-ActionPlanInstance -actionPlanInstanceID $actionPlanInstanceID
            $actionPlanXml = [xml]$actionPlanObj.ProgressAsXml
            Show-EceStep -obj $actionPlanXml.Action -showException $true
        }
    }
}

function Show-EceStep {
    param (
        $obj,
        [int]$indentLevel = 0,
        [bool]$showException
    )

    $spaceBuffer = ""
    for ($i = 0; $i -lt $indentLevel; $i++) {
        $spaceBuffer += "|--"
    }
    $spaceBuffer += "->"

    if ($null -ne $obj.Action) {
        # Next move: Action
        foreach ($action in $obj.Action) {
            Show-EceStep -obj $action -indentLevel $indentLevel -showException $showException
        }
    }
    elseif ($null -ne $obj.Steps) {
        Trace-Output -Message ("{0} {1}" -f $spaceBuffer, $obj.Type)

        # Next move: Steps
        foreach ($steps in $obj.Steps) {
            Show-EceStep -obj $steps -indentLevel $indentLevel -showException $showException
        }
    }
    elseif ($null -ne $obj.Step) {
        # Next move: Step
        foreach ($step in $obj.Step) {
            Show-EceStep -obj $step -indentLevel $indentLevel -showException $showException
        }
    }
    elseif ($null -ne $obj.Task) {
        if ($obj.Status -eq "Error") {
            Trace-Output -Level:Error -Message ("{0}[{1}] {2}" -f $spaceBuffer, $obj.FullStepIndex , $obj.Name)
        }
        elseif ($obj.Status -eq "" -or $null -ieq $obj.Status) {
            Trace-Output -Message ("{0}[{1}] {2}" -f $spaceBuffer, $obj.FullStepIndex , $obj.Name)
        }
        else {
            Trace-Output -Message ("{0}[{1}] {2}" -f $spaceBuffer, $obj.FullStepIndex , $obj.Name)
        }

        $indentLevel = $obj.FullStepIndex.Split(".").Length

        # Next move: Task
        foreach ($task in $obj.Task) {
            Show-EceStep -obj $task -indentLevel $indentLevel -showException $showException
        }
    }
    elseif ($null -ne $obj.Exception) {
        if ($showException) {
            # we are in a task which has an exception linked to it.
            Trace-Output -Level:Exception -Message ($obj.Exception.Message)
        }
    }
}

function Get-AzsSupportECECloudDefinitionXml {
    <#
    .SYNOPSIS
        Retrieves the cloud definition from ECE and returns it as an XML object.
    .DESCRIPTION
        This function retrieves the cloud definition from the ECE deployment and returns it as an XML object
    .EXAMPLE
        PS> Get-AzsSupportECECloudDefinitionXml
    #>

    [CmdletBinding()]
    param()

    Confirm-AzsSupportOSVersion -MinimumVersion 23H2

    $cloudDef = Get-CloudDefinition -ErrorAction Stop
    return ([Xml]($cloudDef.CloudDefinitionAsXmlString)).CustomerConfiguration
}

function Invoke-AzsSupportECECustomActionPlan {
    <#
        .SYNOPSIS
            Executes a custom Enterprise Cloud Engine (ECE) action plan that are included as part of the Azs.Support module
        .PARAMETER Name
            The name of the action plan that should be executed via Enterprise Cloud Engine (ECE). This only looks at ECE action plans packaged within the Azs.Support module.
        .PARAMETER FilePath
            The full path to a custom ECE action plan xml file.
        .PARAMETER WaitForResult
            Waits for the cmdlet operation to complete
    #>


    [CmdletBinding(DefaultParameterSetName = 'Name')]
    param (
        [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
        [ArgumentCompleter({
            $possibleValues = Get-ChildItem -Path "$PSScriptRoot\ActionXml" | Select-Object -ExpandProperty BaseName
            return $possibleValues | ForEach-Object { $_ }
        })]
        [System.String]$Name,

        [Parameter(Mandatory = $true, ParameterSetName = 'FilePath')]
        [ValidateScript({
            if($_ -notmatch "(\.xml)"){
                throw "The leaf name specified must be a .xml file type"
            }
            return $true
        })]
        [System.IO.FileInfo]$FilePath,

        [Parameter(Mandatory = $false, ParameterSetName = 'Name')]
        [Parameter(Mandatory = $false, ParameterSetName = 'FilePath')]
        [Switch]$WaitForResult
    )

    Confirm-AzsSupportOSVersion -MinimumVersion 23H2

    try {
        switch($PSCmdlet.ParameterSetName) {
            'Name' {
                $eceActionPlanXML = Get-ChildItem -Path "$PSScriptRoot\ActionXml" | Where-Object {$_.BaseName -ieq $Name} -ErrorAction Stop
            }
            'FilePath' {
                $eceActionPlanXML = Get-Item -Path $FilePath.FullName -ErrorAction Continue
            }
            default {
                throw New-Object System.Exception("Invalid ParameterSetName")
            }
        }

        if ($eceActionPlanXML) {
            # get the description of the ECE action plan
            [xml]$content = Get-Content -Path $eceActionPlanXML.FullName
            $content.Action.Description | Trace-Output

            # invoke the ECE action plan
            Invoke-ActionPlanInstance -ActionPlanPath $eceActionPlanXML.FullName -WaitForResult:($WaitForResult)
        }
    }
    catch {
        $_ | Trace-Exception
        $_ | Write-Error
    }
}

function Get-AzsSupportEceDeploymentDetails {
    # TODO: Deprecated function - remove in 2026.04 release
    # has been replaced with Show-AzsSupportEceDeploymentDetail to align with PowerShell naming conventions
    $msg.AzsSupportEceDeploymentDetailsDeprecated | Write-Information -InformationAction Continue
}

function Get-AzsSupportLcmDeploymentUserName {

    <#
    .SYNOPSIS
        Retrieves the username of the Local Configuration Manager (LCM) deployment account for the Azure Local cluster.
    .DESCRIPTION
        This function retrieves the username of the Local Configuration Manager (LCM) deployment account for the Azure Local cluster by parsing the ECE cloud definition XML.
    .EXAMPLE
        PS> Get-AzsSupportLcmDeploymentUserName
    #>


    [CmdletBinding()]
    param()

    # Retrieve the latest ECEWinService NuGet Version
    $eceWinService = Get-ChildItem "C:\Agents" -Directory | 
        Where-Object { $_.Name -match 'Microsoft\.AzureStack\.Solution\.ECEWinService\.(\d+\.\d+\.\d+\.\d+)' } |
        ForEach-Object {
            [PSCustomObject]@{
                Path = $_.FullName
                Version = [version]$matches[1]
            }
        } | Sort-Object Version -Descending | Select-Object -First 1

    $eceWinServicePath = $eceWinService.Path

    # Load Assemblies
    $null = [System.Reflection.Assembly]::LoadFile("$eceWinServicePath\content\ECEWinService\CloudEngine.dll")
    $null = [System.Reflection.Assembly]::LoadFile("$eceWinServicePath\content\ECEWinService\Microsoft.AzureStack.Orchestration.Common.Packaging.Contract.dll")
    $null = [System.Reflection.Assembly]::LoadFile("$eceWinServicePath\content\ECEWinService\Microsoft.AzureStack.Orchestration.Common.Packaging.dll")
    $null = [System.Reflection.Assembly]::LoadFile("$eceWinServicePath\content\ECEWinService\Microsoft.Diagnostics.Tracing.EventSource.dll") 

    # Load MetricTelemetry.dll if it exists, otherwise fallback to Telemetry.dll
    $metricTelemetryPath = "$eceWinServicePath\content\ECEWinService\Microsoft.AzureStack.Solution.MetricTelemetry.dll"
    $telemetryPath = "$eceWinServicePath\content\ECEWinService\Microsoft.AzureStack.Solution.Telemetry.dll"

    if (Test-Path -Path $metricTelemetryPath) {
        $null = [System.Reflection.Assembly]::LoadFile($metricTelemetryPath)
    } 
    elseif (Test-Path -Path $telemetryPath) {
        $null = [System.Reflection.Assembly]::LoadFile($telemetryPath)
    } 
    else {
        throw New-Object System.ArgumentNullException("Unable to load MetricTelemetry.dll or Telemetry.dll")
    }

    # retrieve LCM User Username
    $cloudDefinitionAsXmlString = (Get-CloudDefinition -EceClient $eceClient).CloudDefinitionAsXmlString
    $cloudDefElements = [System.Xml.Linq.XElement]::Parse($cloudDefinitionAsXmlString)
    
    $customerConfigurationObject = New-Object -TypeName 'CloudEngine.Configurations.CustomerConfiguration' -ArgumentList $cloudDefElements
    $cloudRoleObject = [CloudEngine.Configurations.ConfigurationPathExtensions]::Find($customerConfigurationObject, 'Cloud')
    [CloudEngine.Configurations.IInterface] $interface = $cloudRoleObject.Interface('Build')
    $eceParams = $interface.GetInterfaceParameters()
    
    $securityInfo = $ECEParams.Roles["Cloud"].PublicConfiguration.PublicInfo.SecurityInfo
    $DAdmin = $securityInfo.DomainUsers.User | Where-Object { $_.Role -eq "DomainAdmin" }
    
    return $($DAdmin.Credential.Credential.UserName)
}

function Get-AzsSupportEceInfrastructure {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [string]$Id
    )
    $cloudDefXml = Get-AzsSupportECECloudDefinitionXml

    if ($Id) {
        return ($cloudDefXml.Role.Roles.Role | Where-Object { $_.Id -eq "Infrastructure" }).Roles.Role | Where-Object { $_.Id -eq $Id }
    }

    return ($cloudDefXml.Role.Roles.Role | Where-Object { $_.Id -eq "Infrastructure" }).Roles.Role
}

function Get-AzsSupportEceFabric {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [string]$Id
    )

    $cloudDefXml = Get-AzsSupportECECloudDefinitionXml

    if ($Id) {
        return ($cloudDefXml.Role.Roles.Role | Where-Object { $_.Id -eq "Fabric" }).Roles.Role | Where-Object { $_.Id -eq $Id }
    }

    return ($cloudDefXml.Role.Roles.Role | Where-Object { $_.Id -eq "Fabric" }).Roles.Role
}

function Get-AzsSupportEceManagementClusterName {
    [CmdletBinding()]
    param ()

    $cluster = Get-AzsSupportEceInfrastructure -Id 'Cluster'
    $clusterName = $cluster.Clusters.Node | Where-Object {$_.IsManagementCluster -ieq $true} | Select-Object -ExpandProperty Name
    return $clusterName
}
# SIG # Begin signature block
# MIIoUgYJKoZIhvcNAQcCoIIoQzCCKD8CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCM3p5anUW7HvcT
# 6+kf1KXUnsE1hKGpJeKtI+Y/1T/Ss6CCDYUwggYDMIID66ADAgECAhMzAAAEhJji
# EuB4ozFdAAAAAASEMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM1WhcNMjYwNjE3MTgyMTM1WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDtekqMKDnzfsyc1T1QpHfFtr+rkir8ldzLPKmMXbRDouVXAsvBfd6E82tPj4Yz
# aSluGDQoX3NpMKooKeVFjjNRq37yyT/h1QTLMB8dpmsZ/70UM+U/sYxvt1PWWxLj
# MNIXqzB8PjG6i7H2YFgk4YOhfGSekvnzW13dLAtfjD0wiwREPvCNlilRz7XoFde5
# KO01eFiWeteh48qUOqUaAkIznC4XB3sFd1LWUmupXHK05QfJSmnei9qZJBYTt8Zh
# ArGDh7nQn+Y1jOA3oBiCUJ4n1CMaWdDhrgdMuu026oWAbfC3prqkUn8LWp28H+2S
# LetNG5KQZZwvy3Zcn7+PQGl5AgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUBN/0b6Fh6nMdE4FAxYG9kWCpbYUw
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwNTM2MjAfBgNVHSMEGDAW
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
# AGLQps1XU4RTcoDIDLP6QG3NnRE3p/WSMp61Cs8Z+JUv3xJWGtBzYmCINmHVFv6i
# 8pYF/e79FNK6P1oKjduxqHSicBdg8Mj0k8kDFA/0eU26bPBRQUIaiWrhsDOrXWdL
# m7Zmu516oQoUWcINs4jBfjDEVV4bmgQYfe+4/MUJwQJ9h6mfE+kcCP4HlP4ChIQB
# UHoSymakcTBvZw+Qst7sbdt5KnQKkSEN01CzPG1awClCI6zLKf/vKIwnqHw/+Wvc
# Ar7gwKlWNmLwTNi807r9rWsXQep1Q8YMkIuGmZ0a1qCd3GuOkSRznz2/0ojeZVYh
# ZyohCQi1Bs+xfRkv/fy0HfV3mNyO22dFUvHzBZgqE5FbGjmUnrSr1x8lCrK+s4A+
# bOGp2IejOphWoZEPGOco/HEznZ5Lk6w6W+E2Jy3PHoFE0Y8TtkSE4/80Y2lBJhLj
# 27d8ueJ8IdQhSpL/WzTjjnuYH7Dx5o9pWdIGSaFNYuSqOYxrVW7N4AEQVRDZeqDc
# fqPG3O6r5SNsxXbd71DCIQURtUKss53ON+vrlV0rjiKBIdwvMNLQ9zK0jy77owDy
# XXoYkQxakN2uFIBO1UNAvCYXjs4rw3SRmBX9qiZ5ENxcn/pLMkiyb68QdwHUXz+1
# fI6ea3/jjpNPz6Dlc/RMcXIWeMMkhup/XEbwu73U+uz/MIIHejCCBWKgAwIBAgIK
# YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
# aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
# OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
# VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
# UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
# 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
# dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
# lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
# kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
# A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
# X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
# 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
# sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
# T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
# 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
# bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
# uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
# cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
# YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
# 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
# v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
# pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
# KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
# CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
# mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
# hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
# BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
# oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
# gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
# cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGiMwghofAgEBMIGVMH4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAASEmOIS4HijMV0AAAAA
# BIQwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFAX
# HaPy8lx8EeBbbDP9Ks2fPxgylLJb/ULZAYewLTaSMEIGCisGAQQBgjcCAQwxNDAy
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20wDQYJKoZIhvcNAQEBBQAEggEAzuXqf2bhkrHuXTPuP8nsE2QM1SR9Z+NLywt+
# V7fizXRCPvpsZOOmChCwyGt57m1hLaBxwEyGic/mt4s10aPkrttjBQcOaOTF8M5R
# +y7j7O6zqMXclWGImr0VScdFcNBlN9FnSqetmTtrae49MDwKQ8ZC4zNQdBEnUGiw
# vgsAIv7p8s96T/dsA/nzRw54nBygKUkGIhXWJqMxIoNihny/rRGAhnG15lO1272M
# yJe4NWrg9ueknGfE2IrNnXO0Z9Y31ae7mDQmMtXxOK3LGM46DIJuEgb5ulL0OvL9
# i7MuvC6plr5eTgK+4tCVES0aynOJ+wNp27kvtQj1kW1Gn5ATKqGCF60wghepBgor
# BgEEAYI3AwMBMYIXmTCCF5UGCSqGSIb3DQEHAqCCF4YwgheCAgEDMQ8wDQYJYIZI
# AWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGE
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCDTtk85nmwCu4NvjOyCNfpYBO9HxbrjLY4E
# Ds0we6KEwQIGaZhfcVr/GBMyMDI2MDIyNDE4NDcxNi40NTFaMASAAgH0oIHZpIHW
# MIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL
# EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsT
# Hm5TaGllbGQgVFNTIEVTTjo1OTFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z
# b2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEfswggcoMIIFEKADAgECAhMzAAACFI3N
# I0TuBt9yAAEAAAIUMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgxOFoXDTI2MTExMzE4NDgxOFowgdMxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jv
# c29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVs
# ZCBUU1MgRVNOOjU5MUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt
# ZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
# yU+nWgCUyvfyGP1zTFkLkdgOutXcVteP/0CeXfrF/66chKl4/MZDCQ6E8Ur4kqgC
# xQvef7Lg1gfso1EWWKG6vix1VxtvO1kPGK4PZKmOeoeL68F6+Mw2ERPy4BL2vJKf
# 6Lo5Z7X0xkRjtcvfM9T0HDgfHUW6z1CbgQiqrExs2NH27rWpUkyTYrMG6TXy39+G
# dMOTgXyUDiRGVHAy3EqYNw3zSWusn0zedl6a/1DbnXIcvn9FaHzd/96EPNBOCd2v
# OpS0Ck7kgkjVxwOptsWa8I+m+DA43cwlErPaId84GbdGzo3VoO7YhCmQIoRab0d8
# or5Pmyg+VMl8jeoN9SeUxVZpBI/cQ4TXXKlLDkfbzzSQriViQGJGJLtKS3DTVNuB
# qpjXLdu2p2Yq9ODPqZCoiNBh4CB6X2iLYUSO8tmbUVLMMEegbvHSLXQR88QNICjF
# oBBDCDydoTo9/TNkq80mO77wDM04tPdvbMmxT01GTod60JJxUGmMTgseghdBGjkN
# +D6GsUpY7ta7hP9PzLrs+Alxu46XT217bBn6EwJsAYAc9C28mKRUcoIZWQRb+Mco
# ZaSu2EcSzuIlAaNIQNtGlz2PF3foSeGmc/V7gCGs8AHkiKwXzJSPftnsH8O/R3pJ
# w2D/2hHE3JzxH2SrLX1FdI7Drw145PkL0hbFL6MVCCkCAwEAAaOCAUkwggFFMB0G
# A1UdDgQWBBTbX/bs1cSpyTYnYuf/Mt9CPNhwGzAfBgNVHSMEGDAWgBSfpxVdAF5i
# XYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENB
# JTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRp
# bWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1Ud
# JQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsF
# AAOCAgEAP3xp9D4Gu0SH9B+1JH0hswFquINaTT+RjpfEr8UmUOeDl4U5uV+i28/e
# SYXMxgem3yBZywYDyvf4qMXUvbDcllNqRyL2Rv8jSu8wclt/VS1+c5cVCJfM+WHv
# kUr+dCfUlOy9n4exCPX1L6uWwFH5eoFfqPEp3Fw30irMN2SonHBK3mB8vDj3D80o
# JKqe2tatO38yMTiREdC2HD7eVIUWL7d54UtoYxzwkJN1t7gEEGosgBpdmwKVYYDO
# 1USWSNmZELglYA4LoVoGDuWbN7mD8VozYBsfkZarOyrJYlF/UCDZLB8XaLfrMfMy
# ZTMCOuEuPD4zj8jy/Jt40clrIW04cvLhkhkydBzcrmC2HxeE36gJsh+jzmivS9Yv
# yiPhLkom1FP0DIFr4VlqyXHKagrtnqSF8QyEpqtQS7wS7ZzZF0eZe0fsYD0J1Rar
# bVuDxmWsq45n1vjRdontuGUdmrG2OGeKd8AtiNghfnabVBbgpYgcx/eLyW/n40eT
# bKIlsm0cseyuWvYFyOqQXjoWtL4/sUHxlWIsrjnNarNr+POkL8C1jGBCJuvm0UYg
# jhIaL+XBXavrbOtX9mrZ3y8GQDxWXn3mhqM21ZcGk83xSRqB9ecfGYNRG6g65v63
# 5gSzUmBKZWWcDNzwAoxsgEjTFXz6ahfyrBLqshrjJXPKfO+9Ar8wggdxMIIFWaAD
# AgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD
# VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
# MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv
# ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIy
# MjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw
# MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5
# vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64
# NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhu
# je3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl
# 3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPg
# yY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I
# 5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2
# ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/
# TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy
# 16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y
# 1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6H
# XtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMB
# AAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQW
# BBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30B
# ATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz
# L0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYB
# BAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMB
# Af8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBL
# oEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv
# TWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggr
# BgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNS
# b29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1Vffwq
# reEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27
# DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pv
# vinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9Ak
# vUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWK
# NsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2
# kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+
# c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep
# 8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+Dvk
# txW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1Zyvg
# DbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/
# 2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDVjCCAj4CAQEwggEBoYHZpIHW
# MIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL
# EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsT
# Hm5TaGllbGQgVFNTIEVTTjo1OTFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z
# b2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUA2RysX196RXLT
# wA/P8RFWdUTpUsaggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx
# MDANBgkqhkiG9w0BAQsFAAIFAO1II7swIhgPMjAyNjAyMjQxMzE4NTFaGA8yMDI2
# MDIyNTEzMTg1MVowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA7UgjuwIBADAHAgEA
# AgIONzAHAgEAAgIavjAKAgUA7Ul1OwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgor
# BgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUA
# A4IBAQAhdvcdefwmb0FUJOZYjbbCgQSRoiPRS/D3FHffhMX31I2FKxCxeBfjC8Zo
# W7T4jSs7KvZ7AMqfphmTALTBy/cK3j4fteqfJyQ85D8EzDGyyN/y86mC8gYLumYR
# EOhRFPjmSdGw30881lDq/ge5OX3w/MESn2qNs5jttEC9554n//RAddwo9N1WJ7r1
# 0cVY9PNeyArYiHBC3kFCp97e0scAzPqe6DURflKHazNahty2RDZEPSVU8akF+UY5
# IJlIoUR+AQyQd3aREoPVPzk+2f4PjjJzQSChSdWDESymvp+DTsKWcdcJPhAC/BcA
# TJdfEU1aNThC/Lh/8bySp+C5BiIQMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgUENBIDIwMTACEzMAAAIUjc0jRO4G33IAAQAAAhQwDQYJYIZIAWUD
# BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B
# CQQxIgQgwF/OhUPRPY6yog+jjYomKBMGlvONTNdH0ZGgKmSGAacwgfoGCyqGSIb3
# DQEJEAIvMYHqMIHnMIHkMIG9BCA2eKvvWx5bcoi43bRO3+EttQUCvyeD2dbXy/6+
# 0xK+xzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAC
# FI3NI0TuBt9yAAEAAAIUMCIEIPxEpLm6zShifuv+NKTaYggROsDzdrpUbYfDKrwi
# aDfJMA0GCSqGSIb3DQEBCwUABIICAI93yQ5m6cmxJXlfZkMXUne20sbu3Lbc3O0p
# CcrCThC7UTPZwU8aIAbfwxciZ1zEg2CMDJMJXZaNJagzg63YRrZfwqNX78RAYdqZ
# 8NF0q7WIlU0qQVufJrSefwweC8EsOl4rA5CUWGZyP+gBXplMGCittTm2yL3Q+ncT
# u3wK+eBTwNvO/j/vYrNNYN3peI2SBChCuO7DGysHA+N0mVeO3y/AwTwEdfNhksAF
# 6nvxKxfEAmGAJkCAJzf8O1O9ryaYuRwN/DdLQaYLeY3bPwomrL6MzX+/gZy3+Ew1
# b2ZZ/8CuL9n9aM7kaYnl9vBt8BALIRX8fSNJUnp1o0R2VLPunA0+X2jP2kxwWFNc
# xgjPCVq7r1vUUJf9h2p6/b6L1U62vF0U/cZNFULblSOJRrlArQ44bk4ph+5WuE+6
# 76YGRki4GAeYUdJ8PZwfZAaZ+WDAM7yH3nWIS92wTjqcyuGWTWbObDHegjofQ9g7
# LolrlHZLE8Fm8SeTeJtv9mv9oEUmgwZ4GEJpybSHA9EmZbMpTbRo2+gFbk4x/3h9
# 4xgN7PIj82eZdQRGHpCENf/nXto69szreBRa3nbyLUjZ6xu1jSrDnWHkJ4SORRQH
# yDu/pvGlw8nEgae7npYLNSV11SsNVaKjo0PDAIwQJfJo4BzdKCRkgLkLgWdHvQ05
# tTxTQ1UW
# SIG # End signature block