Playbook trigger
The playbook trigger is a filter that allows you to select alerts or incidents for which a playbook must be launched. The filter (trigger) is applied to each object (alert or incident) individually and takes a single value: either true
or false
. A trigger consists of expressions in the jq language that processes structured data in the JSON format. For more information about jq expressions, refer to jq Manual.
In Kaspersky Next XDR Expert, gojq is used. It is an implementation of jq written in the go language, which has the following differences from jq:
- Mathematical functions are implemented in a more convenient way.
- Errors messages have a clear indication of where to fix your query.
- Integer calculations are more accurate.
- Functions that work incorrectly in jq are improved in gojq.
For more information about the differences between gojq and jq, refer to GitHub.
How to write a trigger
You can write a trigger in the Trigger section when creating or editing a playbook.
The following suggestions can be displayed:
- Names of functions.
- Special values.
- Fields that are specified as object identifiers in accordance with the data model.
The suitable values are filtered and displayed in the list of suggestions when you start writing.
The jq language also provides syntax highlighting and validation of jq expressions. If the trigger has invalid expressions, you cannot save the playbook.
Depending on the option you select in the Scope list when creating or editing a playbook, alert data model or incident data model is used.
The names of parameters in a playbook trigger must be the same as in the data model. Note that elements of jq expressions are case-sensitive.
To avoid overloading the system, it is not recommended to specify OriginalEvents, Observables, Extra,
and Alerts
data in the trigger.
When writing a trigger, basic syntax rules are used.
To refer to structure properties, you must use dot ".
" and specify the attribute, for example:
.MITRETactics[]
—To view the array of MITRE tactics associated with all triggered IOA rules in the alert..MITRETactics[0]
—To view the first element from the MITRE tactics array.
To refer to child properties, you can either use the pipe (|
) or the same combination without the pipe, for example:
.Assignee[0].Name
orAssignee[0] | .Name
—The expression outputs the name of the user to whom the alert is assigned..MITRETactics[0].ID
or.MITRETactics[0] | .ID
—The expression outputs the ID of the first MITRE tactic.
To get a value, you have to use the following operators: ==, >, <, >=, <=, !=, for example:
.Assignee[0] | .Name == "user"
—The expression returnstrue
if the alert is assigned to the user.(.Serverity == "high") and (.DetectSource == "KES")
—The expression returnstrue
if the alert severity level is high and the source of data is Kaspersky Endpoint Security.[ .DetectionTechnologies[] | . == "IOC" ] | any
—The expression returnstrue
if the IOC detection technology is triggered..DetectionTechnologies | length > 1
—The expression returnstrue
if more than one detection technology is triggered.
To enumerate values in an array of objects, you can use the any
method, for example:
[.Assets[] | .Name == "W21H2-X64-3160"] | any
—The expression filters the alert where any element of theAssets
array has theW21H2-X64-3160
value in theName
field.[.Observables[] | .Value == "127.0.0.1"] | any
—The expression filters the alert where any element of theObservables
array has the127.0.0.1
value in theValue
field.[.Assets[].ID]
—To output the array of IDs.[.Assets[] | select(.AttackerOrVictim=="attacker") | .ID]
—To display an array of IDs for the assets filtered by theAttackerOrVictim
field.
If you want to reuse calculations, specify a variable with $
. For example, the expression event.manual != true as $not_manual | [ .DetectionTechnologies[] | . == "IOC" ] | any and $not_manual
defines and uses the $not_manual
variable that contains a flag that shows if the change is manual or not.
To work with dates, you can use the following functions:
now
—To get the current Unix time in seconds, for example,now == 1690541520.537496.
todate
—To get the current Unix time in seconds, for example,now | todate == "2023-07-28T10:47:36Z".
fromdate
—To convert the date to seconds, for example:.CreatedAt | split(".")[0] + "Z"
—This command removes milliseconds and converts the string to the 2023-07-15T07:49:51Z format.(.CreatedAt | split(".")[0] + "Z") | fromdate == 1689407391
—The conversion to seconds is finished.
Jq uses iterators—an interface that provides access to elements of a collection, for example, an array, and allows you to navigate through them. Iterators are always the result of calculation. The difference is in the number of elements that the iterator contains. In Kaspersky Next XDR Expert, an iterator must have only one element; the other cases are considered an error.
To write a correct trigger, you have to wrap an iterator into square brackets ([ ... ]
). For example, the .DetectionTechnologies[] == "IOC"
trigger will cause an error because it returns an iterator with two elements. The correct trigger must have the following form: [ .DetectionTechnologies == "IOC" ] | any
, where first you have to use []
to wrap the result of the comparison into an array, and then process it with the any
method that returns true
if at least one element of the array is true
. Otherwise, false
is returned.
When the trigger runs
The search for a suitable playbook starts when one of the following triggering events occurs:
- New alert/incident is created.
- Any field of an active alert/incident is changed.
- When creating or editing a playbook, the user selected the Launch the playbook for all matching alerts or incidents. Note that the system may be overloaded check box.
The following types of alert change events are supported:
- Assigning or removing an analyst.
- Changing an alert status.
- Changing basic events.
- Linking or unlinking an alert to or from an incident.
- Changing the value in the
ExternalReference
field.
The following types of incident change events are supported:
- Assigning or removing an analyst.
- Changing an incident status.
- Changing basic events.
- Linking or unlinking an alert to or from an incident.
- Changing an incident name.
- Changing an incident description.
- Changing an incident priority.
- Changing the value in the
ExternalReference
field. - Merging incidents.
The alert/incident structure does not contain any data about the alert/incident changes. This data is transferred in additional information. If in a playbook trigger you want to refer to the changes, use the event function without arguments.
By default, manual changes to an alert or incident details are ignored. If you want a playbook to launch for manual changes, you have to use the event.manual
function in the trigger, for example:
event.manual and ([ event.updateOperations[] | . == "alertReopened" ] | any)
—The trigger works only if the alert is manually reopened.[ event.updateOperations[] | . == "alertLinkedWithIncidentBySystem" ] | any
—The trigger works only if the alert is automatically linked to an incident.event.manual != null and (([ event.updateOperations[] | . == "alertChangedToNew" ] | any) | not)
—The trigger works if the alert status is changed to any status other than New, either manually or automatically.event == null and .Status == "inIncident"
—The trigger works for all alerts with the In incident status, but only when the playbook is changed, not the alert.
If necessary, you can test examples of jq expressions, apply filters, and then view the results in the Jq playground service.