in aristotle/aristotle.py [0:0]
def output_rules(self, sid_list, outfile=None, modify_metadata=None):
"""Output rules, given a list of SIDs.
:param sid_list: list of SIDs of the rules to output
:type sid_list: list, required
:param outfile: filename to output to; if None, output to stdout; defaults to `None`
:type outfile: string or None, optional
:param modify_metadata: modify the rule metadata keyword value on output to contain the internally tracked and normalized metadata data.
:type modify_metadata: bool, optional
:returns: None
:rtype: NoneType
:raises: `AristotleException`
"""
# TODO: handle order because of/based on flowbits? Ideally IDS engine should handle...
# see https://redmine.openinfosecfoundation.org/issues/1399
if not self.output_disabled_rules:
sid_list = [s for s in sid_list if not self.metadata_dict[s]['disabled']]
else:
# 'output_disabled_rules' set so all non-matching and disabled rules get printed as disabled rules
# Set all non-matching rules to 'disabled' and set sid_list to be all rules
for s in list(set(self.get_all_sids()) - set(sid_list)):
self.metadata_dict[s]['disabled'] = True
sid_list = self.get_all_sids()
if modify_metadata is None:
modify_metadata = self.modify_metadata
if modify_metadata:
# Note: this updates/overwrites the self.metadata_dict[<sid>]['raw_rule'] value
# so if your code expects that to be unchanged after calling output_rules(),
# that won't be the case.
print_debug("Modifying metadata...")
for s in sid_list:
metadata_string = ""
# Sort before building; this way the ruleset hash won't change on every run.
# Before Python 3.6, insertion order in dicts isn't necessarily preserved.
# Could use an OrderedDict but doing this instead.
for key in sorted(self.metadata_dict[s]['metadata'].keys()):
if key == "sid" and self.normalize:
# if normalize set, don't include 'sid' in metadata on output per BETTER recommendation
continue
if key == "originally_disabled" and not self.enhance:
# if the 'enhance' option is not enabled, don't include 'originally_disabled' key
continue
for val in sorted(self.metadata_dict[s]['metadata'][key]):
metadata_string += "{} {}, ".format(key, val)
if len(metadata_string) > 0:
metadata_string = metadata_string[:-2] + ';'
if metadata_keyword_re.search(self.metadata_dict[s]['raw_rule']):
self.metadata_dict[s]['raw_rule'] = metadata_keyword_re.sub(r'\g<PRE>' + metadata_string, self.metadata_dict[s]['raw_rule'])
else:
# no 'metadata' keyword in original rule; add one.
metadata_string = " metadata:{})".format(metadata_string)
self.metadata_dict[s]['raw_rule'] = eol_re.sub(metadata_string, self.metadata_dict[s]['raw_rule'])
else:
print_warning("No metadata found for SID {}.".format(s))
if outfile is None:
for s in sid_list:
if not self.metadata_dict[s]['disabled'] or self.output_disabled_rules:
print("{}{}".format('#' if self.metadata_dict[s]['disabled'] else '', self.metadata_dict[s]['raw_rule']))
else:
try:
with open(outfile, "w") as fh:
enabled_count = 0
disabled_count = 0
for s in sid_list:
if not self.metadata_dict[s]['disabled'] or self.output_disabled_rules:
if not self.metadata_dict[s]['disabled']:
fh.write("{}\n".format(self.metadata_dict[s]['raw_rule']))
enabled_count += 1
else:
fh.write("#{}\n".format(self.metadata_dict[s]['raw_rule']))
disabled_count += 1
except Exception as e:
print_error("Problem writing to file '{}':\n{}".format(outfile, e), fatal=True)
print(GREEN + "Wrote {} rules {}to file, '{}'".format(
(enabled_count + disabled_count),
"({} enabled, {} disabled) ".format(enabled_count, disabled_count) if self.output_disabled_rules else '',
outfile) + RESET + "\n")