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]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,
}