AESB - ACMP Defender Telegram Notifier

Feedback und Verbesserungsvorschläge zu ACMP
Antworten
Benutzeravatar
lukas.petermann
Beiträge: 83
Registriert: Mi Jul 22, 2020 8:44 am

Guten Morgen Community.

Ich habe anlässlich des letzten ACMP Anwendertreffen in ACMP 6.4.1 / AESB 1.6.2 das PowerShell Skript nachgebaut.
Habe hier einen per CMD getesteten Telegram ChatBot.
Somit habe ich das mal auf PowerShell umgeschrieben und getestet ob es aus dem AESB PowerShell Skript heraus auch funktioniert, und das klappte.

Dann habe ich das Skript aus dem Vortrag nachgebaut, sowie auch das Schema.
Habe es dann auch als MicroService erstellen lassen, und auch eine Instanze gemacht die mit der Vorlage Automatisch ausgeführt wird.
Diese startet auch ohne Probleme und läuft.

Ich habe es dann mit dem EICAR File getestet, der Defender schlängt erfolgreich an, und sehe das Ereignis auch im Defender Management als Alarm.

Ich bekomme jedoch keine Telegram Notification.

Vielleicht kann mir hier jemand auf dem ersten Blick sagen was ich falsch gemacht habe.

Was vielleicht noch zum erwähnen ist, ich benutze hier die 15 Test Lizenzen, vielleicht liegt es auch daran.

Schema:
Schema
Schema
Schema.png (54.81 KiB) 4825 mal betrachtet

Code: Alles auswählen

$global:TelegramBotKey = ""
$global:TelegramChatIDs = ""
#$global:[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

#
# Telegram API
#
function global:Send-TeleMessage([string] $Botkey , [array] $ChatIDs , [string] $Message)
{
	$sendMsgLink = "https://api.telegram.org/bot$BotKey/sendMessage"
	foreach ($ID in $ChatIDs)
	{
		try
		{
		
			$ExecuteInvokeWeb = Invoke-WebRequest -Uri "$sendMsgLink" -Method Post -ContentType "application/json;charset=utf-8" -Body (ConvertTo-Json -Compress -InputObject @{chat_id=$ID; text="$Message"})
			$Status = (ConvertFrom-Json -InputObject $ExecuteInvokeWeb.Content)
			if($Status.ok){Write-Host "Message successfully sent to Chat ID : $ID (Type : $($Status.result.chat.type))" -ForegroundColor Green}
		}
		catch [Exception]
		{
			$exception = $_.Exception.ToString().Split(".")[2]
			Write-Host "Message faild to  sent at Chat ID : $ID ($exception)" -ForegroundColor Red
		}
	}
}

#
# Windows Notifiaction ansprechen
#
function global:Show-Notification {
	[cmdletbinding()]
	Param (
		[string]
		$ToastTitle,
		[string]
		[parameter(ValueFromPipeline)]
		$ToastText
	)
	
	[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
	$Template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)
	
	$RawXml = [xml] $Template.GetXml()
	($RawXml.toast.visual.binding.text|where {$_.id -eq "1"}).AppendChild($RawXml.CreateTextNode($ToastTitle)) > $null
	($RawXml.toast.visual.binding.text|where {$_.id -eq "2"}).AppendChild($RawXml.CreateTextNode($ToastText)) > $null
	
	$SerializedXml = New-Object Windows.Data.Xml.Dom.XmlDocument
	$SerializedXml.LoadXml($RawXml.OuterXml)
	
	$Toast = [Windows.UI.Notifications.ToastNotifiaction]::new($SerializedXml)
	$Toast.Tag = "PowerShell"
	$Toast.Group = "PowerShell"
	$Toast.ExpirationTime = [DateTimeOffset]::Now.AddMinutes(1)
	
	$Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("PowerShell")
	$Notifier.Show($Toast);
}

#
# die ACMP ClientList anfragen (um die ClientID in einem Hostnamen im Event aufzulösen)
#
function global:GetClient {
	param($clientId)
	$clients = Acmp-GetClientList_V1 -AcmpServerId "*"
	foreach ($client in $clients.Clients) {
		if ($client.ClientId -eq $clientId) {
			return $client.ComputerName
		}
	}
}

#
# @brief: This event gets fired on StartUp.
#
Register-EngineEvent -SourceIdentifier 'MicroService.OnStart' -Action { 
 Write-LogMessage -Message "Starting.. ACMPDefender"
 WriteBusinessLog-Message -Code 0 -Message "Starting.. ACMPDefender" -LogType Info 
}

#
# @brief: This event gets fired on Shut down
#
Register-EngineEvent -SourceIdentifier 'MicroService.OnStop' -Action {
 Write-LogMessage -Message "Stopping.. ACMPDefender"
 WriteBusinessLog-Message -Code 0 -Message "Stopping.. ACMPDefender" -LogType Info
}

#
# brief: This event gets fired when a message is received.
#

#
Register-EngineEvent -SourceIdentifier 'MicroService.OnMessage' -Action {
	Write-LogMessage -Message "Received Event"
	[string]$messageBody = [System.Text.Encoding]::UTF8.GetString($args[0].Body)
	$event = (Select-Xml -Content $messageBody -XPath "/ICQL/ACMP/Event").Node.Name 
	
	if ($event -eq "Event") {
		Write-LogMessage -Message "$messageBody"
		
		#XML auswerten
		$type = (Select-Xml -Content $messageBody -XPath "/ICQL/ACMP/Event/TEventNotifierMessage_V1/Items/TPublicAPIBaseData/EventType").Node.InnerText 
		$clientId = (Select-Xml -Content $messageBody -XPath "/ICQL/ACMP/Event/TEventNotifierMessage_V1/Items/TPublicAPIBaseData/ClientID").Node.InnerText 
		$EventDetail = (Select-Xml -Content $messageBody -XPath "/ICQL/ACMP/Event/TEventNotifierMessage_V1/Items/TPublicAPIBaseData/EventDetail_de").Node.InnerText
	
		#Name des Clients erfahren 
		$clientName = global:GetClient -clientId $clientId
	
		#Nachrichten zusammenbasteln - `r`n ist ein Zeilenumbruch in Powershell 
		$notification = "Type: " + $type + "`r`nClient: " + $clientName 
		$TeleMessage = "Es wurde eine Bedrohung erkannt, bitte überprüfen Sie ihre ACMP Console.`r`n`r`n" + $EventDetail + "`r`n`r`n" + " Client: " + $clientName
	
		Write-LogMessage -Message $notification
	
		#Windows Notfication los schießen
		global:Show-Notification -ToastTitle "ACMP Defender Notification" -ToastText $notification
	
		#Wenn der Eventtyp ein Alarm ist, dann sende die Telegramnachricht
		if ($type -eq "Alarm")
		{
			global:Send-TeleMessage -BotKey "$TelegramBotKey" -ChatIDs "$TelegramChatIDs" -Message "$TeleMessage"
		}
	}	
}

#Lese die Werte aus den AESB Schema
Register-EngineEvent -SourceIdentifier 'MicroService.OnConfigChanged' -Action {
	$config = $args[0]
	Write-LogMessage -Message "Received config: $config"
	
	$global:TelegramBotKey = (Select-Xml -Content $config -XPath "/ACMP.TelegramNotification/TelegramBotKey").Node.InnerText
	$global:TelegramChatIDs = (Select-Xml -Content $config -XPath "/ACMP.TelegramNotification/TelegramChatIDs").Node.InnerText
	
 #	 Write-LogMessage -Message "Parsed values: # $global:TelegramBotKey ## $global:TelegramChatIDs"
 
}
PowerShell Skript:
PowerShellSkript
PowerShellSkript
PowerShellSkript.png (153.89 KiB) 4825 mal betrachtet
Microservices/Instanzen:
AESB Instanze
AESB Instanze
AESB Instanze.png (138.51 KiB) 4825 mal betrachtet
__________________________________________
Mit freundlichen Grüßen

Lukas Petermann
IT-Administration ∙ PC Electric GmbH
ACMP Version 6.5.0
Benutzeravatar
lukas.petermann
Beiträge: 83
Registriert: Mi Jul 22, 2020 8:44 am

Ich habe es leider noch nicht zum laufen gebracht.

Habe auch noch den ACMPServer Dienst gestoppt und in der "Config.xml" den wert "true" bei <DispatchAcmpEventsToSics> eingetragen und den Dienst wieder gestartet.

Im Code habe ich sehr viele Schreibfehler meinerseits ausräumen können, sowie die korrekte Schema Zuweisung (glaube ich).
Schema_2.png
Schema_2.png (11.88 KiB) 4799 mal betrachtet
Schema_3.png
Schema_3.png (18.26 KiB) 4799 mal betrachtet
Der aktuelle PowerShell Code:

Code: Alles auswählen

$global:TelegramBotKey = ""
$global:TelegramChatIDs = ""

#
# Telegram API
#
function global:Send-TeleMessage([string] $Botkey , [array] $ChatIDs , [string] $Message)
{
	$sendMsgLink = "https://api.telegram.org/bot$BotKey/sendMessage"
	foreach ($ID in $ChatIDs)
	{
		try
		{
		
			$ExecuteInvokeWeb = Invoke-WebRequest -Uri "$sendMsgLink" -Method Post -ContentType "application/json;charset=utf-8" -Body (ConvertTo-Json -Compress -InputObject @{chat_id=$ID; text="$Message"})
			$Status = (ConvertFrom-Json -InputObject $ExecuteInvokeWeb.Content)
			if($Status.ok){Write-Host "Message successfully sent to Chat ID : $ID (Type : $($Status.result.chat.type))" -ForegroundColor Green}
		}
		catch [Exception]
		{
			$exception = $_.Exception.ToString().Split(".")[2]
			Write-Host "Message faild to  sent at Chat ID : $ID ($exception)" -ForegroundColor Red
		}
	}
}

#
# Windows Notifiaction ansprechen
#
function global:Show-Notification {
	[cmdletbinding()]
	Param (
		[string]
		$ToastTitle,
		[string]
		[parameter(ValueFromPipeline)]
		$ToastText
	)
	
	[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
	$Template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)
	
	$RawXml = [xml] $Template.GetXml()
	($RawXml.toast.visual.binding.text|where {$_.id -eq "1"}).AppendChild($RawXml.CreateTextNode($ToastTitle)) > $null
	($RawXml.toast.visual.binding.text|where {$_.id -eq "2"}).AppendChild($RawXml.CreateTextNode($ToastText)) > $null
	
	$SerializedXml = New-Object Windows.Data.Xml.Dom.XmlDocument
	$SerializedXml.LoadXml($RawXml.OuterXml)
	
	$Toast = [Windows.UI.Notifications.ToastNotifiaction]::new($SerializedXml)
	$Toast.Tag = "PowerShell"
	$Toast.Group = "PowerShell"
	$Toast.ExpirationTime = [DateTimeOffset]::Now.AddMinutes(1)
	
	$Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("PowerShell")
	$Notifier.Show($Toast);
}

#
# die ACMP ClientList anfragen (um die ClientID in einem Hostnamen im Event aufzulösen)
#
function global:GetClient {
	param($clientId)
	$clients = Acmp-GetClientList_V1 -AcmpServerId "*"
	foreach ($client in $clients.Clients) {
		if ($client.ClientId -eq $clientId) {
			return $client.ComputerName
		}
	}
}

#
# @brief: This event gets fired on StartUp.
#
Register-EngineEvent -SourceIdentifier 'MicroService.OnStart' -Action { 
 Write-LogMessage -Message "Starting.. ACMPDefender"
 WriteBusinessLog-Message -Code 0 -Message "Starting... ACMPDefender" -LogType Info 
}

#
# @brief: This event gets fired on Shut down
#
Register-EngineEvent -SourceIdentifier 'MicroService.OnStop' -Action {
 Write-LogMessage -Message "Stopping.. ACMPDefender"
 WriteBusinessLog-Message -Code 0 -Message "Stopping... ACMPDefender" -LogType Info
}

#
# brief: This event gets fired when a message is received.
#

#
Register-EngineEvent -SourceIdentifier 'MicroService.OnMessage' -Action {
	Write-LogMessage -Message "Received Event"
	#Write-LogMessage -Message "Received Message: $messageBody"
	[string]$messageBody = [System.Text.Encoding]::UTF8.GetString($args[0].Body)
	$event = (Select-Xml -Content $messageBody -XPath "/ICQL/ACMP/Event").Node.Name

	
	if ($event -eq "Event") {
		Write-LogMessage -Message "$messageBody"
		
		#XML auswerten
		$type = (Select-Xml -Content $messageBody -XPath "/ICQL/ACMP/Event/TEventNotifierMessage_V1/Items/TPublicAPIBaseData/EventType").Node.InnerText 
		$clientId = (Select-Xml -Content $messageBody -XPath "/ICQL/ACMP/Event/TEventNotifierMessage_V1/Items/TPublicAPIBaseData/ClientID").Node.InnerText 
		$EventDetail = (Select-Xml -Content $messageBody -XPath "/ICQL/ACMP/Event/TEventNotifierMessage_V1/Items/TPublicAPIBaseData/EventDetail_de").Node.InnerText
	
		#Name des Clients erfahren 
		$clientName = global:GetClient -clientId $clientId
	
		#Nachrichten zusammenbasteln - `r`n ist ein Zeilenumbruch in Powershell 
		$notification = "Type: " + $type + "`r`nClient: " + $clientName 
		$TeleMessage = "Es wurde eine Bedrohung erkannt, bitte überprüfen Sie ihre ACMP Console.`r`n`r`n" + $EventDetail + "`r`n`r`n" + " Client: " + $clientName
	
		Write-LogMessage -Message $notification
	
		#Windows Notfication los schießen
		global:Show-Notification -ToastTitle "ACMP Defender Notification" -ToastText $notification
	
		#Wenn der Eventtyp ein Alarm ist, dann sende die Telegramnachricht
		if ($type -eq "Alarm")
		{
			global:Send-TeleMessage -BotKey "$TelegramBotKey" -ChatIDs "$TelegramChatIDs" -Message "$TeleMessage"
		}
	}	
}

#Lese die Werte aus den AESB Schema
Register-EngineEvent -SourceIdentifier 'MicroService.OnConfigChanged' -Action {
	$config = $args[0]
	Write-LogMessage -Message "Received config: $config"
	
	$global:TelegramBotKey = (Select-Xml -Content $config -XPath "/ACMPTelegramNotification/TelegramBotKey").Node.InnerText
	$global:TelegramChatIDs = (Select-Xml -Content $config -XPath "/ACMPTelegramNotification/TelegramChatIDs").Node.InnerText
	
	Write-LogMessage -Message "Parsed values: # $global:TelegramBotKey ## $global:TelegramChatIDs"
 
}
Ausgabe des PowerShell Skripts
Ausgabe des PowerShell Skripts
Ausgabe.png (193.79 KiB) 4799 mal betrachtet
Unter anderem habe ich auch noch eine Workflow-Vorlage mit den In- & Out RoutingKeys angelegt.
workflow-vorlage
workflow-vorlage
workflow-vorlage.png (34.48 KiB) 4799 mal betrachtet
Ich glaube das aber hier eben im WorkFlow-Editor noch etwas erstellt werden muss.....unter anderem auch damit die Instanze ausführbar ist.
__________________________________________
Mit freundlichen Grüßen

Lukas Petermann
IT-Administration ∙ PC Electric GmbH
ACMP Version 6.5.0
twahl
Beiträge: 366
Registriert: Mo Mär 03, 2014 11:21 am

Hallo,

mit einem Rechtsklick auf die Workflow-Vorlage kann man im Kontext-Menü dann eine neue Workflow Instanz aus der Vorlage erstellen.
Dazu muss man auch eine Workflow Engine auswählen, dabei kann man auch eine bereits bestehende nutzen.
Mit freundlichen Grüßen,

Tobias Wahl
Aagon GmbH
Benutzeravatar
lukas.petermann
Beiträge: 83
Registriert: Mi Jul 22, 2020 8:44 am

Danke, das habe ich bereits gemacht.
workflowengine.png
workflowengine.png (38.32 KiB) 4786 mal betrachtet

Diese läuft auch.
workflowengine2.png
workflowengine2.png (60.63 KiB) 4786 mal betrachtet

Aber in der Vorlage selbst gehört vermutlich noch etwas gemacht.....
workflow-vorlage1.png
workflow-vorlage1.png (124.94 KiB) 4786 mal betrachtet

Und hier habe ich leider keine Ahnung wie was gemacht werden muss....
__________________________________________
Mit freundlichen Grüßen

Lukas Petermann
IT-Administration ∙ PC Electric GmbH
ACMP Version 6.5.0
twahl
Beiträge: 366
Registriert: Mo Mär 03, 2014 11:21 am

Hallo,

ich hatte noch einmal Rücksprache mit einem Kollegen gehalten und wir haben uns das Script und die Einstellungen einmal genauer angeschaut.

Im Script ist im letzten Absatz etwas anders, da ist ACMP.TelegramNotification statt ACMPDefenderNotifier.Extended eingetragen, so sah es eigentlich aus:
#Lese die Werte aus den AESB Schema
Register-EngineEvent -SourceIdentifier 'MicroService.OnConfigChanged' -Action {
$config = $args[0]
Write-LogMessage -Message "Received config: $config"

$global:TelegramBotKey = (Select-Xml -Content $config -XPath "/ACMPDefenderNotifier.Extended/TelegramBotKey").Node.InnerText
$global:TelegramChatIDs = (Select-Xml -Content $config -XPath "/ACMPDefenderNotifier.Extended/TelegramChatIDs").Node.InnerText

# Write-LogMessage -Message "Parsed values: # $global:TelegramBotKey ## $global:TelegramChatIDs"

}

Außerdem ist ein paar mal Notfication falsch geschrieben als Notifiaction, meist aber in einem Kommentar.

Im Workflow Editor muss nicht angepasst werden.

Beim Out RoutingKey könnte man noch mit einer Wildcard arbeiten.
defender_01.png
defender_01.png (218.96 KiB) 4710 mal betrachtet
Im ScriptEditor über Einstellungen kann man noch einen anderen Routing Key angeben und das Script Starten um die Ausgabe zu überprüfen, dann kann man im Defender entsprechend ein Event triggern (eicar file oder sowas) und das sollte in der Ausgabe im Script Editor ankommen.
defender_02.png
defender_02.png (77.26 KiB) 4710 mal betrachtet
defender_03.png
defender_03.png (109.31 KiB) 4710 mal betrachtet
Das Ende vom RoutingKey ist dabei egal, wichtig ist, dass vorne kein SICS. angegeben ist.
Mit freundlichen Grüßen,

Tobias Wahl
Aagon GmbH
Antworten