03-28-2019 02:32 AM - edited 02-20-2020 09:08 PM
Hi
Looks like there's not much example of api scripts down there or on the net for those who are using Powershell except this topic which was very helpful : https://community.cisco.com/t5/advanced-threats/some-handy-tips-for-amp4e-api-connections-with-powershell/td-p/3097485
So I decided to share mine, and I'm pretty sure it could be helpful for others.
I'm also sure that my scripts can be optimized , so feel free to share your thoughts about it
Generating Header (thx @ChiefSec-SF)
# $clientid = "XXXXXXXXXXXXXXX" # $apikey = "xxxx-xxxxx-xxxxx-xxxxx" # $EncodedUsernamePassword = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($('{0}:{1}' -f $clientid, $apikey))) $EncodedUsernamePassword='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' $Headers = @{'Authorization' = "Basic $($EncodedUsernamePassword)"; 'accept' = 'application/json'; 'Content-type' = 'application/json'; 'Accept-Encoding' = 'gzip, deflate'}
Some variables and my log function
$global:computerslist = $null $global:computer = $null $global:result = $null $global:event=$null $global:delete=$null $global:duplicate=$null $Date=Get-date -format "yyyyMMdd-HHmmss" $logfile = "C:\Temp\"+$date+"_Amp.log" #Region Log Function Log($String) { "[$([DateTime]::Now)]: $string" | Out-File -FilePath $logfile -Append } #endregion Log
Retrieving the full connectors list
#region Get Computer list Function Computerlist { $list=$null $url="https://api.eu.amp.cisco.com/v1/computers" Log "Retrieving Computers list" $list = Invoke-RestMethod -Method Get -Uri $url -Headers $Headers -ErrorVariable RestError -ErrorAction SilentlyContinue if ($RestError){ $HttpStatusCode = $RestError.ErrorRecord.Exception.Response.StatusCode.value__ $HttpStatusDescription = $RestError.ErrorRecord.Exception.Response.StatusDescription Log " - Unable to retrieve the computer list" Log " - Http Status Code: $($HttpStatusCode) - Http Status Description: $($HttpStatusDescription)" Log "Exiting the script" Exit } $global:computerslist = $list.data Log "Number of computers retrieved : $($computerslist.Count)" do { $url=$list.metadata.links.next $list = Invoke-RestMethod -Method Get -Uri $url -Headers $Headers -ErrorVariable RestError -ErrorAction SilentlyContinue if ($RestError){ $HttpStatusCode = $RestError.ErrorRecord.Exception.Response.StatusCode.value__ $HttpStatusDescription = $RestError.ErrorRecord.Exception.Response.StatusDescription Log " - Unable to retrieve the computer list" Log " - Http Status Code: $($HttpStatusCode) - Http Status Description: $($HttpStatusDescription)" Log "Exiting the script" Exit } $global:computerslist += $list.data Log "Number of computers retrieved : $($computerslist.Count)" } while ($list.metadata.links.next -ne $null) Log "Total Retrieved: $($List.metadata.results.total)" } #endregion list computers
Deleting connectors based on its guid, using global variable that was populate before calling the function
#region Delete computers Function Delete_Computer { foreach ($connector in $global:delete) { If ($connector.hostname -ne "keepthisconnector.tdomain.com"){ #if you want some to be excluded from the deletion $url = $url="https://api.eu.amp.cisco.com/v1/computers/"+$connector.connector_guid Log "Deleting $($connector.hostname) - $($connector.connector_guid)" $Response = Invoke-RestMethod -Method Delete -Uri $url -Headers $Headers -ErrorVariable RestError -ErrorAction SilentlyContinue if ($RestError){ $HttpStatusCode = $RestError.ErrorRecord.Exception.Response.StatusCode.value__ $HttpStatusDescription = $RestError.ErrorRecord.Exception.Response.StatusDescription Log " - Http Status Code: $($HttpStatusCode) - Http Status Description: $($HttpStatusDescription)" } Else {Log " - $($connector.hostname) deleted : $($response.data.deleted)"} } } } #endregion Delete_Computer
Retrieving All the groups
#region get groups Function Groups { Log "Retrieving Group list" $url="https://api.eu.amp.cisco.com/v1/groups" $global:groups = Invoke-RestMethod -Method Get -Uri $url -Headers $Headers $global:groups = $global:groups.data Log "$($groups.count) groups retrieved" # $global:groups |Format-Table } #endregion groups
Moving a connector to a group (passing the connector guid and the group guid)
#region move computers Function Move_Computer { Param([string[]]$Connector_Guid, [string[]]$group_guid) $url="https://api.eu.amp.cisco.com/v1/computers/"+$Connector_Guid $body = @{"group_guid" = $group_guid} $body = $body | ConvertTo-json Log "Moving $($connector_guid)" $move = Invoke-RestMethod -Method Patch -Uri $url -Headers $Headers -Body $body #-ErrorVariable $RestError -ErrorAction SilentlyContinue if ($RestError){ $HttpStatusCode = $RestError.ErrorRecord.Exception.Response.StatusCode.value__ $HttpStatusDescription = $RestError.ErrorRecord.Exception.Response.StatusDescription Log " - Unable to retrieve the computer list" Log " - Http Status Code: $($HttpStatusCode) - Http Status Description: $($HttpStatusDescription)" Log "Exiting the script" Exit } } #endregion move computers
Deleting duplicate (retrieved the connector list, then filter the duplicate the finally delete every duplicate and keep the latest last_seen)
#region Find_duplicate function Delete_Duplicate { $temp=@() $list=$null $global:duplicate=@() Computerlist $list = $global:computerslist.hostname |Sort $ht = @{} $list | foreach {$ht["$_"] += 1} $ht.keys | where {$ht["$_"] -gt 1} | foreach {$global:duplicate+= $_ } $global:duplicate = $global:duplicate|sort Log "Found $($global:duplicate.count) duplicate " foreach ($connector in $global:duplicate) { $temp = $global:computerslist.where({$_.hostname -like $connector}) $count = $temp.count -1 $global:delete = $temp | Sort-Object { $_.last_seen -as [datetime] } -Descending | Select -Last $count Delete_Computer } } #endregion
Retrieve the full scan event where scan path > 4 for a connector :
#region Get_events_Full_scan_Computer function Get_events_Full_scan { Param([string[]]$Connector_Guid) $global:event = $null $list=$null $url="https://api.eu.amp.cisco.com/v1/events?connector_guid[]="+$connector_guid $list = Invoke-RestMethod -Method Get -Uri $url -Headers $Headers $global:event = $list.data.where({$_.scan.description -like 'Full*' -and $_.scan.scanned_paths -gt 4}) |Sort-Object { $_.date -as [datetime] } -Descending | Select -first 1 } #endregion
Retrieve the list of connector having run a full scan for a specific group
function Get_events_Full_scan_Group { Param([string[]]$Group_Guid) $list=$null $global:event = $null $url="https://api.eu.amp.cisco.com/v1/events?group_guid[]="+$Group_Guid #Cp_Deployment $list = Invoke-RestMethod -Method Get -Uri $url -Headers $Headers $list.data |Format-List $global:event = $list.data.where({$_.scan.description -like 'Full*' -and $_.scan.scanned_paths -gt 4}) | Sort-Object { $_.date -as [datetime] } -Descending $global:event |Format-Table -Property connector_guid,Computer, date } #endregion
Retrive connector list for a specific group
Function Computerlist_Per_Group { Param([string[]]$Group_Guid) $list=$null Log "Retrieving connectors in the group: $($group_guid)" $url="https://api.eu.amp.cisco.com/v1/computers?group_guid[]="+$Group_Guid $list = Invoke-RestMethod -Method Get -Uri $url -Headers $Headers $global:computerslist = $list.data If ($list.metadata.links.next) { do { $url=$list.metadata.links.next $list = Invoke-RestMethod -Method Get -Uri $url -Headers $Headers $global:computerslist += $list.data } while ($list.metadata.links.next -ne $null) } Log "$($global:computerslist.count) connector retrieved" $global:computerslist = $global:computerslist | Sort-Object $_.hostname } #endregion list computers
Move a connector to another group (and optionally "only if a full scan has run on it")
#region Move_Computer_list Function Move_Computer_list { Param([string[]]$Group_Guid, [bool[]]$Full_Scan) $global:computerslist = $null Groups #retrieve the list of group Computerlist_Per_Group $Group_Guid # retrieve the list of connector belonging to a group foreach ($connector in $global:computerslist) { $Move=$false If ($Full_Scan) { Log "Retrieving Full scan Events for $($connector.hostname)" Get_events_full_scan $connector.connector_guid If ($global:event) { Log " Full scan events found" $Move=$True } Else {Log " No Full scan events found"} } Else {$Move=$True} If ($Move -and ($connector.hostname -like 'DT*'-or $connector.hostname -like 'LT*')) { $groupname=$connector.hostname.substring(2,$connector.hostname.length -18) $group= $global:groups.where({$_.name -match $groupname}) If ($group) { Write-Host "Moving $($connector.hostname) to $($groupname) Group" Move_Computer $connector.connector_guid $group.guid } } Else {Log " Skipping $($connector.hostname)"} } } #endregion
So here is how I use it :
#################### Delete connector not seen the past 10 days ################### # $Date_Last_seen = Get-Date -date $(Get-Date).AddDays(-10) -Format u # Computerlist # $global:delete = $global:computerslist.where({$_.last_seen -lt $Date_Last_seen -and $_.hostname -ne "keepthisconnecotr.domain.com"}) # If ($global:delete) { # Log "Starting deletion of $($global:delete.count) connectors" # Delete_Computer # } Else {Log "No computer found with this 10 days filter"} ################################################################################### ################################ Delete duplicate ################################# # Delete_Duplicate ################################################################################### ############## Move connector in "TEST" group if fullscan ok ############### # Move_Computer_list -group_guid 'xxxxx-xxxxx-xxxxx-xxxxxxx' -Full_Scan $true ################################################################################### ######################## Move connector in "temp" group ############################ # Move_Computer_list -group_guid '3xxxxxxx-xxxxx-xxxxx-xxxxxx' -Full_Scan $false ###################################################################################
Once again everything can be improved (like using a variable for the common part of $url, it's on my to do list :) ), I'm not a powershell expert, but those scripts saved me a lot , but a lot of time, and fill a lot of gaps in the portal.
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide