aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake Hunsaker <jhunsake@redhat.com>2020-05-20 16:51:08 -0400
committerJake Hunsaker <jhunsake@redhat.com>2020-06-17 12:11:29 -0400
commit582eacb8d92b741959ad556ffcacd748fa3bbf14 (patch)
treeff2c30fc9ffefd1c760417c83e98d51f77241caf
parentdc3b2014bc0a991dd587851f33f522f00f53fa35 (diff)
downloadsos-582eacb8d92b741959ad556ffcacd748fa3bbf14.tar.gz
[report] Add hook into SoSCleaner
Adds a new option, `--clean` or `--mask`, to hook a report into `SoSCleaner`. This is done after collection is complete, and before the archive is built and compressed. Data is substituted in place for the report, which means there will not be an obfuscated copy on disk. There will however still be a mapping file produced and located in the same directory as the final archive. If it desired to have both an obfuscated and unobfuscated copy, it is recommended to run `sos report` followed by a separate `sos clean`. Related: #1987 Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
-rw-r--r--sos/cleaner/__init__.py30
-rw-r--r--sos/policies/__init__.py12
-rw-r--r--sos/report/__init__.py29
3 files changed, 55 insertions, 16 deletions
diff --git a/sos/cleaner/__init__.py b/sos/cleaner/__init__.py
index 2545e581..ec2d6ce2 100644
--- a/sos/cleaner/__init__.py
+++ b/sos/cleaner/__init__.py
@@ -42,17 +42,26 @@ class SoSCleaner(SoSComponent):
'target': ''
}
- def __init__(self, parser=None, args=None, cmdline=None, in_place=False):
- if parser is not None and args is not None and cmdline is not None:
+ def __init__(self, parser=None, args=None, cmdline=None, in_place=False,
+ hook_commons=None):
+ if not in_place:
# we are running `sos clean` directly
super(SoSCleaner, self).__init__(parser, args, cmdline)
self.from_cmdline = True
else:
# we are being hooked by either SoSReport or SoSCollector, don't
- # re-init everything
+ # re-init everything as that will cause issues, but instead load
+ # the needed bits from the calling component
+ self.opts = hook_commons['options']
+ self.tmpdir = hook_commons['tmpdir']
+ self.sys_tmp = hook_commons['sys_tmp']
+ self.policy = hook_commons['policy']
+ self.from_cmdline = False
+ self.opts.map_file = '/etc/sos/cleaner/default_mapping'
+ self.opts.jobs = 4
+ self.opts.no_update = False
self.soslog = logging.getLogger('sos')
self.ui_log = logging.getLogger('sos_ui')
- self.from_cmdline = False
self.validate_map_file()
os.umask(0o77)
@@ -92,16 +101,14 @@ class SoSCleaner(SoSComponent):
a warning and continue on with cleaning building a fresh map
"""
default_map = '/etc/sos/cleaner/default_mapping'
+ if os.path.isdir(self.opts.map_file):
+ raise Exception("Requested map file %s is a directory"
+ % self.opts.map_file)
if not os.path.exists(self.opts.map_file):
if self.opts.map_file != default_map:
self.log_error(
- "Map file %s does not exist, will not load any obfuscation"
- " matches" % self.opts.map_file)
- if os.path.isdir(self.opts.map_file):
- self.log_error(
- "Requested map file %s is a directory. Ignoring `--map` option"
- " and using %s" % default_map)
- self.opts.map_file = default_map
+ "ERROR: map file %s does not exist, will not load any "
+ "obfuscation matches" % self.opts.map_file)
def print_disclaimer(self):
"""When we are directly running `sos clean`, rather than hooking into
@@ -234,6 +241,7 @@ third party.
% self.opts.target)
self._exit(1)
if os.path.isdir(self.opts.target):
+ self.arc_name = self.opts.target.split('/')[-1]
for _file in os.listdir(self.opts.target):
if _file == 'sos_logs':
self.report_paths.append(self.opts.target)
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
index 7936590b..6fd08adf 100644
--- a/sos/policies/__init__.py
+++ b/sos/policies/__init__.py
@@ -30,6 +30,7 @@ try:
except ImportError:
REQUESTS_LOADED = False
+
def import_policy(name):
policy_fqname = "sos.policies.%s" % name
try:
@@ -800,7 +801,8 @@ any third party.
to use"""
return "md5"
- def display_results(self, archive, directory, checksum, archivestat=None):
+ def display_results(self, archive, directory, checksum, archivestat=None,
+ map_file=None):
# Display results is called from the tail of SoSReport.final_work()
#
# Logging is already shutdown and all terminal output must use the
@@ -812,16 +814,20 @@ any third party.
self._print()
+ if map_file:
+ self._print(_("A mapping of obfuscated elements is available at"
+ "\n\t%s\n" % map_file))
+
if archive:
self._print(_("Your sosreport has been generated and saved "
- "in:\n %s\n") % archive, always=True)
+ "in:\n\t%s\n") % archive, always=True)
self._print(_(" Size\t%s") %
get_human_readable(archivestat.st_size))
self._print(_(" Owner\t%s") %
getpwuid(archivestat.st_uid).pw_name)
else:
self._print(_("Your sosreport build tree has been generated "
- "in:\n %s\n") % directory, always=True)
+ "in:\n\t%s\n") % directory, always=True)
if checksum:
self._print(" " + self.get_preferred_hash_name() + "\t" + checksum)
self._print()
diff --git a/sos/report/__init__.py b/sos/report/__init__.py
index fa0c4573..c0c2eb1b 100644
--- a/sos/report/__init__.py
+++ b/sos/report/__init__.py
@@ -30,6 +30,7 @@ import sos.policies
from sos.report.reporting import (Report, Section, Command, CopiedFile,
CreatedFile, Alert, Note, PlainTextReport,
JSONReport, HTMLReport)
+from sos.cleaner import SoSCleaner
# file system errors that should terminate a run
fatal_fs_errors = (errno.ENOSPC, errno.EROFS)
@@ -78,6 +79,7 @@ class SoSReport(SoSComponent):
'build': False,
'case_id': '',
'chroot': 'auto',
+ 'clean': False,
'desc': '',
'dry_run': False,
'experimental': False,
@@ -174,6 +176,9 @@ class SoSReport(SoSComponent):
dest="all_logs", default=False,
help="collect all available logs regardless "
"of size")
+ parser.add_argument('--clean', '--mask', dest='clean', default=False,
+ action='store_true',
+ help='Obfuscate sensistive network information')
parser.add_argument("--since", action="store",
dest="since", default=None,
type=_format_since,
@@ -1098,6 +1103,21 @@ class SoSReport(SoSComponent):
archive = None # archive path
directory = None # report directory path (--build)
+ map_file = None # path of the map file generated for the report
+
+ if self.opts.clean:
+ try:
+ hook_commons = {
+ 'policy': self.policy,
+ 'tmpdir': self.tmpdir,
+ 'sys_tmp': self.sys_tmp,
+ 'options': self.opts
+ }
+ cleaner = SoSCleaner(in_place=True, hook_commons=hook_commons)
+ cleaner.set_target_path(self.archive.get_archive_path())
+ map_file = cleaner.execute()
+ except Exception as err:
+ print(_("ERROR: Unable to obfuscate report: %s" % err))
# package up and compress the results
if not self.opts.build:
@@ -1154,6 +1174,10 @@ class SoSReport(SoSComponent):
# containing directory.
final_name = os.path.join(self.sys_tmp,
os.path.basename(archive))
+ if self.opts.clean:
+ final_name = cleaner.obfuscate_string(
+ final_name.replace('.tar', '-obfuscated.tar')
+ )
# Get stat on the archive
archivestat = os.stat(archive)
@@ -1187,9 +1211,10 @@ class SoSReport(SoSComponent):
if not self.opts.build:
self.policy.display_results(archive, directory, checksum,
- archivestat)
+ archivestat, map_file=map_file)
else:
- self.policy.display_results(archive, directory, checksum)
+ self.policy.display_results(archive, directory, checksum,
+ map_file=map_file)
if self.opts.upload or self.opts.upload_url:
if not self.opts.build: