# Writing Simple Detections

## Overview

Simple Detections can be created in the CLI workflow in YAML, in addition to being created in the [Simple Detection Builder](https://docs.panther.com/detections/rules/simple-detection-builder) in the Console.

Simple Detections created in the CLI workflow, then uploaded to Panther, can be viewed and edited in the [Simple Detection builder](https://docs.panther.com/detections/rules/simple-detection-builder) in the Console. This may be valuable if members of your team have varying levels of experience with YAML.

Simple detections can be used in [detection derivation](https://docs.panther.com/detections/rules/derived).

If you aren't sure whether to write detections locally as Simple Detections (in YAML) or Python detections, see the [Using Python vs. Simple Detections YAML](https://docs.panther.com/detections/rules/..#using-python-vs.-simple-detections-yaml) section.

{% hint style="info" %}
If your team uses the CLI workflow to manage detection content, the changes made to detections using the [Simple Detection builder](https://docs.panther.com/detections/rules/simple-detection-builder) in the Console will be overwritten on next upload (except for [Inline Filters](#inlinefilters) created in the Console, which will be preserved).

If you create or edit detections using the Simple Detection builder in the Console, copy the resulting YAML representation and include it in your local detections files, in order to prevent the changes from being overwritten on next upload.
{% endhint %}

### Limitations of Simple Detections YAML

* [Scheduled rules](https://docs.panther.com/detections/rules) and [policies](https://docs.panther.com/detections/policies) cannot be created as Simple Detections.
  * Only [rules](https://docs.panther.com/detections/rules) can be created in YAML.
* Panther-managed Simple Detections are not yet available.
  * It is possible, however, to use [Panther-managed Python detections](https://docs.panther.com/detections/panther-managed) alongside your own Simple Detections.
* Many helper functions available in Python, including those for specific log sources, are not represented in YAML.
  * Some [global helpers](https://github.com/panther-labs/panther-analysis/tree/master/global_helpers) have been converted into YAML keys, e.g., [`deep_get()` ](https://docs.panther.com/detections/python/globals#deep_get)is [`DeepKey`](https://docs.panther.com/detections/rules/match-expression#deepkey).
* It is not possible to make external API calls in Simple Detections, including to fetch values from your Dynamo KV store to use [caching](https://docs.panther.com/detections/rules/python/caching).

## How to create a Simple Detection (rule) in YAML

<details>

<summary>Creating a Simple Detection rule in the CLI workflow</summary>

If you're writing Simple Detections locally (instead of in the [Simple Detection Builder](https://docs.panther.com/detections/rules/simple-detection-builder) in the Console), we recommend managing your local detection files in a version control system like GitHub or GitLab.

**Folder setup**

If you group your rules into folders, each folder name must contain `rules` in order for them to be found during upload (using either PAT or the bulk uploader in the Console).

We recommend grouping rules into folders based on log/resource type, e.g., `suricata_rules` or `aws_s3_policies`.

**File setup**

Each rule and scheduled rule consists of:

* A YAML specification file (a file with a `.yml` extension) containing the detection logic, as well as metadata attributes of the detection.
  * This file has similar syntax to the Python YAML files, with some additional keys.

Simple Detection rules contain lists of boolean logic called [match expressions](https://docs.panther.com/detections/rules/writing-simple-detections/match-expression) that detect suspicious behaviors. Returning a value of `True` indicates suspicious activity, which triggers an alert.

Learn more about [Simple Detection YAML syntax](#simple-detection-yaml-syntax), and see a [complete list of required and optional YAML fields below](#simple-detection-rule-specification-reference).

* Create a YAML file (e.g. `my_new_rule.yml`) using the template below (including a top-level `Detection` key):

  ```yaml
  AnalysisType: rule
  DedupPeriodMinutes: 60 # 1 hour
  DisplayName: Example Rule to Check the Format of the Spec
  Enabled: true
  RuleID: Type.Behavior.MoreContext
  Severity: High
  LogTypes:
    - LogType.GoesHere
  Reports:
    ReportName (like CIS, MITRE ATT&CK):
      - The specific report section relevant to this rule
  Tags:
    - Tags
    - Go
    - Here
  Description: >
    This rule exists to validate the CLI workflows of the Panther CLI
  Runbook: >
    First, find out who wrote this the spec format, then notify them with feedback.
  Reference: https://www.a-clickable-link-to-more-info.com
  Detection:
    - KeyPath: hostName
      Condition: Contains
      Value: prod
  ```

After this rule is uploaded to Panther, it will be viewable in the Console in the [Simple Detection builder](https://docs.panther.com/detections/rules/simple-detection-builder).

</details>

## Simple Detection YAML syntax

Each custom Simple Detection can be composed of:

* Detection key

  ```yaml
  Detection: 
  ```
* Filter key

  ```yaml
  InlineFilters: 
  ```
* Metadata keys

  ```yaml
  AnalysisType: 
  Enabled: 
  CreateAlert: 
  RuleID:
  CreatedBy:
  LogTypes: 
  Reports: 
  Tags: 
  Tests: 
  ```
* Alert keys (dynamic)

  ```yaml
  DynamicSeverities: 
  AlertTitle: 
  AlertContext: 
  GroupBy: 
  ```
* Alert keys (static)

  ```yaml
  Severity:
  Description:
  DedupPeriodMinutes:
  Threshold: 
  DisplayName:
  OutputIds:
  Reference:
  Runbook:
  SummaryAttributes: 
  ```

Learn more about each of these keys, including which are required and optional, in the [Simple Detection rule specification reference below](#simple-detection-rule-specification-reference).

### `Detection`

Within the `Detection` key, include one or more [match expressions](https://docs.panther.com/detections/rules/writing-simple-detections/match-expression).

### `InlineFilters`

Learn more about using `InlineFilters` in Simple Detections on [Modifying Detections with Inline Filters](https://docs.panther.com/detections/inline-filters#creating-filters-in-the-cli-workflow).

### Dynamic alert keys in Simple Detections

Alert fields are fields in a Simple Detection definition that are applicable to the alerts generated by that detection.

Alert fields can be static or dynamic. With static alert fields, you provide a set value in the detection definition, which does not change based on the incoming event. Dynamic alert fields, however, can use information in the event to determine the value.

If you are using [alert deduplication](https://docs.panther.com/detections/rules/..#deduplication-of-alerts), the *first* event to match the detection is used by these alert keys.

#### `DynamicSeverities`

Use `DynamicSeverities` to dynamically set the severity of an alert generated by a match on this detection. This field is dynamic because you can use values from the event to determine the severity.

When `DynamicSeverities` is present, its value overrides the value of the `Severity` key. `Severity` is still required, and its value will be the fallback value if there are no matches on any of the [match expressions](https://docs.panther.com/detections/rules/writing-simple-detections/match-expression) contained within `DynamicSeverities`.

Within the `DynamicSeverities` key, include one or more `ChangeTo` keys, each with a corresponding `Conditions` key. The value of `ChangeTo` should be one of the [alert severities](https://docs.panther.com/detections/rules/..#alert-severity). The `ChangeTo` blocks are evaluated in order, from top to bottom, and evaluation stops once a match has been found.

Within `Conditions`, include one or more [match expressions](https://docs.panther.com/detections/rules/writing-simple-detections/match-expression). The `Conditions` list has the following limitations:

* No [list comprehension](https://docs.panther.com/detections/rules/match-expression#list-comprehension-match-expressions), [multi-key](https://docs.panther.com/detections/rules/match-expression#multi-key-match-expressions), or [absolute](https://docs.panther.com/detections/rules/match-expression#absolute-match-expressions) match expressions may be used.
* No [combinators](https://docs.panther.com/detections/rules/match-expression#combinators) may be used.

Example:

```yaml
DynamicSeverities:
  - ChangeTo: CRITICAL
    Conditions:
      - Key: status
        Condition: Equals
        Value: severe
  - ChangeTo: MEDIUM
    Conditions:
      - KeyPath: user.name
        Condition: StartsWith
        Value: admin_
      - DeepKey:
          - user
          - roles
        Condition: Contains
        Value: wheel
```

#### `AlertTitle`

Use `AlertTitle` to dynamically set the title of an alert generated by a match on this detection. This field is dynamic because you can use values from the event in the title.

The value of `AlertTitle` should be a string. You can reference event values by using curly braces. Inside the curly braces, use JSON path syntax.

Example:

```yaml
AlertTitle: "User {actor.username} impersonated {target.username} at {time}"
```

#### `AlertContext`

`AlertContext` lets you identify event data to pass onto generated alerts, formatted as a dictionary.

Within `AlertContext`, include one or more `KeyName` and `KeyValue` pairs. `KeyName` takes a string of your choice, which will become the key in the alert context dictionary. Within `KeyValue`, use a [key specifier](https://docs.panther.com/detections/rules/match-expression#key-specifiers) to indicate an event key—its value will be the value in the alert context dictionary.

`KeyValue` values must be JSON-compliant. Examples of non-compliant values include Python's `nan`, `inf`, and `-inf`.

Example:

```yaml
AlertContext:
  - KeyName: ip
    KeyValue:
      Key: sourceIP
  - KeyName: user
    KeyValue:
      DeepKey:
        - user
        - username
  - KeyName: resource
    KeyValue:
      KeyPath: resource.arns
```

#### `GroupBy`

`GroupBy` sets the deduplication string for your detection. Learn more about deduplication, including the order of precedence for how the deduplication string is set, on [Rules and Scheduled Rules](https://docs.panther.com/detections/rules/..#deduplication-of-alerts).

Within the `GroupBy` key, include a list of one or more event keys defined with [key specifiers](https://docs.panther.com/detections/rules/match-expression#key-specifiers).

Example:

```yaml
GroupBy:
  - Key: sourceIP
  - KeyPath: user.name
  - KeyPath: resource.arn
```

The values of the keys provided under `GroupBy` are joined with a colon to form the deduplication string. The outputted deduplication string for the above example would be:

```
<value of sourceIP>:<value of user.name>:<value of resource.arn>
```

## Simple Detection rule specification reference

The table below contains all available YAML keys for Simple Detections. Required fields are in **bold**.

If you are writing a Python rule, instead see the [Python rule specification reference](https://docs.panther.com/detections/python#python-rule-specification-reference).

<table data-header-hidden data-full-width="false"><thead><tr><th width="231">Field Name</th><th width="264">Description</th><th width="282.5081967213115">Expected Value</th></tr></thead><tbody><tr><td>Field Name</td><td>Description</td><td>Expected Value</td></tr><tr><td><strong><code>AnalysisType</code></strong></td><td>Indicates whether this analysis is a rule, scheduled_rule, policy, or global</td><td><code>rule</code></td></tr><tr><td><strong><code>Enabled</code></strong></td><td>Whether this rule is enabled</td><td>Boolean</td></tr><tr><td><strong><code>RuleID</code></strong></td><td>The unique identifier of the rule</td><td>String</td></tr><tr><td><strong><code>LogTypes</code></strong></td><td>The list of logs to apply this rule to</td><td>List of strings</td></tr><tr><td><code>CreatedBy</code></td><td>The author of this detection. Can be set as a Panther user UUID, email address, or an arbitrary text value. Learn more in <a href="../../../panther-developer-workflows/detections-repo/pat/pat-commands#the-createdby-detection-field">The <code>CreatedBy</code> detection field</a>.</td><td>String</td></tr><tr><td><strong><code>Severity</code></strong></td><td>Which <a href="..#alert-severity">severity</a> an associated alert should have</td><td>One of the following strings: <code>Info</code>, <code>Low</code>, <code>Medium</code>, <code>High</code>, or <code>Critical</code><br>This field is overwritten by <code>DynamicSeverities</code>, but is required even if <code>DynamicSeverities</code> is defined</td></tr><tr><td><code>CreateAlert</code></td><td>Whether the rule should generate <a href="../..#signals-vs.-rule-matches-vs.-alerts">rule matches/an alert</a> on matches (default true)</td><td>Boolean</td></tr><tr><td><strong><code>Detection</code></strong></td><td>The list of match expressions to apply to the event data</td><td>List of <a href="writing-simple-detections/match-expression">match expressions</a></td></tr><tr><td><a href="#dynamicseverities"><code>DynamicSeverities</code></a></td><td>Alternate <a href="..#alert-severity">severities</a> based on custom sets of conditions</td><td>List of dynamic severity configurations, consisting of <code>ChangeTo</code> and <code>Conditions</code> fields. <code>ChangeTo</code> is a <code>Severity</code> value and <code>Conditions</code> is a list of <a href="writing-simple-detections/match-expression">match expressions</a>.</td></tr><tr><td><code>Description</code></td><td>A brief description of the rule</td><td>String</td></tr><tr><td><a href="#groupby"><code>GroupBy</code></a></td><td>Set of event values that will be used to deduplicate alerts by</td><td>List of event keys</td></tr><tr><td><code>DedupPeriodMinutes</code></td><td>The time period (in minutes) during which similar events of an alert will be grouped together</td><td><code>15</code>,<code>30</code>,<code>60</code>,<code>180</code> (3 hours),<code>720</code> (12 hours), or <code>1440</code> (24 hours)</td></tr><tr><td><code>DisplayName</code></td><td>A user-friendly name to show in the Panther Console and alerts. The <code>RuleID</code> will be displayed if this field is not set.</td><td>String</td></tr><tr><td><code>OutputIds</code></td><td>Static destination overrides. These will be used to determine how alerts from this rule are routed, taking priority over default routing based on severity.</td><td>List of strings</td></tr><tr><td><code>Reference</code></td><td>The reason this rule exists, often a link to documentation</td><td>String</td></tr><tr><td><code>Reports</code></td><td>A mapping of framework or report names to values this rule covers for that framework</td><td>Map of strings to list of strings</td></tr><tr><td><code>Runbook</code></td><td>The actions to be carried out if this rule returns an alert. It's recommended to provide a descriptive runbook, as <a href="../../../alerts#panther-ai-alert-triage">Panther AI alert triage</a> will take it into consideration.</td><td>String</td></tr><tr><td><code>SummaryAttributes</code></td><td>A list of fields that alerts should summarize.</td><td>List of strings</td></tr><tr><td><code>Threshold</code></td><td>How many events need to trigger this rule before an alert will be sent.</td><td>Integer</td></tr><tr><td><code>Tags</code></td><td>Tags used to categorize this rule</td><td>List of strings</td></tr><tr><td><code>Tests</code></td><td>Unit tests for this rule</td><td>List of maps</td></tr><tr><td><code>InlineFilters</code></td><td>The list of filters in the form of <a href="writing-simple-detections/match-expression">match expressions</a> to filter in data</td><td>List of <a href="writing-simple-detections/match-expression">match expressions</a> (limited to filter-compatible versions)</td></tr><tr><td><a href="#alerttitle"><code>AlertTitle</code></a></td><td>An alternate <code>DisplayName</code> that can use event values to create a dynamic title for alerts</td><td>String</td></tr><tr><td><a href="#alertcontext"><code>AlertContext</code></a></td><td>Event values to add to the Event under custom keys to create a dynamic alert context</td><td>List of key name and key value pairs</td></tr></tbody></table>
