Add ability to append to rules/macros

Add the ability to append to rules/macros, like we already do with
lists. For rules/macros, if the object has an append: true key, the
condition value is appended to the condition of an existing rule/macro
with the same name.

Like lists, it's an error to specify append: true without there being an
existing rule/macro.

Also add tests that test the same kind of things we did for lists:
 - That append: true really does append
 - That append: false overwrites the rule/macro
 - That it's an error to append with a prior rule/macro existing.
This commit is contained in:
Mark Stemm 2017-09-22 17:08:00 -07:00
parent 2d0963e97c
commit a38f7f181b
8 changed files with 147 additions and 18 deletions

View File

@ -599,3 +599,44 @@ trace_files: !mux
rules_file: rules_file:
- rules/list_append_false.yaml - rules/list_append_false.yaml
trace_file: trace_files/cat_write.scap trace_file: trace_files/cat_write.scap
macro_append_failure:
exit_status: 1
stderr_contains: "Macro my_macro has 'append' key but no macro by that name already exists. Exiting"
rules_file:
- rules/macro_append_failure.yaml
trace_file: trace_files/cat_write.scap
macro_append:
detect: True
detect_level: WARNING
rules_file:
- rules/macro_append.yaml
trace_file: trace_files/cat_write.scap
macro_append_false:
detect: False
rules_file:
- rules/macro_append_false.yaml
trace_file: trace_files/cat_write.scap
rule_append_failure:
exit_status: 1
stderr_contains: "Rule my_rule has 'append' key but no rule by that name already exists. Exiting"
rules_file:
- rules/rule_append_failure.yaml
trace_file: trace_files/cat_write.scap
rule_append:
detect: True
detect_level: WARNING
rules_file:
- rules/rule_append.yaml
trace_file: trace_files/cat_write.scap
rule_append_false:
detect: False
rules_file:
- rules/rule_append_false.yaml
trace_file: trace_files/cat_write.scap

View File

@ -0,0 +1,12 @@
- macro: my_macro
condition: proc.name=not-cat
- macro: my_macro
append: true
condition: or proc.name=cat
- rule: Open From Cat
desc: A process named cat does an open
condition: evt.type=open and my_macro
output: "An open was seen (command=%proc.cmdline)"
priority: WARNING

View File

@ -0,0 +1,3 @@
- macro: my_macro
condition: proc.name=not-cat
append: true

View File

@ -0,0 +1,12 @@
- macro: my_macro
condition: proc.name=cat
- macro: my_macro
append: false
condition: proc.name=not-cat
- rule: Open From Cat
desc: A process named cat does an open
condition: evt.type=open and my_macro
output: "An open was seen (command=%proc.cmdline)"
priority: WARNING

View File

@ -0,0 +1,9 @@
- rule: my_rule
desc: A process named cat does an open
condition: evt.type=open and fd.name=not-a-real-file
output: "An open of /dev/null was seen (command=%proc.cmdline)"
priority: WARNING
- rule: my_rule
append: true
condition: or fd.name=/dev/null

View File

@ -0,0 +1,3 @@
- rule: my_rule
condition: evt.type=open
append: true

View File

@ -0,0 +1,9 @@
- rule: my_rule
desc: A process named cat does an open
condition: evt.type=open and fd.name=/dev/null
output: "An open of /dev/null was seen (command=%proc.cmdline)"
priority: WARNING
- rule: my_rule
append: true
condition: and fd.name=not-a-real-file

View File

@ -208,7 +208,23 @@ function load_rules(rules_content, rules_mgr, verbose, all_events, extra, replac
end end
end end
state.macros_by_name[v['macro']] = v -- Possibly append to the condition field of an existing macro
append = false
if v['append'] then
append = v['append']
end
if append then
if state.macros_by_name[v['macro']] == nil then
error ("Macro " ..v['macro'].. " has 'append' key but no macro by that name already exists")
end
state.macros_by_name[v['macro']]['condition'] = state.macros_by_name[v['macro']]['condition'] .. " " .. v['condition']
else
state.macros_by_name[v['macro']] = v
end
elseif (v['list']) then elseif (v['list']) then
@ -247,25 +263,49 @@ function load_rules(rules_content, rules_mgr, verbose, all_events, extra, replac
error ("Missing name in rule") error ("Missing name in rule")
end end
for i, field in ipairs({'condition', 'output', 'desc', 'priority'}) do -- Possibly append to the condition field of an existing rule
if (v[field] == nil) then append = false
error ("Missing "..field.." in rule with name "..v['rule'])
if v['append'] then
append = v['append']
end
if append then
-- For append rules, all you need is the condition
for i, field in ipairs({'condition'}) do
if (v[field] == nil) then
error ("Missing "..field.." in rule with name "..v['rule'])
end
end end
if state.rules_by_name[v['rule']] == nil then
error ("Rule " ..v['rule'].. " has 'append' key but no rule by that name already exists")
end
state.rules_by_name[v['rule']]['condition'] = state.rules_by_name[v['rule']]['condition'] .. " " .. v['condition']
else
for i, field in ipairs({'condition', 'output', 'desc', 'priority'}) do
if (v[field] == nil) then
error ("Missing "..field.." in rule with name "..v['rule'])
end
end
-- Note that we can overwrite rules, but the rules are still
-- loaded in the order in which they first appeared,
-- potentially across multiple files.
if state.rules_by_name[v['rule']] == nil then
state.ordered_rule_names[#state.ordered_rule_names+1] = v['rule']
end
-- The output field might be a folded-style, which adds a
-- newline to the end. Remove any trailing newlines.
v['output'] = compiler.trim(v['output'])
state.rules_by_name[v['rule']] = v
end end
-- Note that we can overwrite rules, but the rules are still
-- loaded in the order in which they first appeared,
-- potentially across multiple files.
if state.rules_by_name[v['rule']] == nil then
state.ordered_rule_names[#state.ordered_rule_names+1] = v['rule']
end
-- The output field might be a folded-style, which adds a
-- newline to the end. Remove any trailing newlines.
v['output'] = compiler.trim(v['output'])
state.rules_by_name[v['rule']] = v
else else
error ("Unknown rule object: "..table.tostring(v)) error ("Unknown rule object: "..table.tostring(v))
end end