diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html index 62a40a2e..53295722 100644 --- a/data/interfaces/default/settings.html +++ b/data/interfaces/default/settings.html @@ -190,6 +190,13 @@ available_notification_agents = sorted(notifiers.available_notification_agents()

Group successive play history by the same user as a single entry in the tables and watch statistics.

+
+ +

Enable to mask passwords, access tokens, and public IP addresses with asterisks (*) in the logs.
+ Note: Only logs from the time this setting is enabled will be masked. Do not post your logs publically without masking sensitive information!

+

Directories

diff --git a/plexpy/config.py b/plexpy/config.py index 3419f58d..68ed0a58 100644 --- a/plexpy/config.py +++ b/plexpy/config.py @@ -169,6 +169,7 @@ _CONFIG_DEFINITIONS = { 'IFTTT_ON_PMSUPDATE': (int, 'IFTTT', 0), 'JOURNAL_MODE': (str, 'Advanced', 'wal'), 'LAUNCH_BROWSER': (int, 'General', 1), + 'LOG_BLACKLIST': (int, 'General', 1), 'LOG_DIR': (str, 'General', ''), 'LOGGING_IGNORE_INTERVAL': (int, 'Monitoring', 120), 'MOVIE_LOGGING_ENABLE': (int, 'Monitoring', 1), @@ -449,9 +450,7 @@ class Config(object): for key in _CONFIG_DEFINITIONS.keys(): self.check_setting(key) self._upgrade() - - if not plexpy.DEV: - self._blacklist() + self._blacklist() def _blacklist(self): """ Add tokens and passwords to blacklisted words in logger """ @@ -522,8 +521,7 @@ class Config(object): except IOError as e: plexpy.logger.error("Error writing configuration file: %s", e) - if not plexpy.DEV: - self._blacklist() + self._blacklist() def __getattr__(self, name): """ diff --git a/plexpy/logger.py b/plexpy/logger.py index 8eee7c0c..b8e4085f 100644 --- a/plexpy/logger.py +++ b/plexpy/logger.py @@ -27,6 +27,7 @@ import logging import errno import sys import os +import re # These settings are for file logging only FILENAME = "plexpy.log" @@ -73,17 +74,53 @@ class BlacklistFilter(logging.Filter): pass def filter(self, record): + if not plexpy.CONFIG.LOG_BLACKLIST: + return True + for item in _BLACKLIST_WORDS: try: if item in record.msg: record.msg = record.msg.replace(item, 8 * '*' + item[-2:]) if any(item in str(arg) for arg in record.args): - record.args = tuple(arg.replace(item, 8 * '*' + item[-2:]) for arg in record.args) + record.args = tuple(arg.replace(item, 8 * '*' + item[-2:]) if isinstance(arg, basestring) else arg + for arg in record.args) except: pass return True +class PublicIPFilter(logging.Filter): + """ + Log filter for public IP addresses + """ + def __init__(self): + pass + + def filter(self, record): + if not plexpy.CONFIG.LOG_BLACKLIST: + return True + + try: + # Currently only checking for ipv4 addresses + ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}', record.msg) + for ip in ipv4: + if helpers.is_ip_public(ip): + record.msg = record.msg.replace(ip, ip.partition('.')[0] + '.***.***.***') + + args = [] + for arg in record.args: + ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}', arg) if isinstance(arg, basestring) else [] + for ip in ipv4: + if helpers.is_ip_public(ip): + arg = arg.replace(ip, ip.partition('.')[0] + '.***.***.***') + args.append(arg) + record.args = tuple(args) + except: + pass + + return True + + @contextlib.contextmanager def listener(): """ @@ -175,7 +212,6 @@ def initLogger(console=False, log_dir=False, verbose=False): # Add list logger loglist_handler = LogListHandler() loglist_handler.setLevel(logging.DEBUG) - loglist_handler.addFilter(BlacklistFilter()) logger.addHandler(loglist_handler) @@ -187,7 +223,6 @@ def initLogger(console=False, log_dir=False, verbose=False): file_handler = handlers.RotatingFileHandler(filename, maxBytes=MAX_SIZE, backupCount=MAX_FILES) file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(file_formatter) - file_handler.addFilter(BlacklistFilter()) logger.addHandler(file_handler) @@ -197,10 +232,17 @@ def initLogger(console=False, log_dir=False, verbose=False): console_handler = logging.StreamHandler() console_handler.setFormatter(console_formatter) console_handler.setLevel(logging.DEBUG) - console_handler.addFilter(BlacklistFilter()) logger.addHandler(console_handler) + # Add filters to log handlers + # Only add filters after the config file has been initialized + # Nothing prior to initialization should contain sensitive information + if not plexpy.DEV and plexpy.CONFIG: + for handler in logger.handlers: + handler.addFilter(BlacklistFilter()) + handler.addFilter(PublicIPFilter()) + # Install exception hooks initHooks() diff --git a/plexpy/webserve.py b/plexpy/webserve.py index 548eb555..784e48ae 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -1180,6 +1180,7 @@ class WebInterface(object): "backup_dir": plexpy.CONFIG.BACKUP_DIR, "cache_dir": plexpy.CONFIG.CACHE_DIR, "log_dir": plexpy.CONFIG.LOG_DIR, + "log_blacklist": checked(plexpy.CONFIG.LOG_BLACKLIST), "check_github": checked(plexpy.CONFIG.CHECK_GITHUB), "interface_list": interface_list, "cache_sizemb": plexpy.CONFIG.CACHE_SIZEMB, @@ -1282,7 +1283,7 @@ class WebInterface(object): "ip_logging_enable", "movie_logging_enable", "tv_logging_enable", "music_logging_enable", "pms_is_remote", "home_stats_type", "group_history_tables", "notify_consecutive", "notify_upload_posters", "notify_recently_added", "notify_recently_added_grandparent", - "monitor_pms_updates", "monitor_remote_access", "get_file_sizes" + "monitor_pms_updates", "monitor_remote_access", "get_file_sizes", "log_blacklist" ] for checked_config in checked_configs: if checked_config not in kwargs: