aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake Hunsaker <jhunsake@redhat.com>2021-01-06 12:51:38 -0500
committerJake Hunsaker <jhunsake@redhat.com>2021-01-13 13:12:27 -0500
commit0f74186752d85d80006187261e9bdb8b104a05fe (patch)
treedbb8534d027023fc521122135eeaac9f564fe961
parent5fb859f52a5a77657d509c7f4d3590fdca694931 (diff)
downloadsos-0f74186752d85d80006187261e9bdb8b104a05fe.tar.gz
[Policy] Add policy-controlled forbidden paths
This adds policy-controlled forbidden path checking, which should be the final part of implementing "global" forbidden paths. With this commit, policies may now add paths and glob matches for paths which should never be collected in any plugin. Combined with plugin-defined paths and user-defined paths already available, plugins should now be able to be properly restricted from sensitive collections. Note that the way this is implemented is that policies that define the `set_forbidden_paths()` classmethod *extend* this forbidden list as it is built from the subclass(es) that also define one. This way, "top-level" policies do not need to maintain independent copies of entire trees of paths just to add a few specific additional ones that are not forbidden within other policies. This initial commit adds paths that are either very well-known to be ones we should avoid, or are paths that have previously been part of reported issues where these paths/files should not be collected. Closes: #316 Closes: #796 Closes: #919 Closes: #1316 Resolves: #2360 Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
-rw-r--r--sos/policies/__init__.py28
-rw-r--r--sos/policies/distros/__init__.py7
-rw-r--r--sos/report/plugins/__init__.py9
-rw-r--r--tests/policy_tests.py16
4 files changed, 60 insertions, 0 deletions
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
index 00243a91..a123926d 100644
--- a/sos/policies/__init__.py
+++ b/sos/policies/__init__.py
@@ -141,6 +141,34 @@ any third party.
"""
return False
+ @property
+ def forbidden_paths(self):
+ """This property is used to determine the list of forbidden paths
+ set by the policy. Note that this property will construct a
+ *cumulative* list based on all subclasses of a given policy.
+
+ :returns: All patterns of policy forbidden paths
+ :rtype: ``list``
+ """
+ if not hasattr(self, '_forbidden_paths'):
+ self._forbidden_paths = []
+ for cls in self.__class__.__mro__:
+ if hasattr(cls, 'set_forbidden_paths'):
+ self._forbidden_paths.extend(cls.set_forbidden_paths())
+ return list(set(self._forbidden_paths))
+
+ @classmethod
+ def set_forbidden_paths(cls):
+ """Use this to *append* policy-specifc forbidden paths that apply to
+ all plugins. Setting this classmethod on an invidual policy will *not*
+ override subclass-specific paths
+ """
+ return [
+ '*.pyc',
+ '*.pyo',
+ '*.swp'
+ ]
+
def in_container(self):
"""Are we running inside a container?
diff --git a/sos/policies/distros/__init__.py b/sos/policies/distros/__init__.py
index c97cc1a5..c5fb4801 100644
--- a/sos/policies/distros/__init__.py
+++ b/sos/policies/distros/__init__.py
@@ -94,6 +94,13 @@ class LinuxPolicy(Policy):
idx = list(self.runtimes.keys())
self.runtimes['default'] = self.runtimes[idx[0]]
+ @classmethod
+ def set_forbidden_paths(cls):
+ return [
+ '/etc/passwd',
+ '/etc/shadow'
+ ]
+
def get_preferred_hash_name(self):
if self._preferred_hash_name:
diff --git a/sos/report/plugins/__init__.py b/sos/report/plugins/__init__.py
index 1527caea..3ae6507d 100644
--- a/sos/report/plugins/__init__.py
+++ b/sos/report/plugins/__init__.py
@@ -1082,6 +1082,11 @@ class Plugin(object):
def _is_forbidden_path(self, path):
return _path_in_path_list(path, self.forbidden_paths)
+ def _is_policy_forbidden_path(self, path):
+ return any([
+ fnmatch.fnmatch(path, fp) for fp in self.policy.forbidden_paths
+ ])
+
def _is_skipped_path(self, path):
"""Check if the given path matches a user-provided specification to
ignore collection of via the ``--skip-files`` option
@@ -1441,6 +1446,10 @@ class Plugin(object):
if self._is_forbidden_path(_file):
self._log_debug("skipping forbidden path '%s'" % _file)
continue
+ if self._is_policy_forbidden_path(_file):
+ self._log_debug("skipping policy forbidden path '%s'"
+ % _file)
+ continue
if self._is_skipped_path(_file):
self._log_debug("skipping excluded path '%s'" % _file)
continue
diff --git a/tests/policy_tests.py b/tests/policy_tests.py
index 4b248b70..6d0c42b9 100644
--- a/tests/policy_tests.py
+++ b/tests/policy_tests.py
@@ -8,6 +8,7 @@
import unittest
from sos.policies import Policy, import_policy
+from sos.policies.distros import LinuxPolicy
from sos.policies.package_managers import PackageManager
from sos.report.plugins import (Plugin, IndependentPlugin,
RedHatPlugin, DebianPlugin)
@@ -17,6 +18,14 @@ class FauxPolicy(Policy):
distro = "Faux"
+class FauxLinuxPolicy(LinuxPolicy):
+ distro = "FauxLinux"
+
+ @classmethod
+ def set_forbidden_paths(cls):
+ return ['/etc/secret']
+
+
class FauxPlugin(Plugin, IndependentPlugin):
pass
@@ -31,12 +40,19 @@ class FauxDebianPlugin(Plugin, DebianPlugin):
class PolicyTests(unittest.TestCase):
+
def test_independent_only(self):
p = FauxPolicy()
p.valid_subclasses = []
self.assertTrue(p.validate_plugin(FauxPlugin))
+ def test_forbidden_paths_building(self):
+ p = FauxLinuxPolicy(probe_runtime=False)
+ self.assertTrue('*.pyc' in p.forbidden_paths)
+ self.assertTrue('/etc/passwd' in p.forbidden_paths)
+ self.assertTrue('/etc/secret' in p.forbidden_paths)
+
def test_redhat(self):
p = FauxPolicy()
p.valid_subclasses = [RedHatPlugin]