Scripting out a list of SyncroMSP duplicate assets

Contents
show
Issue / Fault definition
SyncroMSP has a flaw where if you re-image a device when the agent is installed, it will create a duplicate asset rather than merge into the old existing asset; over time, you end up with many hundreds of duplicated assets.
Here’s a step-by-step breakdown of the script:
- Variables are defined to store the assets, tenant, authorization details, and the base URL of the API.
- The script then tries to authenticate to the SyncroMSP API using the provided tenant and API key.
- If authentication is successful, it requests the API to get all the assets.
- The script then starts gathering all the assets from each page by sending a GET request for each page. The progress of this process is shown to the user.
- After gathering the assets, it “explodes” the JSON response into an array of assets, excluding the ones whose form factor is ‘Server’.
- Next, it identifies all duplicate assets based on their serial numbers.
- Then, for each duplicate, the script selects the asset that hasn’t checked in for the longest time, presumably to mark them for deletion.
- Lastly, the script sends a PUT request to the API for each selected asset, marking them for deletion by updating their properties to include “Old_Duplicate” = “Yes”.
- In case of any error during the execution of the script, it is caught and displayed to the user.
Known Fixes / Solutions
SyncroMSP currently provides no known solutions in-house, but I have been able to use the API to create a PowerShell script that will identify these for manual deletion. (Fingers crossed, providing SyncroMSP can confirm the API is able to delete the script can do this also)
Clear-Host $Asset_Array = @() $Asset_Array_exploded = @() $Asset_Duplicates = @() $Data = @() $tenant = "your tenant name" $Authorization = "your API key" $baseUri = 'https://' + $tenant + '.syncromsp.com/api/v1/customer_assets' try{ Write-Host "Authenticating to SyncroMSP, please wait... " -ForegroundColor Blue -NoNewline $headers = @{ 'method' = 'GET' 'Accept' = 'Application/Json' 'Authorization' = $Authorization } $Json = Invoke-RestMethod -Uri $baseUri -Headers $headers -ErrorAction Stop $Max_Pages = $Json.meta.total_pages $Total_entries = $Json.meta.total_entries Write-Host "Done." -ForegroundColor Green Write-Host "Gathering $Total_entries assets from $Max_Pages pages, please wait... " -ForegroundColor Blue #Loop around each page and get the assets and ID's into an array for ($Page_Number = 1; $Page_Number -le $Max_Pages; $Page_Number++){ $uri = $baseUri + '?page=' + $Page_Number $Json = Invoke-RestMethod -Uri $uri -Headers $headers -ErrorAction Stop foreach ($asset in $Json.assets){ $Asset_Array += @([pscustomobject]@{Asset_Name = $asset.name; Asset_id = $asset.id; Asset_serial_number = $asset.asset_serial; Asset_updated_at = $asset.updated_at; Asset_form_factor = $asset.properties.form_factor}) } } Write-Host "Done." -ForegroundColor Green Write-Host "Explode the JSON content into an array, please wait... " -ForegroundColor Blue -NoNewline #break the array down into an exploded array and add to a table $Asset_Array_exploded = $Asset_Array | Where-Object {$_.Asset_form_factor -notmatch "Server"} Write-Host "Done." -ForegroundColor Green Write-Host "Gathering all duplicates, please wait... " -ForegroundColor Blue -NoNewline #Get the duplicates and counts $Asset_Duplicates_list = $Asset_Array_exploded.Asset_serial_number | Group-Object | Where-Object {$_.Count -gt 1} | Select-Object Name, Count #loop around each duplicate and get the details $StartDate = Get-Date $Asset_Duplicates = foreach ($duplicate in $Asset_Duplicates_list) { $Asset_Array | Where-Object { $duplicate.Name -eq $_.Asset_serial_number } | ForEach-Object { [pscustomobject]@{AssetName = $_.Asset_Name; AssetID = $_.Asset_id; AssetSerial = $_.Asset_serial_number; LastCheckinDays = ($StartDate - [DateTime]$_.Asset_updated_at).Days; LastCheckinDate = [DateTime]$_.Asset_updated_at; Asset_form_factor = $_.Asset_form_factor} } } Write-Host "Done." -ForegroundColor Green Write-Host "Gathering duplicates to delete, please wait... " -ForegroundColor Blue -NoNewline Write-Host "Done." -ForegroundColor Green $deletes = $Asset_Duplicates | Sort-Object AssetSerial, LastCheckinDate | Group-Object AssetSerial | ForEach-Object { $_.group | Select-Object -First 1 } $deletes | Sort-Object -Property LastCheckinDate | Format-Table Write-Host "Updating SyncroMSP duplicates, please wait... " -ForegroundColor Blue foreach ($delete in $deletes) { $uri = $baseUri + '/' + $delete.AssetID Write-Host "Marking asset for deletion ID:" $delete.AssetID -ForegroundColor Yellow $null = Invoke-RestMethod -Method Put -Uri $uri -Headers $headers -Body (ConvertTo-Json @{"asset" = @{"properties" = @{"Old_Duplicate" = "Yes"}}}) -ContentType "application/json" -ErrorAction Stop } Write-Host "Done." -ForegroundColor Green } catch { Write-Host "There was an error in execution:" $_.Exception.Message -ForegroundColor Red exit }