Source code for pylog.formatters

# TODO: support additional apache formats (http://ossec-docs.readthedocs.org/en/latest/log_samples/apache/apache.html)  # NOQA

import random
from abc import abstractmethod, ABCMeta
from faker import Factory
from format_mappings import *  # NOQA


[docs]def fake_data(data_type): fake = Factory.create() try: return str(getattr(fake, data_type)()) except AttributeError: print('cannot randomize data for {}. run "pylog list fake" ' 'to print a list of possible types.'.format(data_type)) raise RuntimeError('cannot randomize data type {}'.format( data_type))
[docs]class BaseFormatter(object): __metaclass__ = ABCMeta @abstractmethod def __init__(self, config): return @abstractmethod
[docs] def generate_data(self): return
[docs]class CustomFormatter(BaseFormatter): """generates log strings in a custom format this is also the the formatter other formatters can rely on to generate application specific logs. see the ApacheAccessFormatter class for reference. """ def __init__(self, config): self.format = config['format'] self.data = config['data']
[docs] def generate_data(self): """returns a log string for every item in the format list, if an item in the data dict corresponds with it and the field's data equals "$RAND", use faker to fake an item for it. else, choose one item from the list randomly. if there no item in the data to correspond with the format, it will just append to format's field name to the log. .. code-block:: python example: 'CustomFormatter': { 'format': ['name', ' - ', 'level'], 'data': { 'name': $RAND, 'level': ['ERROR', 'DEBUG', 'INFO', 'CRITICAL'], } } the output of the above example might be: .. code-block:: python Sally Fields - ERROR or Jason Banks - DEBUG or Danny Milwee - ERROR or ... """ log = '' for field_name in self.format: for field, data in self.data.items(): if field_name == field: if data == '$RAND': log += fake_data(field_name) else: log += random.choice(self.data[field_name]) if field_name not in self.data.keys(): log += field_name return log
[docs]class JsonFormatter(BaseFormatter): """generates log strings in json format""" def __init__(self, config): self.data = config['data']
[docs] def generate_data(self): """returns a json string all fields in the data dict will be iterated over. if $RAND is set in one of the fields, random data will be generate_data for that field. If not, data will be chosen from the list. .. code-block:: python example: 'JsonFormatter': { 'data': { 'date_time': '$RAND', 'level': ['ERROR', 'DEBUG'], 'address': '$RAND', } }, the output of the above example might be: .. code-block:: python {'date_time': '2006-11-05 13:31:09', 'name': 'Miss Nona Breitenberg DVM', 'level': 'ERROR'} # NOQA or {'date_time': '1985-01-20 11:41:16', 'name': 'Almeda Lindgren', 'level': 'DEBUG'} # NOQA or {'date_time': '1973-05-21 01:06:04', 'name': 'Jase Heaney', 'level': 'DEBUG'} # NOQA or ... """ log = {} for field, data in self.data.items(): if data == '$RAND': log[field] = fake_data(field) else: log[field] = random.choice(data) return log
[docs]class ApacheAccessFormatter(CustomFormatter): # 192.168.72.177 - - [22/Dec/2002:23:32:19 -0400] "GET /search.php HTTP/1.1" 400 1997 www.yahoo.com "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ...)" "-" # NOQA # 127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 # NOQA # 192.168.2.20 - - [28/Jul/2006:10:27:10 -0300] "GET /cgi-bin/try/ HTTP/1.0" 200 3395 # NOQA # %{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-) # NOQA def __init__(self, config): self.format = [ 'ipv4', ' - - [', 'day_of_month', '/', 'month_name_short', '/', 'year', ':', 'time', ' ', 'time_zone_number', '] "', 'http_verb', ' /', 'uri_path', ' ', 'http_version', '" ', 'http_error_codes', ' ', 'random_int' ] self.data = { 'ipv4': '$RAND', 'day_of_month': CURRENT_DAY_OF_MONTH, 'month_name_short': CURRENT_MONTH_NAME_SHORT, 'year': CURRENT_YEAR, 'time': CURRENT_TIME, 'time_zone_number': CURRENT_TIME_ZONE_NUMBER, 'http_version': HTTP_VERSIONS, 'http_verb': HTTP_VERBS, 'uri_path': '$RAND', 'http_error_codes': HTTP_ERROR_CODES, 'random_int': '$RAND', }
[docs]class ApacheErrorFormatter(CustomFormatter): # [Fri Dec 16 01:46:23 2005] [error] [client 1.2.3.4] Directory index forbidden by rule: /home/test/ # NOQA # [Mon Dec 19 23:02:01 2005] [error] [client 1.2.3.4] user test: authentication failure for "/~dcid/test1": Password Mismatch # NOQA def __init__(self, config): self.format = [ '[', 'day_of_week_short', ' ', 'month_name_short', ' ', 'day_of_month', ' ', 'time', ' ', 'year', '] [', 'syslog_error_levels_lower', '] [client ', 'ipv4', '] ', 'catch_phrase' ] self.data = { 'day_of_week_short': CURRENT_DAY_OF_WEEK_SHORT, 'ipv4': '$RAND', 'day_of_month': CURRENT_DAY_OF_MONTH, 'month_name_short': CURRENT_MONTH_NAME_SHORT, 'year': CURRENT_YEAR, 'time': CURRENT_TIME, 'catch_phrase': '$RAND', 'syslog_error_levels_lower': SYSLOG_ERROR_LEVELS_LOWER, }