diff options
-rw-r--r-- | man/en/sos-clean.1 | 12 | ||||
-rw-r--r-- | sos/cleaner/__init__.py | 17 | ||||
-rw-r--r-- | sos/collector/__init__.py | 5 | ||||
-rw-r--r-- | sos/report/__init__.py | 5 | ||||
-rw-r--r-- | tests/cleaner_tests/report_disabled_parsers.py | 61 |
5 files changed, 100 insertions, 0 deletions
diff --git a/man/en/sos-clean.1 b/man/en/sos-clean.1 index 358ec0cb..7fd2df08 100644 --- a/man/en/sos-clean.1 +++ b/man/en/sos-clean.1 @@ -4,6 +4,7 @@ sos clean - Obfuscate sensitive data from one or more sosreports .SH SYNOPSIS .B sos clean TARGET [options] [\-\-domains] + [\-\-disable-parsers] [\-\-keywords] [\-\-keyword-file] [\-\-map-file] @@ -51,6 +52,17 @@ match a domain given via this option will also be obfuscated. For example, if \fB\-\-domains redhat.com\fR is specified, then 'redhat.com' will be obfuscated, as will 'www.redhat.com' and subdomains such as 'foo.redhat.com'. .TP +.B \-\-disable-parsers PARSERS +Provide a comma-delimited list of parsers to disable when cleaning an archive. By +default all parsers are enabled. + +Note that using this option is very likely to leave sensitive information in place in +the target archive, so only use this option when absolutely necessary or you have complete +trust in the party/parties that may handle the generated report. + +Valid values for this option are currently: \fBhostname\fR, \fBip\fR, \fBmac\fR, \fBkeyword\fR, +and \fBusername\fR. +.TP .B \-\-keywords KEYWORDS Provide a comma-delimited list of keywords to scrub in addition to the default parsers. diff --git a/sos/cleaner/__init__.py b/sos/cleaner/__init__.py index 0f1458d7..a6a7fa7a 100644 --- a/sos/cleaner/__init__.py +++ b/sos/cleaner/__init__.py @@ -76,6 +76,7 @@ class SoSCleaner(SoSComponent): arg_defaults = { 'archive_type': 'auto', 'domains': [], + 'disable_parsers': [], 'jobs': 4, 'keywords': [], 'keyword_file': None, @@ -127,6 +128,18 @@ class SoSCleaner(SoSComponent): SoSUsernameParser(self.cleaner_mapping, self.opts.usernames) ] + for _parser in self.opts.disable_parsers: + for _loaded in self.parsers: + _loaded_name = _loaded.name.lower().split('parser')[0].strip() + if _parser.lower().strip() == _loaded_name: + self.log_info("Disabling parser: %s" % _loaded_name) + self.ui_log.warn( + "Disabling the '%s' parser. Be aware that this may " + "leave sensitive plain-text data in the archive." + % _parser + ) + self.parsers.remove(_loaded) + self.archive_types = [ SoSReportDirectory, SoSReportArchive, @@ -239,6 +252,10 @@ third party. 'was generated as')) clean_grp.add_argument('--domains', action='extend', default=[], help='List of domain names to obfuscate') + clean_grp.add_argument('--disable-parsers', action='extend', + default=[], dest='disable_parsers', + help=('Disable specific parsers, so that those ' + 'elements are not obfuscated')) clean_grp.add_argument('-j', '--jobs', default=4, type=int, help='Number of concurrent archives to clean') clean_grp.add_argument('--keywords', action='extend', default=[], diff --git a/sos/collector/__init__.py b/sos/collector/__init__.py index 66c3d932..5883c14c 100644 --- a/sos/collector/__init__.py +++ b/sos/collector/__init__.py @@ -80,6 +80,7 @@ class SoSCollector(SoSComponent): 'cluster_type': None, 'container_runtime': 'auto', 'domains': [], + 'disable_parsers': [], 'enable_plugins': [], 'encrypt_key': '', 'encrypt_pass': '', @@ -451,6 +452,10 @@ class SoSCollector(SoSComponent): cleaner_grp.add_argument('--domains', dest='domains', default=[], action='extend', help='Additional domain names to obfuscate') + cleaner_grp.add_argument('--disable-parsers', action='extend', + default=[], dest='disable_parsers', + help=('Disable specific parsers, so that ' + 'those elements are not obfuscated')) cleaner_grp.add_argument('--keywords', action='extend', default=[], dest='keywords', help='List of keywords to obfuscate') diff --git a/sos/report/__init__.py b/sos/report/__init__.py index b9e6620f..5322e658 100644 --- a/sos/report/__init__.py +++ b/sos/report/__init__.py @@ -86,6 +86,7 @@ class SoSReport(SoSComponent): 'keep_binary_files': False, 'desc': '', 'domains': [], + 'disable_parsers': [], 'dry_run': False, 'estimate_only': False, 'experimental': False, @@ -346,6 +347,10 @@ class SoSReport(SoSComponent): cleaner_grp.add_argument('--domains', dest='domains', default=[], action='extend', help='Additional domain names to obfuscate') + cleaner_grp.add_argument('--disable-parsers', action='extend', + default=[], dest='disable_parsers', + help=('Disable specific parsers, so that ' + 'those elements are not obfuscated')) cleaner_grp.add_argument('--keywords', action='extend', default=[], dest='keywords', help='List of keywords to obfuscate') diff --git a/tests/cleaner_tests/report_disabled_parsers.py b/tests/cleaner_tests/report_disabled_parsers.py new file mode 100644 index 00000000..84af7893 --- /dev/null +++ b/tests/cleaner_tests/report_disabled_parsers.py @@ -0,0 +1,61 @@ +# This file is part of the sos project: https://github.com/sosreport/sos +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions of +# version 2 of the GNU General Public License. +# +# See the LICENSE file in the source distribution for further information. + +from sos_tests import StageOneReportTest, StageTwoReportTest + + +ARCHIVE = 'sosreport-cleanertest-2021-08-03-qpkxdid.tar.xz' + +class ReportDisabledParsersTest(StageOneReportTest): + """Run report with selected disabled parsers and ensure those parsers are + in fact disabled and unused. + + :avocado: tags=stageone + """ + + sos_cmd = '--clean -o host,kernel,networking --disable-parsers=ip' + + def test_local_ip_not_obfuscated(self): + self.assertFileHasContent('ip_addr', self.sysinfo['pre']['networking']['ip_addr']) + + def test_disable_message_logged(self): + self.assertSosLogContains('Disabling parser: ip') + + def test_ui_log_message_shown(self): + self.assertSosUILogContains( + '.*Be aware that this may leave sensitive plain-text data in the archive.' + ) + + # make sure that the other parsers remain functional + def test_localhost_was_obfuscated(self): + self.assertFileHasContent('/etc/hostname', 'host0') + + def test_mac_addrs_were_obfuscated(self): + content = self.get_file_content('sos_commands/networking/ip_maddr_show') + for line in content.splitlines(): + if line.strip().startswith('link'): + mac = line.strip().split()[1] + assert mac.startswith('53:4f:53'), "Found unobfuscated mac addr %s" % mac + + +class NativeCleanDisabledParsersTest(StageTwoReportTest): + """Ensure that disabling parsers works when calling 'clean' directly as + well. + + :avocado: tags=stagetwo + """ + + sos_cmd = "--disable-parsers=hostname tests/test_data/%s" % ARCHIVE + sos_component = 'clean' + + def test_localhost_not_obfuscated(self): + self.assertFileNotHasContent('/etc/hostname', self.sysinfo['pre']['networking']['hostname']) + self.assertFileNotHasContent('uname', self.sysinfo['pre']['networking']['hostname']) + + def test_local_ip_was_obfuscated(self): + self.assertFileNotHasContent('ip_addr', self.sysinfo['pre']['networking']['ip_addr']) |