Blame SOURCES/scap-security-guide-0.1.53-add-ansible-platform_PR_6025.patch

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