Playbook trigger

17 June 2024

ID 273327

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.

When you start writing, 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 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 or Assignee[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 returns true if the alert is assigned to the user.
  • (.Serverity == "high") and (.DetectSource == "KES")—The expression returns true if the alert severity level is high and the source of data is Kaspersky Endpoint Security.
  • [ .DetectionTechnologies[] | . == "IOC" ] | any —The expression returns true if the IOC detection technology is triggered.
  • .DetectionTechnologies | length > 1—The expression returns true 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 the Assets array has the W21H2-X64-3160 value in the Name field.
  • [.Observables[] | .Value == "127.0.0.1"] | any—The expression filters the alert where any element of the Observables array has the 127.0.0.1 value in the Value 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 the AttackerOrVictim 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:

The following types of incident change events are supported:

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.

Did you find this article helpful?
What can we do better?
Thank you for your feedback! You're helping us improve.
Thank you for your feedback! You're helping us improve.