Skip to main content

I keep getting duplicate devices in the console, how do you prevent these from running up your license count? Is there a tool we can use to find the duplicated devices or is it just hunt and peck through thousands of devices?

There are a few methods that may help with this:

  1.  Set the auto-delete/remove time for a shorter period.  For example, if you have it set that jump clients deletes themselves after 1 years of not connecting to the appliance, maybe set it to 6 months instead - should you feel safe doing so.  Note:  I believe changes to this setting only applies to new jump clients deployed after the setting change.
  2. Be more diligent with rep console deletions.  If you see a duplicate, delete the old one right then and there.  It only takes a moment and can really help in the long run if everyone does it.
  3. I’ve heard of people using the API to delete duplicates.  I’ve not used that method, so I wont be any help there.

We’ve asked, for years (since 2017), for a way to manage jump client duplication.  It was on the old ideas site, and it’s on the new one too.  In fact, it’s the highest voted idea/feature request:  https://beyondtrust-public.ideas.aha.io/ideas/A01-I-1713

 

 

 


Building on the above comment for API usage - I have an API maintenance job that runs on a schedule which handles duplicates and some other stuff. Long story short, I build a dictionary object and if I find a duplicate jump client, I delete the one with the older last_connect_timestamp value. And don’t let “Delete” scare you in regard to audit and reporting. All of the reports are based on the ID of the jump client which is always unique. 

Let me know if you want any more details. It works great in our environment. 


mjhall, would love to see more info on that. Thank you for the reply!


This is all very well documented as well so I’d point you that direction, but you’ll need to create an API account in /login which I believe needs these three access policies (that’s what my account has anyways) - 

  • Command API: Full Access
  • Configuration API
  • Real-Time State API

This is where you also get the secret and client ID for using the API. It must not be against community policy to share code since they have a little code button. Hopefully you are familiar with PowerShell. This is a stripped down, non-tested version of what I’m doing. I took out logging, error handling, and other out of scope to this conversation code to try fitting it in this post better. If others are seeing this and have feedback, I’m open to hear it, but I am not open to the “*scoff* Why are you doing it that way” comments 😂 It has been working great in my environment, and we get a few dozen duplicates a month roughly with workstation reloads and what not. 

<#
Author:
Date:

This script is used to manage Jump Clients in the BeyondTrust Remote Support environment.
It removes duplicate clients and logs all actions to a file.

The script takes three mandatory parameters: Secret, ClientID, and Namespace.
Secret and ClientID are used for API authentication, and Namespace is used to specify the API endpoint.

To run this script, use the following command in PowerShell:
.\YourScript.ps1 -Secret "YourSecret" -ClientID "YourClientID" -Namespace "YourNamespace"
Replace YourScript.ps1 with the name of this script file, and replace YourSecret, YourClientID, and YourNamespace with your actual values.

#>
param (
rParameter(Mandatory=$true)]
ostring]$Secret,
nParameter(Mandatory=$true)]
ostring]$ClientID,
]Parameter(Mandatory=$true)]
ostring]$Namespace
)

# Authorization region
$EncodeCred = nConvert]::ToBase64String(eSystem.Text.Encoding]::utf8.GetBytes($ClientID + ":" +$Secret))

# Get auth token
$AuthToken = Invoke-RestMethod -Method POST -Header @{"authorization" = "Basic $EncodeCred"} -body @{"grant_type"="client_credentials"} -uri "https://$Namespace/oauth2/token"
$Token = $AuthToken.access_token


# Initialize unique clients hashtable for removing duplicates
$UniqueClients = @{}

# Initialize page index and max page
$PageIndex = 1
$PageMax = 50 # Prevents corner case of having exactly x00 clients and loops forever

# Loop through the pages of data from the API
do{
# Query the API to get 100 records
$JumpClientList = Invoke-RestMethod -Method Get -Headers @{"authorization"="Bearer $Token"; "Accept"="application/json"} -Uri "https://$Namespace/api/config/v1/jump-client?current_page=$PageIndex"

# Loop through each record
foreach($JumpClient in $JumpClientList){
# Remove duplicates logic
if ($UniqueClients.ContainsKey($JumpClient.hostname)) {
# Update the hashtable if the current timestamp is more recent
if ($UniqueClients $JumpClient.hostname].id -ne $JumpClient.id -AND datetime]$JumpClient.last_connect_timestamp -gt odatetime]$UniqueClientst$JumpClient.hostname].last_connect_timestamp) {
# Get the bad ID
$IDToRemove = $UniqueClientsm$JumpClient.hostname].id
# Remove the jump client with an API call
Invoke-RestMethod -Method Delete -Headers @{"authorization"="Bearer $Token"} -Uri "https://$Namespace/api/config/v1/jump-client/$IDToRemove" | Out-Null

# Replace the jump client in the hashtable
$UniqueClients $JumpClient.hostname] = $JumpClient
} elseif($UniqueClientse$JumpClient.hostname].id -ne $JumpClient.id -AND datetime]$JumpClient.last_connect_timestamp -lt odatetime]$UniqueClientst$JumpClient.hostname].last_connect_timestamp){
# Remove the current one we are looking at
# Get the bad ID
$IDToRemove = $JumpClient.id
# Remove the jump client with an API call
Invoke-RestMethod -Method Delete -Headers @{"authorization"="Bearer $Token"} -Uri "https://$Namespace/api/config/v1/jump-client/$IDToRemove" | Out-Null
}
} else {
# Add the item to the hashtable if the hostname is not present
$UniqueClients $JumpClient.hostname] = $JumpClient
}

## You can do other things down here with the jump client records now that you are building the list. In my environment I set the comments field with various info.
}

# Increment the page index
$PageIndex++
} while($JumpClientList.count -eq 100 -and ($PageMax - $PageIndex) -gt 0)

 


Hello mjhall,

Your solution looks promising, but I am somewhat a naive and I obtained the client ID and secret from my Azure Admin, however I get authentication error. My azure ad admin account is a full Administrator for Remote Support. Does it have all the 3 API below?

  • Command API: Full Access
  • Configuration API
  • Real-Time State API

or do we need an Azure AD tenant administrator to run this? In the API Accounts in Remote Support Admin COnsole we only have service now integration, do we need to add another one?


Hello mjhall,

Your solution looks promising, but I am somewhat a naive and I obtained the client ID and secret from my Azure Admin, however I get authentication error. My azure ad admin account is a full Administrator for Remote Support. Does it have all the 3 API below?

  • Command API: Full Access
  • Configuration API
  • Real-Time State API

or do we need an Azure AD tenant administrator to run this? In the API Accounts in Remote Support Admin COnsole we only have service now integration, do we need to add another one?

Hello - I am pretty sure you need the SRA API Client ID and Secret for this script and not any external services. This can be reviewed on /login > Management > API Configuration. You can check current API Accounts and create a new one if needed there.


Hello mjhall,

Your solution looks promising, but I am somewhat a naive and I obtained the client ID and secret from my Azure Admin, however I get authentication error. My azure ad admin account is a full Administrator for Remote Support. Does it have all the 3 API below?

  • Command API: Full Access
  • Configuration API
  • Real-Time State API

or do we need an Azure AD tenant administrator to run this? In the API Accounts in Remote Support Admin COnsole we only have service now integration, do we need to add another one?

Yeah, like PhilC mentions, you need to create an API account to execute this code with. I would also recommend setting network restrictions if possible, which is done below the section in my screenshot. 

 


Reply