From 3339d0190e809d907d25b88fd176d6b5b236b165 Mon Sep 17 00:00:00 2001
From: Jan Lieskovsky <jlieskov@redhat.com>
Date: Tue, 17 Sep 2013 16:26:02 +0200
Subject: [PATCH 2/8] Add input/checks subdir content: Two gpgchecks,
 testcheck.py script, F-19 detection, and F-19 CPE
 dictionary.


Signed-off-by: Jan Lieskovsky <jlieskov@redhat.com>
---
 .../checks/ensure_gpgcheck_never_disabled.xml      |  28 +++++
 FEDORA/input/checks/installed_OS_is_fedora19.xml   |  41 +++++++
 .../checks/platform/fedora-cpe-dictionary.xml      |  10 ++
 FEDORA/input/checks/testcheck.py                   | 124 +++++++++++++++++++++
 .../checks/yum_gpgcheck_global_activation.xml      |  24 ++++
 5 files changed, 227 insertions(+)
 create mode 100644 FEDORA/input/checks/ensure_gpgcheck_never_disabled.xml
 create mode 100644 FEDORA/input/checks/installed_OS_is_fedora19.xml
 create mode 100644 FEDORA/input/checks/platform/fedora-cpe-dictionary.xml
 create mode 100755 FEDORA/input/checks/testcheck.py
 create mode 100644 FEDORA/input/checks/yum_gpgcheck_global_activation.xml

diff --git a/FEDORA/input/checks/ensure_gpgcheck_never_disabled.xml b/FEDORA/input/checks/ensure_gpgcheck_never_disabled.xml
new file mode 100644
index 0000000..8c21e83
--- /dev/null
+++ b/FEDORA/input/checks/ensure_gpgcheck_never_disabled.xml
@@ -0,0 +1,28 @@
+<def-group>
+  <definition class="compliance" id="ensure_gpgcheck_never_disabled"
+  version="1">
+    <metadata>
+      <title>Ensure gpgcheck Enabled For All Yum Package Repositories</title>
+      <affected family="unix">
+        <platform>Fedora 19</platform>
+      </affected>
+      <description>Ensure all yum repositories utilize signature checking.</description>
+    </metadata>
+    <criteria comment="ensure all yum repositories utilize signiature checking" operator="AND">
+      <criterion comment="verify no gpgpcheck=0 present in /etc/yum.repos.d files"
+      test_ref="test_ensure_gpgcheck_never_disabled" />
+    </criteria>
+  </definition>
+  <ind:textfilecontent54_test check="all" check_existence="none_exist"
+  comment="check for existence of gpgcheck=0 in /etc/yum.repos.d/ files"
+  id="test_ensure_gpgcheck_never_disabled" version="1">
+    <ind:object object_ref="obj_ensure_gpgcheck_never_disabled" />
+  </ind:textfilecontent54_test>
+  <ind:textfilecontent54_object id="obj_ensure_gpgcheck_never_disabled"
+  version="1">
+    <ind:path>/etc/yum.repos.d</ind:path>
+    <ind:filename operation="pattern match">.*</ind:filename>
+    <ind:pattern operation="pattern match">^\s*gpgcheck\s*=\s*0\s*$</ind:pattern>
+    <ind:instance datatype="int">1</ind:instance>
+  </ind:textfilecontent54_object>
+</def-group>
diff --git a/FEDORA/input/checks/installed_OS_is_fedora19.xml b/FEDORA/input/checks/installed_OS_is_fedora19.xml
new file mode 100644
index 0000000..7e2e7ac
--- /dev/null
+++ b/FEDORA/input/checks/installed_OS_is_fedora19.xml
@@ -0,0 +1,41 @@
+<def-group>
+  <definition class="inventory"
+  id="installed_OS_is_fedora19" version="1">
+    <metadata>
+      <title>Fedora release 19 (Schrödinger's Cat)</title>
+      <affected family="unix">
+        <platform>Fedora 19</platform>
+      </affected>
+      <reference ref_id="cpe:/o:fedoraproject:fedora:19"
+      source="CPE" />
+      <description>The operating system installed on the system is
+      Fedora release 19 (Schrödinger's Cat)</description>
+    </metadata>
+    <criteria>
+      <criterion comment="Installed operating system is part of the unix family"
+      test_ref="test_unix_family" />
+      <criterion comment="Fedora release 19 is installed"
+      test_ref="test_fedora_release" />
+    </criteria>
+  </definition>
+
+  <ind:family_test check="all" check_existence="at_least_one_exists" comment="installed OS part of unix family" id="test_unix_family" version="1">
+    <ind:object object_ref="obj_unix_family" />
+    <ind:state state_ref="state_unix_family" />
+  </ind:family_test>
+  <ind:family_state id="state_unix_family" version="1">
+    <ind:family>unix</ind:family>
+  </ind:family_state>
+  <ind:family_object id="obj_unix_family" version="1" />
+
+  <linux:rpminfo_test check="all" check_existence="only_one_exists" comment="fedora-release is version 19" id="test_fedora_release" version="1">
+    <linux:object object_ref="obj_fedora_release" />
+    <linux:state state_ref="state_fedora_release" />
+  </linux:rpminfo_test>
+  <linux:rpminfo_state id="state_fedora_release" version="1">
+    <linux:version operation="pattern match">^19$</linux:version>
+  </linux:rpminfo_state>
+  <linux:rpminfo_object id="obj_fedora_release" version="1">
+    <linux:name>fedora-release</linux:name>
+  </linux:rpminfo_object>
+</def-group>
diff --git a/FEDORA/input/checks/platform/fedora-cpe-dictionary.xml b/FEDORA/input/checks/platform/fedora-cpe-dictionary.xml
new file mode 100644
index 0000000..b457e21
--- /dev/null
+++ b/FEDORA/input/checks/platform/fedora-cpe-dictionary.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cpe-list xmlns="http://cpe.mitre.org/dictionary/2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cpe.mitre.org/dictionary/2.0 http://cpe.mitre.org/files/cpe-dictionary_2.1.xsd">
+      <cpe-item name="cpe:/o:fedoraproject:fedora:19">
+            <title xml:lang="en-us">Fedora release 19 (Schrödinger's Cat)</title>
+            <!-- the check references an OVAL file that contains an inventory definition -->
+            <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="filename">installed_OS_is_fedora19</check>
+      </cpe-item>
+</cpe-list>
diff --git a/FEDORA/input/checks/testcheck.py b/FEDORA/input/checks/testcheck.py
new file mode 100755
index 0000000..72e724e
--- /dev/null
+++ b/FEDORA/input/checks/testcheck.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+
+import sys, os, tempfile, subprocess, platform
+import idtranslate
+import lxml.etree as ET
+
+header = '''<?xml version="1.0" encoding="UTF-8"?>
+<oval_definitions
+	xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5"
+    xmlns:unix="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix"
+    xmlns:ind="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent"
+    xmlns:linux="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux"
+    xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix unix-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5#independent independent-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5#linux linux-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5 oval-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-common-5 oval-common-schema.xsd">
+       <generator>
+        <oval:product_name>testcheck.py</oval:product_name>
+        <oval:product_version>0.0.1</oval:product_version>
+        <oval:schema_version>5.10</oval:schema_version>
+        <oval:timestamp>2011-09-23T13:44:00</oval:timestamp>
+    </generator>'''
+footer = '</oval_definitions>'
+
+ovalns = "{http://oval.mitre.org/XMLSchema/oval-definitions-5}"
+
+# globals, to make recursion easier in case we encounter extend_definition
+definitions = ET.Element("definitions")
+tests = ET.Element("tests")
+objects = ET.Element("objects")
+states = ET.Element("states")
+variables = ET.Element("variables")
+
+# add oval elements to the global Elements defined above
+def add_oval_elements(body):
+    tree = ET.fromstring(header + body + footer)
+    tree = replace_external_vars(tree)
+    # parse new file(string) as an etree, so we can arrange elements appropriately 
+    for childnode in tree.findall("./" + ovalns + "def-group/*"):
+        # print "childnode.tag is " + childnode.tag
+        if childnode.tag is ET.Comment: continue 
+        if childnode.tag == ( ovalns + "definition"):
+            definitions.append(childnode)
+            defname = childnode.get("id")
+            # extend_definition is a special case: must include a whole other definition
+            for defchild in childnode.findall(".//" + ovalns + "extend_definition"):
+                defid = defchild.get("definition_ref")            
+                includedbody = read_ovaldefgroup_file(defid+".xml")
+                # recursively add the elements in the other file
+                add_oval_elements(includedbody)
+        if childnode.tag.endswith("_test"): tests.append(childnode)
+        if childnode.tag.endswith("_object"): objects.append(childnode)
+        if childnode.tag.endswith("_state"): states.append(childnode)
+        if childnode.tag.endswith("_variable"): variables.append(childnode)
+    return defname
+
+# replace external_variables with local_variables, so the definition can be tested
+# independently of an XCCDF file
+def replace_external_vars(tree):
+    # external_variable is a special case: we turn it into a local_variable so we can test
+    for node in tree.findall(".//"+ovalns+"external_variable"):
+        print "external_variable with id : " + node.get("id") 
+        extvar_id = node.get("id")
+        #for envkey, envval in os.environ.iteritems():
+        #    print envkey + " = " + envval
+        #sys.exit()
+        if extvar_id not in os.environ.keys():
+            sys.exit("external_variable specified, but no value provided via environment variable")
+        node.tag = ovalns + "local_variable"    # replace tag name: external -> local
+        literal = ET.Element("literal_component")
+        literal.text = os.environ[extvar_id]
+        node.append(literal)
+        # TODO: assignment of external_variable via environment vars, for testing
+    return tree
+
+
+def read_ovaldefgroup_file(testfile):
+    with open( testfile, 'r') as f:
+        body = f.read()
+    return body
+
+def main():
+    global definitions
+    global tests
+    global objects
+    global states
+    global variables
+
+    if len(sys.argv) < 2:
+        print "Provide the name of an XML file, which contains the definition to test."
+        sys.exit(1)
+
+    for testfile in sys.argv[1:]:
+        body = read_ovaldefgroup_file(testfile)
+        defname = add_oval_elements(body)
+        ovaltree = ET.fromstring(header + footer)
+        # append each major element type, if it has subelements
+        for element in [definitions, tests, objects, states, variables]:
+            if element.getchildren():
+                ovaltree.append(element)
+        # re-map all the element ids from meaningful names to meaningless numbers
+        testtranslator = idtranslate.idtranslator("testids.ini", "scap-security-guide.testing")
+        ovaltree = testtranslator.translate(ovaltree)
+        (ovalfile, fname) = tempfile.mkstemp(prefix=defname,suffix=".xml")
+        os.write(ovalfile, ET.tostring(ovaltree))
+        os.close(ovalfile)
+        print "Evaluating with OVAL tempfile : " + fname
+        print "Writing results to : " + fname + "-results"
+        subprocess.call("oscap oval eval --results "+ fname + "-results " + fname, shell=True)
+        # perhaps delete tempfile?
+        definitions = ET.Element("definitions")
+        tests = ET.Element("tests")
+        objects = ET.Element("objects")
+        states = ET.Element("states")
+        variables = ET.Element("variables")
+
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
+
diff --git a/FEDORA/input/checks/yum_gpgcheck_global_activation.xml b/FEDORA/input/checks/yum_gpgcheck_global_activation.xml
new file mode 100644
index 0000000..a313351
--- /dev/null
+++ b/FEDORA/input/checks/yum_gpgcheck_global_activation.xml
@@ -0,0 +1,24 @@
+<def-group>
+  <definition class="compliance" id="yum_gpgcheck_global_activation" version="1">
+    <metadata>
+      <title>Ensure Yum gpgcheck Globally Activated</title>
+      <affected family="unix">
+        <platform>Fedora 19</platform>
+      </affected>
+      <description>The gpgcheck option should be used to ensure that checking
+      of an RPM package's signature always occurs prior to its
+      installation.</description>
+    </metadata>
+    <criteria>
+      <criterion comment="check value of gpgcheck in /etc/yum.conf" test_ref="test_yum_gpgcheck_global_activation" />
+    </criteria>
+  </definition>
+  <ind:textfilecontent54_test check="all" check_existence="all_exist" comment="check value of gpgcheck in /etc/yum.conf" id="test_yum_gpgcheck_global_activation" version="1">
+    <ind:object object_ref="object_yum_gpgcheck_global_activation" />
+  </ind:textfilecontent54_test>
+  <ind:textfilecontent54_object id="object_yum_gpgcheck_global_activation" comment="gpgcheck set in /etc/yum.conf" version="1">
+    <ind:filepath>/etc/yum.conf</ind:filepath>
+    <ind:pattern operation="pattern match">^\s*gpgcheck\s*=\s*1\s*$</ind:pattern>
+    <ind:instance datatype="int" operation="equals">1</ind:instance>
+  </ind:textfilecontent54_object>
+</def-group>
-- 
1.7.11.7

