AzStackHciRemoteSupport/AzStackHCI.RemoteSupport.Helpers.psm1

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

Import-LocalizedData -BindingVariable lvsTxt -FileName AzStackHCI.RemoteSupport.Strings.psd1

function Invoke-InstallModule
{
    param (
        [Parameter(Mandatory=$true)]
        [string]
        $ModuleName
    )

    try
    {
        $module = Get-Module -Name $ModuleName -ListAvailable | Sort-Object -Property Version -Descending | Microsoft.PowerShell.Utility\Select-Object "Name", "Version"

        if([string]::IsNullOrWhiteSpace($module))
        {
            Trace-Execution "Installing $ModuleName module..."
            Install-Module $ModuleName -Force -AllowClobber | Out-Null
        }
        else
        {
            Trace-Execution "$ModuleName module already exists $($module.Name) $($module.Version)"
        }
    }
    catch
    {
        $exception = $_
        Trace-Execution "Install module failed. $exception"
        Trace-Execution "$($exception.ScriptStackTrace)"
        throw $exception
    }
}

function Install-AzStackHciRemoteSupport
{
    param (
    )

    try
    {
        $OperationType = $MyInvocation.MyCommand

        # Install Az.StackHCI module if doesn't exist
        Invoke-InstallModule -ModuleName "Az.StackHCI"

        # Install Remote Support
        Az.StackHCI\Install-AzStackHCIRemoteSupport
    }
    catch
    {
        $exception = $_
        Trace-Execution "Install-AzStackHciRemoteSupport failed. $exception"
        Trace-Execution "$($exception.ScriptStackTrace)"
        throw $exception
    }
}


function Enable-AzStackHciRemoteSupport
{
    param (
        [Parameter(Mandatory=$true)]
        [ValidateSet("Diagnostics","DiagnosticsRepair")]
        [string]
        $AccessLevel,

        [Parameter(Mandatory=$false)]
        [int]
        $ExpireInMinutes = 480,

        [Parameter(Mandatory=$false)]
        [string]
        $SasCredential,

        [Parameter(Mandatory=$false)]
        [switch]
        $AgreeToRemoteSupportConsent
    )

    try
    {
        $OperationType = $MyInvocation.MyCommand

        # Install Az.StackHCI module if doesn't exist
        Invoke-InstallModule -ModuleName "Az.StackHCI"

        # Install Remote Support
        Az.StackHCI\Install-AzStackHCIRemoteSupport

        # Enable Remote Support
        $cmdResult = Az.StackHCI\Enable-AzStackHCIRemoteSupport -AccessLevel $AccessLevel -ExpireInMinutes $ExpireInMinutes -SasCredential $SasCredential -AgreeToRemoteSupportConsent:$AgreeToRemoteSupportConsent

        # Build Result
        $now = [datetime]::UtcNow
        $targetComputerName = $ENV:COMPUTERNAME

        $aggregateStatus = if( -not ([string]::IsNullOrWhiteSpace($cmdResult)) -and $cmdResult.State -eq "Active" -and $cmdResult.ConnectionStatus -eq "Connected" -or "Connecting") {'SUCCESS'} else {'FAILURE'}

        $params = @{
            Name               = 'AzStackHci_Enable_RemoteSupport'
            Title              = 'Standalone Remote Support: Enable'
            DisplayName        = 'Standalone Remote Support: Enable'
            Severity           = 'INFORMATIONAL'
            Description        = 'Test to check observability RemoteSupport requirement is met'
            Tags               = @{
                'OperationType' = $OperationType
            }
            Remediation        = ''
            TargetResourceID   = $targetComputerName
            TargetResourceName = $targetComputerName
            TargetResourceType = 'RemoteSupportEndpoint'
            Timestamp          = [datetime]::UtcNow
            Status             = $cmdResult.State
            AdditionalData     = @{
                State = $cmdResult.State
                CreatedAt = $cmdResult.CreatedAt
                UpdatedAt = $cmdResult.UpdatedAt
                ConnectionStatus = $cmdResult.ConnectionStatus
                ConnectionErrorMessage = $cmdResult.ConnectionErrorMessage
                TargetService = $cmdResult.TargetService
                AccessLevel = $cmdResult.AccessLevel
                ExpiresAt = $cmdResult.ExpiresAt
            }
            HealthCheckSource  = $ENV:EnvChkrId
        }
        $enableResult = New-AzStackHciResultObject @params
        return $enableResult
    }
    catch
    {
        $exception = $_
        Trace-Execution "Enable-AzStackHciRemoteSupport failed. $exception"
        Trace-Execution "$($exception.ScriptStackTrace)"
        throw $exception
    }
}

function Get-AzStackHCIRemoteSupportAccess
{
    Param(
        [Parameter(Mandatory=$false)]
        [switch]
        $Cluster,

        [Parameter(Mandatory=$false)]
        [switch]
        $IncludeExpired
    )

    try
    {
        $OperationType = $MyInvocation.MyCommand

        # Install Az.StackHCI module if doesn't exist
        Invoke-InstallModule -ModuleName "Az.StackHCI"

        # Get Remote Support access
        $cmdResult = Az.StackHCI\Get-AzStackHCIRemoteSupportAccess -Cluster:$Cluster -IncludeExpired:$IncludeExpired

        # Build Result
        $now = [datetime]::UtcNow
        $targetComputerName = $ENV:COMPUTERNAME
        $cmdResultEmpty = [string]::IsNullOrWhiteSpace($cmdResult)

        if($cmdResultEmpty)
        {
            $aggregateStatus = 'SUCCESS'
        }
        else{
            $aggregateStatus = if( -not $cmdResultEmpty -and $cmdResult.State -eq "Active" -and $cmdResult.ConnectionStatus -eq "Connected" -or "Connecting") {'SUCCESS'} else {'FAILURE'}
        }

        $params = @{
            Name               = 'AzStackHci_Get_RemoteSupportAccess'
            Title              = 'Standalone Remote Support: Get Access'
            DisplayName        = 'Standalone Remote Support: Get Access'
            Severity           = 'INFORMATIONAL'
            Description        = 'Get AzStackHCI Remote Support Access'
            Tags               = @{
                'OperationType' = $OperationType
            }
            Remediation        = ''
            TargetResourceID   = $targetComputerName
            TargetResourceName = $targetComputerName
            TargetResourceType = 'RemoteSupportEndpoint'
            Timestamp          = [datetime]::UtcNow
            Status             = $aggregateStatus
            AdditionalData     = @{
                State = if(-not $cmdResultEmpty) {$cmdResult.State} else {''}
                CreatedAt = if(-not $cmdResultEmpty) {$cmdResult.CreatedAt} else {''}
                UpdatedAt = if(-not $cmdResultEmpty) {$cmdResult.UpdatedAt} else {''}
                ConnectionStatus = if(-not $cmdResultEmpty) {$cmdResult.ConnectionStatus} else {''}
                ConnectionErrorMessage = if(-not $cmdResultEmpty) {$cmdResult.ConnectionErrorMessage} else{''}
                TargetService = if(-not $cmdResultEmpty) {$cmdResult.TargetService} else {''}
                AccessLevel = if(-not $cmdResultEmpty) {$cmdResult.AccessLevel} else {''}
                ExpiresAt = if(-not $cmdResultEmpty) {$cmdResult.ExpiresAt} else {''}
            }
            HealthCheckSource  = $ENV:EnvChkrId
        }
        $GetAccessResult = New-AzStackHciResultObject @params
        return $getAccessResult
    }
    catch
    {
        $exception = $_
        Trace-Execution "Get-AzStackHCIRemoteSupportAccess failed. $exception"
        Trace-Execution "$($exception.ScriptStackTrace)"
        throw $exception
    }
}

function Get-AzStackHCIRemoteSupportSessionHistory
{
    Param(
        [Parameter(Mandatory=$false)]
        [string]
        $SessionId,

        [Parameter(Mandatory=$false)]
        [switch]
        $IncludeSessionTranscript,

        [Parameter(Mandatory=$false)]
        [DateTime]
        $FromDate = (Get-Date).AddDays(-7)
    )

    try
    {
        $OperationType = $MyInvocation.MyCommand

        # Install Az.StackHCI module if doesn't exist
        Invoke-InstallModule -ModuleName "Az.StackHCI"

        # Get Remote Support session history
        $cmdResult = Az.StackHCI\Get-AzStackHCIRemoteSupportSessionHistory -SessionId $SessionId -FromDate $FromDate -IncludeSessionTranscript:$IncludeSessionTranscript

        # Build Result
        $now = [datetime]::UtcNow
        $targetComputerName = $ENV:COMPUTERNAME
        $cmdResultEmpty = [string]::IsNullOrWhiteSpace($cmdResult)

        if($cmdResultEmpty)
        {
            $aggregateStatus = 'SUCCESS'
        }
        else{
            $aggregateStatus = if( -not $cmdResultEmpty -and $cmdResult.State -eq "Active" -and $cmdResult.ConnectionStatus -eq "Connected" -or "Connecting") {'SUCCESS'} else {'FAILURE'}
        }

        $params = @{
            Name               = 'AzStackHci_Get_RemoteSupportSessionHistory'
            Title              = 'Standalone Remote Support: Get Session History'
            DisplayName        = 'Standalone Remote Support: Get Session History'
            Severity           = 'INFORMATIONAL'
            Description        = 'Get AzStackHCI Remote Support session history'
            Tags               = @{
                'OperationType' = $OperationType
            }
            Remediation        = ''
            TargetResourceID   = $targetComputerName
            TargetResourceName = $targetComputerName
            TargetResourceType = 'RemoteSupportEndpoint'
            Timestamp          = [datetime]::UtcNow
            Status             = $aggregateStatus
            AdditionalData     = $cmdResult | ConvertTo-Json
            HealthCheckSource  = $ENV:EnvChkrId
        }
        $getSessionHistoryResult = New-AzStackHciResultObject @params
    }
    catch
    {
        $exception = $_
        Trace-Execution "Get-AzStackHCIRemoteSupportSessionHistory failed. $exception"
        Trace-Execution "$($exception.ScriptStackTrace)"
        throw $exception
    }
}

function Disable-AzStackHciRemoteSupport
{
    param ()

    try
    {
        $OperationType = $MyInvocation.MyCommand

        # Install Az.StackHCI module if doesn't exist
        Invoke-InstallModule -ModuleName "Az.StackHCI"

        # Disable Remote Support
        Az.StackHCI\Disable-AzStackHCIRemoteSupport

        $now = [datetime]::UtcNow
        $targetComputerName = $ENV:COMPUTERNAME

        $aggregateStatus = "SUCCESS"

        $params = @{
            Name               = 'AzStackHci_Disable_RemoteSupport'
            Title              = 'Standalone Remote Support: Disable'
            DisplayName        = 'Standalone Remote Support: Disable'
            Severity           = 'INFORMATIONAL'
            Description        = 'Disable AzStackHCI Remote Support'
            Tags               = @{
                'OperationType' = $OperationType
            }
            Remediation        = ''
            TargetResourceID   = $targetComputerName
            TargetResourceName = $targetComputerName
            TargetResourceType = 'RemoteSupportEndpoint'
            Timestamp          = [datetime]::UtcNow
            Status             = $aggregateStatus
            AdditionalData     = @{}
            HealthCheckSource  = $ENV:EnvChkrId
        }
        $getSessionHistoryResult = New-AzStackHciResultObject @params
        return $getSessionHistoryResult
    }
    catch
    {
        $exception = $_
        Trace-Execution "Disable-AzStackHciRemoteSupport failed. $exception"
        Trace-Execution "$($exception.ScriptStackTrace)"
        throw $exception
    }
}

function Remove-AzStackHciRemoteSupport
{
    param ()

    try
    {
        $OperationType = $MyInvocation.MyCommand

        # Install Az.StackHCI module if doesn't exist
        Invoke-InstallModule -ModuleName "Az.StackHCI"

        # Install Remote Support
        Az.StackHCI\Remove-AzStackHCIRemoteSupport

        $now = [datetime]::UtcNow
        $targetComputerName = $ENV:COMPUTERNAME

        $aggregateStatus = "SUCCESS"
        $params = @{
            Name               = 'AzStackHci_Remove_RemoteSupport'
            Title              = 'Standalone Remote Support: Remove'
            DisplayName        = 'Standalone Remote Support: Remove'
            Severity           = 'INFORMATIONAL'
            Description        = 'Remove AzStackHCI Remote Support'
            Tags               = @{
                'OperationType' = $OperationType
            }
            Remediation        = ''
            TargetResourceID   = $targetComputerName
            TargetResourceName = $targetComputerName
            TargetResourceType = 'RemoteSupportEndpoint'
            Timestamp          = [datetime]::UtcNow
            Status             = $aggregateStatus
            AdditionalData     = @{}
            HealthCheckSource  = $ENV:EnvChkrId
        }
        $removeSessionResult = New-AzStackHciResultObject @params
        return $removeSessionResult
    }
    catch
    {
        $exception = $_
        Trace-Execution "Remove-AzStackHciRemoteSupport failed. $exception"
        Trace-Execution "$($exception.ScriptStackTrace)"
        throw $exception
    }
}

Export-ModuleMember -Function Install-AzStackHciRemoteSupport -Variable MetaData
Export-ModuleMember -Function Enable-AzStackHciRemoteSupport -Variable MetaData
Export-ModuleMember -Function Disable-AzStackHciRemoteSupport -Variable MetaData
Export-ModuleMember -Function Get-AzStackHCIRemoteSupportAccess -Variable MetaData
Export-ModuleMember -Function Get-AzStackHCIRemoteSupportSessionHistory -Variable MetaData
Export-ModuleMember -Function Remove-AzStackHciRemoteSupport -Variable MetaData
# SIG # Begin signature block
# MIIoQgYJKoZIhvcNAQcCoIIoMzCCKC8CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAFxgSi1FVyzbwh
# q1Xt1EMDNAu/izX7+MCSDQJZWNa9jqCCDXYwggX0MIID3KADAgECAhMzAAAEhV6Z
# 7A5ZL83XAAAAAASFMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM3WhcNMjYwNjE3MTgyMTM3WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDASkh1cpvuUqfbqxele7LCSHEamVNBfFE4uY1FkGsAdUF/vnjpE1dnAD9vMOqy
# 5ZO49ILhP4jiP/P2Pn9ao+5TDtKmcQ+pZdzbG7t43yRXJC3nXvTGQroodPi9USQi
# 9rI+0gwuXRKBII7L+k3kMkKLmFrsWUjzgXVCLYa6ZH7BCALAcJWZTwWPoiT4HpqQ
# hJcYLB7pfetAVCeBEVZD8itKQ6QA5/LQR+9X6dlSj4Vxta4JnpxvgSrkjXCz+tlJ
# 67ABZ551lw23RWU1uyfgCfEFhBfiyPR2WSjskPl9ap6qrf8fNQ1sGYun2p4JdXxe
# UAKf1hVa/3TQXjvPTiRXCnJPAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUuCZyGiCuLYE0aU7j5TFqY05kko0w
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
# MBQGA1UEBRMNMjMwMDEyKzUwNTM1OTAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBACjmqAp2Ci4sTHZci+qk
# tEAKsFk5HNVGKyWR2rFGXsd7cggZ04H5U4SV0fAL6fOE9dLvt4I7HBHLhpGdE5Uj
# Ly4NxLTG2bDAkeAVmxmd2uKWVGKym1aarDxXfv3GCN4mRX+Pn4c+py3S/6Kkt5eS
# DAIIsrzKw3Kh2SW1hCwXX/k1v4b+NH1Fjl+i/xPJspXCFuZB4aC5FLT5fgbRKqns
# WeAdn8DsrYQhT3QXLt6Nv3/dMzv7G/Cdpbdcoul8FYl+t3dmXM+SIClC3l2ae0wO
# lNrQ42yQEycuPU5OoqLT85jsZ7+4CaScfFINlO7l7Y7r/xauqHbSPQ1r3oIC+e71
# 5s2G3ClZa3y99aYx2lnXYe1srcrIx8NAXTViiypXVn9ZGmEkfNcfDiqGQwkml5z9
# nm3pWiBZ69adaBBbAFEjyJG4y0a76bel/4sDCVvaZzLM3TFbxVO9BQrjZRtbJZbk
# C3XArpLqZSfx53SuYdddxPX8pvcqFuEu8wcUeD05t9xNbJ4TtdAECJlEi0vvBxlm
# M5tzFXy2qZeqPMXHSQYqPgZ9jvScZ6NwznFD0+33kbzyhOSz/WuGbAu4cHZG8gKn
# lQVT4uA2Diex9DMs2WHiokNknYlLoUeWXW1QrJLpqO82TLyKTbBM/oZHAdIc0kzo
# STro9b3+vjn2809D0+SOOCVZMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
# 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
# /Xmfwb1tbWrJUnMTDXpQzTGCGiIwghoeAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAASFXpnsDlkvzdcAAAAABIUwDQYJYIZIAWUDBAIB
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEINB0X0BO3jb0Xm7aeTWP31su
# 8imJlPrCiN8sBKQUPjv9MEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
# BQAEggEAjr2Fad23yIRU7doC1r68fW/CmDXg1YR4O5XTzpsmwRBYDxA5Do6q0Yvs
# 06FAzx297fWiqI6q1jCRUAnPv+JzIQONMkHFDWOF0HoilyruvDVxAoOl2ZM0E/d1
# 4dvpYiTZbTtEP6YwRcjHeCErElXuCy9lwMxQA291BKuPhwOespZ4C35DugibvFzM
# SHPVj0SmYFnsAZjMwsgmInXKLogPN4hkC4c8PcIMPX0kVNTElCUAnI5qTZYQWhhW
# K9KMKS6slUHLshNcHK9E0NcmutZYOi+b50aOVZr1NSSZxxihFKI6U8YlelMuJYcq
# i0hA6sDLcE6/ACDTLEr7ABqEFRxcI6GCF6wwgheoBgorBgEEAYI3AwMBMYIXmDCC
# F5QGCSqGSIb3DQEHAqCCF4UwgheBAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq
# hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCAViYUTclHuFFIFuty4nwOp/WCRkzKhMnTjFLyU8v99RQIGaKR12Qp/
# GBIyMDI1MDkwOTE5MjIwNC4yN1owBIACAfSggdmkgdYwgdMxCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVs
# YW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNO
# OjQzMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT
# ZXJ2aWNloIIR+zCCBygwggUQoAMCAQICEzMAAAH6+ztE03czxtMAAQAAAfowDQYJ
# KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjQw
# NzI1MTgzMTExWhcNMjUxMDIyMTgzMTExWjCB0zELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl
# cmF0aW9ucyBMaW1pdGVkMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046NDMxQS0w
# NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Uw
# ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKFlUEzc9lwF8SkB/t8giH
# KDBhVU/rhRJ5ltKVFHem8l5u9rQtAINbjnI6u2nAikbIMZf4RsJseFLlN3gnRiVz
# zfO0sRttAPszqSpHReP6fzZwax79CcwfRZFkufCCAl16elDpRyIzicxhm91CPJsD
# ip6M571jTvcmVe/dUht2RAfYkbJPygH8uy88v+QCcnjmhAintLHntE9D/Q7qprIn
# ZImvByMDxq4x0Cdko6LEWXOiiiHtLLJwjsEQ0dOmRUqtFXlh6VG9Y1ODWkfgQLYo
# 7ZvGwE3bdu0x5O9kWJ4Yiv4PyZ/WVBCzQe3+0w5V1qHXi3tiT7GXk/hPDfF8AaAe
# y+xrq6CvHCYpNNfWSpcflcJ3DdNV4oJrHolX7KAzmLU2ugkrAEJbXU/CLTP+SL3R
# l47pd8QT2YKcmbvpBzGLe2db9j/dm6YpDpf+JUgmjsuTRn+kBNHAAg2rB2/Ol21f
# aE4mJvgZHyKzZukqSzTga6t/B5Y+f3PqNjsYEL6OzylLAZ7Ct9/CABs0qbzZkMW+
# oEZBBUnAgdJemORL4bf17Jg4batwgsEgOXNTMwUUls2Hm0O/cZ4ncQq8Li81IDG0
# Z9ob+ZCErjdiN6+wHvYui5TvyvG02G4xdLNoerl8WIbfNyxgdprj7D5iYyuFMTMP
# hICKyHfkGOhc/U/UK3hVrQIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFGOMcpsvlZXq
# R3ToqhxAemEr1T+/MB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8G
# A1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
# Y3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBs
# BggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy
# MDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH
# AwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQC4VsKisWu+h0b5
# k0kfdj43PlClTK1BU5s7JgWuBwavGroxRrjIubE3jFZ0vWTKBpbkE5nfEGU9jtWm
# 5/lvl5pc/upGrrXF46tfd/riQaJJahGL0QlrAlYLMl9RBFOEMvjPEjalhzXCc+nt
# Dr3lserBnTZ5o4G52H8h8SQZ7Q5+PohLejJmwk/XJq1ybiQGogfp1vX7B4zirjo2
# EB8B/TvTMXoX4ilQfKG0xtCDn5Ad867IHOu3rsKIwlIpwnecxXJ82We/rK+21jMs
# rfBL7RDAlSJstgkwjoUZxK5HEqWrpGM6Er0vdA6OHRUIzXWsczXVmY3R64ltsEJV
# 9AS584s2QbzwwUJQ0TXRJJsz86D8JtOSjQznBtW9AnoKosqO0dKh6gAY955fbh/l
# w9jJNwqVszouhR07Y/klJ0jmzUkX86fouJRPnRp2lGy1lqNtgR5f83tG9JuSfR2M
# PcG9PY5/dZ/2Ah5pAgdu/UnY78/lA49CJWjz7QAqbozRMo526KGErEC3/pjKTXsW
# /dEh2NPrCIvapEgSyA4mnd8gvDiZBE+7eylF9qRKhB7k3R7gdYV/xZbZkvT5zzdD
# OHdW0Q8jpjZ7YE795aFNhshsempgN8C0Bi1pgh17ztnKZcbcw7bBSOEv0e9JDOOi
# q6r46hSa98FRwHZ7kvpAIc7qpM7tajCCB3EwggVZoAMCAQICEzMAAAAVxedrngKb
# SZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmlj
# YXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIy
# NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXI
# yjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjo
# YH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1y
# aa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v
# 3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pG
# ve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viS
# kR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYr
# bqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlM
# jgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSL
# W6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AF
# emzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIu
# rQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIE
# FgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWn
# G1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEW
# M2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5
# Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBi
# AEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV
# 9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js
# Lm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAx
# MC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2
# LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv
# 6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZn
# OlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1
# bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4
# rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU
# 6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDF
# NLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/
# HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdU
# CbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKi
# excdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTm
# dHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZq
# ELQdVTNYs6FwZvKhggNWMIICPgIBATCCAQGhgdmkgdYwgdMxCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVs
# YW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNO
# OjQzMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT
# ZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQD3hn5tQmf6crAG8gjqyDQ3Lto8NqCBgzCB
# gKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV
# BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUA
# AgUA7Gqh4zAiGA8yMDI1MDkwOTEyNTM1NVoYDzIwMjUwOTEwMTI1MzU1WjB0MDoG
# CisGAQQBhFkKBAExLDAqMAoCBQDsaqHjAgEAMAcCAQACAg1TMAcCAQACAhISMAoC
# BQDsa/NjAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEA
# AgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBANfPEEOTqs/iQrkU
# xOZZuYkxrrW5A4gKrWTvcyla0v7t4ZxCItvhxhqJcWivO6tj9LzDtb6jAqG1jaIm
# c7ZzO4myDgcYs+qmvjM1pFUJ1u7+Q5xm9FGMH8KyTPignAITO73ba2v2KrzVRJWU
# HMXd+DM36NnvfycZZGYAVxSWY7cV+QGMSPggeZhCEEIcKyfZvl/g/8l3b7eAfg+9
# 19x1SKtIvpJXYnF9vvAAoy6Arl+5vxM2+egacF85uDQLPWYbkYttz0SdyGGYCvOR
# K/vL7uUZoUESddwo0tE1Pu4vxdn67QBf4UfJyQKGqIe8ULFk8BtaS5iPy0uU815P
# fF99HAQxggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx
# MAITMwAAAfr7O0TTdzPG0wABAAAB+jANBglghkgBZQMEAgEFAKCCAUowGgYJKoZI
# hvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCCthl7rmMoArC/6
# lJTJPyCGjBeUUHnQ4fnwqT8EjdxYoDCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQw
# gb0EIH3yfy3Jrz4HaONT92klEjAfAcelyjmiA1K1ihxuQ55WMIGYMIGApH4wfDEL
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWlj
# cm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAH6+ztE03czxtMAAQAAAfow
# IgQgxR+TPtkokl2CwUxa3sTOXMBvH8FdT6q8c3nL6jkgpzAwDQYJKoZIhvcNAQEL
# BQAEggIABLQG/PZ8Antitol1/kECK9UMB+YGbDevW0u62Annvrz8Go6O3wfidxj9
# ViGMWlVRcTg7kFYSfmvT6zVNTRkdC4Zeqwl5/mf4w/ykMfoWp/krMq6BeB41JxZP
# pcGFjCsrcxTdl9TdokistrW02VixvpMuTi3QbdCh/JKfMf7mRoELmk5LolLHUd3c
# w2L+EyJkqcMoOviWaGnzSa8X32yxml/lV6hmrmGQv4PeByFSJBnEjoKOhHyAbq8k
# P+GcWnv9++LAfI58MkqilWzuLNADmglF/xHfXoXRFrrHJFgapoY4ZuICC6ZDoXFg
# 4U5Xj6w8FltZgbbUd7x4bdBcKNvdJLwd9wVMSu6ByVTHPno5E2KYXbh2I7mU5tbU
# MZAwQqsHxpuvVmioU2uf9LQW3K36q14u0TY7aax8kGQAXrIxK8MHfnchL0j0IUDm
# eYtzAGWqfkZwX8Mwz5qtNQwSr6uBNpHSvoSfkJNhF+2TEfhM6/uyNbcH/U7qEr+d
# EvScVnmE5f63W0wwYaSI7P95ehRO+Oa5H/E4VhuAtY3ly7RzpD0lUWFUBTuES+DN
# EUYBOHjmeyVS3RcEwWnnsnCsryO5wU/sCoroK+pzvfT6/DJ7zJ3sp0WyuaZPfwiJ
# iWBLv+XD1M9w5bpMUxZdUcgROW2RNSYhCsCPTv9V5q+bDBd4src=
# SIG # End signature block