diff options
author | Bryn M. Reeves <bmr@redhat.com> | 2019-10-08 14:48:02 +0100 |
---|---|---|
committer | Bryn M. Reeves <bmr@redhat.com> | 2019-10-08 14:54:20 +0100 |
commit | de5fd69e594d6c182e1a2d3539bcabebc941ed4d (patch) | |
tree | 5ca66ae3df23497a399b4f105090c4e21907ed42 | |
parent | df6deb2ff7acd84afe2e5f2823565329af333018 (diff) | |
download | sos-de5fd69e594d6c182e1a2d3539bcabebc941ed4d.tar.gz |
[Plugin] simplify file and command cert substitution methods
Simplify the methods for substituting file and command certificate
data, and add a "desc" keyword argument allowing plugins to add a
description of the data that was removed.
Related: #1690
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
-rw-r--r-- | sos/plugins/__init__.py | 65 |
1 files changed, 24 insertions, 41 deletions
diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py index 66916dd7..d3d42e79 100644 --- a/sos/plugins/__init__.py +++ b/sos/plugins/__init__.py @@ -92,6 +92,10 @@ def _file_is_compressed(path): return path.endswith(('.gz', '.xz', '.bz', '.bz2')) +_certmatch = re.compile("-*BEGIN.*?-*END", re.DOTALL) +_cert_replace = "-----SCRUBBED" + + class SoSPredicate(object): """A class to implement collection predicates. @@ -467,7 +471,7 @@ class Plugin(object): self._log_warn(msg % (cmd, needs)) - def do_cmd_private_sub(self, cmd): + def do_cmd_private_sub(self, cmd, desc=""): '''Remove certificate and key output archived by sosreport. cmd is the command name from which output is collected (i.e. exlcuding parameters). Any matching instances are replaced with: '-----SCRUBBED' @@ -475,35 +479,16 @@ class Plugin(object): This function returns the number of replacements made. ''' + if not self.executed_commands: + return 0 + globstr = '*' + cmd + '*' self._log_debug("Scrubbing certs and keys for commands matching %s" % (cmd)) - if not self.executed_commands: - return 0 + replace = "%s %s" % (_cert_replace, desc) if desc else _cert_replace - replacements = None - try: - for called in self.executed_commands: - if called['file'] is None: - continue - if called['binary'] == 'yes': - self._log_warn("Cannot apply regex substitution to binary" - " output: '%s'" % called['exe']) - continue - if fnmatch.fnmatch(called['exe'], globstr): - path = os.path.join(self.commons['cmddir'], called['file']) - readable = self.archive.open_file(path) - certmatch = re.compile("-----BEGIN.*?-----END", re.DOTALL) - result, replacements = certmatch.subn( - "-----SCRUBBED", readable.read()) - if replacements: - self.archive.add_string(result, path) - except Exception as e: - msg = "Certificate/key scrubbing failed for '%s' with: '%s'" - self._log_error(msg % (called['exe'], e)) - replacements = None - return replacements + return self.do_cmd_output_sub(cmd, _certmatch, replace) def do_cmd_output_sub(self, cmd, regexp, subst): '''Apply a regexp substitution to command output archived by sosreport. @@ -517,8 +502,9 @@ class Plugin(object): This function returns the number of replacements made. ''' globstr = '*' + cmd + '*' + pattern = regexp.pattern if hasattr(regexp, "pattern") else regexp self._log_debug("substituting '%s' for '%s' in commands matching '%s'" - % (subst, regexp, globstr)) + % (subst, pattern, globstr)) if not self.executed_commands: return 0 @@ -548,34 +534,30 @@ class Plugin(object): replacements = None return replacements - def do_file_private_sub(self, pathregex): + def do_file_private_sub(self, pathregex, desc=""): '''Scrub certificate/key/etc information from files collected by sos. Files matching the provided pathregex are searched for content that resembles certificate, ssh keys, or similar information. Any matches - are replaced with "-----SCRUBBED $thing" where $thing is the specific - type of content being replaced, e.g. "-----SCRUBBED RSA PRIVATE KEY" so - that support representatives can at least be informed of what type of - content it was originally. + are replaced with "-----SCRUBBED $desc" where `desc` is a description + of the specific type of content being replaced, e.g. + "-----SCRUBBED RSA PRIVATE KEY" so that support representatives can + at least be informed of what type of content it was originally. Positional arguments: :param pathregex: A string or regex of a filename to match against + :param desc: A description of the replaced content ''' - certmatch = re.compile("-*BEGIN.*?-*END", re.DOTALL) + self._log_debug("Scrubbing certs and keys for paths matching %s" + % pathregex) match = re.compile(pathregex).match + replace = "%s %s" % (_cert_replace, desc) if desc else _cert_replace file_list = [f for f in self.copied_files if match(f['srcpath'])] for i in file_list: path = i['dstpath'] if not path: continue - self._log_debug("Scrubbing %s for certificate content" % path) - readable = self.archive.open_file(path) - content = readable.read() - if not isinstance(content, six.string_types): - content = content.decode('utf-8', 'ignore') - result, replacements = certmatch.subn('-----SCRUBBED', content) - if replacements: - self.archive.add_string(result, path) + self.do_file_sub(path, _certmatch, replace) def do_file_sub(self, srcpath, regexp, subst): '''Apply a regexp substitution to a file archived by sosreport. @@ -587,9 +569,10 @@ class Plugin(object): ''' try: path = self._get_dest_for_srcpath(srcpath) + pattern = regexp.pattern if hasattr(regexp, "pattern") else regexp self._log_debug("substituting scrpath '%s'" % srcpath) self._log_debug("substituting '%s' for '%s' in '%s'" - % (subst, regexp, path)) + % (subst, pattern, path)) if not path: return 0 readable = self.archive.open_file(path) |