Public/Start_Stop/Start-NewPSRemoteSession.ps1
|
function Start-NewPSRemoteSession { <# .SYNOPSIS Create a remote PSSession, preferring PowerShell 7 endpoint (WSMan) with fallback to Windows PowerShell. Also supports SSH transport. .DESCRIPTION - For WSMan: tries -ConfigurationName PowerShell.7 first, then falls back to Microsoft.PowerShell. - For SSH: uses New-PSSession -HostName (PowerShell 7+ locally). Supports password or key. - Applies sensible timeouts; returns a live PSSession or throws. .PARAMETER ComputerName Target computer (DNS name or IP). .PARAMETER Credential PSCredential for WSMan or SSH (username/password). For SSH+Key, Username can come from the credential or -UserName. .PARAMETER UseSsh Use SSH transport instead of WSMan. .PARAMETER UseCredSSP Enables CredSSP for WSMan remoting and bootstraps the remote host's WSMan CredSSP server setting before opening the delegated session. .PARAMETER Port SSH port (default 22). .PARAMETER Ps7ConfigName WSMan endpoint name for PS7 (default 'PowerShell.7'). .PARAMETER WinPsConfigName WSMan endpoint name for Windows PowerShell (default 'Microsoft.PowerShell'). .PARAMETER UserName SSH username when not using PSCredential. .PARAMETER KeyFilePath SSH private key path (if using key-based auth). .PARAMETER ConnectTimeoutSec Open/operation timeout (seconds) used in session options. .PARAMETER IdleTimeoutSec Idle timeout (milliseconds) for the session. .PARAMETER AsList When set, returns a list-style summary object for display instead of the raw PSSession object. .OUTPUTS System.Management.Automation.Runspaces.PSSession #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$ComputerName, [pscredential]$Credential, [string]$SessionName, [switch]$UseSsh, [switch]$UseCredSSP, [int]$Port = 22, [string]$Ps7ConfigName = 'PowerShell.7', [string]$WinPsConfigName = 'Microsoft.PowerShell', [string]$UserName, [string]$KeyFilePath, [int]$ConnectTimeoutSec = 20, [int]$IdleTimeoutSec = 1800000, # 30 minutes [switch]$AsList ) Set-StrictMode -Version Latest $oldEAP = $ErrorActionPreference $ErrorActionPreference = 'Stop' try { $sessOpts = New-PSSessionOption -OpenTimeout ($ConnectTimeoutSec * 1000) ` -OperationTimeout ($ConnectTimeoutSec * 1000) ` -IdleTimeout $IdleTimeoutSec function Test-LocalAdministrator { $id = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = [Security.Principal.WindowsPrincipal]$id return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } function Get-SessionOutputObject { param( [Parameter(Mandatory)] [System.Management.Automation.Runspaces.PSSession]$Session, [switch]$AsList ) if (-not $AsList) { return $Session } [pscustomobject]@{ Id = $Session.Id Name = $Session.Name Transport = $Session.Transport ComputerName = $Session.ComputerName ComputerType = $Session.ComputerType State = $Session.State ConfigurationName = $Session.ConfigurationName Availability = $Session.Availability RunspaceId = $Session.Runspace.InstanceId PSSession = $Session } } function Test-CredSSPClientDelegationConfigured { param([Parameter(Mandatory)][string]$TargetComputer) # First check the local WSMan CredSSP client auth toggle. This read is # available in normal sessions and avoids false negatives when # Get-WSManCredSSP itself requires elevation. try { $authEnabled = (Get-Item -Path WSMan:\localhost\Client\Auth\CredSSP -ErrorAction Stop).Value } catch { return $false } if ([string]$authEnabled -ne 'true') { return $false } try { $status = Get-WSManCredSSP } catch { # In non-elevated sessions this cmdlet can throw AccessDenied. # If CredSSP client auth is on, treat configuration as present. return $true } if (-not $status) { return $true } $patterns = @() foreach ($line in @($status -split "`r?`n")) { $trimmed = $line.Trim() if ([string]::IsNullOrWhiteSpace($trimmed)) { continue } $matches = [regex]::Matches($trimmed, '(?i)wsman/[^\s,;]+') foreach ($match in $matches) { if ($match.Success) { $patterns += $match.Value.ToLowerInvariant() } } } $patterns = @($patterns | Select-Object -Unique) if ($patterns.Count -eq 0) { return $false } $shortComputer = ($TargetComputer -split '\.')[0] $targetsToMatch = @( ("wsman/{0}" -f $TargetComputer), ("wsman/{0}" -f $shortComputer), $TargetComputer, $shortComputer ) foreach ($pattern in $patterns) { foreach ($candidate in $targetsToMatch) { if ($candidate -like $pattern) { return $true } } } return $false } function Get-CredSSPDelegateTargets { param([Parameter(Mandatory)][string]$TargetComputer) $configuredTargets = @() $remoting = $null if ($script:cfg -and $script:cfg.settings) { $remoting = $script:cfg.settings.remoting } if ($remoting -and $remoting.ContainsKey('credSSPDelegateComputers')) { $rawTargets = $remoting['credSSPDelegateComputers'] if ($rawTargets -is [string]) { $configuredTargets = @($rawTargets) } elseif ($rawTargets -is [System.Collections.IEnumerable]) { $configuredTargets = @($rawTargets) } } $normalizedTargets = @( $configuredTargets | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) } | ForEach-Object { $value = [string]$_ if ($value -like 'wsman/*') { $value.Substring(6) } else { $value } } | Select-Object -Unique ) if ($normalizedTargets.Count -gt 0) { return $normalizedTargets } return @($TargetComputer) } function Enable-RemoteCredSSPServer { param( [Parameter(Mandatory)][string]$TargetComputer, [pscredential]$TargetCredential, [Parameter(Mandatory)][System.Management.Automation.Remoting.PSSessionOption]$SessionOptions, [Parameter(Mandatory)][string]$PrimaryConfig, [Parameter(Mandatory)][string]$FallbackConfig, [Parameter(Mandatory)][string]$TargetSessionName ) Write-Log -Level Info -Message "Ensuring CredSSP is enabled on $TargetComputer for WSMan remoting." $delegateTargets = Get-CredSSPDelegateTargets -TargetComputer $TargetComputer $clientConfigured = Test-CredSSPClientDelegationConfigured -TargetComputer $TargetComputer if (-not $clientConfigured) { if (-not (Test-LocalAdministrator)) { $delegateArg = ($delegateTargets | ForEach-Object { "'{0}'" -f $_ }) -join ', ' throw "CredSSP client delegation is not configured locally for $TargetComputer and enabling it requires an elevated PowerShell session. Run once as administrator: Enable-WSManCredSSP -Role Client -DelegateComputer $delegateArg -Force" } Enable-WSManCredSSP -Role Client -DelegateComputer $delegateTargets -Force | Out-Null } $bootstrap = $null try { $bootstrapParams = @{ ComputerName = $TargetComputer Credential = $TargetCredential Authentication = 'Default' ConfigurationName = $PrimaryConfig ErrorAction = 'Stop' SessionOption = $SessionOptions Name = "$TargetSessionName:bootstrap" } try { $bootstrap = New-PSSession @bootstrapParams } catch { $bootstrapParams.ConfigurationName = $FallbackConfig $bootstrap = New-PSSession @bootstrapParams } $serverEnabled = Invoke-Command -Session $bootstrap -ScriptBlock { $value = (Get-Item -Path WSMan:\localhost\Service\Auth\CredSSP -ErrorAction Stop).Value return [string]$value -eq 'true' } -ErrorAction Stop if (-not $serverEnabled) { Invoke-Command -Session $bootstrap -ScriptBlock { Enable-WSManCredSSP -Role Server -Force | Out-Null } -ErrorAction Stop | Out-Null } } finally { if ($bootstrap) { Remove-PSSession -Session $bootstrap -ErrorAction SilentlyContinue } } } if (-not $SessionName) { $SessionName = "TT:Remote:{0}:{1:yyyyMMdd-HHmmss}" -f $ComputerName, (Get-Date) } if ($UseSsh) { # --- Preflight: must be PowerShell 7+ (or 6+) locally for SSH remoting parameter set --- if ($PSVersionTable.PSVersion.Major -lt 7) { throw "SSH transport requires PowerShell 7+ locally." } # PowerShell remoting over SSH is supported in PowerShell 6+ / 7+. [1](https://learn.microsoft.com/en-us/powershell/scripting/security/remoting/ssh-remoting-in-powershell?view=powershell-7.6)[3](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_remote_requirements?view=powershell-7.5) # --- Preflight: ensure OpenSSH client is present (ssh.exe) --- if (-not (Get-Command ssh -ErrorAction SilentlyContinue)) { throw "SSH transport requires OpenSSH client (ssh.exe) available on PATH." } # SSH transport depends on SSH being installed. [1](https://learn.microsoft.com/en-us/powershell/scripting/security/remoting/ssh-remoting-in-powershell?view=powershell-7.6) # --- Resolve username --- $resolvedUser = $null if ($UserName) { $resolvedUser = $UserName } elseif ($Credential) { $resolvedUser = $Credential.UserName } # --- Guardrail: by default, require KeyFilePath to avoid interactive prompts (worker-safe) --- # If you *want* to allow prompting, do it only when truly interactive. $isInteractive = $Host.Name -match 'ConsoleHost|Visual Studio Code Host' -and [Environment]::UserInteractive -and -not [Console]::IsInputRedirected if (-not $KeyFilePath) { if (-not $isInteractive) { throw "SSH requires -KeyFilePath in non-interactive contexts to prevent password prompts/hangs." } # Interactive session without key: require username so prompt can occur if (-not $resolvedUser) { throw "For interactive SSH without -KeyFilePath, specify -UserName or -Credential (username only)." } } else { # Key auth requires username (PowerShell uses -UserName + -KeyFilePath). [1](https://learn.microsoft.com/en-us/powershell/scripting/security/remoting/ssh-remoting-in-powershell?view=powershell-7.6)[2](https://bing.com/search?q=PowerShell+remoting+over+SSH+New-PSSession+-HostName+-UserName+-SSHTransport+key+authentication+requirements) if (-not $resolvedUser) { throw "For SSH key auth, specify -UserName or -Credential (username only)." } if (-not (Test-Path -LiteralPath $KeyFilePath)) { throw "SSH key file not found: $KeyFilePath" } } # --- Build SSH session params (only params valid/meaningful for SSH parameter set) --- $sshParams = @{ HostName = $ComputerName ErrorAction = 'Stop' Name = $SessionName } # Only add Port if user supplied it (avoid passing null/0) if ($PSBoundParameters.ContainsKey('Port') -and $Port) { $sshParams.Port = $Port } if ($resolvedUser) { $sshParams.UserName = $resolvedUser } if ($KeyFilePath) { $sshParams.KeyFilePath = $KeyFilePath } # Optional: session options are fine to pass if ($sessOpts) { $sshParams.SessionOption = $sessOpts } # NOTE: No ConfigurationName here - SSH remoting doesn't use WinRM-style endpoint configuration/JEA. [1](https://learn.microsoft.com/en-us/powershell/scripting/security/remoting/ssh-remoting-in-powershell?view=powershell-7.6) $s = New-PSSession @sshParams $portInfo = if ($sshParams.Port) { " (port $($sshParams.Port))" } else { "" } Write-Log -Level Ok -Message "Connected to $ComputerName via SSH$portInfo." return (Get-SessionOutputObject -Session $s -AsList:$AsList) } else { if ($UseCredSSP) { Enable-RemoteCredSSPServer ` -TargetComputer $ComputerName ` -TargetCredential $Credential ` -SessionOptions $sessOpts ` -PrimaryConfig $Ps7ConfigName ` -FallbackConfig $WinPsConfigName ` -TargetSessionName $SessionName } $auth = if ($UseCredSSP) { 'CredSSP' } else { 'Default' } # WSMan: PS7 endpoint first try { $wsmanParams = @{ ComputerName = $ComputerName Credential = $Credential Authentication = $auth ConfigurationName = $Ps7ConfigName ErrorAction = 'Stop' SessionOption = $sessOpts Name = $SessionName } $s = New-PSSession @wsmanParams Write-Log -Level Ok -Message "Connected to $ComputerName via WSMan ($Ps7ConfigName)." return (Get-SessionOutputObject -Session $s -AsList:$AsList) } catch { # Fallback to Windows PowerShell endpoint $wsmanParams = @{ ComputerName = $ComputerName Credential = $Credential Authentication = $auth ConfigurationName = $WinPsConfigName ErrorAction = 'Stop' SessionOption = $sessOpts Name = $SessionName } $s = New-PSSession @wsmanParams Write-Log -Level Ok -Message "Connected to $ComputerName via WSMan ($WinPsConfigName)." return (Get-SessionOutputObject -Session $s -AsList:$AsList) } } } catch { $msg = $_.Exception.Message Write-Log -Level Error -Message "Failed to create PSSession to ${ComputerName}: $msg" throw } finally { $ErrorActionPreference = $oldEAP } } # SIG # Begin signature block # MIIfAgYJKoZIhvcNAQcCoIIe8zCCHu8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAnDxubrT0sWDMO # MkzRGCA3xWWIkTP2seNiIez3K4IR3KCCGEowggUMMIIC9KADAgECAhAR+U4xG7FH # qkyqS9NIt7l5MA0GCSqGSIb3DQEBCwUAMB4xHDAaBgNVBAMME1ZBRFRFSyBDb2Rl # IFNpZ25pbmcwHhcNMjUxMjE5MTk1NDIxWhcNMjYxMjE5MjAwNDIxWjAeMRwwGgYD # VQQDDBNWQURURUsgQ29kZSBTaWduaW5nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEA3pzzZIUEY92GDldMWuzvbLeivHOuMupgpwbezoG5v90KeuN03S5d # nM/eom/PcIz08+fGZF04ueuCS6b48q1qFnylwg/C/TkcVRo0WFcKoFGT8yGxdfXi # caHtapZfbSRh73r7qR7w0CioVveNBVgfMsTgE0WKcuwxemvIe/ptmkfzwAiw/IAC # Ib0E0BjiX4PySbwWy/QKy/qMXYY19xpRItVTKNBtXzADUtzPzUcFqJU83vM2gZFs # Or0MhPvM7xEVkOWZFBAWAubbMCJ3rmwyVv9keVDJChhCeLSz2XR11VGDOEA2OO90 # Y30WfY9aOI2sCfQcKMeJ9ypkHl0xORdhUwZ3Wz48d3yJDXGkduPm2vl05RvnA4T6 # 29HVZTmMdvP2475/8nLxCte9IB7TobAOGl6P1NuwplAMKM8qyZh62Br23vcx1fXZ # TJlKCxBFx1nTa6VlIJk+UbM4ZPm954peB/fIqEacm8LkZ0cPwmLE5ckW7hfK4Trs # o+RaudU1sKeA+FvpOWgsPccVRWcEYyGkwbyTB3xrIBXA+YckbANZ0XL7fv7x29hn # gXbZipGu3DnTISiFB43V4MhNDKZYfbWdxze0SwLe8KzIaKnwlwRgvXDMwXgk99Mi # EbYa3DvA/5ZWikLW9PxBFD7Vdr8ZiG/tRC9I2Y6fnb+PVoZKc/2xsW0CAwEAAaNG # MEQwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQW # BBRfYLVE8caSc990rnrIHUjoB7X/KjANBgkqhkiG9w0BAQsFAAOCAgEAiGB2Wmk3 # QBtd1LcynmxHzmu+X4Y5DIpMMNC2ahsqZtPUVcGqmb5IFbVuAdQphL6PSrDjaAR8 # 1S8uTfUnMa119LmIb7di7TlH2F5K3530h5x8JMj5EErl0xmZyJtSg7BTiBA/UrMz # 6WCf8wWIG2/4NbV6aAyFwIojfAcKoO8ng44Dal/oLGzLO3FDE5AWhcda/FbqVjSJ # 1zMfiW8odd4LgbmoyEI024KkwOkkPyJQ2Ugn6HMqlFLazAmBBpyS7wxdaAGrl18n # 6bS7QuAwCd9hitdMMitG8YyWL6tKeRSbuTP5E+ASbu0Ga8/fxRO5ZSQhO6/5ro1j # PGe1/Kr49Uyuf9VSCZdNIZAyjjeVAoxmV0IfxQLKz6VOG0kGDYkFGskvllIpQbQg # WLuPLJxoskJsoJllk7MjZJwrpr08+3FQnLkRuisjDOc3l4VxFUsUe4fnJhMUONXT # Sk7vdspgxirNbLmXU4yYWdsizz3nMUR0zebUW29A+HYme16hzrMPOeyoQjy4I5XX # 3wXAFdworfPEr/ozDFrdXKgbLwZopymKbBwv6wtT7+1zVhJXr+jGVQ1TWr6R+8ea # tIOFnY7HqGaxe5XB7HzOwJKdj+bpHAfXft1vUoiKr16VajLigcYCG8MdwC3sngO3 # JDyv2V+YMfsYBmItMGBwvizlQ6557NbK95EwggWNMIIEdaADAgECAhAOmxiO+dAt # 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa # Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E # MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy # unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF # xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1 # 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB # MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR # WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6 # nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB # YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S # UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x # q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB # NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP # TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC # AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp # Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0 # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB # LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc # Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov # Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy # oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW # juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF # mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z # twGpn1eqXijiuZQwgga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0GCSqG # SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy # dXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTlaMGkx # CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4 # RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYg # MjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHTCphB # cr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPhof6p # vF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mAxAHe # HYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBvMgEd # gkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps0wjU # jsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF83bR # VFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXiUOeS # LsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOMCZIV # NSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydPpOjL # 6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrUG2Zd # SoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+sdFU # eEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0TAQH/ # BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYDVR0j # BBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1Ud # JQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8E # PDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz # dGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEw # DQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WIGjB/ # T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+IQhQ # E7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8Myb9r # EVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2th9y # 1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjajV/gx # dEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2Lr3t # y9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFzeGxcy # tL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG7uEB # YTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+NJpud # /v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckTetiS # uEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszWkPZP # ubdcMIIG7TCCBNWgAwIBAgIQCoDvGEuN8QWC0cR2p5V0aDANBgkqhkiG9w0BAQsF # ADBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNV # BAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hB # MjU2IDIwMjUgQ0ExMB4XDTI1MDYwNDAwMDAwMFoXDTM2MDkwMzIzNTk1OVowYzEL # MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE # aWdpQ2VydCBTSEEyNTYgUlNBNDA5NiBUaW1lc3RhbXAgUmVzcG9uZGVyIDIwMjUg # MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANBGrC0Sxp7Q6q5gVrMr # V7pvUf+GcAoB38o3zBlCMGMyqJnfFNZx+wvA69HFTBdwbHwBSOeLpvPnZ8ZN+vo8 # dE2/pPvOx/Vj8TchTySA2R4QKpVD7dvNZh6wW2R6kSu9RJt/4QhguSssp3qome7M # rxVyfQO9sMx6ZAWjFDYOzDi8SOhPUWlLnh00Cll8pjrUcCV3K3E0zz09ldQ//nBZ # ZREr4h/GI6Dxb2UoyrN0ijtUDVHRXdmncOOMA3CoB/iUSROUINDT98oksouTMYFO # nHoRh6+86Ltc5zjPKHW5KqCvpSduSwhwUmotuQhcg9tw2YD3w6ySSSu+3qU8DD+n # igNJFmt6LAHvH3KSuNLoZLc1Hf2JNMVL4Q1OpbybpMe46YceNA0LfNsnqcnpJeIt # K/DhKbPxTTuGoX7wJNdoRORVbPR1VVnDuSeHVZlc4seAO+6d2sC26/PQPdP51ho1 # zBp+xUIZkpSFA8vWdoUoHLWnqWU3dCCyFG1roSrgHjSHlq8xymLnjCbSLZ49kPmk # 8iyyizNDIXj//cOgrY7rlRyTlaCCfw7aSUROwnu7zER6EaJ+AliL7ojTdS5PWPsW # eupWs7NpChUk555K096V1hE0yZIXe+giAwW00aHzrDchIc2bQhpp0IoKRR7YufAk # prxMiXAJQ1XCmnCfgPf8+3mnAgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAAMB0G # A1UdDgQWBBTkO/zyMe39/dfzkXFjGVBDz2GM6DAfBgNVHSMEGDAWgBTvb1NK6eQG # fHrK4pBW9i/USezLTjAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYB # BQUHAwgwgZUGCCsGAQUFBwEBBIGIMIGFMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz # cC5kaWdpY2VydC5jb20wXQYIKwYBBQUHMAKGUWh0dHA6Ly9jYWNlcnRzLmRpZ2lj # ZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZTSEEy # NTYyMDI1Q0ExLmNydDBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vY3JsMy5kaWdp # Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hB # MjU2MjAyNUNBMS5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcB # MA0GCSqGSIb3DQEBCwUAA4ICAQBlKq3xHCcEua5gQezRCESeY0ByIfjk9iJP2zWL # pQq1b4URGnwWBdEZD9gBq9fNaNmFj6Eh8/YmRDfxT7C0k8FUFqNh+tshgb4O6Lgj # g8K8elC4+oWCqnU/ML9lFfim8/9yJmZSe2F8AQ/UdKFOtj7YMTmqPO9mzskgiC3Q # YIUP2S3HQvHG1FDu+WUqW4daIqToXFE/JQ/EABgfZXLWU0ziTN6R3ygQBHMUBaB5 # bdrPbF6MRYs03h4obEMnxYOX8VBRKe1uNnzQVTeLni2nHkX/QqvXnNb+YkDFkxUG # tMTaiLR9wjxUxu2hECZpqyU1d0IbX6Wq8/gVutDojBIFeRlqAcuEVT0cKsb+zJNE # suEB7O7/cuvTQasnM9AWcIQfVjnzrvwiCZ85EE8LUkqRhoS3Y50OHgaY7T/lwd6U # Arb+BOVAkg2oOvol/DJgddJ35XTxfUlQ+8Hggt8l2Yv7roancJIFcbojBcxlRcGG # 0LIhp6GvReQGgMgYxQbV1S3CrWqZzBt1R9xJgKf47CdxVRd/ndUlQ05oxYy2zRWV # FjF7mcr4C34Mj3ocCVccAvlKV9jEnstrniLvUxxVZE/rptb7IRE2lskKPIJgbaP5 # t2nGj/ULLi49xTcBZU8atufk+EMF/cWuiC7POGT75qaL6vdCvHlshtjdNXOCIUjs # arfNZzGCBg4wggYKAgEBMDIwHjEcMBoGA1UEAwwTVkFEVEVLIENvZGUgU2lnbmlu # ZwIQEflOMRuxR6pMqkvTSLe5eTANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3 # AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG # AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCB8gPHl3FeN # zqMuh81vKygRX6qY8wIrGbD4o7KviNYU/zANBgkqhkiG9w0BAQEFAASCAgABIJxZ # fKyezNp8UO8mBKYDy6Iu3bcUp1mVXH8UJvS1a4T51PsDi9i74SvkKO1sTDPOtDHe # m9ehC7aZKb5ynC6hsDvRDJxTpYHuswaKCkT/E4mC6uGW/jJavX011/VyECtGC0bJ # bKqQP9GOjZ1dwCXHUcxdaf7XKPwD9NtQrcFouLLWjpUWqWEMwkRBsDSbFOzhjdWE # CkXCDftYFQg3hwyUc4ld8NSDge9MupzjwTuz1Ewaowep6YvnYuV2zQp1XzgvmOFV # SwDIRz2zxBxSv1KCZG1u2B5OSLPOBG2r6xb69XLAy2gRiv6HY0xYGx8tmncCy8Ts # tg2aepR7SIwE7sHELMaXk+UiCmglmGne2XO2OxUUctKkiP3OefCqfZvtiPCv6djt # fpBBVinM9y9bM+motW8Y+7ZtWhfxSbVwzGFXkT36jVtUnliPe350uMLLsj7Rfrfh # Ng2UE/7WgD9BR16LPvCq0hGVqBTjsWSpf97vLJPfIX3A6u7M2SH/h2ypwXcVEPis # vIKqr4ZJ0j4jmTl57SXVNhDfSmu25Vdhw3tzuO88R0X63skjByvj+oLhAYLCTzmU # l3PdWD6wsmjrPcRGHa0DbfKjbRIphWcEu0kO3Viz3BtLlqdXAZSo2/nVf8f6OfJU # urfuR6FbP624p9rGdKURwJ8Lht45Z8atHFjh9qGCAyYwggMiBgkqhkiG9w0BCQYx # ggMTMIIDDwIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcg # UlNBNDA5NiBTSEEyNTYgMjAyNSBDQTECEAqA7xhLjfEFgtHEdqeVdGgwDQYJYIZI # AWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJ # BTEPFw0yNjA1MjgxMzU3NTFaMC8GCSqGSIb3DQEJBDEiBCC/cX5geNLp7o0xlaoN # kjTL4Lzg8fQGiuSjFRIXsUFqczANBgkqhkiG9w0BAQEFAASCAgBrR9EmdlKFMGle # SEClfs91rXhpKwiNRZfWGVIr8AC0SB+Ec+Dyd4yKGlUpSHs1/iYyp9wdqdtq2uyK # Kg5rnk/5gD0QP6biCwOLiD1lw2CYBFi+SlCOny17Y3KFbxrLmcKjaKWZmsm2OEp6 # u3Rr81s8grfTdOP+99tYBW9Ny/jRdBZ2LWoBqMLCvxrBxfsaYEiveJutz9/0Njsm # smK29psZcarp++fI9zs+pb8UhRWaLzvLqSRXvIOaRquXldtsW+cy5AUfJVnhZJSb # tkhRFzbwpRgDlhHzTsTgImUrmDbeenyFFYktlsp4Pb9DneepTjKEUIWBBfiffH2h # ktZHI6BPlb4AaVfocQYRdhkknk/ni5NGXYzv8j+6NM1JM/2GWRtWx2nq3D5paZLo # CJ9cdt5c+DNN3uSkt+veLqNThuYPePoMr2KdmQFttvrfh1ChsC+9zuFap6cZmeKn # GfAL2I1paIQrQVat/WAUGqznnZdadickl600pE4X4kbOgGusjMcceqsV1NO9rGSV # s1QF0AyY4H6mOqRkqbr/CD7Ue/QBm4EG0oa4Nv31WTTyux+ew+pIS7X8+fFhyKIv # xBkPs3l4kjY4vTMrmSztczMUVZKyDLXwS1KX7RU1lEYAU5NFjJL24GJfgWu2SNso # Ec66N5LEGUbDMDm78bMu+QdLsvn+ug== # SIG # End signature block |