def output_rules()

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")