From 7e471676fe41dab155a939c60446cc7b7dab773b Mon Sep 17 00:00:00 2001 From: Jake Hunsaker Date: Tue, 20 Jul 2021 11:09:29 -0400 Subject: [PATCH] [username parser] Load usernames from `last` for LDAP users AD/LDAP users are not reported into `lastlog` generally, however they are reported in `last`. Conversely, `last` does not report local users who have not logged in but still exist. In order to obfuscate both kinds of users, we need to look at both sources. For this, first allow parsers to specify multiple prep files. Second, update the username parser to search through all `lastlog` collections as well as the `last` collection. Also includes a small update to the username parser's prep loading logic to ensure we are iterating over each username discovered only once. Signed-off-by: Jake Hunsaker --- sos/cleaner/__init__.py | 38 ++++++++++++++------------ sos/cleaner/parsers/__init__.py | 2 +- sos/cleaner/parsers/username_parser.py | 24 +++++++++++++--- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/sos/cleaner/__init__.py b/sos/cleaner/__init__.py index ca5f93e5..6aadfe79 100644 --- a/sos/cleaner/__init__.py +++ b/sos/cleaner/__init__.py @@ -518,23 +518,27 @@ third party. for _parser in self.parsers: if not _parser.prep_map_file: continue - _arc_path = os.path.join(_arc_name, _parser.prep_map_file) - try: - if is_dir: - _pfile = open(_arc_path, 'r') - content = _pfile.read() - else: - _pfile = archive.extractfile(_arc_path) - content = _pfile.read().decode('utf-8') - _pfile.close() - if isinstance(_parser, SoSUsernameParser): - _parser.load_usernames_into_map(content) - for line in content.splitlines(): - if isinstance(_parser, SoSHostnameParser): - _parser.load_hostname_into_map(line) - self.obfuscate_line(line) - except Exception as err: - self.log_debug("Could not prep %s: %s" % (_arc_path, err)) + if isinstance(_parser.prep_map_file, str): + _parser.prep_map_file = [_parser.prep_map_file] + for parse_file in _parser.prep_map_file: + _arc_path = os.path.join(_arc_name, parse_file) + try: + if is_dir: + _pfile = open(_arc_path, 'r') + content = _pfile.read() + else: + _pfile = archive.extractfile(_arc_path) + content = _pfile.read().decode('utf-8') + _pfile.close() + if isinstance(_parser, SoSUsernameParser): + _parser.load_usernames_into_map(content) + for line in content.splitlines(): + if isinstance(_parser, SoSHostnameParser): + _parser.load_hostname_into_map(line) + self.obfuscate_line(line) + except Exception as err: + self.log_debug("Could not prep %s: %s" + % (_arc_path, err)) def obfuscate_report(self, report): """Individually handle each archive or directory we've discovered by diff --git a/sos/cleaner/parsers/__init__.py b/sos/cleaner/parsers/__init__.py index 3076db39..af6e375e 100644 --- a/sos/cleaner/parsers/__init__.py +++ b/sos/cleaner/parsers/__init__.py @@ -50,7 +50,7 @@ class SoSCleanerParser(): skip_line_patterns = [] skip_files = [] map_file_key = 'unset' - prep_map_file = 'unset' + prep_map_file = [] def __init__(self, conf_file=None): # attempt to load previous run data into the mapping for the parser diff --git a/sos/cleaner/parsers/username_parser.py b/sos/cleaner/parsers/username_parser.py index 96ce5f0c..b142e371 100644 --- a/sos/cleaner/parsers/username_parser.py +++ b/sos/cleaner/parsers/username_parser.py @@ -25,13 +25,24 @@ class SoSUsernameParser(SoSCleanerParser name = 'Username Parser' map_file_key = 'username_map' - prep_map_file = 'sos_commands/login/lastlog_-u_1000-60000' + prep_map_file = [ + 'sos_commands/login/lastlog_-u_1000-60000', + 'sos_commands/login/lastlog_-u_60001-65536', + 'sos_commands/login/lastlog_-u_65537-4294967295', + # AD users will be reported here, but favor the lastlog files since + # those will include local users who have not logged in + 'sos_commands/login/last' + ] regex_patterns = [] skip_list = [ 'core', 'nobody', 'nfsnobody', - 'root' + 'shutdown', + 'reboot', + 'root', + 'ubuntu', + 'wtmp' ] def __init__(self, conf_file=None, opt_names=None): @@ -44,11 +54,17 @@ class SoSUsernameParser(SoSCleanerParser): """Since we don't get the list of usernames from a straight regex for this parser, we need to override the initial parser prepping here. """ + users = set() for line in content.splitlines()[1:]: - user = line.split()[0] + try: + user = line.split()[0] + except Exception: + continue if user in self.skip_list: continue - self.mapping.get(user) + users.add(user) + for each in users: + self.mapping.get(each) def parse_line(self, line): count = 0 -- 2.31.1