Skip to main content

Powershell: Locate and delete any nodes disconnected after specified days.

  • 11 September 2020
  • 1 reply
  • 120 views

To execute - run .\CleanAutomoxDevices.psl (includes help on required paremeters)


Example run MVP run:


.\Clean-AutomoxDevices.ps1



Params:


orgID (required) - Your Automox Org ID


apiKey (required) - Your Automox API Key


maxDays (optional) - Defaults to 120 days. Override with any reasonable number.


apiEndpoint (optional) - What is the API endpoint to communicate with Automox?


logFolder (optional) - Override log folder. Defaults to popping out a log where script is run



apiTable (optional) - Override location in URI servers are found. This probably will never be used



weaponize (optional) - must be set to $true if you want anything other than a test run.



-verbose: All meaningful output not in the log can be brought to screen using this command. Most screen output is hidden without this param.



Destrictive run:


.\Clean-AutomoxDevices.ps1 -weaponize $true



All parameters are position and will be acceppepted either by their location in this above list - or using -. Also supported use -verbose if you want to see what is happening on the script. WARNING - This will output your apikey to screen!



System will return a usable json blob for further automation or reporting. You should be able to execute this script as a command line scheduled task - injecting the needed secrets at run time - and automate this entire process 🙂



The procesed device arrays are still stubbed out if someone finds use in tracking more detailed data.



Enjoy!





<#


Copyright 2020 Jeffrey Bragdon



Licensed under the Apache License, Version 2.0 (the “License”);


you may not use this file except in compliance with the License.


You may obtain a copy of the License at



   http://www.apache.org/licenses/LICENSE-2.0



Unless required by applicable law or agreed to in writing, software


distributed under the License is distributed on an “AS IS” BASIS,


WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.


See the License for the specific language governing permissions and


limitations under the License.



Credits:


Inspired by: Nic Tolstoshev - Automox Employee


Powershell script to remove devices that have been disconnected longer than X days



#>



Param(


>


parameter(


Mandatory=$True,


Position=0,


HelpMessage=‘Org ID found in Automox Site URI after the o=.’


)


]rString]$orgID,



/


parameter(


Mandatory=$True,


Position=1,


HelpMessage=‘API key found in the Automox console under Settings->Keys. Do not share!’


)


]rString]$apiKey,



<


parameter(


Mandatory=$False,


Position=2,


HelpMessage=‘Any device older than this is removed. Defaults to 120 days.’


)


] String] $maxDays=‘120’,






parameter(


Mandatory=$False,


Position=3,


HelpMessage=‘Automox endpoint. In case it changes, or there is a test endpoint.’


)


]/String]$apiEndpoint=‘https://console.automox.com/api/’,



a


parameter(


Mandatory=$False,


Position=4,


HelpMessage=‘Change the logfile folder. Otherwise, it drops a logfile where this script was executed.’


)


]

r


parameter(


Mandatory=$False,


Position=5,


HelpMessage=“API Table Reference.”


)


].String]$apiTable=‘servers’,



$


parameter(


Mandatory=$False,


Position=6,


HelpMessage=“Must be set to true, or this system will not do anything destructive.”


)


]tbool]$weaponize=$false



)



Try {



Used for time spans from the start of this script



$scriptStartTime=Get-Date


$scriptName=$MyInvocation.MyCommand.Name


Write-Verbose “$scriptName Initial Setup, Started running on $scriptStartTime”



if ($logFolder)


{


write-host “logFolder override was found. Writing logfile to $logFolder$scriptName.log”


$scriptLog = “$logFolder$scriptName.log”


}


else


{


Write-Verbose “No logFolder was defined. Writing log file locally.”


$path = Get-Location


$scriptLog = “$path$scriptName.log”


}


“----- Execution started at: $scriptStartTime -----” | Out-File -FilePath $scriptLog -Append



Setup the object with default values. This value is used for all relevent return information.



$returnObject = New-Object PSObject


$returnObject | Add-Member –MemberType NoteProperty –Name OrgID –Value $orgId


$returnObject | Add-Member –MemberType NoteProperty –Name ApiEndpoint –Value $apiEndpoint



Setup the needed keys to access the Automox API.



$orgAndKey="?o=$orgID&api_key=$apiKey"



Optional Query for fine tuning the search. We’ve only set this to search for dissconnected devices.



$query=’&connected=0’


$returnObject | Add-Member –MemberType NoteProperty –Name Query –Value $query



#Prepare the entire URI to communicate with the Automox API


$getURI=$apiEndpoint + $apiTable + $orgAndKey + $query



#Get the json body of the Web Request


$request=$(Invoke-WebRequest -UseBasicParsing -Method Get -Uri $getURI)


$jsonReturn=$request.Content



#Convert to object with manipulatable properties/values


$devices = $jsonReturn | ConvertFrom-Json


$returnObject | Add-Member –MemberType NoteProperty –Name ServerCount –Value $($devices.count)



Let’s return early if our server count is zero.



if ($devices.count -le 0)


{


Return $returnObject


}


else


{


" $($devices.count) devices found…" | Out-File -FilePath $scriptLog -Append


}


$pulledServersIn=$((New-TimeSpan -Start $scriptStartTime -End $(Get-Date)).Seconds).ToString() + " seconds"


Write-Verbose “Pulled servers from Automox API in $pulledServersIn”


#################\ Server Count Completed /#################


############################################################


#################/ Start Processing #################



Some prep work



$processed =@()


$skipped =@()


$successDelete =@()


$failDelete =@()



Write-Verbose “VVVVVVVVVVVVVVVVVVVVVVVV Processing VVVVVVVVVVVVVVVVVVVVVV”


if ($weaponize) {" !!! System is Weaponized !!!" | Out-File -FilePath $scriptLog -Append}


" going after systems that have not been seen for $maxDays days." | Out-File -FilePath $scriptLog -Append



foreach ($target in $devices)


{


# Pull useful information


$deviceID = $target.id


$deviceName = $target.name


$lastCheckin = rdatetime]$target.last_disconnect_time


Write-Verbose “~~~~~~~ Checking Device: $deviceName ID: $deviceID ~~~~~~~”



$span = New-TimeSpan -Start $lastCheckin

if ($span.Days -ge $maxDays)

{

Write-Verbose " Last checked in date was $lastCheckin which is longer than $maxDays days ago."

$processed += @{"DeviceName"=$deviceName;"ServerID"=$deviceID;"last_disconnect_time"=$lastCheckin}

if ($weaponize)

{

Write-Verbose " Weaponized ~~> Attempting to process deletion."



$delURI = $apiEndpoint + $apiTable + '/' + $deviceID + $orgAndKey

try {

$delResponse = Invoke-WebRequest -UseBasicParsing -Method Delete -Uri $delURI

Write-Verbose " Successfully deleted server!"

" Deleted $deviceName" | Out-File -FilePath $scriptLog -Append

$successDelete += @{"ServerName"=$deviceName;"ServerID"=$deviceID;"last_disconnectn_time"=$lastCheckin}

}

catch {

$ThisThrowMessage = $_.Exception.Message

Write-Verbose " Failed to Delete Server: $deviceName --> $ThisThrowMessage"

" Something went wrong with deleting $deviceName --> $ThisThrowMessage" | Out-File -FilePath $scriptLog -Append

$failDelete += @{"ServerName"=$deviceName;"ServerID"=$deviceID;"last_disconnect_time"=$lastCheckin}

}

}

else

{

Write-Verbose " What if ~~> This is running in protected mode."

" I would have Deleted $deviceName" | Out-File -FilePath $scriptLog -Append

}



}

else

{

Write-Verbose " Skipping....."

$skipped += @{"DeviceName"=$deviceName;"ServerID"=$deviceID;"last_disconnect_time"=$lastCheckin}

}



}



" We skipped over $($skipped.count) devices that were last seen within $maxDays days." | Out-File -FilePath $scriptLog -Append



$returnObject | Add-Member –MemberType NoteProperty –Name Processed –Value $($processed.count)


$returnObject | Add-Member –MemberType NoteProperty –Name Skipped –Value $($skipped.count)


$returnObject | Add-Member –MemberType NoteProperty –Name Deleted –Value $($successDelete.count)


$returnObject | Add-Member –MemberType NoteProperty –Name Failed –Value $($failDelete.count)


$returnObject | Add-Member –MemberType NoteProperty –Name Weaponized –Value $(int]$weaponized)


return (ConvertTo-Json $returnObject -Depth 3)


}



Catch {


$ThisThrowMessage = "Failure: $scriptName threw: " + $_.Exception.Message


Return $ThisThrowMessage


}



Finally {


$totalExecutionTime = $((New-TimeSpan -Start $scriptStartTime -End $(Get-Date)).Seconds).ToString() + " seconds"


Write-Verbose “Executed in: $totalExecutionTime”


“----- Executed completed in: $totalExecutionTime -----” | Out-File -FilePath $scriptLog -Append


}



1 reply


https://github.com/bragdonjm/PS-Automox-Worklets/blob/main/Powershell/Clean-AutomoxDevices.ps1 Formatting gets messed up. This should fix that.

Reply