281 lines
11 KiB
Diff
281 lines
11 KiB
Diff
From 844be904d8de624abe9bbe620d7a06417dfff842 Mon Sep 17 00:00:00 2001
|
|
From: Watson Sato <wsato@redhat.com>
|
|
Date: Thu, 27 Aug 2020 13:19:01 +0200
|
|
Subject: [PATCH 1/5] Align Ansible task applicability with CPE platform
|
|
|
|
Adds a when clause to Ansible snippets of rules with Package CPE platform.
|
|
|
|
If the when clause is added, a fact_packages Task needs to added as
|
|
well.
|
|
---
|
|
ssg/build_remediations.py | 52 ++++++++++++++++++++++++++++++++++++---
|
|
1 file changed, 49 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
|
|
index a9ef3014ac..597aed5889 100644
|
|
--- a/ssg/build_remediations.py
|
|
+++ b/ssg/build_remediations.py
|
|
@@ -6,8 +6,7 @@
|
|
import os.path
|
|
import re
|
|
import codecs
|
|
-from collections import defaultdict, namedtuple
|
|
-
|
|
+from collections import defaultdict, namedtuple, OrderedDict
|
|
|
|
import ssg.yaml
|
|
from . import build_yaml
|
|
@@ -343,11 +342,46 @@ def _get_rule_reference(self, ref_class):
|
|
else:
|
|
return []
|
|
|
|
+ def inject_package_facts_task(self, parsed_snippet):
|
|
+ """ Injects a package_facts task only if
|
|
+ the snippet has a task with a when clause with ansible_facts.packages,
|
|
+ and the snippet doesn't already have an package_facts task
|
|
+ """
|
|
+ has_package_facts_task = False
|
|
+ has_ansible_facts_packages_clause = False
|
|
+
|
|
+ for p_task in parsed_snippet:
|
|
+ # We are only interested in the OrderedDicts, which represent Ansible tasks
|
|
+ if not isinstance(p_task, dict):
|
|
+ continue
|
|
+
|
|
+ if "package_facts" in p_task:
|
|
+ has_package_facts_task = True
|
|
+
|
|
+ if "ansible_facts.packages" in p_task.get("when", ""):
|
|
+ has_ansible_facts_packages_clause = True
|
|
+
|
|
+ if has_ansible_facts_packages_clause and not has_package_facts_task:
|
|
+ facts_task = OrderedDict({'name': 'Gather the package facts',
|
|
+ 'package_facts': {'manager': 'auto'}})
|
|
+ parsed_snippet.insert(0, facts_task)
|
|
+
|
|
def update_when_from_rule(self, to_update):
|
|
additional_when = ""
|
|
- if self.associated_rule.platform == "machine":
|
|
- additional_when = ('ansible_virtualization_role != "guest" '
|
|
- 'or ansible_virtualization_type != "docker"')
|
|
+ rule_platform = self.associated_rule.platform
|
|
+ if rule_platform == "machine":
|
|
+ additional_when = 'ansible_virtualization_type not in ["docker", "lxc", "openvz"]'
|
|
+ elif rule_platform is not None:
|
|
+ # Assume any other platform is a Package CPE
|
|
+
|
|
+ # It doesn't make sense to add a conditional on the task that
|
|
+ # gathers data for the conditional
|
|
+ if "package_facts" in to_update:
|
|
+ return
|
|
+
|
|
+ additional_when = '"' + rule_platform + '" in ansible_facts.packages'
|
|
+ # After adding the conditional, we need to make sure package_facts are collected.
|
|
+ # This is done via inject_package_facts_task()
|
|
to_update.setdefault("when", "")
|
|
new_when = ssg.yaml.update_yaml_list_or_string(to_update["when"], additional_when)
|
|
if not new_when:
|
|
@@ -355,10 +390,21 @@ def update_when_from_rule(self, to_update):
|
|
to_update["when"] = new_when
|
|
|
|
def update(self, parsed, config):
|
|
+ # We split the remediation update in three steps
|
|
+
|
|
+ # 1. Update the when clause
|
|
for p in parsed:
|
|
if not isinstance(p, dict):
|
|
continue
|
|
self.update_when_from_rule(p)
|
|
+
|
|
+ # 2. Inject any extra task necessary
|
|
+ self.inject_package_facts_task(parsed)
|
|
+
|
|
+ # 3. Add tags to all tasks, including the ones we have injected
|
|
+ for p in parsed:
|
|
+ if not isinstance(p, dict):
|
|
+ continue
|
|
self.update_tags_from_config(p, config)
|
|
self.update_tags_from_rule(p)
|
|
|
|
|
|
From 60e5723e0e35ec8d79bafdd113f04691e61738e7 Mon Sep 17 00:00:00 2001
|
|
From: Watson Sato <wsato@redhat.com>
|
|
Date: Thu, 27 Aug 2020 17:09:06 +0200
|
|
Subject: [PATCH 2/5] Add inherited_platform to Rule
|
|
|
|
This field is exported to the rule when it is resolved.
|
|
---
|
|
ssg/build_yaml.py | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/ssg/build_yaml.py b/ssg/build_yaml.py
|
|
index 4ba114eee4..fe290ffc05 100644
|
|
--- a/ssg/build_yaml.py
|
|
+++ b/ssg/build_yaml.py
|
|
@@ -832,6 +832,7 @@ class Rule(object):
|
|
"conflicts": lambda: list(),
|
|
"requires": lambda: list(),
|
|
"platform": lambda: None,
|
|
+ "inherited_platforms": lambda: list(),
|
|
"template": lambda: None,
|
|
}
|
|
|
|
@@ -851,6 +852,7 @@ def __init__(self, id_):
|
|
self.requires = []
|
|
self.conflicts = []
|
|
self.platform = None
|
|
+ self.inherited_platforms = [] # platforms inherited from the group
|
|
self.template = None
|
|
|
|
@classmethod
|
|
@@ -1293,6 +1295,9 @@ def _process_rules(self):
|
|
continue
|
|
self.all_rules.add(rule)
|
|
self.loaded_group.add_rule(rule)
|
|
+
|
|
+ rule.inherited_platforms.append(self.loaded_group.platform)
|
|
+
|
|
if self.resolved_rules_dir:
|
|
output_for_rule = os.path.join(
|
|
self.resolved_rules_dir, "{id_}.yml".format(id_=rule.id_))
|
|
|
|
From 3a0bb0d2981670e90a8eaca53b28e1a6f7cc29d6 Mon Sep 17 00:00:00 2001
|
|
From: Watson Sato <wsato@redhat.com>
|
|
Date: Thu, 27 Aug 2020 17:21:35 +0200
|
|
Subject: [PATCH 3/5] Add when clauses for inherited platforms too
|
|
|
|
Consider the Rule's Group platform while including 'when' clauses to
|
|
Ansible snippets.
|
|
|
|
Some rules have two platforms, a machine platform and a package
|
|
platform. One of them is represented of the Rule, and the other is
|
|
represented in the Rule's Group.
|
|
|
|
The platforms are organized like this to due limiation in XCCDF,
|
|
multiple platforms in a Rule are ORed, not ANDed.
|
|
---
|
|
ssg/build_remediations.py | 44 ++++++++++++++++++++++++---------------
|
|
1 file changed, 27 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
|
|
index 597aed5889..a2a996d0af 100644
|
|
--- a/ssg/build_remediations.py
|
|
+++ b/ssg/build_remediations.py
|
|
@@ -358,8 +358,13 @@ def inject_package_facts_task(self, parsed_snippet):
|
|
if "package_facts" in p_task:
|
|
has_package_facts_task = True
|
|
|
|
- if "ansible_facts.packages" in p_task.get("when", ""):
|
|
- has_ansible_facts_packages_clause = True
|
|
+ # When clause of the task can be string or a list, lets normalize to list
|
|
+ task_when = p_task.get("when", "")
|
|
+ if type(task_when) is str:
|
|
+ task_when = [ task_when ]
|
|
+ for when in task_when:
|
|
+ if "ansible_facts.packages" in when:
|
|
+ has_ansible_facts_packages_clause = True
|
|
|
|
if has_ansible_facts_packages_clause and not has_package_facts_task:
|
|
facts_task = OrderedDict({'name': 'Gather the package facts',
|
|
@@ -367,21 +372,26 @@ def inject_package_facts_task(self, parsed_snippet):
|
|
parsed_snippet.insert(0, facts_task)
|
|
|
|
def update_when_from_rule(self, to_update):
|
|
- additional_when = ""
|
|
- rule_platform = self.associated_rule.platform
|
|
- if rule_platform == "machine":
|
|
- additional_when = 'ansible_virtualization_type not in ["docker", "lxc", "openvz"]'
|
|
- elif rule_platform is not None:
|
|
- # Assume any other platform is a Package CPE
|
|
-
|
|
- # It doesn't make sense to add a conditional on the task that
|
|
- # gathers data for the conditional
|
|
- if "package_facts" in to_update:
|
|
- return
|
|
-
|
|
- additional_when = '"' + rule_platform + '" in ansible_facts.packages'
|
|
- # After adding the conditional, we need to make sure package_facts are collected.
|
|
- # This is done via inject_package_facts_task()
|
|
+ additional_when = []
|
|
+
|
|
+ rule_platforms = set([self.associated_rule.platform] +
|
|
+ self.associated_rule.inherited_platforms)
|
|
+
|
|
+ for platform in rule_platforms:
|
|
+ if platform == "machine":
|
|
+ additional_when.append('ansible_virtualization_type not in ["docker", "lxc", "openvz"]')
|
|
+ elif platform is not None:
|
|
+ # Assume any other platform is a Package CPE
|
|
+
|
|
+ # It doesn't make sense to add a conditional on the task that
|
|
+ # gathers data for the conditional
|
|
+ if "package_facts" in to_update:
|
|
+ continue
|
|
+
|
|
+ additional_when.append('"' + platform + '" in ansible_facts.packages')
|
|
+ # After adding the conditional, we need to make sure package_facts are collected.
|
|
+ # This is done via inject_package_facts_task()
|
|
+
|
|
to_update.setdefault("when", "")
|
|
new_when = ssg.yaml.update_yaml_list_or_string(to_update["when"], additional_when)
|
|
if not new_when:
|
|
|
|
From 99c92e39bccc3fcfadca41096e66ca146137b207 Mon Sep 17 00:00:00 2001
|
|
From: Watson Sato <wsato@redhat.com>
|
|
Date: Mon, 31 Aug 2020 16:06:14 +0200
|
|
Subject: [PATCH 4/5] Improve inherihted and rule's platforms handling
|
|
|
|
Add a quick comment too.
|
|
---
|
|
ssg/build_remediations.py | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
|
|
index a2a996d0af..9e622ef740 100644
|
|
--- a/ssg/build_remediations.py
|
|
+++ b/ssg/build_remediations.py
|
|
@@ -374,8 +374,9 @@ def inject_package_facts_task(self, parsed_snippet):
|
|
def update_when_from_rule(self, to_update):
|
|
additional_when = []
|
|
|
|
- rule_platforms = set([self.associated_rule.platform] +
|
|
- self.associated_rule.inherited_platforms)
|
|
+ # There can be repeated inherited platforms and rule platforms
|
|
+ rule_platforms = set(self.associated_rule.inherited_platforms)
|
|
+ rule_platforms.add(self.associated_rule.platform)
|
|
|
|
for platform in rule_platforms:
|
|
if platform == "machine":
|
|
|
|
From 596da9993edfbd244cbaa6d797abbd68b2e82185 Mon Sep 17 00:00:00 2001
|
|
From: Watson Sato <wsato@redhat.com>
|
|
Date: Mon, 31 Aug 2020 16:10:53 +0200
|
|
Subject: [PATCH 5/5] Code style and grammar changes
|
|
|
|
---
|
|
ssg/build_remediations.py | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/ssg/build_remediations.py b/ssg/build_remediations.py
|
|
index 9e622ef740..866450dd8c 100644
|
|
--- a/ssg/build_remediations.py
|
|
+++ b/ssg/build_remediations.py
|
|
@@ -345,7 +345,7 @@ def _get_rule_reference(self, ref_class):
|
|
def inject_package_facts_task(self, parsed_snippet):
|
|
""" Injects a package_facts task only if
|
|
the snippet has a task with a when clause with ansible_facts.packages,
|
|
- and the snippet doesn't already have an package_facts task
|
|
+ and the snippet doesn't already have a package_facts task
|
|
"""
|
|
has_package_facts_task = False
|
|
has_ansible_facts_packages_clause = False
|
|
@@ -361,7 +361,7 @@ def inject_package_facts_task(self, parsed_snippet):
|
|
# When clause of the task can be string or a list, lets normalize to list
|
|
task_when = p_task.get("when", "")
|
|
if type(task_when) is str:
|
|
- task_when = [ task_when ]
|
|
+ task_when = [task_when]
|
|
for when in task_when:
|
|
if "ansible_facts.packages" in when:
|
|
has_ansible_facts_packages_clause = True
|