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 LogRetrieving 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 computersDeleting 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_ComputerRetrieving 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 groupsMoving 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 computersDeleting 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
}
}
#endregionRetrieve 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
}
#endregionRetrieve 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
}
#endregionRetrive 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 computersMove 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