Panther's real-time analysis engine examines events one-by-one and sometimes it's helpful to keep state across invocations. To accommodate stateful checks, rules can cache values by using built-in helper functions.
The first step is to import the open source helper library:
import panther_oss_helpers
You may import specific functions:
from panther_oss_helpers import increment_counter
To implement a counter-based rule, use one or more of the following functions:
get_counter
: Get the latest counter value
increment_counter
: Add to the counter (default of 1)
reset_counter
: Reset the counter to 0
set_key_expiration
: Set the lifetime of the counter
The rule below provides a demonstration of using counters.
from panther_oss_helpers import increment_counter, set_key_expiration, reset_counter​​def rule(event):# Filter to only analyze AccessDenied callsif event.get('errorCode') != 'AccessDenied':return False​# Create our counter key, which should be fairly uniquekey = '{}-AccessDeniedCounter'.format(event['userIdentity'].get('arn'))​# Increment the counter, and then check the current valuehourly_error_count = increment_counter(key)if hourly_error_count == 1:set_key_expiration(time.time() + 3600)elif failure_hourly_count >= 10:# If it exceeds our threshold, reset and then return an alertreset_counter(key)return Truereturn False
To keep track of sets of strings, use the following functions:
get_string_set
: Get the string set's current value
put_string_set
: Overwrite a string set
add_to_string_set
: Add one or more strings to a set
remove_from_string_set
: Remove one or more strings from a set
reset_string_set
: Empty the set
from panther_oss_helpers import add_to_string_set​​def rule(event):if event['eventName'] != 'AssumeRole':return False​role_arn = event['requestParameters'].get('roleArn')if not role_arn:return False​role_arn_key = '{}-UniqueSourceIPs'.format(role_arn)ip_addr = event['sourceIPAddress']​previously_seen_ips = get_string_set(role_arn_key)​# If this the only value, trust on first useif len(previously_seen_ips) == 0:add_to_string_set(role_arn_key, ip_addr)return False​if ip_addr not in previously_seen_ips:return True​return False
Currently, CLI testing does not support mocking function calls.