"""YAML-based filter file."""
import io
import yaml
from plaso.engine import path_filters
from plaso.lib import errors
[docs]
class YAMLFilterFile:
"""YAML-based filter file.
A YAML-based filter file contains one or more path filters.
description: Include filter with Linux paths.
type: include
path_separator: '/'
paths:
- '/usr/bin'
Where:
* description, is an optional description of the purpose of the path filter;
* type, defines the filter type, which can be "include" or "exclude";
* path_separator, defines the path segment separator, which is "/" by default;
* paths, defines regular expression of paths to filter on.
Note that the regular expression need to be defined per path segment, for
example to filter "/usr/bin/echo" and "/usr/sbin/echo" the following
expression could be defined "/usr/(bin|sbin)/echo".
Note that when the path segment separator is defined as "\\" it needs to be
escaped as "\\\\", since "\\" is used by the regular expression as escape
character.
A path may contain path expansion attributes, for example:
%{SystemRoot}\\\\System32
"""
_SUPPORTED_KEYS = frozenset(["description", "path_separator", "paths", "type"])
def _ReadFilterDefinition(self, filter_definition_values):
"""Reads a filter definition from a dictionary.
Args:
filter_definition_values (dict[str, object]): filter definition values.
Returns:
PathFilter: a path filter.
Raises:
ParseError: if the format of the filter definition is not set
or incorrect.
"""
if not filter_definition_values:
raise errors.ParseError("Missing filter definition values.")
different_keys = set(filter_definition_values) - self._SUPPORTED_KEYS
if different_keys:
different_keys = ", ".join(different_keys)
raise errors.ParseError(f"Undefined keys: {different_keys:s}")
filter_type = filter_definition_values.get("type")
if not filter_type:
raise errors.ParseError("Invalid path filter definition missing type.")
if filter_type not in (
path_filters.PathFilter.FILTER_TYPE_EXCLUDE,
path_filters.PathFilter.FILTER_TYPE_INCLUDE,
):
raise errors.ParseError(
f"Invalid path filter definition unsupported type: {filter_type!s}."
)
paths = filter_definition_values.get("paths")
if not paths:
raise errors.ParseError("Invalid path filter definition missing paths.")
description = filter_definition_values.get("description")
path_separator = filter_definition_values.get("path_separator", "/")
return path_filters.PathFilter(
filter_type,
description=description,
path_separator=path_separator,
paths=paths,
)
def _ReadFromFileObject(self, file_object):
"""Reads the path filters from a file-like object.
Args:
file_object (file): filter file-like object.
Yields:
PathFilter: path filter.
"""
yaml_generator = yaml.safe_load_all(file_object)
for yaml_definition in yaml_generator:
yield self._ReadFilterDefinition(yaml_definition)
[docs]
def ReadFromFile(self, path):
"""Reads the path filters from the YAML-based filter file.
Args:
path (str): path to a filter file.
Returns:
list[PathFilter]: path filters.
"""
with io.open(path, "r", encoding="utf-8") as file_object:
return list(self._ReadFromFileObject(file_object))