From 7e471676fe41dab155a939c60446cc7b7dab773b Mon Sep 17 00:00:00 2001
From: Jake Hunsaker <jhunsake@redhat.com>
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 <jhunsake@redhat.com>
---
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