IGEL - Shadow terminal

Version: 2.7.22
Creator Name: trentent.tye
Date Created: 2019-12-16
Date Modified: 2020-08-11
Scripting language: PS
Download Count: 15

Starts a VNC connection to the selected IGEL device Updated to remove certificate requirements.
Tags: igel

The Script

<#
    .SYNOPSIS
        Starts a vnc program to connect to a IGEL endpoint.

    .DESCRIPTION
        Starts a vnc program to connect to a IGEL endpoint.

    .EXAMPLE
        . .\IGEL_Shadow.ps1 -device IGEL01 -UMSServer igelums.acme.local -VNCExe "C:\Program Files\vnviewer.exe"
        Starts a VNC Shadow operation on the targetted IGEL device.

    .CONTEXT
        Machine

    .MODIFICATION_HISTORY
        Created TTYE : 2019-12-12


    AUTHOR: Trentent Tye
#>
[CmdLetBinding()]
Param (
    [Parameter(Mandatory=$true,HelpMessage='Enter the machine name of the endpoint')][ValidateNotNullOrEmpty()]   [string]$Device,
    [Parameter(Mandatory=$true,HelpMessage='FQDN of the IGEL UMS server')][ValidateNotNullOrEmpty()]              [string]$UMSServer,
    [Parameter(Mandatory=$true,HelpMessage='Path to vnc.exe')][ValidateNotNullOrEmpty()]                          [string]$VNCExe
    
)


Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$VerbosePreference = "continue"

function Invoke-IGELRestAPI {
    Param
    (
        [Parameter(Mandatory=$true)] [string]$URI,
        [Parameter(Mandatory=$true)] [hashtable]$Headers,
        [Parameter(Mandatory=$true)][ValidateSet("GET","POST","PUT","DELETE")] [string]$Method,
        [Parameter(Mandatory=$false)] $Body,
        [Parameter(Mandatory=$false)] [string]$ContentType,
        [Parameter(Mandatory=$false)] [switch]$Session
    )

    if ([bool]($body -as [xml])) {
        $body = [xml]$body
    }
    

    if ($body) {
        try {
        if ($session) {
            Write-Verbose "Executing REST API with a body and a new session variable"
            Invoke-WebRequest -Uri $URI -Method $method -Headers $headers -SessionVariable script:session -ContentType $ContentType -Body $body -UseBasicParsing -OutVariable webResult | Out-Null
            } else {
            Write-Verbose "Executing REST API with a body and a webSession variable"
            Invoke-WebRequest -Uri $URI -Method $method -Headers $headers -WebSession $script:session -ContentType $ContentType -Body $body -UseBasicParsing -OutVariable webResult  | Out-Null
            }
        } catch {
            $Failure = $_.Exception.Response
            return $Failure
        }
        Write-Verbose "Return Result with Body sent"
        return $webResult
    } else {
        try {
        if ($session) {
            Write-Verbose "Executing REST API and a new session variable"
            Invoke-WebRequest -Uri $URI -Method $method -Headers $headers -SessionVariable script:session -UseBasicParsing -OutVariable webResult  | Out-Null
            } else {
            Write-Verbose "Executing REST API with a webSession variable"
            Invoke-WebRequest -Uri $URI -Method $method -Headers $headers -WebSession $script:session -UseBasicParsing -OutVariable webResult  | Out-Null
            }
        } catch {
            $Failure = $_.Exception.Response
            return $Failure
        }
        return $webResult
    }
}

function Create-RESTBody {
    Param
    (
        [Parameter(Mandatory=$false,HelpMessage='ID of the device')] [string]$ID,
        [Parameter(Mandatory=$false,HelpMessage='objectType')] [string]$objectType
    )

 
        $JSONObject = New-Object -TypeName PSObject
        if ($ID)         { $JSONObject | add-member -name id -value $ID -MemberType NoteProperty           }
        if ($ObjectType) { $JSONObject | add-member -name type -value $objectType -MemberType NoteProperty }
        "[$($JSONObject | ConvertTo-Json)]"
}

function Create-Cookie($name, $value, $domain, $path="/"){
    $c=New-Object System.Net.Cookie;
    $c.Name=$name;
    $c.Path=$path;
    $c.Value = $value
    $c.Domain =$domain;
    return $c;
}

Write-Verbose "Variables:"
Write-Verbose "   Device :   $Device"
Write-Verbose "   UMSServer: $UMSServer"
Write-Verbose "   VNC Path:   $VNCExe"

if (-not(Test-Path "$env:temp\IGELCreds.xml")) {
    Write-Verbose "Saving new credentials..."
    $IGELCreds = Get-Credential -Message "Enter the credentials of an account that can authenticate to the UMS server"
    $IGELCreds | Export-Clixml "$env:temp\IGELCreds.xml"
} else {
    Write-Verbose "Found existing credentials. Importing..."
    $IGELCreds = Import-Clixml "$env:temp\IGELCreds.xml"
}

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($IGELCreds.Password)

# Step 1. Encode the credentials to Base64 string
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("$($IGELCreds.UserName):$([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR))"))

# Step 2. Form the header and add the Authorization attribute to it
$headers = @{ "Authorization" = "Basic $encodedCredentials" 
            "User-Agent"="ControlUp Powershell"
            }

# Most IGEL UMS servers (igelrmserver) dont have valid SSL Cert, thus ignore them
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
# https://stackoverflow.com/questions/11696944/powershell-v3-invoke-webrequest-https-error
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy



#Set the UMS Server to contain the port number. Set to the defaul 8443 if it was not specified on the parameter
if ($UMSServer -notlike "*:*") {
    $UMSServer = $UMSServer + ":8443"
}
Write-Verbose "UMSServer set to $UMSServer"

    
#test if IGEL server will respond
$serverResponse = Invoke-IGELRestAPI -URI "https://$UMSServer/umsapi/v3/serverstatus" -headers $headers -method GET -Session
if ($serverResponse.StatusCode -ne 200) 
{
    Write-Error "The script was unable to communicate to the IGEL UMS Server successfully."
}

#region Setup Session
$IGELSessionId = ($session.Cookies.GetCookies("https://$UMSServer/umsapi/v3/serverstatus")).value
$cookiedomain = ($session.Cookies.GetCookies("https://$UMSServer/umsapi/v3/serverstatus")).Domain
$cookiePath = ($session.Cookies.GetCookies("https://$UMSServer/umsapi/v3/serverstatus")).Path
$IGELAuthCookie = Create-Cookie -name "JSESSIONID" -value "$IGELSessionId" -domain "$cookieDomain" -path "$cookiePath"
Write-Verbose "Created cookie: JSESSIONID:$IGELSessionId"
$script:session.Cookies.Add($IGELAuthCookie)
#endregion Setup Session
 
#region authenticate
$auth = Invoke-IGELRestAPI -URI "https://$UMSServer/umsapi/v3/login" -headers $headers -method POST

if ($auth.StatusCode -ne "200") {
    Write-Error "Failed to login to the IGEL UMS via REST API.  Please check your username/password"
}

Write-Verbose "Authenticated Sucessfully.  Setting session information"
#endregion



$selectedDevice = $null
#Select Thin Client
$thinClients = Invoke-IGELRestAPI -URI "https://$UMSServer/umsapi/v3/thinclients" -headers $headers -method GET 
foreach ($thinClient in ($thinClients.Content | ConvertFrom-Json)) {
    if ($Device -like $thinClient.Name) {
        $selectedDevice = $thinClient
        Write-Verbose "Found a match!"
        Write-Verbose "$thinClient"
    }
}

if ($selectedDevice -eq $null) {
    Write-Error "Unable to find device : $Device"
}

$PostBody = Create-RESTBody -ID $selectedDevice.id -objectType $selectedDevice.objectType
$tcID = $selectedDevice.id


$commandResult = Invoke-IGELRestAPI -URI "https://$UMSServer/umsapi/v3/thinclients/$($tcId)?facets=shadow"               -headers $headers -method GET 

$lastIP = ($commandResult.Content | ConvertFrom-Json).lastIp
$VNCHostPort = "$lastIP`:5900"

if (-not(Test-Path -Path $VNCExe)) {
    Write-Output "Unable to find $VNCExe. Check your path and try again" | Msg *
}


$VNCProperties = Get-Item $VNCExe
$VNCProductName = $VNCProperties.VersionInfo.ProductName

## https://kb.igel.com/endpointmgmt-5.08/en/external-vnc-viewer-22459975.html
switch ($VNCProductName) {
    "TightVNC" { Start-Process -FilePath $VNCExe -ArgumentList ("$VNCHostPort") }
    "RealVNC"  { Start-Process -FilePath $VNCExe -ArgumentList ("$VNCHostPort") }
    "TigerVNC" { Start-Process -FilePath $VNCExe -ArgumentList ("$VNCHostPort") }
    "UltraVNC" { Start-Process -FilePath $VNCExe -ArgumentList ("-connect","$VNCHostPort") }
    default { Write-Output "Unable to determine VNC type. Trying default arguments"
              Start-Process -FilePath $VNCExe -ArgumentList ("$VNCHostPort") 
            }
}