1

Below is an example syslog message coming into Sentinel from Cisco Secure Workload (formerly Tetration):

Alert[11]: [WARNING] {"keyId":"SEN::u0mvypu37b9fwimpr4zn168c2ht159n6xdhwtaanm-upgrade_srv_check_in","eventTime":"1684974923000","alertTime":"1684974949559","alertText":"Agent Inactive: centos7","severity":"MEDIUM","tenantId":"000457","type":"SENSOR","alertDetails":"{\"details\":{\"AgentType\":\"ENFORCER\",\"Bios\":\"57D84D56-0000-0000-7E3C-9DD10F02AFD5\",\"CurrentVersion\":\"3.7.1.40-enforcer\",\"DesiredVersion\":\"\",\"HostName\":\"centos7\",\"IP\":\"1.1.1.1 (Gateway IP)\",\"LastConfigFetchAt\":\"2023-05-03 15:47:53 +0000 UTC\",\"Platform\":\"CentOS-7.9\"},\"agent_uuid\":\"u0mvypu37b9fwimpr4zn168c2ht159n6xdhwtaanm\",\"scope_name\":\"MYLAB\",\"scope_id\":\"f5qeybblv5oktpnte4ccrf5pw\",\"vrf_id\":700457}","rootScopeId":"f5qeybblv5oktpnte4ccrf5pw"}

Need assistance in parsing this as there is currently no existing parsers for this product. Looks like there's JSON involved, but not certain if I should be using extractjson or parse_json.

I’ve started the following query, but am I having trouble with extracting/filtering values (likely because the JSON parsing is missing from this query):

Syslog
| where ProcessName contains "Tetration"
| extend AlertID = extract(????, 1, SyslogMessage) 
| extend Severity = extract(????,1, SyslogMessage)
| extend TenantID = extract(????, 1, SyslogMessage)
| extend IP = extract(????, 1, SyslogMessage)
| extend ScopeName = extract(????, 1, SyslogMessage)

Any assistance the community can provide would be greatly appreciated.

Erik Oppedijk
  • 3,496
  • 4
  • 31
  • 42

2 Answers2

1

you could use a combination of:

for example:

print input = ```Alert[11]: [WARNING] {"keyId":"SEN::u0mvypu37b9fwimpr4zn168c2ht159n6xdhwtaanm-upgrade_srv_check_in","eventTime":"1684974923000","alertTime":"1684974949559","alertText":"Agent Inactive: centos7","severity":"MEDIUM","tenantId":"000457","type":"SENSOR","alertDetails":"{\"details\":{\"AgentType\":\"ENFORCER\",\"Bios\":\"57D84D56-0000-0000-7E3C-9DD10F02AFD5\",\"CurrentVersion\":\"3.7.1.40-enforcer\",\"DesiredVersion\":\"\",\"HostName\":\"centos7\",\"IP\":\"1.1.1.1 (Gateway IP)\",\"LastConfigFetchAt\":\"2023-05-03 15:47:53 +0000 UTC\",\"Platform\":\"CentOS-7.9\"},\"agent_uuid\":\"u0mvypu37b9fwimpr4zn168c2ht159n6xdhwtaanm\",\"scope_name\":\"MYLAB\",\"scope_id\":\"f5qeybblv5oktpnte4ccrf5pw\",\"vrf_id\":700457}","rootScopeId":"f5qeybblv5oktpnte4ccrf5pw"}```
| extend start_position = indexof(input, "{")
| extend input = parse_json(substring(input, start_position))
| project
    AlertID = input.keyId,
    Severity = input.severity,
    TenantID = input.tenantId,
    AlertDetails = parse_json(tostring(input.alertDetails))
| extend
    IP = AlertDetails.details.IP,
    ScopeName = AlertDetails.scope_name
| project-away AlertDetails
AlertID Severity TenantID IP ScopeName
SEN::u0mvypu37b9fwimpr4zn168c2ht159n6xdhwtaanm-upgrade_srv_check_in MEDIUM 000457 1.1.1.1 (Gateway IP) MYLAB

or, you could use the parse operator:

print input = ```Alert[11]: [WARNING] {"keyId":"SEN::u0mvypu37b9fwimpr4zn168c2ht159n6xdhwtaanm-upgrade_srv_check_in","eventTime":"1684974923000","alertTime":"1684974949559","alertText":"Agent Inactive: centos7","severity":"MEDIUM","tenantId":"000457","type":"SENSOR","alertDetails":"{\"details\":{\"AgentType\":\"ENFORCER\",\"Bios\":\"57D84D56-0000-0000-7E3C-9DD10F02AFD5\",\"CurrentVersion\":\"3.7.1.40-enforcer\",\"DesiredVersion\":\"\",\"HostName\":\"centos7\",\"IP\":\"1.1.1.1 (Gateway IP)\",\"LastConfigFetchAt\":\"2023-05-03 15:47:53 +0000 UTC\",\"Platform\":\"CentOS-7.9\"},\"agent_uuid\":\"u0mvypu37b9fwimpr4zn168c2ht159n6xdhwtaanm\",\"scope_name\":\"MYLAB\",\"scope_id\":\"f5qeybblv5oktpnte4ccrf5pw\",\"vrf_id\":700457}","rootScopeId":"f5qeybblv5oktpnte4ccrf5pw"}```
| parse input with "Alert[" AlertId "]: [" Severity "] " input:dynamic
| project
    AlertId,
    Severity = input.severity,
    TenantID = input.tenantId,
    AlertDetails = parse_json(tostring(input.alertDetails))
| extend
    IP = AlertDetails.details.IP,
    ScopeName = AlertDetails.scope_name
| project-away AlertDetails
AlertId Severity TenantID IP ScopeName
11 MEDIUM 000457 1.1.1.1 (Gateway IP) MYLAB
Yoni L.
  • 22,627
  • 2
  • 29
  • 48
  • Thanks Yoni. What would that look like if starting the query as: Syslog | where ProcessName contains "Tetration" The print input = above assumes a static entry, but this would be a KQL I would save as a function in Sentinel to query syslog data as it comes. – user21962463 May 25 '23 at 20:56
  • Yoni, I may have answered my question. Does this look like the right start: Syslog | where ProcessName contains "Tetration" | extend start_position = indexof(SyslogMessage, "{") | extend input = parse_json(substring(SyslogMessage, start_position)) – user21962463 May 25 '23 at 21:05
  • OK. Getting close to having this resolved, just need the AlertID column to pull the value from the very first portion of the syslog message, which in this example would be Alert[11] (just need the numerical value 11. If you can help filter that then I can test and share the full & tested query. Thanks! – user21962463 May 25 '23 at 21:30
  • please see the 2nd example in the answer – Yoni L. May 26 '23 at 00:04
1

Thanks Yoni. Here's the full query I'm using in Sentinel (still testing but looking good).

Syslog 
| where ProcessName contains "Tetration"
| take 10
| parse SyslogMessage with "Alert[" AlertId "]: [" Severity "] " input:dynamic
| project
    AlertId,
    AlertText = input.alertText,
    Severity = input.severity,
    TenantID = input.tenantId,
    Type = input.type,
    AlertDetails = parse_json(tostring(input.alertDetails))
| extend
    Host_Name = AlertDetails.details.HostName,
    IP = AlertDetails.details.IP,
    Scope_Name = AlertDetails.scope_name,
    Version = AlertDetails.details.CurrentVersion,
    OS = AlertDetails.details.Platform,
    Agent_ID = AlertDetails.agent_uuid,
    Scope_ID = AlertDetails.scope_id,
    VRF_ID = AlertDetails.vrf_id
| project-away AlertDetails