Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #########################################################################################
- # LogRhythm | Cisco AMP for Endpoints - Get Events from API
- #########################################################################################
- #
- # LogRhythm - AHP
- # 26th April, 2018
- #
- # Version 1.5
- #
- # This script should be deployed in conjuction with the
- # LogRhythm - Cisco AMP for Endpoints Configuration Guide
- #
- # Change Log:
- #
- # Version | Date | Developer Name | Changes
- # 1.0 | 12th April, 2018 | Andy Habibi-Parker | First workable script
- # 1.1 | 16th April, 2018 | Andy Habibi-Parker | Added external log file
- # 1.2 | 24th April, 2018 | Andy Habibi-Parker | Added additional log output
- # 1.3 | 25th April, 2018 | Andy Habibi-Parker | Script is now HA aware
- # 1.4 | 26th April, 2018 | Andy Habibi-Parker | Script is now Proxy aware
- # 1.5 | 29th May, 2018 | Andy Habibi-Parker | Fixed Proxy detection bug
- #
- #########################################################################################
- # ################################
- # Define Parameters for the script
- # ################################
- [CmdletBinding()]
- param(
- [Parameter(Mandatory = $true)] $CredentialsFile,
- $logfile = " ",
- $MaxLogFileSizeBytes = 10 * 1000 * 1000,
- [switch]$DebugOutput
- )
- # If we're in debug mode, tell Powershell to write output to console
- if ($DebugOutput) {
- $DebugPreference = "Continue"
- }
- function Write-Log {
- [CmdletBinding()]
- param(
- [Parameter()]
- [ValidateNotNullOrEmpty()]
- [ValidateSet('Information', 'Warning', 'Error')]
- [string]$Severity = 'Information',
- [Parameter()]
- [ValidateNotNullOrEmpty()]
- [string]$Message
- )
- [pscustomobject]@{
- Time = (Get-Date -Format "dd-MMM-yyyy HH:mm:ss.fff")
- Severity = $Severity
- Message = $Message
- } | Export-Csv -Path $logfile -Append -NoTypeInformation
- }
- # Check if we're a HA System Monitor
- $HAservice = Get-Service -Name LifeKeeper -ErrorAction SilentlyContinue
- if ($HAservice.Length -gt 0) {
- if ((Get-Service -Name LifeKeeper).Status -eq 'Running') {
- $ServiceStatus = (Get-Service -Name "LifeKeeper").Status
- $HA = $true
- $StateFile = "D:\LogRhythmHA\LogRhythm System Monitor\AMP4EP\State\AMP4EP.pos"
- $EventsFile = "D:\LogRhythmHA\LogRhythm System Monitor\AMP4EP\Events\AMP4EP.txt"
- $logFile = "D:\LogRhythmHA\LogRhythm System Monitor\AMP4EP\Log\AMP4EP.log"
- Write-Log -Message ("This is a HA system. LifeKeeper service found: " + "LifeKeeper -" + $ServiceStatus) -Severity Information
- # Check if we're the active HA System Monitor
- if ($HA -eq $true -and ((Get-Service -Name "scsm").Status -ne 'Running')) {
- Write-Log -Message ("This is not the active HA node. Exiting") -Severity Warning
- exit
- }
- else {
- Write-Log -Message ("This is the active HA node") -Severity Information
- }
- }
- else {
- $logFile = "D:\LogRhythmHA\LogRhythm System Monitor\AMP4EP\Log\AMP4EP.log"
- Write-Log -Message ("This is a HA node but the LifeKeeper service is not running. Exiting") -Severity Warning
- exit
- }
- }
- else {
- $StateFile = "C:\Program Files\LogRhythm\LogRhythm System Monitor\AMP4EP\State\AMP4EP.pos"
- $EventsFile = "C:\Program Files\LogRhythm\LogRhythm System Monitor\AMP4EP\Events\AMP4EP.txt"
- $logFile = "C:\Program Files\LogRhythm\LogRhythm System Monitor\AMP4EP\Log\AMP4EP.log"
- Write-Log -Message ("This is not a HA system") -Severity Information
- }
- # Check if log file exists
- if (Test-Path $logFile) {
- # Check if the log file is larger than the Max allowable log file size
- if ((Get-Item $logFile).Length -ge $MaxLogFileSizeBytes) {
- # If so, clear the log file to start fresh
- Clear-Content $logFile
- Write-Debug ("Log File " + $logFile + " exceeded " + $MaxLogFileSizeBytes.ToString() + " bytes; truncating.")
- Write-Log -Message ("Log File " + $logFile + " exceeded " + $MaxLogFileSizeBytes.ToString() + " bytes; truncating.") -Severity Information
- }
- }
- # Check if the credentials file exists
- if (Test-Path $CredentialsFile) {
- Write-Debug ("Credentials file found: " + $CredentialsFile)
- Write-Log -Message ("Credentials file found: " + $CredentialsFile) -Severity Information
- try {
- $Credentials = Import-Clixml -Path $CredentialsFile
- $Clientid = $Credentials.Username
- $Apikey = $Credentials.GetNetworkCredential().Password
- }
- catch {
- Write-Error ("The credentials within the credentials file are corrupt. Please recreate the file: " + $CredentialsFile)
- Write-Log -Message ("The credentials within the credentials file are corrupt. Please recreate the file: " + $CredentialsFile) -Severity Error
- exit
- }
- }
- else {
- Write-Error ("Could not find credentials file: " + $CredentialsFile + ". Exiting")
- Write-Log -Message ("Could not find credentials file: " + $CredentialsFile + ". Exiting") -Severity Error
- Exit
- }
- # Datetime format for the state file
- $StateFileFormat = "yyyy-MM-ddTHH:mm:ss"
- # Define a default start time for message logs
- $DefaultStartTime = (Get-Date).AddDays(-7).ToUniversalTime()
- # Start by using the default start time
- $StartTime = $DefaultStartTime
- # Check if the state file exists
- if (Test-Path $StateFile) {
- Write-Debug ("State file " + $StateFile + " exists.")
- Write-Log -Message ("State file " + $StateFile + " exists.") -Severity Information
- try {
- $StateContent = Get-Content $StateFile
- # Attempt to parse the state file
- $StartTime = [datetime]::ParseExact($StateContent, $StateFileFormat, $null).ToUniversalTime()
- }
- catch {
- # If the state file doesn't contain a valid date, use the default
- $StartTime = $DefaultStartTime
- Write-Debug "Failed to parse date from the state file"
- Write-Debug $_.Exception
- Write-Log -Message "Failed to parse date from the state file" -Severity Error
- Write-Log -Message $_.Exception -Severity Error
- }
- }
- else {
- Write-Debug "State file did not exist, using default start time"
- Write-Log -Message "State file did not exist, using default start time" -Severity Information
- }
- Write-Debug ("Requesting AMP4EP logs from " + ($StartTime.ToString($StateFileFormat)))
- Write-Log -Message ("Requesting AMP4EP logs from " + ($StartTime.ToString($StateFileFormat))) -Severity Information
- # Base64 encode the username and password for authorization header
- $EncodedUTF8 = [System.Text.Encoding]::UTF8.GetBytes($Clientid + ":" + $Apikey)
- $EncodedPassword = [System.Convert]::ToBase64String($EncodedUTF8)
- $Header = @{ 'Authorization' = "Basic $($EncodedPassword)"; 'accept' = 'application/json'; 'Content-type' = 'application/json'; 'Accept-Encoding' = 'gzip, deflate' }
- $APIendpoint = "https://api.amp.cisco.com"
- $Filter1 = ("/v1/events")
- $Uri = ($APIendpoint + $Filter1)
- $Uri += "?start_date=" + ($StartTime.ToString($StateFileFormat))
- if (!(Test-Path $StateFile)) {
- $Uri += "&offset=500"
- }
- Write-Debug ("Calling AMP4EP API: " + $Uri)
- Write-Log -Message ("Calling AMP4EP API: " + $Uri) -Severity Information
- $proxyUri = [Uri]$null
- $proxy = [System.Net.WebRequest]::GetSystemWebProxy()
- if ($proxy) {
- $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
- $proxyUri = $proxy.GetProxy($Uri)
- }
- if ($proxyUri.AbsoluteUri -ne $Uri) {
- Write-Debug ("Using proxy: " + $proxyUri)
- Write-Log -Message ("Using proxy: " + $proxyUri) -Severity Information
- try {
- $Response = Invoke-RestMethod -Uri $Uri -Headers $Header -Method GET -UseDefaultCredentials -Proxy $proxyUri -ProxyUseDefaultCredentials
- }
- catch {
- Write-Error "Failed to call the AMP4EP API. Exiting"
- Write-Debug $_.Exception
- Write-Log -Message "Failed to call the AMP4EP API. Exiting" -Severity Error
- Write-Log -Message $_.Exception -Severity Error
- exit
- }
- }
- else {
- try {
- Write-Debug ("No proxy server detected")
- Write-Log -Message ("No proxy server detected") -Severity Information
- $Response = Invoke-RestMethod -Uri $Uri -Headers $Header -Method GET
- }
- catch {
- Write-Error "Failed to call the AMP4EP API. Exiting"
- Write-Debug $_.Exception
- Write-Log -Message "Failed to call the AMP4EP API. Exiting" -Severity Error
- Write-Log -Message $_.Exception -Severity Error
- exit
- }
- }
- # Which properties do we want from the output?
- $Properties = $(
- #Non-Array Extract
- @{ Name = "Date"; Expression = { "Date=" + $_.date } },
- @{ Name = "Timestamp"; Expression = { "Timestamp=" + $_.timestamp } },
- @{ Name = "EventID"; Expression = { "EventID=" + $_.id } },
- @{ Name = "Event_Type"; Expression = { "Event_Type=" + $_.event_type } },
- @{ Name = "Event_TypeID"; Expression = { "Event_TypeID=" + $_.event_type_id } },
- @{ Name = "Detection"; Expression = { "Detection=" + $_.detection } },
- @{ Name = "DetectionID"; Expression = { "DetectionID=" + $_.detection_id } },
- @{ Name = "Group_GUIDs"; Expression = { "Group_GUIDs=" + $_.group_guids } },
- # Computer Array Extract
- @{ Name = "Computer_Connector_GUID"; Expression = { "Computer_Connector_GUID=" + $_.computer.connector_guid } },
- @{ Name = "Computer_Hostname"; Expression = { "Computer_Hostname=" + $_.computer.hostname } },
- @{ Name = "Computer_External_IP"; Expression = { "Computer_External_IP=" + $_.computer.external_ip } },
- @{ Name = "Computer_User"; Expression = { "Computer_User=" + $_.computer.user } },
- @{ Name = "Computer_Active"; Expression = { "Computer_Active=" + $_.computer.active } },
- @{ Name = "Network_Addr_IP"; Expression = { "Network_Addr_IP=" + $_.computer.network_addresses.ip } },
- @{ Name = "Network_Addr.MAC"; Expression = { "Network_Addr_MAC=" + $_.network_addresses.mac } },
- @{ Name = "Links_Computer"; Expression = { "Links_Computer=" + $_.computer.links.computer } },
- @{ Name = "Links_Computer_Trajectory"; Expression = { "Links_Trajectory=" + $_.computer.links.trajectory } },
- @{ Name = "Links_Computer_Group"; Expression = { "Links_Group=" + $_.computer.links.group } },
- #File Array Extract
- @{ Name = "File_Disposition"; Expression = { "File_Disposition=" + $_.file.disposition } },
- @{ Name = "File_Name"; Expression = { "File_Name=" + $_.file.file_name } },
- @{ Name = "File_Path"; Expression = { "File_Path=" + $_.file.file_path } },
- @{ Name = "File_Identity_SHA1"; Expression = { "File_Identity_SHA1=" + $_.file.identity.sha1 } },
- @{ Name = "File_Identity_SHA256"; Expression = { "File_Identity_SHA256=" + $_.file.identity.sha256 } },
- @{ Name = "File_Parent_Disposition"; Expression = { "File_Parent_Disposition=" + $_.file.Parent.disposition } },
- @{ Name = "File_Parent_File_Name"; Expression = { "File_Parent_File_Name=" + $_.file.Parent.file_name } },
- @{ Name = "File_Parent_Identity_SHA1"; Expression = { "File_Parent_Identity_SHA1=" + $_.file.Parent.identity.sha1 } },
- @{ Name = "File_Parent_Identity_SHA256"; Expression = { "File_Parent_Identity_SHA256=" + $_.file.Parent.identity.sha256 } },
- #Scan Array Extract
- @{ Name = "Scan_Description"; Expression = { "Scan_Description=" + $_.scan.description } },
- @{ Name = "Scan_Clean"; Expression = { "Scan_Clean=" + $_.scan.clean } },
- @{ Name = "Scanned_Files"; Expression = { "Scanned_Files=" + $_.scan.scanned_files } },
- @{ Name = "Scanned_Processes"; Expression = { "Scanned_Processes=" + $_.scan.scanned_processes } },
- @{ Name = "Scanned_Paths"; Expression = { "Scanned_Paths=" + $_.scan.scanned_paths } },
- @{ Name = "Malicious_Detections"; Expression = { "Malicious_Detections=" + $_.scan.malicious_detections } }
- #Vulnerabilities Array Extract
- @{ Name = "Vuln_Name"; Expression = { "Vuln_Name=" + $_.vulnerabilities.Name } },
- @{ Name = "Vuln_Version"; Expression = { "Vuln_Version=" + $_.vulnerabilities.version } },
- @{ Name = "Vuln_CVEs"; Expression = { "Vuln_CVEs=" + $_.vulnerabilities.cve } },
- @{ Name = "Vuln_Scores"; Expression = { "Vuln_Scores=" + $_.vulnerabilities.score } },
- @{ Name = "CVE_URLs"; Expression = { "CVE_URLs=" + $_.vulnerabilities.url } },
- #Network_Info Array Extract
- @{ Name = "Dirty_URL"; Expression = { "Dirty_URL=" + $_.network_info.dirty_url } },
- @{ Name = "Remote_IP"; Expression = { "Remote_IP=" + $_.network_info.remote_ip } },
- @{ Name = "Remote_Port"; Expression = { "Remote_Port=" + $_.network_info.remote_port } },
- @{ Name = "Local_IP"; Expression = { "Local_IP=" + $_.network_info.local_ip } },
- @{ Name = "Local_Port"; Expression = { "Local_Port=" + $_.network_info.local_port } },
- #Generic_IOC Array Extract
- @{ Name = "IOC_Desc"; Expression = { "IOC_Desc=" + $_.generic_ioc.description } },
- @{ Name = "IOC_Short_Desc"; Expression = { "IOC_Short_Desc=" + $_.generic_ioc.short_description } }
- )
- # Check if events file exists
- if (Test-Path $EventsFile) {
- # Check if the events file is larger than the Max allowable log file size
- if ((Get-Item $EventsFile).Length -ge $MaxLogFileSizeBytes) {
- # If so, clear the log file to start fresh
- Clear-Content $EventsFile
- Write-Debug ("Events File " + $EventsFile + " exceeded " + $MaxLogFileSizeBytes.ToString() + " bytes; truncating.")
- Write-Log -Message ("Events File " + $EventsFile + " exceeded " + $MaxLogFileSizeBytes.ToString() + " bytes; truncating.") -Severity Information
- }
- }
- # Pull out the properties we want and sort by time
- $Output = $Response.data | Select-Object $Properties | Sort-Object timestamp
- try {
- # Export the logs, appending to the log file
- $Output |
- ConvertTo-Csv -NoTypeInformation |
- # This removes the header row
- Select-Object -Skip 1 |
- Out-File $EventsFile -Append -Encoding UTF8
- Write-Debug ("Wrote " + (@($Output).Length.ToString()) + " logs to file " + $EventsFile)
- Write-Log -Message ("Wrote " + (@($Output).Length.ToString()) + " logs to file " + $EventsFile) -Severity Information
- }
- catch {
- Write-Error ("Could not write logs to the file " + $EventsFile)
- Write-Debug $_.Exception
- Write-Log -Message ("Could not write logs to the events file: " + $EventsFile) -Severity Warning
- Write-Log -Message $_.Exception -Severity Error
- exit
- }
- # If number of received events is greater than 0
- if ((@($Output).Length.ToString()) -gt 0) {
- try {
- # Get the last date entry in the response
- $EndTime = $Response.data.Item(0) | date
- }
- catch {
- Write-Error "Could not get last date entry from received events"
- Write-Debug $_.Exception
- Write-Log -Message "Could not get last date entry from received events" -Severity Warning
- Write-Log -Message $_.Exception -Severity Error
- }
- try {
- # Add the last date entry to the StateFile
- $EndTime.ToString($StateFileFormat) | Out-File $StateFile
- }
- catch {
- Write-Error ("Could not write timestamp to state file: " + $StateFile + ". This may result in duplicate logs")
- Write-Debug $_.Exception
- Write-Log -Message ("Could not write timestamp to state file: " + $StateFile + ". This may result in duplicate logs") -Severity Warning
- Write-Log -Message $_.Exception -Severity Error
- }
- }
- else {
- Write-Debug "No new events available from AMP4EP"
- Write-Log -Message "No new events available from AMP4EP" -Severity Information
- }
Add Comment
Please, Sign In to add comment