コード例 #1
0
    def __init__(self, configyaml=None):
        if configyaml == None:
            self.config = None
            self.order = None
            self.fieldmappings = dict()
            self.logsources = dict()
            self.defaultindex = None
            self.backend = None
        else:
            config = yaml.safe_load(configyaml)
            self.config = config

            self.fieldmappings = dict()
            try:
                for source, target in config['fieldmappings'].items():
                    self.fieldmappings[source] = FieldMapping(source, target)
            except TypeError as e:
                raise SigmaConfigParseError("Configuration has wrong type, should be map") from e
            except KeyError:
                pass

            if type(self.fieldmappings) != dict:
                raise SigmaConfigParseError("Fieldmappings must be a map")

            self.order = config.setdefault("order", None)
            self.defaultindex = config.setdefault('defaultindex', None)

            self.logsources = list()
            self.backend = None
コード例 #2
0
    def __init__(self, configyaml=None):
        if configyaml == None:
            self.config = None
            self.fieldmappings = dict()
            self.logsources = dict()
            self.logsourcemerging = SigmaLogsourceConfiguration.MM_AND
            self.defaultindex = None
            self.backend = None
        else:
            config = yaml.safe_load(configyaml)
            self.config = config

            self.fieldmappings = dict()
            try:
                for source, target in config['fieldmappings'].items():
                    self.fieldmappings[source] = FieldMapping(source, target)
            except KeyError:
                pass
            if type(self.fieldmappings) != dict:
                raise SigmaConfigParseError("Fieldmappings must be a map")

            try:
                self.logsourcemerging = config['logsourcemerging']
            except KeyError:
                self.logsourcemerging = SigmaLogsourceConfiguration.MM_AND

            try:
                self.defaultindex = config['defaultindex']
            except KeyError:
                self.defaultindex = None

            self.logsources = list()
            self.backend = None
コード例 #3
0
 def set_backend(self, backend):
     """Set backend. This is used by other code to determine target properties for index addressing"""
     self.backend = backend
     if self.config != None:
         if 'logsources' in self.config:
             logsources = self.config['logsources']
             if type(logsources) != dict:
                 raise SigmaConfigParseError("Logsources must be a map")
             for name, logsource in logsources.items():
                 self.logsources.append(SigmaLogsourceConfiguration(logsource, self.defaultindex))
コード例 #4
0
    def __init__(self, logsource=None, defaultindex=None):
        if logsource == None:  # create empty object
            self.merged = False
            self.category = None
            self.product = None
            self.service = None
            self.index = list()
            self.conditions = list(
            )  # a list of (field, value) tuples which are OR-linked in the generated query. May also contain such a list as list element (in case of merged log sources)
            self.rewrite = None
        elif type(logsource) == list and all([
                isinstance(o, SigmaLogsourceConfiguration) for o in logsource
        ]):  # list of SigmaLogsourceConfigurations: merge
            self.merged = True
            if any([
                    ls.merged for ls in logsource
            ]):  # Ensure that already merged objects are not merged again
                raise TypeError(
                    "Nested merging of SigmaLogsourceConfiguration objects is not allowed"
                )
            rewrites = {
                ls.rewrite
                for ls in logsource if ls.rewrite is not None
            }
            if len(rewrites) > 1:
                raise ValueError(
                    "More than one matching log source contains a rewrite part"
                )
            elif len(rewrites) == 1:
                self.rewrite = rewrites.pop()
            else:
                self.rewrite = None

            # Merge category, product and service
            categories = {
                ls.category
                for ls in logsource if ls.category is not None
            }
            products = {
                ls.product
                for ls in logsource if ls.product is not None
            }
            services = {
                ls.service
                for ls in logsource if ls.service is not None
            }
            if len(categories) > 1 or len(products) > 1 or len(services) > 1:
                raise ValueError(
                    "Merged SigmaLogsourceConfigurations must have disjunct categories (%s), products (%s) and services (%s)"
                    % (str(categories), str(products), str(services)))

            try:
                self.category = categories.pop()
            except KeyError:
                self.category = None
            try:
                self.product = products.pop()
            except KeyError:
                self.product = None
            try:
                self.service = services.pop()
            except KeyError:
                self.service = None

            # Merge all index patterns
            self.index = list(
                set([index for ls in logsource
                     for index in ls.index]))  # unique(flat(logsources.index))
            if len(
                    self.index
            ) == 0 and defaultindex is not None:  # if no index pattern matched and default index is present: use default index
                if type(defaultindex) == str:
                    self.index = [defaultindex]
                elif type(defaultindex) == list and all(
                    [type(i) == str for i in defaultindex]):
                    self.index = defaultindex
                else:
                    raise TypeError(
                        "Default index must be string or list of strings")

            self.conditions = [
                ls.conditions for ls in logsource if ls.conditions
            ]  # build list of list of (field, value) tuples as base for merged query condition.
        elif type(logsource
                  ) == dict:  # create logsource configuration from parsed yaml
            self.merged = False
            if 'category' in logsource and type(logsource['category']) != str \
                    or 'product' in logsource and type(logsource['product']) != str \
                    or 'service' in logsource and type(logsource['service']) != str:
                raise SigmaConfigParseError(
                    "Logsource category, product or service must be a string")
            try:
                self.category = logsource['category']
            except KeyError:
                self.category = None
            try:
                self.product = logsource['product']
            except KeyError:
                self.product = None
            try:
                self.service = logsource['service']
            except KeyError:
                self.service = None
            if self.category == None and self.product == None and self.service == None:
                raise SigmaConfigParseError(
                    "Log source definition will not match")

            try:
                if type(logsource['rewrite']) is not dict:
                    raise SigmaConfigParseError("Rewrite rule must be a map")
                rewrite = logsource['rewrite']
                if not {'category', 'product', 'service'}.issuperset(
                        rewrite.keys()):
                    raise SigmaConfigParseError(
                        "Rewrite rule in log source configuration may only contain the keys 'category', 'product' and 'service'"
                    )
                if {str} != {type(value) for value in rewrite.values()}:
                    raise SigmaConfigParseError(
                        "Rewrite rule values may only contain strings")
                self.rewrite = tuple(
                    (rewrite.get(key)
                     for key in ('category', 'product', 'service')
                     ))  # build a (category, product, service) tuple from dict
            except KeyError:
                self.rewrite = None

            if 'index' in logsource:
                index = logsource['index']
                if type(index) not in (str, list):
                    raise SigmaConfigParseError(
                        "Logsource index must be string or list of strings")
                if type(index) == list and not all(
                    [type(index) == str for index in logsource['index']]):
                    raise SigmaConfigParseError(
                        "Logsource index patterns must be strings")
                if type(index) == list:
                    self.index = index
                else:
                    self.index = [index]
            else:
                # no default index handling here - this branch is executed if log source definitions are parsed from
                # config and these must not necessarily contain an index definition. A valid index may later be result
                # from a merge, where default index handling applies.
                self.index = []

            try:
                if type(logsource['conditions']) != dict:
                    raise SigmaConfigParseError(
                        "Logsource conditions must be a map")
                self.conditions = [
                    (field, value)
                    for field, value in logsource['conditions'].items()
                ]  # build list of (field, value) tuples as base for query condition
            except KeyError:
                self.conditions = list()
        else:
            raise SigmaConfigParseError("Logsource definitions must be maps")
コード例 #5
0
    def __init__(self, logsource=None, defaultindex=None, name=None, mergemethod=MM_AND, indexfield=None):
        self.name = name
        self.indexfield = indexfield
        if logsource == None:               # create empty object
            self.category = None
            self.product = None
            self.service = None
            self.index = list()
            self.conditions = None
        elif type(logsource) == list and all([isinstance(o, SigmaLogsourceConfiguration) for o in logsource]):      # list of SigmaLogsourceConfigurations: merge according to mergemethod
            # Merge category, product and service
            categories = set([ ls.category for ls in logsource if ls.category != None ])
            products = set([ ls.product for ls in logsource if ls.product != None ])
            services = set([ ls.service for ls in logsource if ls.service != None])
            if len(categories) > 1 or len(products) > 1 or len(services) > 1:
                raise ValueError("Merged SigmaLogsourceConfigurations must have disjunct categories (%s), products (%s) and services (%s)" % (str(categories), str(products), str(services)))

            try:
                self.category = categories.pop()
            except KeyError:
                self.category = None
            try:
                self.product = products.pop()
            except KeyError:
                self.product = None
            try:
                self.service = services.pop()
            except KeyError:
                self.service = None

            # Merge all index patterns
            self.index = list(set([index for ls in logsource for index in ls.index]))       # unique(flat(logsources.index))
            if len(self.index) == 0 and defaultindex is not None:   # if no index pattern matched and default index is present: use default index
                if type(defaultindex) == str:
                    self.index = [defaultindex]
                elif type(defaultindex) == list and all([type(i) == str for i in defaultindex]):
                    self.index = defaultindex
                else:
                    raise TypeError("Default index must be string or list of strings")

            # "merge" index field (should never differ between instances because it is provided by backend class
            indexfields = [ ls.indexfield for ls in logsource if ls.indexfield != None ]
            try:
                self.indexfield = indexfields[0]
            except IndexError:
                self.indexfield = None

            # Merge conditions according to mergemethod
            if mergemethod == self.MM_AND:
                cond = ConditionAND()
            elif mergemethod == self.MM_OR:
                cond = ConditionOR()
            else:
                raise ValueError("Mergemethod must be '%s' or '%s'" % (self.MM_AND, self.MM_OR))
            for ls in logsource:
                if ls.conditions != None:
                    cond.add(ls.conditions)
            if len(cond) > 0:
                self.conditions = cond
            else:
                self.conditions = None
        elif type(logsource) == dict:       # create logsource configuration from parsed yaml
            if 'category' in logsource and type(logsource['category']) != str \
                    or 'product' in logsource and type(logsource['product']) != str \
                    or 'service' in logsource and type(logsource['service']) != str:
                raise SigmaConfigParseError("Logsource category, product or service must be a string")
            try:
                self.category = logsource['category']
            except KeyError:
                self.category = None
            try:
                self.product = logsource['product']
            except KeyError:
                self.product = None
            try:
                self.service = logsource['service']
            except KeyError:
                self.service = None
            if self.category == None and self.product == None and self.service == None:
                raise SigmaConfigParseError("Log source definition will not match")

            if 'index' in logsource:
                index = logsource['index']
                if type(index) not in (str, list):
                    raise SigmaConfigParseError("Logsource index must be string or list of strings")
                if type(index) == list and not all([type(index) == str for index in logsource['index']]):
                    raise SigmaConfigParseError("Logsource index patterns must be strings")
                if type(index) == list:
                    self.index = index
                else:
                    self.index = [ index ]
            else:
                # no default index handling here - this branch is executed if log source definitions are parsed from
                # config and these must not necessarily contain an index definition. A valid index may later be result
                # from a merge, where default index handling applies.
                self.index = []

            if 'conditions' in logsource:
                if type(logsource['conditions']) != dict:
                    raise SigmaConfigParseError("Logsource conditions must be a map")
                cond = ConditionAND()
                for key, value in logsource['conditions'].items():
                    cond.add((key, value))
                self.conditions = cond
            else:
                self.conditions = None
        else:
            raise SigmaConfigParseError("Logsource definitions must be maps")