This ia a rather quick one as I already had some of the basics in my last script to send messages to global sessions. I have created a script that will gather all sessions in a Horizon environment. The global sessions api call has only been available since Horizon 2111 so when trying with an older version of Horizon it will return errors. Because some of the methods I use Powershell 7 is required.
There are 4 arguments:
- Credential : Optional credentials object from get-credential (wil ask for credentials if not provided)
- ConnectionServerFQDN : name says enough, fqdn for a connection server to connect to
- global : switch to enable gathering of all Global sessions
- pod_name: name of a single pod to collect all sessions from in case of a CPA
Usage:
.\Horizon_Rest_Get_Sessions.ps1 -Credential $creds -ConnectionServerFQDN "server.domain.dom"
And the other options are
.\Horizon_Rest_Get_Sessions.ps1 -Credential $creds -ConnectionServerFQDN "server.domain.dom" -global
.\Horizon_Rest_Get_Sessions.ps1 -Credential $creds -ConnectionServerFQDN "server.domain.dom" -global -pod_name "podname"
The Script can be found down below or on Github:
<#
.SYNOPSIS
Gets all (global) sessions for an Horizon environment
.DESCRIPTION
This script uses the Horizon rest api's to all gather alls essions in a Horizon (Cloud Pod) environment
.EXAMPLE
.\Horizon_Rest_Get_Sessions.ps1 -Credential $creds -ConnectionServerFQDN pod2cbr1.loft.lab
.EXAMPLE
.\Horizon_Rest_Get_Sessions.ps1 -Credential $creds -ConnectionServerFQDN pod2cbr1.loft.lab -global
.EXAMPLE
.\Horizon_Rest_Get_Sessions.ps1 -Credential $creds -ConnectionServerFQDN pod2cbr1.loft.lab -pod_name "Horizon_pod2"
.PARAMETER Credential
Mandatory: No
Type: PSCredential
Object with credentials for the connection server with domain\username and password
.PARAMETER ConnectionServerFQDN
Mandatory: Yes
Default: String
FQDN of the connection server to connect to
.PARAMETER global
Mandatory: No
Switch to select global sessions or only sessions for the local pod (Horizon 2111 and later)
.PARAMETER pod_name
Mandatory: No
String for name of the pod to get sessions for. (Horizon 2111 and later)
.NOTES
Created by: Wouter Kursten
First version: 03-06-2022
.COMPONENT
Powershell Core
#>
[CmdletBinding()]
param (
[Parameter(Mandatory=$false,
HelpMessage='Credential object as domain\username with password' )]
[PSCredential] $Credential,
[Parameter(Mandatory=$true, HelpMessage='FQDN of the connectionserver' )]
[ValidateNotNullOrEmpty()]
[string] $ConnectionServerFQDN,
[Parameter(Mandatory=$false,
ParameterSetName="globalsessions",
HelpMessage='Parameter to select Global Sessions' )]
[switch] $global,
[Parameter(Mandatory=$false,
ParameterSetName="globalsessions",
HelpMessage='Name of the pod to get the sessions for, needs -Global, defaults to *' )]
[string] $pod_name
)
function Get-HRHeader(){
param($accessToken)
return @{
'Authorization' = 'Bearer ' + $($accessToken.access_token)
'Content-Type' = "application/json"
}
}
function Open-HRConnection(){
param(
[string] $username,
[string] $password,
[string] $domain,
[string] $url
)
$Credentials = New-Object psobject -Property @{
username = $username
password = $password
domain = $domain
}
return invoke-restmethod -Method Post -uri "$url/rest/login" -ContentType "application/json" -Body ($Credentials | ConvertTo-Json)
}
function Close-HRConnection(){
param(
$accessToken,
$url
)
return Invoke-RestMethod -Method post -uri "$url/rest/logout" -ContentType "application/json" -Body ($accessToken | ConvertTo-Json)
}
function Get-HorizonRestData(){
[CmdletBinding(DefaultParametersetName='None')]
param(
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $ServerURL,
[Parameter(Mandatory=$false,
ParameterSetName="filteringandpagination",
HelpMessage='Array of ordered hashtables' )]
[array] $filters,
[Parameter(Mandatory=$false,
ParameterSetName="filteringandpagination",
HelpMessage='Type of filter Options: And, Or' )]
[ValidateSet('And','Or')]
[string] $Filtertype,
[Parameter(Mandatory=$false,
ParameterSetName="filteringandpagination",
HelpMessage='Page size, default = 500' )]
[int] $pagesize = 500,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[string] $RestMethod,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[PSCustomObject] $accessToken,
[Parameter(Mandatory=$false,
ParameterSetName="filteringandpagination",
HelpMessage='$True for rest methods that contain pagination and filtering, default = False' )]
[switch] $filteringandpagination,
[Parameter(Mandatory=$false,
ParameterSetName="id",
HelpMessage='To be used with single id based queries like /monitor/v1/connection-servers/{id}' )]
[string] $id,
[Parameter(Mandatory=$false,
HelpMessage='Extra additions to the query url that comes before the paging/filtering parts like brokering_pod_id=806ca in /rest/inventory/v1/global-sessions?brokering_pod_id=806ca&page=2&size=100' )]
[string] $urldetails
)
if($filteringandpagination){
if ($filters){
$filterhashtable = [ordered]@{}
$filterhashtable.add('type',$filtertype)
$filterhashtable.filters = @()
foreach($filter in $filters){
$filterhashtable.filters+=$filter
}
$filterflat=$filterhashtable | convertto-json -Compress
if($urldetails){
$urlstart= $ServerURL+"/rest/"+$RestMethod+"?"+$urldetails+"&filter="+$filterflat+"&page="
}
else{
$urlstart= $ServerURL+"/rest/"+$RestMethod+"?filter="+$filterflat+"&page="
}
}
else{
if($urldetails){
$urlstart= $ServerURL+"/rest/"+$RestMethod+"?"+$urldetails+"&page="
}
else{
$urlstart= $ServerURL+"/rest/"+$RestMethod+"?page="
}
}
$results = [System.Collections.ArrayList]@()
$page = 1
$uri = $urlstart+$page+"&size=$pagesize"
$response = Invoke-RestMethod $uri -Method 'GET' -Headers (Get-HRHeader -accessToken $accessToken) -ResponseHeadersVariable responseheader
$response.foreach({$results.add($_)}) | out-null
if ($responseheader.HAS_MORE_RECORDS -contains "TRUE") {
do {
$page++
$uri = $urlstart+$page+"&size=$pagesize"
$response = Invoke-RestMethod $uri -Method 'GET' -Headers (Get-HRHeader -accessToken $accessToken) -ResponseHeadersVariable responseheader
$response.foreach({$results.add($_)}) | out-null
} until ($responseheader.HAS_MORE_RECORDS -notcontains "TRUE")
}
}
elseif($id){
$uri= $ServerURL+"/rest/"+$RestMethod+"/"+$id
$results = Invoke-RestMethod $uri -Method 'GET' -Headers (Get-HRHeader -accessToken $accessToken) -ResponseHeadersVariable responseheader
}
else{
if($urldetails){
$uri= $ServerURL+"/rest/"+$RestMethod+"?"+$urldetails
}
else{
$uri= $ServerURL+"/rest/"+$RestMethod
}
$results = Invoke-RestMethod $uri -Method 'GET' -Headers (Get-HRHeader -accessToken $accessToken) -ResponseHeadersVariable responseheader
}
return $results
}
function get-horizonglobalsessions(){
[CmdletBinding(DefaultParametersetName='None')]
param(
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $ServerURL,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[PSCustomObject] $accessToken,
[Parameter(Mandatory=$true,
HelpMessage='Id of the Local pod to query' )]
[string] $podid
)
try{
$results=Get-HorizonRestData -ServerURL $url -RestMethod "/inventory/v1/global-sessions" -accessToken $accessToken -urldetails "pod_id=$podid"
}
catch{
throw $_
}
return $results
}
function Get-Pods(){
[CmdletBinding(DefaultParametersetName='None')]
param(
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $ServerURL,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[PSCustomObject] $accessToken
)
try{
$results=Get-HorizonRestData -ServerURL $url -RestMethod "/federation/v1/pods" -accessToken $accessToken
}
catch{
throw $_
}
return $results
}
if($Credential){
$creds = $credential
}
else{
$creds = get-credential
}
$ErrorActionPreference = 'Stop'
$username=($creds.username).split("\")[1]
$domain=($creds.username).split("\")[0]
$password=$creds.password
$url = "https://$ConnectionServerFQDN"
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
$accessToken = Open-HRConnection -username $username -password $UnsecurePassword -domain $Domain -url $url
if($global){
$pods=get-pods -accessToken $accessToken -ServerURL $url
if($pod_name){
$pod = $pods | Where-Object {$_.name -eq $pod_name}
$podid=$pod.id
$sessions = get-horizonglobalsessions -accessToken $accessToken -ServerURL $url -podid $podid -filteringandpagination
return $sessions
}
else{
$sessions=@()
foreach ($pod in $pods){
$podid=$pod.id
$sessions += get-horizonglobalsessions -accessToken $accessToken -ServerURL $url -podid $podid -filteringandpagination
}
return $sessions
}
}
else{
$sessions = Get-HorizonRestData -ServerURL $url -RestMethod "/inventory/v1/sessions" -accessToken $accessToken -filteringandpagination
return $sessions
}

