"""The parser and parser plugin presets."""
import yaml
from plaso.containers import artifacts
from plaso.lib import errors
from plaso.parsers import logger
[docs]
class ParserPreset:
"""Parser and parser plugin preset.
Attributes:
deprecated (bool): True if the preset is deprecated.
name (str): name of the preset.
operating_systems (list[OperatingSystemArtifact]): operating system
artifact attribute containers, that specify to which operating
systems the preset applies.
parsers (list[str]): names of parser and parser plugins.
"""
[docs]
def __init__(self, name, parsers):
"""Initializes a parser and parser plugin preset.
Attributes:
name (str): name of the preset.
parsers (list[str]): names of parser and parser plugins.
"""
super().__init__()
self.deprecated = False
self.name = name
self.operating_systems = []
self.parsers = parsers
[docs]
class ParserPresetsManager:
"""The parsers and plugin presets manager."""
[docs]
def __init__(self):
"""Initializes a parser and parser plugin presets manager."""
super().__init__()
self._definitions = {}
def _ReadOperatingSystemArtifactValues(self, operating_system_values):
"""Reads an operating system artifact from a dictionary.
Args:
operating_system_values (dict[str, object]): operating system values.
Returns:
OperatingSystemArtifact: an operating system artifact attribute container.
Raises:
MalformedPresetError: if the format of the operating system values are
not set or incorrect.
"""
if not operating_system_values:
raise errors.MalformedPresetError("Missing operating system values.")
family = operating_system_values.get("family")
product = operating_system_values.get("product")
version = operating_system_values.get("version")
if not family and not product:
raise errors.MalformedPresetError(
"Invalid operating system missing family and product."
)
return artifacts.OperatingSystemArtifact(
family=family, product=product, version=version
)
def _ReadParserPresetValues(self, preset_definition_values):
"""Reads a parser preset from a dictionary.
Args:
preset_definition_values (dict[str, object]): preset definition values.
Returns:
ParserPreset: a parser preset.
Raises:
MalformedPresetError: if the format of the preset definition is not set
or incorrect, or the preset of a specific operating system has already
been set.
"""
if not preset_definition_values:
raise errors.MalformedPresetError("Missing preset definition values.")
name = preset_definition_values.get("name")
if not name:
raise errors.MalformedPresetError("Invalid preset definition missing name.")
parsers = preset_definition_values.get("parsers")
if not parsers:
raise errors.MalformedPresetError(
"Invalid preset definition missing parsers."
)
parser_preset = ParserPreset(name, parsers)
parser_preset.deprecated = preset_definition_values.get("deprecated", False)
for operating_system_values in preset_definition_values.get(
"operating_systems", []
):
operating_system = self._ReadOperatingSystemArtifactValues(
operating_system_values
)
parser_preset.operating_systems.append(operating_system)
return parser_preset
def _ReadPresetsFromFileObject(self, file_object):
"""Reads parser and parser plugin presets from a file-like object.
Args:
file_object (file): file-like object containing the parser and parser
plugin presets definitions.
Yields:
ParserPreset: a parser preset.
Raises:
MalformedPresetError: if one or more plugin preset definitions are
malformed.
"""
yaml_generator = yaml.safe_load_all(file_object)
last_preset_definition = None
for yaml_definition in yaml_generator:
try:
preset_definition = self._ReadParserPresetValues(yaml_definition)
except errors.MalformedPresetError as exception:
error_location = "At start"
if last_preset_definition:
error_location = f"After: {last_preset_definition.name!s}"
raise errors.MalformedPresetError(f"{error_location!s} {exception!s}")
yield preset_definition
last_preset_definition = preset_definition
[docs]
def GetNames(self):
"""Retrieves the preset names.
Returns:
list[str]: preset names in alphabetical order.
"""
return sorted(self._definitions.keys())
[docs]
def GetParsersByPreset(self, preset_name):
"""Retrieves the parser and plugin names of a specific preset.
Args:
preset_name (str): name of the preset.
Returns:
list[str]: parser and plugin names in alphabetical order.
Raises:
KeyError: if the preset does not exist.
"""
lookup_name = preset_name.lower()
preset_definition = self._definitions.get(lookup_name)
if preset_definition is None:
raise KeyError(f"Preset: {preset_name!s} is not defined")
if preset_definition.deprecated:
logger.warning(
f"Preset: {preset_name!s} is deprecated and will be removed "
f"in a future version"
)
return sorted(preset_definition.parsers)
[docs]
def GetPresetByName(self, name):
"""Retrieves a specific preset definition by name.
Args:
name (str): name of the preset.
Returns:
ParserPreset: a parser preset or None if not available.
"""
lookup_name = name.lower()
return self._definitions.get(lookup_name)
[docs]
def GetPresetsByOperatingSystem(self, operating_system):
"""Retrieves preset definitions for a specific operating system.
Args:
operating_system (OperatingSystemArtifact): an operating system artifact
attribute container.
Returns:
list[PresetDefinition]: preset definition that correspond with the
operating system.
"""
preset_definitions = []
for preset_definition in self._definitions.values():
for preset_operating_system in preset_definition.operating_systems:
if preset_operating_system.IsEquivalent(operating_system):
preset_definitions.append(preset_definition)
return preset_definitions
[docs]
def ReadFromFile(self, path):
"""Reads parser and parser plugin presets from a file.
Args:
path (str): path of file that contains the the parser and parser plugin
presets configuration.
Raises:
MalformedPresetError: if one or more plugin preset definitions are
malformed.
"""
self._definitions = {}
with open(path, "r", encoding="utf-8") as file_object:
for preset_definition in self._ReadPresetsFromFileObject(file_object):
self._definitions[preset_definition.name] = preset_definition