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