新增一个规则类型
此文档系描述如何如何创建一个规则类型.内建的规则类型在elastalert/ruletypes.py
中并且是RuleType
的子类.要新增规则,最基本的需要实现add\_data
方法.
你所新增的类可能会实现RuleType
的以下几个方法:
class AwesomeNewRule(RuleType):
# ...
def add_data(self,data):
# ...
def get_match_str(self,match):
# ...
def garbage_collect(self,timestamp):
# ...
新的规则类型你可以按照module.file.RuleName
的形式进行导入,其中module是Python的module(模块),或者包含__init__.py
的文件夹名称,file则是包含继承RuleType
的子类名字为RuleName
的类的Python文件的名称.
基本信息
ElastAlert在运行过程 中RuleType
配置会一直停留在内存中,接收数据,跟踪其状态,生成匹配项.部分重要的特征创建在RuleType
类的__init__
函数中:
self.rules
: 该字典是从规则配置文件中获取.如果有timeframe
配置项,当规则被加载时,该值将自动被覆盖为datetime.timedelta
对象.
self.matches
: 该值用于 ElastAlert 检查规则(rule)当中的匹配(matches).任何与匹配相关的信息(通常是 Elasticsearch 的字段)需要存放在字典对象并添加到self.matches
当中.ElastAlert 将定期弹出(pop)项目并依赖这些对象发送警报.推荐使用self.add_match(match)
新增匹配.除了附加到self.matches
之外,self.add_match
还会将datetime@timestamp
转换回 ISO8061 时间戳.
self.required_options
: 该值是一组必须存在在配置文件中的选项集. ElastAlert 将确保在尝试实例化RuleType
这个实例之前,存在这些字段.
add_data(self, data):
当 ElastAlert 查询 Elasticsearch, 它将通过调用add_data
将所有匹配传递给规则类型.data
是一个字典对象的列表,它包含include
,query_key
和compare_key
的所有字段(如果它们存在的话),以及@timestamp
作为一个datetime对象.它们将始终按照'@timestamp'排序的时间顺序排列.
get_match_str(self, match):
报警器通过调用此函数获取关于匹配警报的易读的字符串.匹配项将会和添加到self.matches
中的对象相同,rule
与self.rules
关系也与此相同.RuleType
基本实现将返回一个空的字符串.请注意,默认情况下,警报文本将包含匹配中的键值对.这应该返回一个字符串,该字符串在特定的RuleType的上下文当中提供有关匹配的信息.
garbage_collect(self, timestamp):
该函数将在 ElastAlert 在"timestamp"结束的时间段内运行,并且应该用于清除"timestamp"作为可能已经过时的状态."timestamp"是一个datetime对象.
教程
举例来说,我们将对检查可疑登录创建一个规则类型.让我们构想一下我们查询的是包含 IP 地址,用户名以及一个时间戳的登录事件.配置文件将获取哟凝固名列表以及时间范围以及警报,如果在时间范围内发生登录.首先,我们在ElastAlert根文件夹当中创建一个模板文件夹:
$ mkdir elastalert_modules
$cd elastalert_modules
$ touch __init__.py
现在,在名称为my_rules.py
文件当中,新增如下内容
import dateutil.parser
from elastalert.ruletypes import RuleType
# elastalert.util includes useful utility functions
# such as converting from timestamp to datetime obj
from elastalert.util import ts_to_dt
class AwesomeRule(RuleType):
# By setting required_options to a set of strings
# You can ensure that the rule config file specifies all
# of the options. Otherwise, ElastAlert will throw an exception
# when trying to load the rule.
required_options=set(['time_start','time_end','usernames'])
# add_data will be called each time Elasticsearch is queried.
# data is a list of documents from Elasticsearch, sorted by timestamp,
# including all the fields that the config specifies with "include"
def add_data(self,data):
for document in data:
# To access config options, use self.rules
if document['username'] in self.rules['usernames']:
# Convert the timestamp to a time object
login_time=document['@timestamp'].time()
# Convert time_start and time_end to time objects
time_start=dateutil.parser.parse(self.rules['time_start']).time()
time_end=dateutil.parser.parse(self.rules['time_end']).time()
# If the time falls between start and end
if login_time>time_start and login_time<time_end:
# To add a match, use self.add_match
self.add_match(document)
# The results of get_match_str will appear in the alert text
def get_match_str(self,match):
return "%s logged in between %s and %s" % (match['username'],self.rules['time_start'],self.rules['time_end'])
# garbage_collect is called indicating that ElastAlert has already been run up to timestamp
# It is useful for knowing that there were no query results from Elasticsearch because
# add_data will not be called with an empty list
def garbage_collect(self,timestamp):
pass
在规则配置文件,example_rules/example_login_rule.yaml
中,我们将通过如下方式指定规则
name: "Example login rule"
es_host: elasticsearch.example.com
es_port: 14900
type: "elastalert_modules.my_rules.AwesomeRule"
# Alert if admin, userXYZ or foobaz log in between 8 PM and midnight
time_start: "20:00"
time_end: "24:00"
usernames:
- "admin"
- "userXYZ"
- "foobaz"
# We require the username field from documents
include:
- "username"
alert:
- debug
ElastAlert 将尝试通过from elastalert_modules.my_rules import AwesomeRule
导入(import)规则.这意味着文件夹必须在可以为导入为python模块的位置.
来自这条规则的警报内容将与下文类似:
Example login rule
userXYZ logged in between 20:00 and 24:00
@timestamp: 2015-03-02T22:23:24Z
username: userXYZ