Creating PyPanther Detections
Last updated
Was this helpful?
Last updated
Was this helpful?
You can import Panther-managed PyPanther Detections and make your own modifications, as well as create your own custom ones. After you've created detections, you can .
This page describes how to create PyPanther Detections in the CLI workflow. If you'd like to create PyPanther Detections in the Console instead, see .
When working with PyPanther Detections in the CLI workflow:
A main.py
file controls your entire detection configuration, outlining which rules to register, override configurations, and custom rule definitions. You can either:
(Recommended) Define your detections in various other files/folders, then import them into main.py
(learn more in the )
Define your detections in main.py
A PyPanther rule is defined in a single Python file. Within it, you can import Panther-managed (or your own custom) PyPanther rules and specify overrides. A single Python file can define multiple detections.
All PyPanther rules subclass the pypanther
Rule
class or a parent class of type Rule
.
Rules must be to be tested and uploaded to your Panther instance.
All event object functions currently available in v1 detections are available in PyPanther Detections. These include: , , , and .
All are available in PyPanther Detections, such as title()
and severity()
. See .
Use the pypanther
type-ahead hints in your IDE, like searching for available rules or viewing properties of classes.
Define a rule()
function
(Optional) Define additional attributes, such as threshold
or dedup_period_minutes
Panther-managed rules can be imported directly or using the get_panther_rules()
function.
To import a Panther-managed rule directly using the rules
module, you would use a statement like:
The get_panther_rules()
function can filter on any Rule
class attribute, such as default_severity
, log_types
, or tag
. When filtering, keys use AND
logic, and values use OR
logic.
Get all Panther-managed rules using get_panther_rules()
:
Get Panther-managed rules with certain severities using get_panther_rules()
:
Get Panther-managed rules for certain log types using get_panther_rules()
:
Get Panther-managed rules that meet multiple criteria using get_panther_rules()
:
When making overrides on Panther-managed detections, it's recommended to:
Outside of main.py
, store all of your overrides in apply_overrides()
functions.
In main.py
, call pypanther
's apply_overrides()
to apply each of your apply_overrides()
functions.
You can override a single rule attribute in a one-line statement using the override()
function:
It’s also possible to make multi-attribute overrides with the override()
function:
To apply overrides on multiple rules at once, iterate over the collection using a for
loop.
This could be useful, for example, when updating a certain attribute for all rules associated to a certain LogType
.
When making modifications to an existing rule, you might want to add items to a list-type rule attribute (like tags
, tests
, include_filters
, or exclude_filters
) while preserving the existing list.
PyPanther Detection filters let you exclude certain events from being evaluated by a rule. Filters are designed to be applied on top of existing rule logic (likely for Panther-managed PyPanther Detections you are importing).
Each filter defines logic that is run before the rule()
function, and the outcome of the filter determines whether or not the event should go on to be evaluated by the rule.
There are two types of filters:
include_filters
: If the filter returns True
for an event, the event is evaluated by rule()
exclude_filters
: If the filter returns True
for an event, the event is dismissed (i.e., not evaluated by rule()
)
Examples as standalone functions:
Example as part of an inherited rule definition:
Filters can also be reused with a for
loop to be applied to multiple rules:
Panther-managed rules that require some customer configuration before they are uploaded into a Panther environment may include a validate_config()
function, which defines one or more conditions that must be met for the rule to pass the test
command (and function properly).
Example:
In this example, if allowed_domains
is not assigned a non-empty list, an assertion error will be thrown during pypanther
test
.
To set this value, you can use a statement like:
You can use inheritance to create rules that are subclasses of other rules (that are Panther-managed or custom).
It’s recommended to use inheritance when you’re creating a collection of rules that all share a number of characteristics—for example, rule()
function logic, property values, class variables, or helper functions. In this case, it’s useful to create a base rule that all related rules inherit from.
For example, it may be useful to create a base rule for each LogType
, from which all rules for that LogType
are extended.
Example:
Because PyPanther rules are fully defined in Python, you can use its full expressiveness when customizing your detections.
super()
For more advanced use cases, you can supplement the logic in functions defined by the parent rule.
You can use Python’s list comprehension functionality to create a new list based on an existing list with condensed syntax. This may be particularly useful when you want to filter a list of detections fetched using get_panther_rules()
.
A "custom" PyPanther rule is one that you write completely from scratch—i.e., one that isn't built from a . Custom PyPanther rules are defined in a Python class that subclasses the pypanther
Rule
class. In this class, you must:
(Optional) Define any of the , like title()
or destinations()
Define certain , such as log_types
The id
attribute is only required for a rule if you plan to it.
See the section for a full list of required and optional fields.
You may want to import Panther-managed rules (into main.py
or another file) to either them individually as-is, set on them, or them. You can import Panther-managed rules directly (from the pypanther.rules
module) or by using the get_panther_rules()
function.
See for an example of how to use get_panther_rules()
with advanced Python.
Once you’ve imported a Panther-managed rule, you can modify it using or .
If your objective is to modify a rule's logic, it's recommended to use instead of overriding the rule()
function itself. Learn more in .
Learn more about apply_overrides()
in .
Instead of overriding the attribute (using one of the methods in ), which would replace the existing list value, use the pypanther
extend()
function to append new values to the list attribute.
The has include_filters
and exclude_filters
attributes, which each contain a list of functions that will be evaluated against the log event.
Most commonly, validate_config()
verifies that some class variable, such as an allowlist or denylist, has been assigned a value. If the requirements included in validate_config()
are not met, an exception will be raised when the pypanther
test
command is run (if the rule is ).
Inheritance is commonly used with —i.e., subclassed rules can define additional criteria an event must meet in order to be processed by the rule.
If you don’t plan to a base rule, it’s not required to provide it an id
property.