diff --git a/plaso/output/interface.py b/plaso/output/interface.py index e7641ae94e..39168a89d8 100644 --- a/plaso/output/interface.py +++ b/plaso/output/interface.py @@ -152,11 +152,6 @@ def WriteHeader(self): class LinearOutputModule(OutputModule): """Linear output module.""" - # Need to suppress this since these classes do not implement the - # abstract method WriteEventBody, classes that inherit from one of these - # classes need to implement that function. - # pylint: disable=abstract-method - def __init__(self, output_mediator): """Initializes a linear output module. @@ -170,6 +165,16 @@ def __init__(self, output_mediator): super(LinearOutputModule, self).__init__(output_mediator) self._output_writer = None + @abc.abstractmethod + def WriteEventBody(self, event, event_data, event_tag): + """Writes event values to the output. + + Args: + event (EventObject): event. + event_data (EventData): event data. + event_tag (EventTag): event tag. + """ + def SetOutputWriter(self, output_writer): """Set the output writer. diff --git a/plaso/output/json_line.py b/plaso/output/json_line.py index 3dff321f40..ce736f5078 100644 --- a/plaso/output/json_line.py +++ b/plaso/output/json_line.py @@ -7,25 +7,16 @@ from __future__ import unicode_literals -import codecs -import copy -import json - -from plaso.lib import errors -from plaso.lib import py2to3 -from plaso.output import interface from plaso.output import manager -from plaso.serializer import json_serializer +from plaso.output import shared_json -class JSONLineOutputModule(interface.LinearOutputModule): +class JSONLineOutputModule(shared_json.SharedJSONOutputModule): """Output module for the JSON line format.""" NAME = 'json_line' DESCRIPTION = 'Saves the events into a JSON line format.' - _JSON_SERIALIZER = json_serializer.JSONAttributeContainerSerializer - def WriteEventBody(self, event, event_data, event_tag): """Writes event values to the output. @@ -34,32 +25,7 @@ def WriteEventBody(self, event, event_data, event_tag): event_data (EventData): event data. event_tag (EventTag): event tag. """ - # TODO: since the internal serializer can change move functionality - # to serialize into a shared json output module class. - # TODO: refactor to separately serialize event and event data - copy_of_event = copy.deepcopy(event) - for attribute_name, attribute_value in event_data.GetAttributes(): - setattr(copy_of_event, attribute_name, attribute_value) - - copy_of_event.tag = event_tag - - inode = getattr(event_data, 'inode', None) - if inode is None: - copy_of_event.inode = 0 - - try: - message, _ = self._output_mediator.GetFormattedMessages(event_data) - except errors.WrongFormatter: - message = None - - if message: - copy_of_event.message = message - - json_dict = self._JSON_SERIALIZER.WriteSerializedDict(copy_of_event) - json_string = json.dumps(json_dict, sort_keys=True) - # dumps() returns an ascii-encoded byte string in Python 2. - if py2to3.PY_2: - json_string = codecs.decode(json_string, 'ascii') + json_string = self._WriteSerialized(event, event_data, event_tag) self._output_writer.Write(json_string) self._output_writer.Write('\n') diff --git a/plaso/output/json_out.py b/plaso/output/json_out.py index fb64af2fe9..53eb404d55 100644 --- a/plaso/output/json_out.py +++ b/plaso/output/json_out.py @@ -3,22 +3,16 @@ from __future__ import unicode_literals -import copy -import json - -from plaso.output import interface from plaso.output import manager -from plaso.serializer import json_serializer +from plaso.output import shared_json -class JSONOutputModule(interface.LinearOutputModule): +class JSONOutputModule(shared_json.SharedJSONOutputModule): """Output module for the JSON format.""" NAME = 'json' DESCRIPTION = 'Saves the events into a JSON format.' - _JSON_SERIALIZER = json_serializer.JSONAttributeContainerSerializer - def __init__(self, output_mediator): """Initializes the output module object. @@ -37,21 +31,7 @@ def WriteEventBody(self, event, event_data, event_tag): event_data (EventData): event data. event_tag (EventTag): event tag. """ - # TODO: since the internal serializer can change move functionality - # to serialize into a shared json output module class. - # TODO: refactor to separately serialize event and event data - copy_of_event = copy.deepcopy(event) - for attribute_name, attribute_value in event_data.GetAttributes(): - setattr(copy_of_event, attribute_name, attribute_value) - - copy_of_event.tag = event_tag - - inode = getattr(event_data, 'inode', None) - if inode is None: - copy_of_event.inode = 0 - - json_dict = self._JSON_SERIALIZER.WriteSerializedDict(copy_of_event) - json_string = json.dumps(json_dict, sort_keys=True) + json_string = self._WriteSerialized(event, event_data, event_tag) if self._event_counter != 0: self._output_writer.Write(', ') diff --git a/plaso/output/shared_elastic.py b/plaso/output/shared_elastic.py index 9ab91a840f..91d9e52cc9 100644 --- a/plaso/output/shared_elastic.py +++ b/plaso/output/shared_elastic.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Shared code for Elasticsearch based output modules.""" +"""Shared functionality for Elasticsearch output modules.""" from __future__ import unicode_literals diff --git a/plaso/output/shared_json.py b/plaso/output/shared_json.py new file mode 100644 index 0000000000..c649bf8deb --- /dev/null +++ b/plaso/output/shared_json.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +"""Shared functionality for JSON based output modules.""" + +from __future__ import unicode_literals + +import abc +import json + +from plaso.lib import errors +from plaso.lib import py2to3 +from plaso.output import interface +from plaso.serializer import json_serializer + + +class SharedJSONOutputModule(interface.LinearOutputModule): + """Shared functionality for a JSON output module.""" + + _JSON_SERIALIZER = json_serializer.JSONAttributeContainerSerializer + + def _WriteSerialized(self, event, event_data, event_tag): + """Writes an event, event data and event tag to serialized form. + + Args: + event (EventObject): event. + event_data (EventData): event data. + event_tag (EventTag): event tag. + + Returns: + str: A JSON string containing the serialized form. + """ + json_dict = self._WriteSerializedDict(event, event_data, event_tag) + + json_string = json.dumps(json_dict, sort_keys=True) + # json.dumps() returns an ascii-encoded byte string in Python 2. + if py2to3.PY_2: + json_string = json_string.decode('ascii') + + return json_string + + def _WriteSerializedDict(self, event, event_data, event_tag): + """Writes an event, event data and event tag to serialized form. + + Args: + event (EventObject): event. + event_data (EventData): event data. + event_tag (EventTag): event tag. + + Returns: + dict[str, object]: JSON serialized objects. + """ + event_data_json_dict = self._JSON_SERIALIZER.WriteSerializedDict(event_data) + del event_data_json_dict['__container_type__'] + del event_data_json_dict['__type__'] + + inode = event_data_json_dict.get('inode', None) + if inode is None: + event_data_json_dict['inode'] = 0 + + try: + message, _ = self._output_mediator.GetFormattedMessages(event_data) + event_data_json_dict['message'] = message + except errors.WrongFormatter: + pass + + event_json_dict = self._JSON_SERIALIZER.WriteSerializedDict(event) + event_json_dict['__container_type__'] = 'event' + + event_json_dict.update(event_data_json_dict) + + if event_tag: + event_tag_json_dict = self._JSON_SERIALIZER.WriteSerializedDict(event_tag) + + event_json_dict['tag'] = event_tag_json_dict + + return event_json_dict + + @abc.abstractmethod + def WriteEventBody(self, event, event_data, event_tag): + """Writes event values to the output. + + Args: + event (EventObject): event. + event_data (EventData): event data. + event_tag (EventTag): event tag. + """ diff --git a/test_data/end_to_end/json.log b/test_data/end_to_end/json.log index a79dfb2594..1f6cb556ee 100644 --- a/test_data/end_to_end/json.log +++ b/test_data/end_to_end/json.log @@ -1,21 +1,21 @@ -{"event_0": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "INFO No change in [/etc/netgroup]. Done", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 30840, "reporter": "client", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218753000000, "timestamp_desc": "Content Modification Time"} -, "event_1": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "INFO No new content in \u00edmynd.dd.", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 30840, "reporter": "client", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218753000000, "timestamp_desc": "Content Modification Time"} -, "event_2": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "(root) CMD (touch /var/run/crond.somecheck)", "command": "touch /var/run/crond.somecheck", "data_type": "syslog:cron:task_run", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 31051, "reporter": "CRON", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218781000000, "timestamp_desc": "Content Modification Time", "username": "root"} -, "event_3": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "(root) CMD (/sbin/status.mycheck))", "command": "/sbin/status.mycheck)", "data_type": "syslog:cron:task_run", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 31067, "reporter": "CRON", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218841000000, "timestamp_desc": "Content Modification Time", "username": "root"} -, "event_4": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "(root) CMD (touch /var/run/crond.somecheck)", "command": "touch /var/run/crond.somecheck", "data_type": "syslog:cron:task_run", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 31068, "reporter": "CRON", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218841000000, "timestamp_desc": "Content Modification Time", "username": "root"} -, "event_5": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "`cron.daily' terminated", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "Job", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218872000000, "timestamp_desc": "Content Modification Time"} -, "event_6": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "testing leap year in parsing, events take place in 2012 ---", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": ":", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "---", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1330478143000000, "timestamp_desc": "Content Modification Time"} -, "event_7": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "No true exit can exist (124 job run)", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 1234, "reporter": "anacron", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "tag": {"__container_type__": "event_tag", "__type__": "AttributeContainer", "comment": "Tag applied by tagging analysis plugin.Tag applied by tagging analysis plugin.", "labels": ["exit2", "exit1"]}, "timestamp": 1355853272000000, "timestamp_desc": "Content Modification Time"} -, "event_8": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "This syslog message has a fractional value for seconds.", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 19, "reporter": "somrandomexe", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1364079678000000, "timestamp_desc": "Content Modification Time"} -, "event_9": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "This syslog message is brought to you by me (and not the other guy)", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 1915, "reporter": "somrandomexe", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1364079678000000, "timestamp_desc": "Content Modification Time"} -, "event_10": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "This is a multi-line message that screws up\n\tmany syslog parsers.", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 10100, "reporter": "aprocess", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1384737320000000, "timestamp_desc": "Content Modification Time"} -, "event_11": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "Another one just like this (124 job run)", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 1234, "reporter": "/sbin/anacron", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1388512472000000, "timestamp_desc": "Content Modification Time"} -, "event_12": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "Test message with single character day", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "victoria", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 2085, "reporter": "process", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1391699790000000, "timestamp_desc": "Content Modification Time"} -, "event_13": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "last message repeated 5 times ---", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": ":", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "---", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "tag": {"__container_type__": "event_tag", "__type__": "AttributeContainer", "comment": "Tag applied by tagging analysis plugin.Tag applied by tagging analysis plugin.", "labels": ["repeated"]}, "timestamp": 1416273343000000, "timestamp_desc": "Content Modification Time"} -, "event_14": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "[997.390602] sda2: rw=0, want=65, limit=2", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "kernel", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1416299420000000, "timestamp_desc": "Content Modification Time"} -, "event_15": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "[998.390602] sda2: rw=0, want=66, limit=2", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "victoria", "inode": 862607, "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "kernel", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1416299480000000, "timestamp_desc": "Content Modification Time"} -, "event_16": {"__container_type__": "event", "__type__": "AttributeContainer", "data_type": "fs:stat", "display_name": "OS:/tmp/test/test_data/syslog", "file_entry_type": "file", "file_size": 1509, "file_system_type": "OS", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "is_allocated": true, "parser": "filestat", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1557057062000000, "timestamp_desc": "Content Modification Time"} -, "event_17": {"__container_type__": "event", "__type__": "AttributeContainer", "data_type": "fs:stat", "display_name": "OS:/tmp/test/test_data/syslog", "file_entry_type": "file", "file_size": 1509, "file_system_type": "OS", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "is_allocated": true, "parser": "filestat", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1557057062000000, "timestamp_desc": "Metadata Modification Time"} -, "event_18": {"__container_type__": "event", "__type__": "AttributeContainer", "data_type": "fs:stat", "display_name": "OS:/tmp/test/test_data/syslog", "file_entry_type": "file", "file_size": 1509, "file_system_type": "OS", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "is_allocated": true, "parser": "filestat", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1557057113000000, "timestamp_desc": "Last Access Time"} -, "event_19": {"__container_type__": "event", "__type__": "AttributeContainer", "data_type": "fs:stat", "display_name": "OS:/tmp/test/test_data/syslog", "file_entry_type": "file", "file_size": 1509, "file_system_type": "OS", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "is_allocated": true, "parser": "filestat", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1557057117000000, "timestamp_desc": "Last Access Time"} +{"event_0": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "INFO No change in [/etc/netgroup]. Done", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "[client, pid: 30840] INFO No change in [/etc/netgroup]. Done", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 30840, "reporter": "client", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218753000000, "timestamp_desc": "Content Modification Time"} +, "event_1": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "INFO No new content in \u00edmynd.dd.", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "[client, pid: 30840] INFO No new content in \u00edmynd.dd.", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 30840, "reporter": "client", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218753000000, "timestamp_desc": "Content Modification Time"} +, "event_2": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "(root) CMD (touch /var/run/crond.somecheck)", "command": "touch /var/run/crond.somecheck", "data_type": "syslog:cron:task_run", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "Cron ran: touch /var/run/crond.somecheck for user: root pid: 31051", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 31051, "reporter": "CRON", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218781000000, "timestamp_desc": "Content Modification Time", "username": "root"} +, "event_3": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "(root) CMD (/sbin/status.mycheck))", "command": "/sbin/status.mycheck)", "data_type": "syslog:cron:task_run", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "Cron ran: /sbin/status.mycheck) for user: root pid: 31067", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 31067, "reporter": "CRON", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218841000000, "timestamp_desc": "Content Modification Time", "username": "root"} +, "event_4": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "(root) CMD (touch /var/run/crond.somecheck)", "command": "touch /var/run/crond.somecheck", "data_type": "syslog:cron:task_run", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "Cron ran: touch /var/run/crond.somecheck for user: root pid: 31068", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 31068, "reporter": "CRON", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218841000000, "timestamp_desc": "Content Modification Time", "username": "root"} +, "event_5": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "`cron.daily' terminated", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "[Job] `cron.daily' terminated", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "Job", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1327218872000000, "timestamp_desc": "Content Modification Time"} +, "event_6": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "testing leap year in parsing, events take place in 2012 ---", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": ":", "inode": 862607, "message": "[---] testing leap year in parsing, events take place in 2012 ---", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "---", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1330478143000000, "timestamp_desc": "Content Modification Time"} +, "event_7": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "No true exit can exist (124 job run)", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "[anacron, pid: 1234] No true exit can exist (124 job run)", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 1234, "reporter": "anacron", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "tag": {"__container_type__": "event_tag", "__type__": "AttributeContainer", "comment": "Tag applied by tagging analysis plugin.Tag applied by tagging analysis plugin.", "labels": ["exit2", "exit1"]}, "timestamp": 1355853272000000, "timestamp_desc": "Content Modification Time"} +, "event_8": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "This syslog message has a fractional value for seconds.", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "[somrandomexe, pid: 19] This syslog message has a fractional value for seconds.", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 19, "reporter": "somrandomexe", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1364079678000000, "timestamp_desc": "Content Modification Time"} +, "event_9": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "This syslog message is brought to you by me (and not the other guy)", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "[somrandomexe, pid: 1915] This syslog message is brought to you by me (and not the other guy)", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 1915, "reporter": "somrandomexe", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1364079678000000, "timestamp_desc": "Content Modification Time"} +, "event_10": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "This is a multi-line message that screws up\n\tmany syslog parsers.", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "[aprocess, pid: 10100] This is a multi-line message that screws up\tmany syslog parsers.", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 10100, "reporter": "aprocess", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1384737320000000, "timestamp_desc": "Content Modification Time"} +, "event_11": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "Another one just like this (124 job run)", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "myhostname.myhost.com", "inode": 862607, "message": "[/sbin/anacron, pid: 1234] Another one just like this (124 job run)", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 1234, "reporter": "/sbin/anacron", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1388512472000000, "timestamp_desc": "Content Modification Time"} +, "event_12": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "Test message with single character day", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "victoria", "inode": 862607, "message": "[process, pid: 2085] Test message with single character day", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": 2085, "reporter": "process", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1391699790000000, "timestamp_desc": "Content Modification Time"} +, "event_13": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "last message repeated 5 times ---", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": ":", "inode": 862607, "message": "[---] last message repeated 5 times ---", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "---", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "tag": {"__container_type__": "event_tag", "__type__": "AttributeContainer", "comment": "Tag applied by tagging analysis plugin.Tag applied by tagging analysis plugin.", "labels": ["repeated"]}, "timestamp": 1416273343000000, "timestamp_desc": "Content Modification Time"} +, "event_14": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "[997.390602] sda2: rw=0, want=65, limit=2", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "message": "[kernel] [997.390602] sda2: rw=0, want=65, limit=2", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "kernel", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1416299420000000, "timestamp_desc": "Content Modification Time"} +, "event_15": {"__container_type__": "event", "__type__": "AttributeContainer", "body": "[998.390602] sda2: rw=0, want=66, limit=2", "data_type": "syslog:line", "display_name": "OS:/tmp/test/test_data/syslog", "filename": "/tmp/test/test_data/syslog", "hostname": "victoria", "inode": 862607, "message": "[kernel] [998.390602] sda2: rw=0, want=66, limit=2", "offset": 0, "parser": "syslog", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "pid": {"__type__": "bytes", "stream": ""}, "reporter": "kernel", "severity": {"__type__": "bytes", "stream": ""}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1416299480000000, "timestamp_desc": "Content Modification Time"} +, "event_16": {"__container_type__": "event", "__type__": "AttributeContainer", "data_type": "fs:stat", "display_name": "OS:/tmp/test/test_data/syslog", "file_entry_type": "file", "file_size": 1509, "file_system_type": "OS", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "is_allocated": true, "message": "OS:/tmp/test/test_data/syslog Type: file", "parser": "filestat", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1557057062000000, "timestamp_desc": "Content Modification Time"} +, "event_17": {"__container_type__": "event", "__type__": "AttributeContainer", "data_type": "fs:stat", "display_name": "OS:/tmp/test/test_data/syslog", "file_entry_type": "file", "file_size": 1509, "file_system_type": "OS", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "is_allocated": true, "message": "OS:/tmp/test/test_data/syslog Type: file", "parser": "filestat", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1557057062000000, "timestamp_desc": "Metadata Modification Time"} +, "event_18": {"__container_type__": "event", "__type__": "AttributeContainer", "data_type": "fs:stat", "display_name": "OS:/tmp/test/test_data/syslog", "file_entry_type": "file", "file_size": 1509, "file_system_type": "OS", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "is_allocated": true, "message": "OS:/tmp/test/test_data/syslog Type: file", "parser": "filestat", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1557057113000000, "timestamp_desc": "Last Access Time"} +, "event_19": {"__container_type__": "event", "__type__": "AttributeContainer", "data_type": "fs:stat", "display_name": "OS:/tmp/test/test_data/syslog", "file_entry_type": "file", "file_size": 1509, "file_system_type": "OS", "filename": "/tmp/test/test_data/syslog", "inode": 862607, "is_allocated": true, "message": "OS:/tmp/test/test_data/syslog Type: file", "parser": "filestat", "pathspec": {"__type__": "PathSpec", "location": "/tmp/test/test_data/syslog", "type_indicator": "OS"}, "sha256_hash": "1f0105612f6ad2d225d6bd9ba631148740e312598878adcd2b74098a3dab50c4", "timestamp": 1557057117000000, "timestamp_desc": "Last Access Time"} } \ No newline at end of file diff --git a/tests/output/init_imports.py b/tests/output/init_imports.py index 93b20d2f47..a0cf8621d2 100644 --- a/tests/output/init_imports.py +++ b/tests/output/init_imports.py @@ -16,7 +16,7 @@ class OutputImportTest(test_lib.ImportCheckTestCase): _OUTPUT_PATH = os.path.join(os.getcwd(), 'plaso', 'output') _IGNORABLE_FILES = frozenset([ 'logger.py', 'manager.py', 'mediator.py', 'interface.py', - 'shared_4n6time.py', 'shared_elastic.py']) + 'shared_4n6time.py', 'shared_elastic.py', 'shared_json.py']) def testOutputModulesImported(self): """Tests that all output modules are imported.""" diff --git a/tests/output/json_out.py b/tests/output/json_out.py index 444ced77c2..f4a962d47a 100644 --- a/tests/output/json_out.py +++ b/tests/output/json_out.py @@ -12,6 +12,7 @@ from dfvfs.lib import definitions as dfvfs_definitions from dfvfs.path import factory as path_spec_factory +from plaso.formatters import manager as formatters_manager from plaso.lib import definitions from plaso.lib import timelib from plaso.output import json_out @@ -70,10 +71,16 @@ def testWriteFooter(self): def testWriteEventBody(self): """Tests the WriteEventBody function.""" + formatters_manager.FormattersManager.RegisterFormatter( + test_lib.TestEventFormatter) + event, event_data = containers_test_lib.CreateEventFromValues( self._TEST_EVENTS[0]) self._output_module.WriteEventBody(event, event_data, None) + formatters_manager.FormattersManager.DeregisterFormatter( + test_lib.TestEventFormatter) + expected_timestamp = timelib.Timestamp.CopyFromString( '2012-06-27 18:17:01') @@ -94,6 +101,9 @@ def testWriteEventBody(self): 'display_name': 'OS: /var/log/syslog.1', 'hostname': 'ubuntu', 'inode': 12345678, + 'message': ( + 'Reporter PID: |8442| (pam_unix(cron:session): ' + 'session closed for user root)'), 'pathspec': { '__type__': 'PathSpec', 'type_indicator': 'TSK', diff --git a/tests/output/shared_elastic.py b/tests/output/shared_elastic.py index 80dc26c5f8..d969494ce2 100644 --- a/tests/output/shared_elastic.py +++ b/tests/output/shared_elastic.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -"""Tests for the shared code for Elasticsearch based output modules.""" +"""Tests for the shared functionality for Elasticsearch output modules.""" from __future__ import unicode_literals @@ -31,7 +31,7 @@ def _Connect(self): @unittest.skipIf(shared_elastic.elasticsearch is None, 'missing elasticsearch') class SharedElasticsearchOutputModuleTest(test_lib.OutputModuleTestCase): - """Tests for SharedElasticsearchOutputModule.""" + """Tests the shared functionality for Elasticsearch output modules.""" # pylint: disable=protected-access diff --git a/tests/output/shared_json.py b/tests/output/shared_json.py new file mode 100644 index 0000000000..f4de62bc11 --- /dev/null +++ b/tests/output/shared_json.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Tests for the shared functionality for JSON output modules.""" + +from __future__ import unicode_literals + +import os +import sys +import unittest + +from dfvfs.lib import definitions as dfvfs_definitions +from dfvfs.path import factory as path_spec_factory + +from plaso.formatters import manager as formatters_manager +from plaso.lib import definitions +from plaso.lib import timelib +from plaso.output import shared_json + +from tests.containers import test_lib as containers_test_lib +from tests.output import test_lib + + +class SharedJSONOutputModuleTest(test_lib.OutputModuleTestCase): + """Tests the shared functionality for JSON output modules.""" + + # pylint: disable=protected-access + + _OS_PATH_SPEC = path_spec_factory.Factory.NewPathSpec( + dfvfs_definitions.TYPE_INDICATOR_OS, location='{0:s}{1:s}'.format( + os.path.sep, os.path.join('cases', 'image.dd'))) + + _TEST_EVENTS = [ + {'data_type': 'test:output', + 'display_name': 'OS: /var/log/syslog.1', + 'hostname': 'ubuntu', + 'inode': 12345678, + 'pathspec': path_spec_factory.Factory.NewPathSpec( + dfvfs_definitions.TYPE_INDICATOR_TSK, inode=15, + location='/var/log/syslog.1', parent=_OS_PATH_SPEC), + 'text': ( + 'Reporter PID: |8442| (pam_unix(cron:session): session\n ' + 'closed for user root)'), + 'timestamp': timelib.Timestamp.CopyFromString('2012-06-27 18:17:01'), + 'timestamp_desc': definitions.TIME_DESCRIPTION_UNKNOWN, + 'username': 'root'}] + + def testWriteSerialized(self): + """Tests the _WriteSerialized function.""" + output_mediator = self._CreateOutputMediator() + output_module = shared_json.SharedJSONOutputModule(output_mediator) + + event, event_data = containers_test_lib.CreateEventFromValues( + self._TEST_EVENTS[0]) + + if sys.platform.startswith('win'): + # The dict comparison is very picky on Windows hence we + # have to make sure the drive letter is in the same case. + expected_os_location = os.path.abspath('\\{0:s}'.format( + os.path.join('cases', 'image.dd'))) + expected_os_location = expected_os_location.replace('\\', '\\\\') + else: + expected_os_location = '{0:s}{1:s}'.format( + os.path.sep, os.path.join('cases', 'image.dd')) + + expected_json_string = ( + '{{"__container_type__": "event", "__type__": "AttributeContainer", ' + '"data_type": "test:output", "display_name": "OS: /var/log/syslog.1", ' + '"hostname": "ubuntu", "inode": 12345678, "message": "Reporter ' + 'PID: |8442| (pam_unix(cron:session): session closed for user root)", ' + '"pathspec": {{"__type__": "PathSpec", "inode": 15, "location": ' + '"/var/log/syslog.1", "parent": {{"__type__": "PathSpec", "location": ' + '"{0:s}", "type_indicator": "OS"}}, "type_indicator": "TSK"}}, "text": ' + '"Reporter PID: |8442| (pam_unix(cron:session): session\\n ' + 'closed for user root)", "timestamp": 1340821021000000, ' + '"timestamp_desc": "Unknown Time", "username": "root"}}').format( + expected_os_location) + + formatters_manager.FormattersManager.RegisterFormatter( + test_lib.TestEventFormatter) + + json_string = output_module._WriteSerialized(event, event_data, None) + + formatters_manager.FormattersManager.DeregisterFormatter( + test_lib.TestEventFormatter) + + self.assertEqual(json_string, expected_json_string) + + def testWriteSerializedDict(self): + """Tests the _WriteSerializedDict function.""" + output_mediator = self._CreateOutputMediator() + output_module = shared_json.SharedJSONOutputModule(output_mediator) + + event, event_data = containers_test_lib.CreateEventFromValues( + self._TEST_EVENTS[0]) + + expected_timestamp = timelib.Timestamp.CopyFromString( + '2012-06-27 18:17:01') + + if sys.platform.startswith('win'): + # The dict comparison is very picky on Windows hence we + # have to make sure the drive letter is in the same case. + expected_os_location = os.path.abspath('\\{0:s}'.format( + os.path.join('cases', 'image.dd'))) + else: + expected_os_location = '{0:s}{1:s}'.format( + os.path.sep, os.path.join('cases', 'image.dd')) + + expected_json_dict = { + '__container_type__': 'event', + '__type__': 'AttributeContainer', + 'data_type': 'test:output', + 'display_name': 'OS: /var/log/syslog.1', + 'hostname': 'ubuntu', + 'inode': 12345678, + 'message': ( + 'Reporter PID: |8442| (pam_unix(cron:session): session ' + 'closed for user root)'), + 'pathspec': { + '__type__': 'PathSpec', + 'type_indicator': 'TSK', + 'location': '/var/log/syslog.1', + 'inode': 15, + 'parent': { + '__type__': 'PathSpec', + 'type_indicator': 'OS', + 'location': expected_os_location, + } + }, + 'text': ( + 'Reporter PID: |8442| (pam_unix(cron:session): ' + 'session\n closed for user root)'), + 'timestamp': expected_timestamp, + 'timestamp_desc': definitions.TIME_DESCRIPTION_UNKNOWN, + 'username': 'root', + } + formatters_manager.FormattersManager.RegisterFormatter( + test_lib.TestEventFormatter) + + json_dict = output_module._WriteSerializedDict( + event, event_data, None) + + formatters_manager.FormattersManager.DeregisterFormatter( + test_lib.TestEventFormatter) + + self.assertEqual(json_dict, expected_json_dict) + + +if __name__ == '__main__': + unittest.main()