Skip to content

Alert configuration templates

Sophos Linux Sensor (SLS) lets users decide which data they need to best serve their workflows. As such, we support custom formatting of alerts through alert templates. Alerts may be translated to a UTF-8 string via a Go template instead of the default JSON format.

Alert templates are strings set in either the template field of the individual outputs listed in the outputs section of the alert dispatcher or at the top level under alert_output, which will apply the template to any output that doesn't have a template set. This allows an operator to set a global alert template that can optionally be overridden for a given output.

This guide covers basic usage as well as some common scenarios. See the Go template documentation for a complete overview.

Alert template examples

To create an alert template, first select the names of the alert fields you wish to include in your alert output. Alert fields are selected using the Go template {{.FieldName}} syntax. The syntax is similar to Mustache templates, but the Go template language is much more powerful. For example, to log the name of an alert's policy name, thread group ID, and program name you could do the following:

template: `{{.StrategyName}} - {{.ProcessInfo.Tgid}} {{.ProcessInfo.Program.Path}}`

This will produce an alert that looks like the following string:

WGET - Blacklist 6620 /usr/bin/wget

This template selected the nested TGID value from the alert's ProcessInfo struct. Note that everything except the template parameters was passed through as plain text. This allowed us to add a hyphen between the Policy Name and the rest of the log statement for clarity. Taking this one step further, we could even format the alert as JSON:

template: `{"policy_name":"{{.StrategyName}}","process_tgid":"{{.ProcessInfo.Tgid}}"}`

This would produce the following JSON string:

{"policy_name":"Blacklist wget","process_tgid":"22144"}

Should you need to wrap the full aert JSON in another JSON object for compatibility with another system, SLS provides a helper function called AlertJSON. This example creates a new JSON object with an id field, a timestamp field, and the full alert payload assigned to a field called payload:

template: `{"id":"{{.UUID}}","timestamp":"{{.Timestamp}}","payload":{{AlertJSON .}}}`

You should always test the output of new templates before deploying to ensure that the formatting of your output is what you expect. This is especially important for formats like JSON that another system will likely parse. This example was intentionally compacted onto one line to avoid introducing multi-line output which isn't compatible by default with most logging systems.

Overall, alert templates are a powerful and flexible way to extend the alert format to better integrate into your existing workflows. When combined with the alert Webhook feature, this is a powerful way to easily integrate SLS with other systems. When the sensor starts, it silently compiles and tests any templates with a test alert which allows the sensor to verify that the templates are syntactically correct and that it can successfully apply them to an alert without error. There's no output from this process.

Filtering with alert templates

It's possible using go template if statements to send alerts to specific output locations. This works because SLS won't send empty alerts to an output. For example, it's possible to send only high-priority alerts to a Slack channel.

Here's an example:

alert_output:
 outputs:
     # Send alerts to Slack using their webhook JSON format
   - type: webhook
     enabled: true
     url: https://hooks.slack.com/services/123ABC/ab914B12eeigVh2xZ
     template: |
               {{- if eq .Priority 4 -}}
               {"text": "New Sophos alert {{.PolicyType}} {{.Description}}"}
               {{- end -}}
     # Send all alerts except for Heartbeat alerts
   - type: webhook 
     enabled: true 
     url: https://hooks.slack.com/services/123ABC/ab914B12eeigVh2xZ 
     template: |
               {{- if ne (print .PolicyType) "Heartbeat" -}}
               {"data": {{AlertJSON .}}}
               {{- end -}}

Note

The "-" in the above template tells go to ignore any whitespace before and after the template. This is important to prevent empty new lines from displaying around the alert JSON.

More information on if statements in go templates can be found here. For more information on available boolean and comparison functions see this godoc.

Alert template Enums

SLS alerts make use of enums for many fields which have a set number of possible values. For usability these enums are converted to strings when alerts are generated but when referencing the value in templates the integer value must be used. For example in order to only generate high priority alerts:

{{if eq .Priority 4 -}}
  {"text": "Alert {{.PolicyType}} {{.StrategyName}}"}
{{- end}}

Functions in alert templates

Alert Templating allows several functions that can make formatting easier.

AlertJSON

Outputs the entire alert json. This can be useful for wrapping the alert json when other systems have a required input format, for example web hooks, Splunk, and so on.

To use the function:

template: `{"uuid": "{{.UUID}}", "data": {{AlertJSON}}}```

This will generate the expected output of:

{"uuid": "2fb9e1fd-cd9b-4dbc-adca-70c29446f808", "data": {"timestamp":"2020-07-29T19:35:57.440109088Z","scope":"Process","priority":"Low","confidence":"Max","comments":"Alerts when an command is executed by a valid system user via SSH.","alert_labels":{},"notifications":[{"timestamp":"2020-07-29T19:35:57.440109088Z",
...
,"name":"Shell Command Executed","categories":["C8.Abnormal Activity.System Activity","MITRE.Execution.Command-Line Interface","MITRE.Execution.User Execution","MITRE.Initial Access.Valid Accounts"]}}

RFC3339Date, RFC3339NanoDate, and ToSeconds

These functions allow for easy formatting the date in alerts. This allows for the output alerts to display the date in whatever format the destination expects. 

  • RFC3339Date displays the date in YYYY-MM-DDTHH:mm:SSZ format.
  • RFC3339NanoDate displays the date in YYYY-MM-DDTHH:mm:SS.NNNNNNNNNZ format.
  • ToSeconds converts the Unix Nano Seconds to a Unix Timestamp in seconds.

To use these functions:

template: |
   {{.UUID}} .Timestamp {{.Timestamp}}
   {{.UUID}} RFC3339Date .Timestamp {{RFC3339Date .Timestamp}}
   {{.UUID}} RFC3339NanoDate .Timestamp {{RFC3339NanoDate .Timestamp}}
   {{.UUID}} ToSeconds .Timestamp {{ToSeconds .Timestamp}}

Which will output:

9dae63f9-110f-40d0-9dfe-ebac85b9433f .Timestamp 1596053056936135157
9dae63f9-110f-40d0-9dfe-ebac85b9433f RFC3339Date .Timestamp 2020-07-29T20:04:16Z
9dae63f9-110f-40d0-9dfe-ebac85b9433f RFC3339NanoDate .Timestamp 2020-07-29T20:04:16.936135157Z
9dae63f9-110f-40d0-9dfe-ebac85b9433f ToSeconds .Timestamp 1596053056

Alert template errors

If the template value is not a syntactically valid template, it's treated as a fatal error and will prevent SLS from starting. Included in the output is a line number, e.g. template:1, to indicate the error is on the first line.

root@peterm:~# ./sophoslinuxsensor
Sophos Linux Runtime Detections Agent version 5.0.0.28 (Build: 1917)
INFO[0000] fetching metadata
INFO[0000] fetched metadata
INFO[0001] Starting Embedded Analytics 
FATA[0001] Unable to start analytics: template: error: template: template:1: unexpected"}" in operand

If the template is syntactically valid but an invalid alert field is specified, this will result in a non-fatal error on alerts.

For example, if you had the following template with the Path field misspelled as Psth like:

template: |
{{.StrategyName}} {{.ProcessInfo.Tgid}} {{.ProcessInfo.Program.Psth}}

you would get the following error:

ERRO[0005] template: template:1:53: executing "template" at <.ProcessInfo.Program...>: can`t evaluate field Psth in type *processtree.ProgramInfo

To resolve this, you will need to update the template and restart SLS.

More information