Blame SOURCES/scap-security-guide-0.1.53-bash_platforms-PR_6061.patch

fe0dde
From c05cce1a4a5eb95be857b07948fda0c95cdaa106 Mon Sep 17 00:00:00 2001
fe0dde
From: Watson Sato <wsato@redhat.com>
fe0dde
Date: Tue, 8 Sep 2020 14:36:07 +0200
fe0dde
Subject: [PATCH 1/5] Align Bash applicability with CPE platform
fe0dde
fe0dde
Wraps the remediation of rules with Packager CPE Platform
fe0dde
with an if condition that checks for the respective
fe0dde
platforms's package.
fe0dde
---
fe0dde
 ssg/build_remediations.py | 45 +++++++++++++++++++++++++++++++++++++++
fe0dde
 1 file changed, 45 insertions(+)
fe0dde
fe0dde
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
fe0dde
index ccbdf9fc1f..2d4a805e78 100644
fe0dde
--- a/ssg/build_remediations.py
fe0dde
+++ b/ssg/build_remediations.py
fe0dde
@@ -27,6 +27,13 @@
fe0dde
     'kubernetes': '.yml'
fe0dde
 }
fe0dde
 
fe0dde
+PKG_MANAGER_TO_PACKAGE_CHECK_COMMAND = {
fe0dde
+    'apt_get': 'dpkg-query -s {} &>/dev/null',
fe0dde
+    'dnf': 'rpm --quiet -q {}',
fe0dde
+    'yum': 'rpm --quiet -q {}',
fe0dde
+    'zypper': 'rpm --quiet -q {}',
fe0dde
+}
fe0dde
+
fe0dde
 FILE_GENERATED_HASH_COMMENT = '# THIS FILE IS GENERATED'
fe0dde
 
fe0dde
 REMEDIATION_CONFIG_KEYS = ['complexity', 'disruption', 'platform', 'reboot',
fe0dde
@@ -262,6 +269,44 @@ class BashRemediation(Remediation):
fe0dde
     def __init__(self, file_path):
fe0dde
         super(BashRemediation, self).__init__(file_path, "bash")
fe0dde
 
fe0dde
+    def parse_from_file_with_jinja(self, env_yaml):
fe0dde
+        self.local_env_yaml.update(env_yaml)
fe0dde
+        result = super(BashRemediation, self).parse_from_file_with_jinja(self.local_env_yaml)
fe0dde
+
fe0dde
+        # There can be repeated inherited platforms and rule platforms
fe0dde
+        rule_platforms = set(self.associated_rule.inherited_platforms)
fe0dde
+        rule_platforms.add(self.associated_rule.platform)
fe0dde
+
fe0dde
+        platform_conditionals = []
fe0dde
+        for platform in rule_platforms:
fe0dde
+            if platform == "machine":
fe0dde
+                # Based on check installed_env_is_a_container
fe0dde
+                platform_conditionals.append('[ ! -f /.dockerenv -a ! -f /run/.containerenv ]')
fe0dde
+            elif platform is not None:
fe0dde
+                # Assume any other platform is a Package CPE
fe0dde
+
fe0dde
+                # Some package names are different from the platform names
fe0dde
+                if platform in self.local_env_yaml["platform_package_overrides"]:
fe0dde
+                    platform = self.local_env_yaml["platform_package_overrides"].get(platform)
fe0dde
+
fe0dde
+                # Adjust package check command according to the pkg_manager
fe0dde
+                pkg_manager = self.local_env_yaml["pkg_manager"]
fe0dde
+                pkg_check_command = PKG_MANAGER_TO_PACKAGE_CHECK_COMMAND[pkg_manager]
fe0dde
+                platform_conditionals.append(pkg_check_command.format(platform))
fe0dde
+
fe0dde
+        if platform_conditionals:
fe0dde
+            platform_fix_text = "# Remediation is applicable only in certain platforms\n"
fe0dde
+
fe0dde
+            cond = platform_conditionals.pop(0)
fe0dde
+            platform_fix_text += "if {}".format(cond)
fe0dde
+            for cond in platform_conditionals:
fe0dde
+                platform_fix_text += " && {}".format(cond)
fe0dde
+            platform_fix_text += '; then\n{}\nelse\necho "Remediation is not applicable, nothing was done"\nfi'.format(result.contents)
fe0dde
+
fe0dde
+            remediation = namedtuple('remediation', ['contents', 'config'])
fe0dde
+            result = remediation(contents=platform_fix_text, config=result.config)
fe0dde
+
fe0dde
+        return result
fe0dde
 
fe0dde
 class AnsibleRemediation(Remediation):
fe0dde
     def __init__(self, file_path):
fe0dde
fe0dde
From 19e0c3b709e091159655d37b8ce5d693750f0a81 Mon Sep 17 00:00:00 2001
fe0dde
From: Watson Sato <wsato@redhat.com>
fe0dde
Date: Tue, 8 Sep 2020 14:41:01 +0200
fe0dde
Subject: [PATCH 2/5] Handle Bash platform wrapping in xccdf expansion
fe0dde
fe0dde
Adjust expansion of subs and variables not to remove the whole beginning
fe0dde
of the fix test. This was removing the package conditional wrapping.
fe0dde
---
fe0dde
 ssg/build_remediations.py | 21 ++++++++++++---------
fe0dde
 1 file changed, 12 insertions(+), 9 deletions(-)
fe0dde
fe0dde
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
fe0dde
index 2d4a805e78..49ec557000 100644
fe0dde
--- a/ssg/build_remediations.py
fe0dde
+++ b/ssg/build_remediations.py
fe0dde
@@ -736,14 +736,16 @@ def expand_xccdf_subs(fix, remediation_type, remediation_functions):
fe0dde
         patcomp = re.compile(pattern, re.DOTALL)
fe0dde
         fixparts = re.split(patcomp, fix.text)
fe0dde
         if fixparts[0] is not None:
fe0dde
-            # Split the portion of fix.text from fix start to first call of
fe0dde
-            # remediation function, keeping only the third part:
fe0dde
-            # * tail        to hold part of the fix.text after inclusion,
fe0dde
-            #               but before first call of remediation function
fe0dde
+            # Split the portion of fix.text at the string remediation_functions,
fe0dde
+            # and remove preceeding comment whenever it is there.
fe0dde
+            # * head        holds part of the fix.text before
fe0dde
+            #               remediation_functions string
fe0dde
+            # * tail        holds part of the fix.text after the
fe0dde
+            #               remediation_functions string
fe0dde
             try:
fe0dde
-                rfpattern = '(.*remediation_functions)(.*)'
fe0dde
-                rfpatcomp = re.compile(rfpattern, re.DOTALL)
fe0dde
-                _, _, tail, _ = re.split(rfpatcomp, fixparts[0], maxsplit=2)
fe0dde
+                rfpattern = r'((?:# Include source function library\.\n)?.*remediation_functions)'
fe0dde
+                rfpatcomp = re.compile(rfpattern)
fe0dde
+                head, _, tail = re.split(rfpatcomp, fixparts[0], maxsplit=1)
fe0dde
             except ValueError:
fe0dde
                 sys.stderr.write("Processing fix.text for: %s rule\n"
fe0dde
                                  % fix.get('rule'))
fe0dde
@@ -751,9 +753,10 @@ def expand_xccdf_subs(fix, remediation_type, remediation_functions):
fe0dde
                                  "after inclusion of remediation functions."
fe0dde
                                  " Aborting..\n")
fe0dde
                 sys.exit(1)
fe0dde
-            # If the 'tail' is not empty, make it new fix.text.
fe0dde
+            # If the 'head' is not empty, make it new fix.text.
fe0dde
             # Otherwise use ''
fe0dde
-            fix.text = tail if tail is not None else ''
fe0dde
+            fix.text = head if head is not None else ''
fe0dde
+            fix.text += tail if tail is not None else ''
fe0dde
             # Drop the first element of 'fixparts' since it has been processed
fe0dde
             fixparts.pop(0)
fe0dde
             # Perform sanity check on new 'fixparts' list content (to continue
fe0dde
fe0dde
From 1292b93dc35a9a308464f1effb7f10f8de6db457 Mon Sep 17 00:00:00 2001
fe0dde
From: Watson Sato <wsato@redhat.com>
fe0dde
Date: Tue, 8 Sep 2020 20:56:17 +0200
fe0dde
Subject: [PATCH 3/5] Check if remediation has associated rule before use
fe0dde
fe0dde
---
fe0dde
 ssg/build_remediations.py | 8 +++++---
fe0dde
 1 file changed, 5 insertions(+), 3 deletions(-)
fe0dde
fe0dde
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
fe0dde
index 49ec557000..85f7139d8f 100644
fe0dde
--- a/ssg/build_remediations.py
fe0dde
+++ b/ssg/build_remediations.py
fe0dde
@@ -273,9 +273,11 @@ def parse_from_file_with_jinja(self, env_yaml):
fe0dde
         self.local_env_yaml.update(env_yaml)
fe0dde
         result = super(BashRemediation, self).parse_from_file_with_jinja(self.local_env_yaml)
fe0dde
 
fe0dde
-        # There can be repeated inherited platforms and rule platforms
fe0dde
-        rule_platforms = set(self.associated_rule.inherited_platforms)
fe0dde
-        rule_platforms.add(self.associated_rule.platform)
fe0dde
+        rule_platforms = set()
fe0dde
+        if self.associated_rule:
fe0dde
+            # There can be repeated inherited platforms and rule platforms
fe0dde
+            rule_platforms.update(self.associated_rule.inherited_platforms)
fe0dde
+            rule_platforms.add(self.associated_rule.platform)
fe0dde
 
fe0dde
         platform_conditionals = []
fe0dde
         for platform in rule_platforms:
fe0dde
fe0dde
From 7953a02e61bb56b501c56f46972247751292dcbb Mon Sep 17 00:00:00 2001
fe0dde
From: Watson Sato <wsato@redhat.com>
fe0dde
Date: Thu, 10 Sep 2020 10:59:43 +0200
fe0dde
Subject: [PATCH 4/5] Fix python2 compat and improve code readability
fe0dde
fe0dde
---
fe0dde
 ssg/build_remediations.py | 29 ++++++++++++++++++-----------
fe0dde
 1 file changed, 18 insertions(+), 11 deletions(-)
fe0dde
fe0dde
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
fe0dde
index 85f7139d8f..673d6d0cc6 100644
fe0dde
--- a/ssg/build_remediations.py
fe0dde
+++ b/ssg/build_remediations.py
fe0dde
@@ -28,10 +28,10 @@
fe0dde
 }
fe0dde
 
fe0dde
 PKG_MANAGER_TO_PACKAGE_CHECK_COMMAND = {
fe0dde
-    'apt_get': 'dpkg-query -s {} &>/dev/null',
fe0dde
-    'dnf': 'rpm --quiet -q {}',
fe0dde
-    'yum': 'rpm --quiet -q {}',
fe0dde
-    'zypper': 'rpm --quiet -q {}',
fe0dde
+    'apt_get': 'dpkg-query -s {0} &>/dev/null',
fe0dde
+    'dnf': 'rpm --quiet -q {0}',
fe0dde
+    'yum': 'rpm --quiet -q {0}',
fe0dde
+    'zypper': 'rpm --quiet -q {0}',
fe0dde
 }
fe0dde
 
fe0dde
 FILE_GENERATED_HASH_COMMENT = '# THIS FILE IS GENERATED'
fe0dde
@@ -297,16 +297,23 @@ def parse_from_file_with_jinja(self, env_yaml):
fe0dde
                 platform_conditionals.append(pkg_check_command.format(platform))
fe0dde
 
fe0dde
         if platform_conditionals:
fe0dde
-            platform_fix_text = "# Remediation is applicable only in certain platforms\n"
fe0dde
+            wrapped_fix_text = ["# Remediation is applicable only in certain platforms"]
fe0dde
 
fe0dde
-            cond = platform_conditionals.pop(0)
fe0dde
-            platform_fix_text += "if {}".format(cond)
fe0dde
-            for cond in platform_conditionals:
fe0dde
-                platform_fix_text += " && {}".format(cond)
fe0dde
-            platform_fix_text += '; then\n{}\nelse\necho "Remediation is not applicable, nothing was done"\nfi'.format(result.contents)
fe0dde
+            all_conditions = " && ".join(platform_conditionals)
fe0dde
+            wrapped_fix_text.append("if {0}; then".format(all_conditions))
fe0dde
+
fe0dde
+            # Avoid adding extra blank line
fe0dde
+            if not result.contents.startswith("\n"):
fe0dde
+                wrapped_fix_text.append("")
fe0dde
+
fe0dde
+            wrapped_fix_text.append("{0}".format(result.contents))
fe0dde
+            wrapped_fix_text.append("")
fe0dde
+            wrapped_fix_text.append("else")
fe0dde
+            wrapped_fix_text.append("    >&2 echo 'Remediation is not applicable, nothing was done'")
fe0dde
+            wrapped_fix_text.append("fi")
fe0dde
 
fe0dde
             remediation = namedtuple('remediation', ['contents', 'config'])
fe0dde
-            result = remediation(contents=platform_fix_text, config=result.config)
fe0dde
+            result = remediation(contents="\n".join(wrapped_fix_text), config=result.config)
fe0dde
 
fe0dde
         return result
fe0dde
 
fe0dde
fe0dde
From 0bd3912651367c64789bb3d67b44c3b8848708c0 Mon Sep 17 00:00:00 2001
fe0dde
From: Watson Sato <wsato@redhat.com>
fe0dde
Date: Thu, 10 Sep 2020 17:25:27 +0200
fe0dde
Subject: [PATCH 5/5] Document the perils of indenting wrapped Bash fixes
fe0dde
fe0dde
---
fe0dde
 ssg/build_remediations.py | 3 +++
fe0dde
 1 file changed, 3 insertions(+)
fe0dde
fe0dde
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
fe0dde
index 673d6d0cc6..f269d4d2d6 100644
fe0dde
--- a/ssg/build_remediations.py
fe0dde
+++ b/ssg/build_remediations.py
fe0dde
@@ -306,6 +306,9 @@ def parse_from_file_with_jinja(self, env_yaml):
fe0dde
             if not result.contents.startswith("\n"):
fe0dde
                 wrapped_fix_text.append("")
fe0dde
 
fe0dde
+            # It is possible to indent the original body of the remediation with textwrap.indent(),
fe0dde
+            # however, it is not supported by python2, and there is a risk of breaking remediations
fe0dde
+            # For example, remediations with a here-doc block could be affected.
fe0dde
             wrapped_fix_text.append("{0}".format(result.contents))
fe0dde
             wrapped_fix_text.append("")
fe0dde
             wrapped_fix_text.append("else")