Obs/bin/ObsAgent/lib/Artifacts/SessionTools.psm1

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


<#
.SYNOPSIS
Invokes a scriptblock in a try block and upon exception retries until $MaxTries with a delay of $IntervalInSeconds
 
.DESCRIPTION
Should be used for invoking any powershell script or commands that needs a retry
 
.PARAMETER ScriptBlock
Script block to be executed
 
.PARAMETER MaxTries
Maximum number of attempts that should be attempted
 
.PARAMETER IntervalInSeconds
Interval between retries
 
 
#>

 function Invoke-ScriptBlockWithRetries {
    param
    (
        [Parameter(Mandatory = $true)]
        [ScriptBlock] $ScriptBlock,

        [Parameter(Mandatory = $false)]
        [Object] $Argument,

        [Parameter(Mandatory = $true)]
        [int] $MaxTries,

        [Parameter(Mandatory = $false)]
        [int] $IntervalInSeconds = 60
    )

    Write-Information "Invoke-ScriptBlockWithRetries: Retrying max $MaxTries interval [$IntervalInSeconds] ScriptBlock = [$ScriptBlock]" -Verbose

    $attempt = 1
    $success = $false
    do
    {
        Write-Information "Invoke-ScriptBlockWithRetries:===============> Starting attempt $attempt" -Verbose
        try
        {
            $result = Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $Argument -ErrorAction Stop
            $success = $true
        }
        catch
        {
            $message = "Exception occurred while trying to execute [$ScriptBlock] command:" + $_.Exception.ToString()
            Write-Information $message -Verbose

            if ($attempt -ge $MaxTries)
            {
                throw
            }

            Start-Sleep -Seconds $IntervalInSeconds            
        }
        finally
        {
            Write-Information "Invoke-ScriptBlockWithRetries:===============> Completed attempt $attempt --- Status = $success" -Verbose
            $attempt++
        }
    }
    while (!$success)

    return $result
}

<#
.SYNOPSIS
Initializes a JEA PS session
 
.DESCRIPTION
Uses the current user's credentials to create a JEA PowerShell session
 
.PARAMETER EndpointName
The name of the JEA endpoint to access
 
.PARAMETER ComputerName
The name of the computer on which to invoke the endpoint
#>

function Get-JEASession{
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $EndpointName,

        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ComputerName
    )

    $currentSessions = Get-PSSession -ComputerName $ComputerName -ConfigurationName $EndpointName

    # Remove any existing JEA sessions to this endpoint
    if ($currentSessions -ne $null)
    {
        Write-Information "Found $($currentSessions.Count) open sessions for $EndpointName" -Verbose
        Remove-PSConfigurationSession -ComputerName $ComputerName -ConfigurationName $EndpointName
    }

    Write-Information "Opening session on $ComputerName with endpoint $EndpointName" -Verbose
    $PSSessionOption = New-PSSessionOption -IdleTimeoutMSec 60000
    
    $scriptBlock =     { New-PSSession -ComputerName $ComputerName -ConfigurationName $EndpointName -Verbose -SessionOption $PSSessionOption -ErrorAction Stop }
    $session = Invoke-ScriptBlockWithRetries -ScriptBlock $scriptBlock -MaxTries 10 -IntervalInSeconds 10

    return $session
}

<#
.SYNOPSIS
Initializes a PEP Session
 
.DESCRIPTION
Uses the current user's credentials to create session
 
.PARAMETER ErcsComputerNames
Comma seperated list of ERCS machine names.
#>

function Get-EcePepSession {
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ErcsComputerNames
    )

    Write-Information "Getting reachable sessions on $EceComputerNames"
    
    $ComputerNames = $ErcsComputerNames.Split(',')
    foreach($ComputerName in $ComputerNames)
    {
        Write-Information "Trying to get session $ComputerName"
        try{
            $session = Get-JEASession -EndpointName 'PrivilegedEndpoint' -ComputerName $ComputerName
            return $session
        }
        catch{
            Write-Information "Error getting session $ComputerName : $_"
        }
    }

    return $null
}

<#
.SYNOPSIS
Removes all PS session instances for a specified configuration
#>

function Remove-PSConfigurationSession {
    Param(
        # The configuration name
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ConfigurationName,

        # The host name to target
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ComputerName
    )

    $instanceConnectionUrl = "http://${ComputerName}:5985/wsman"
    
    Write-Information "Removing outstanding session instances for $ConfigurationName"
    try
    {
        Write-Information "Enumerating outstanding session instances for $ConfigurationName"

        # Get all shell sessions that match the specified configuration
        $sessionInstances = Get-WSManInstance -ConnectionUri $instanceConnectionUrl shell -Enumerate `
        | Where-Object { $_.ResourceUri -match $ConfigurationName } `
        | Select-Object -Property "ShellId"

        # Forcefully terminate the sessions
        if ($sessionInstances -ne $null)
        {
            foreach($sessionInstance in $sessionInstances)
            {
                try
                {
                    Write-Information "Removing session instance $($sessionInstance.ShellId)"
                    Remove-WSManInstance -ConnectionURI $instanceConnectionUrl shell @{ ShellID = $sessionInstance.ShellId }
                }
                catch
                {
                    Write-Error "An error occurred when removing the session instance $_"
                }
            }
        }
        else{
            Write-Information "No outstanding sessions were found"
        }

        # Verify no outstanding PS sessions exist for the specified configuration
        $outstandingPSSessions = Get-PSSession -ComputerName $ComputerName -ConfigurationName $ConfigurationName
        if ($outstandingPSSessions -ne $null)
        {
            Write-Error "Outstanding session instances could not be removed."
        }
    }
    catch
    {
        Write-Error "An error occurred when removing the outstanding sessions. $_"
    }
}

Export-ModuleMember -Function Invoke-ScriptBlockWithRetries
Export-ModuleMember -Function Get-JEASession
Export-ModuleMember -Function Get-EcePepSession

# SIG # Begin signature block
# MIIoKAYJKoZIhvcNAQcCoIIoGTCCKBUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCLjsmVNpG88Eca
# asqb34/XdrAAwVpX4WVISrBWLfo8v6CCDXYwggX0MIID3KADAgECAhMzAAADrzBA
# 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
# /Xmfwb1tbWrJUnMTDXpQzTGCGggwghoEAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAAOvMEAOTKNNBUEAAAAAA68wDQYJYIZIAWUDBAIB
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIIKYX7gzzcSLCls2P3oY8f1H
# BSpAwfh4+W4yzTrjmDjdMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
# BQAEggEAhLcnPKoUG39SS+Nzp6yQbcLP5o8HNLE6d9S1oCAzb/AC4tTYrfyQ53DW
# Btd0nZTi/1Bf/lh2HFUhIRiVAIjrNYWmMB89IX2YJREJYHabW7KhhWDL6MFOvtHu
# Fi4ufXTtvlIGqnTzkpVjeEXYtb/8m7WYcLpLzMkTrpuZcY4wBF4dIk0j2VWuyjKK
# xdtxaFcfu8Tehf6Yz4FNQbk9u4KcnMMj9l/+zw2MrqxDDGiQCdTS7LuSiTToXScj
# HZ8iFh6iQTrZ6zd1tQA28nDWFTT8vGKDQhnblTuKHkQhRqLaTF0whW+QyR59BFAJ
# uuHZU9eokc3E2sC5nY76OX4UYgVfyqGCF5IwgheOBgorBgEEAYI3AwMBMYIXfjCC
# F3oGCSqGSIb3DQEHAqCCF2swghdnAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFQBgsq
# hkiG9w0BCRABBKCCAT8EggE7MIIBNwIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCDFvXxMcBE5eKySMA23l5TffHUbDpLrZT7FYkBrPc1GfgIGZr3+q2Kv
# GBEyMDI0MDgxOTE3Mjc1Ny40WjAEgAIB9KCB0aSBzjCByzELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJp
# Y2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjhEMDAtMDVF
# MC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIR
# 6jCCByAwggUIoAMCAQICEzMAAAHzxQpDrgPMHTEAAQAAAfMwDQYJKoZIhvcNAQEL
# BQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjMxMjA2MTg0NjAy
# WhcNMjUwMzA1MTg0NjAyWjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEn
# MCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjhEMDAtMDVFMC1EOTQ3MSUwIwYDVQQD
# ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEF
# AAOCAg8AMIICCgKCAgEA/p+m2uErgfYkjuVjIW54KmAG/s9yH8zaWSFkv7IH14ZS
# 2Jhp7FLaxl9zlXIPvJKyXYsbjVDDu2QDqgmbF1Izs/M3J9WlA+Q9q9j4c1Sox7Yr
# 1hoBo+MecKlntUKL97zM/Fh7CrH2nSJVo3wTJ1SlaJjsm0O/to3OGn849lyUEEph
# PY0EaAaIA8JqmWpHmJyMdBJjrrnD6+u+E+v2Gkz4iGJRn/l1druqEBwJDBuesWD0
# IpIrUI4zVhwA3wamwRGqqaWrLcaUTXOIndktcVUMXEBl45wIHnlW2z2wKBC4W8Ps
# 91XrUcLhBSUc0+oW1hIL8/SzGD0m4qBy/MPmYlqN8bsN0e3ybKnu6arJ48L54j+7
# HxNbrX4u5NDUGTKb4jrP/9t/R+ngOiDlbRfMOuoqRO9RGK3EjazhpU5ubqqvrMjt
# bnWTnijNMWO9vDXBgxap47hT2xBJuvnrWSn7VPY8Swks6lzlTs3agPDuV2txONY9
# 7OzJUxeEOwWK0Jm6caoU737iJWMCNgM3jtzor3HsycAY9hUIE4lR2nLzEA4EgOxO
# b8rWpNPjCwZtAHFuCD3q/AOIDhg/aEqa5sgLtSesBZAa39ko5/onjauhcdLVo/CK
# YN7kL3LoN+40mnReqta1BGqDyGo2QhlZPqOcJ+q7fnMHSd/URFON2lgsJ9Avl8cC
# AwEAAaOCAUkwggFFMB0GA1UdDgQWBBTDZBX2pRFRDIwNwKaFMfag6w0KJDAfBgNV
# HSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5o
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBU
# aW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwG
# CCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRz
# L01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNV
# HRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIH
# gDANBgkqhkiG9w0BAQsFAAOCAgEA38Qcj/zR/u/b3N5YjuHO51zP1ChXAJucOtRc
# UcT8Ql0V5YjY2e7A6jT9A81EwVPbUuQ6pKkUoiFdeY+6vHunpYPP3A9279LFuBqP
# QDC+JYQOTAYN8MynYoXydBPxyKnB19dZsLW6U4gtrIAFIe/jmZ2/U8CRO6WxATyU
# FMcbgokuf69LNkFYqQZov/DBFtniIuJifrxyOQwmgBqKE+ANef+6DY/c8s0QAU1C
# AjTa0tfSn68hDeXYeZKjhuEIHGvcOi+wi/krrk2YtEmfGauuYitoUPCDADlcXsAq
# Q+JWS+jQ7FTUsATVzlJbMTgDtxtMDU/nAboPxw+NwexNqHVX7Oh9hGAmcVEta4EX
# hndrqkMYENsKzLk2+cpDvqnfuJ4Wn//Ujd4HraJrUJ+SM4XwpK2k9Sp2RfEyN8nt
# Wd6Z3q9Ap/6deR+8DcA5AQImftos/TVBHmC3zBpvbxKw1QQ0TIxrBPx6qmO0E0k7
# Q71O/s2cETxo4mGFBV0/lYJH3R4haSsONl7JtDHy+Wjmt9RcgjNe/6T0yCk0YirA
# xd+9EsCMGQI1c4g//UIRBQbvaaIxVCzmb87i+YkhCSHKqKVQMHWzXa6GYthzfJ3w
# 48yWvAjE5EHkn0LEKSq/NzoQZhNzBdrM/IKnt5aHNOQ1vCTb2d9vCabNyyQgC7dK
# 0DyWJzswggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3
# DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIw
# MAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx
# MDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1l
# LVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
# 5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/
# XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1
# hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7
# M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3K
# Ni1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy
# 1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF80
# 3RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQc
# NIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahha
# YQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkL
# iWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV
# 2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIG
# CSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUp
# zxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBT
# MFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYI
# KwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGG
# MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186a
# GMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br
# aS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsG
# AQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcN
# AQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1
# OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYA
# A7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbz
# aN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6L
# GYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3m
# Sj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0
# SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxko
# JLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFm
# PWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC482
# 2rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7
# vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDTTCC
# AjUCAQEwgfmhgdGkgc4wgcsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAl
# BgNVBAsTHm5TaGllbGQgVFNTIEVTTjo4RDAwLTA1RTAtRDk0NzElMCMGA1UEAxMc
# TWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAbvoG
# LNi0YWuaRTu/YNy5H8CkZyiggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UE
# CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
# b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ
# Q0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAOptwtEwIhgPMjAyNDA4MTkxMzEwNDFa
# GA8yMDI0MDgyMDEzMTA0MVowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA6m3C0QIB
# ADAHAgEAAgILqjAHAgEAAgIS9TAKAgUA6m8UUQIBADA2BgorBgEEAYRZCgQCMSgw
# JjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3
# DQEBCwUAA4IBAQAtASYq7xDUkekb605fOCXAal+adChT12uTo+pIcp3kK6nQeV8T
# dlW6uB5nAJc2/O4Nymn+mSeDetoUwJB8/ypV5y+CbtlofzgNswLvq8bPpX5CmjQF
# Yn9tzgNJN4WqaDsXbAWsOiSVbJ5+nuJcnpm/QrNA/2Lj5YjeJ/7szsb2ZuK8SbON
# 4lY+3LQ7QBMM0aoCDXm4ATG2RCwkyOQfLO31U+GXp5iR6akkRJklNv2VgF4oqMZ1
# c40HsIJT4AK/gJt5HmBY2EZg7HVXGszYw6+sb7Crno4KfpQfaRZwFSs6fPbLTzAs
# m1QkevXPEFJWPXINYoS7Qj1MtYicW3PVe+m+MYIEDTCCBAkCAQEwgZMwfDELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9z
# b2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAHzxQpDrgPMHTEAAQAAAfMwDQYJ
# YIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkq
# hkiG9w0BCQQxIgQgmvut6imTNfRvmBjpfErMgBSgOo0uXIFKW0y6Uhqw8s8wgfoG
# CyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCAYvNk0i7bhuFZKfMAZiZP0/kQIfONb
# Bv2gzsMYOjti6DCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw
# AhMzAAAB88UKQ64DzB0xAAEAAAHzMCIEIEQ6Ib90Vz+ekV5GN7+NCWJ+LCYw7R++
# iJYlBkyTX92GMA0GCSqGSIb3DQEBCwUABIICAIqesqDQ9bzRcIp7UTpdGeuY0wJb
# Y7FufHTZTsGi4et/YUFzmQnUTlczMDt5rlAtAZtpPM/JljhivUCgZw9d9d5KzO+l
# trtfoQVvBEpabphTFYER5+DzY1q5jpUkBrL6UvRLKPSv1Hu7fGy/sE4xkemDYQma
# BNnN7S3Sn1JB/tEq5OJ4vKMK0LPs1TBWgX/3+MI67Uwn7wkJ2XVEGBa6nFhi+FtP
# bxpTeLfyEjaOhbX0wvo83vqtF0LRfH9+oyAQNkS8q4RIti8uNIj6Hw/Dgn55jAUy
# 9HBXWZi3gQbJdxQWzMSn9dqFI8J8dhgehBHJR4nxQ3F8yp5YQRZqKSIRsiHYSy9a
# aqQ2y85VMO7795AgYA2u27HvZ+J1K/QJXI5l5mLSUL8NV62t/bwWcUqtZW6+4P1x
# ngt5ml9l08rXPPiKwrJKdPEgZ8XxeUyRNDg9HQxQEr78QXuOcwXZDYWbrTpazJwZ
# +/fa0KDe57bCu5FZS/Ta44KLxi8gHsc6nHwTMG6pUPj8lc2eBCFdsZuLxZA363Es
# YL/eKjCd9Xo7KfpX4QujUxfUMhJ1xJYemkkAv2yNyGVhf8FY7uBZ0rs1IWhlPOM+
# 20MP+yhbvBpMPf0cf1o36UquAhEizdQGt1dAxKELxoxtaQBn92GXty/jkVkjMnK1
# kW85poWIP/YPYKk1
# SIG # End signature block