"""YAML-based timeliner configuration file."""
import yaml
from plaso.lib import errors
[docs]
class TimelinerDefinition:
"""Timeliner definition.
Attributes:
attribute_mappings (dict[str, str]): date and time description
(timestamp_desc) per attribute name.
data_type (str): event data type indicator.
place_holder_event (bool): True if the timeliner should generate
a placeholder event if no date and time values were found in
the event data.
"""
[docs]
def __init__(self, data_type):
"""Initializes a timeliner definition.
Args:
data_type (str): event data type indicator.
"""
super().__init__()
self.attribute_mappings = {}
self.data_type = data_type
self.place_holder_event = True
[docs]
class YAMLTimelinerConfigurationFile:
"""YAML-based timeliner configuration file.
A YAML-based timeliner configuration file contains one or more timeliner
definitions. A timeliner definitions consists of:
data_type: 'fs:stat'
attribute_mappings:
- name: 'access_time'
description: 'Last Access Time'
place_holder_event: true
Where:
* data_type, defines the corresponding event data type;
* attribute_mappings, defines attribute mappings;
* place_holder_event, defines if the timeliner should generate a placeholder
event.
"""
_SUPPORTED_KEYS = frozenset(
["attribute_mappings", "data_type", "place_holder_event"]
)
def _ReadTimelinerDefinition(self, timeliner_definition_values):
"""Reads a timeliner definition from a dictionary.
Args:
timeliner_definition_values (dict[str, object]): timeliner definition
values.
Returns:
TimelinerDefinition: a timeliner definition.
Raises:
ParseError: if the format of the timeliner definition is not set
or incorrect.
"""
if not timeliner_definition_values:
raise errors.ParseError("Missing timeliner definition values.")
different_keys = set(timeliner_definition_values) - self._SUPPORTED_KEYS
if different_keys:
different_keys = ", ".join(different_keys)
raise errors.ParseError(f"Undefined keys: {different_keys:s}")
data_type = timeliner_definition_values.get("data_type")
if not data_type:
raise errors.ParseError(
"Invalid event timeliner definition missing data type."
)
attribute_mappings = (
timeliner_definition_values.get("attribute_mappings", None) or []
)
timeliner_definition = TimelinerDefinition(data_type)
timeliner_definition.attribute_mappings = {
attribute_mapping["name"]: attribute_mapping["description"]
for attribute_mapping in attribute_mappings
}
timeliner_definition.place_holder_event = timeliner_definition_values.get(
"place_holder_event", True
)
return timeliner_definition
def _ReadFromFileObject(self, file_object):
"""Reads the timeliner definitions from a file-like object.
Args:
file_object (file): timeliner definitions file-like object.
Yields:
TimelinerDefinition: a timeliner definition.
"""
yaml_generator = yaml.safe_load_all(file_object)
for yaml_definition in yaml_generator:
yield self._ReadTimelinerDefinition(yaml_definition)
[docs]
def ReadFromFile(self, path):
"""Reads the timeliner definitions from a YAML file.
Args:
path (str): path to a timeliner configuration file.
Yields:
TimelinerDefinition: a timeliner definition.
"""
with open(path, "r", encoding="utf-8") as file_object:
yield from self._ReadFromFileObject(file_object)