Signed-off-by: Jeffrey Blank <blank(a)eclipse.ncsc.mil>
---
RHEL6/transforms/constants.xslt | 4 +-
RHEL6/transforms/cpe_generate.py | 4 +-
RHEL6/transforms/idtranslate.py | 206 +++++++++++++++++++++++---------------
RHEL6/transforms/relabelids.py | 151 ++++++++++++++++------------
4 files changed, 217 insertions(+), 148 deletions(-)
diff --git a/RHEL6/transforms/constants.xslt b/RHEL6/transforms/constants.xslt
index 3159cc9..7289561 100644
--- a/RHEL6/transforms/constants.xslt
+++ b/RHEL6/transforms/constants.xslt
@@ -13,6 +13,8 @@
<xsl:variable
name="disa-cciuri">http://iase.disa.mil/cci/index.html</x...
<xsl:variable
name="ovaluri">http://oval.mitre.org/XMLSchema/oval-definiti...
-<xsl:variable
name="ociluri">http://www.mitre.org/ocil/2</xsl:variable>
+
<xsl:variable
name="ociltransitional">ocil-transitional</xsl:variable>
+<xsl:variable
name="ocil_cs">http://scap.nist.gov/schema/ocil/2</xsl:va...
+<xsl:variable
name="ocil_ns">http://scap.nist.gov/schema/ocil/2.0</xsl:...
</xsl:stylesheet>
diff --git a/RHEL6/transforms/cpe_generate.py b/RHEL6/transforms/cpe_generate.py
index a42cc3b..dcc1448 100755
--- a/RHEL6/transforms/cpe_generate.py
+++ b/RHEL6/transforms/cpe_generate.py
@@ -88,7 +88,7 @@ def main():
ovaltree.remove(variables)
# turn IDs into meaningless numbers
- translator = idtranslate.idtranslator("./output/"+idname+".ini",
"oval:"+idname)
+ translator = idtranslate.idtranslator("./output/"+idname+".ini",
idname)
ovaltree = translator.translate(ovaltree)
newovalfile = ovalfile.replace("oval", "cpe-oval-"+idname)
@@ -99,7 +99,7 @@ def main():
newcpedictfile =
os.path.basename(cpedictfile).replace(".xml","-"+idname+".xml")
for check in cpedicttree.findall(".//{%s}check" % cpe_ns):
check.set("href",os.path.basename(newovalfile))
- check.text = translator.assign_id("definition", check.text)
+ check.text = translator.assign_id("{" + oval_ns + "}definition",
check.text)
ET.ElementTree(cpedicttree).write("./output/"+newcpedictfile)
sys.exit(0)
diff --git a/RHEL6/transforms/idtranslate.py b/RHEL6/transforms/idtranslate.py
index 638011c..77f078a 100755
--- a/RHEL6/transforms/idtranslate.py
+++ b/RHEL6/transforms/idtranslate.py
@@ -1,94 +1,138 @@
-import ConfigParser
+import ConfigParser, sys
import lxml.etree as ET
-# This class is designed to handle the mapping of human-readable names to
-# OVAL-style IDs. This is intentionally similar to code in
-# Tresys SCC, to enable future integration.
+# This class is designed to handle the mapping of meaningful, human-readable
+# names to IDs in the formats required by the SCAP checking systems, such as
+# OVAL and OCIL.
-ovalns = "{http://oval.mitre.org/XMLSchema/oval-definitions-5}"
+oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+oval_cs = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
-keyword_to_abbrev = {
- 'definition' : 'def',
- 'criteria' : 'crit',
- 'test' : 'tst',
- 'object' : 'obj',
- 'state' : 'ste',
- 'variable' : 'var',
+ocil_ns = "http://scap.nist.gov/schema/ocil/2.0"
+ocil_cs = "http://scap.nist.gov/schema/ocil/2"
+
+ovaltag_to_abbrev = {
+ 'definition' : 'def',
+ 'criteria' : 'crit',
+ 'test' : 'tst',
+ 'object' : 'obj',
+ 'state' : 'ste',
+ 'variable' : 'var',
+}
+
+ociltag_to_abbrev = {
+ 'questionnaire' : 'questionnaire',
+ 'action' : 'testaction',
+ 'question' : 'question',
+ 'artifact' : 'artifact',
+ 'variable' : 'variable',
+}
+
+ovalrefattr_to_tag = {
+ "definition_ref" : "definition",
+ "test_ref" : "test",
+ "object_ref" : "object",
+ "state_ref" : "state",
+ "var_ref" : "variable",
+}
+
+ocilrefattr_to_tag = {
+ "question_ref" : "question",
}
-refattr_to_keyword = {
- "definition_ref" : "definition",
- "test_ref" : "test",
- "object_ref" : "object",
- "state_ref" : "state",
- "var_ref" : "variable",
+ocilrefchild_to_tag = {
+ "test_action_ref" : "action",
}
+def split_namespace(tag):
+ # returns a tuple of (namespace,name) removing any fragment id from namespace
+ if tag[:1] == "{":
+ namespace, name = tag[1:].split("}", 1)
+ return namespace.split("#")[0], name
+ else:
+ return (None,tag)
+
+def namespace_to_prefix(tag):
+ namespace, name = split_namespace(tag)
+ if namespace == ocil_ns:
+ return "ocil"
+ if namespace == oval_ns:
+ return "oval"
+ sys.exit("Error: unknown checksystem referenced in tag : %s" % tag)
+
def tagname_to_abbrev(tag):
- tag = tag.split("}")[-1]
- if tag == "extend_definition":
- return tag
- tag = tag.rsplit("_", 1)[-1]
- return keyword_to_abbrev[tag]
+ namespace, tag = split_namespace(tag)
+ if tag == "extend_definition":
+ return tag
+ # grab the last part of the tag name to determine its type
+ tag = tag.rsplit("_", 1)[-1]
+ if namespace == ocil_ns:
+ return ociltag_to_abbrev[tag]
+ if namespace == oval_ns:
+ return ovaltag_to_abbrev[tag]
+ sys.exit("Error: unknown checksystem referenced in tag : %s" % tag)
class idtranslator:
- def __init__(self, fname, prefix):
- self.fname = fname
- self.prefix = prefix
- self.config = ConfigParser.ConfigParser()
- f = self.config.read(fname)
- if len(f) == 0:
- self.__setup()
-
- def __get_next_id(self):
- i = self.config.getint("general", "next_id")
- n = "%d" % (i + 1)
- self.config.set("general", "next_id", n)
- return i
-
- def save(self):
- fd = open(self.fname, "wb")
- self.config.write(fd)
-
- def __setup(self):
- self.config.add_section("general")
- self.config.set("general", "id_prefix", self.prefix)
- self.config.set("general", "next_id", "100")
- self.config.add_section("assigned")
-
- def assign_id(self, tagname, name):
- i = None
- try:
- i = self.config.getint("assigned", name)
- except:
- i = self.__get_next_id()
- self.config.set("assigned", name, str(i))
-
- pre = self.config.get("general", "id_prefix")
- str_id = "%s:%s:%d" % (pre, tagname_to_abbrev(tagname), i)
- return str_id
-
- def translate(self, tree, store_defname=False, refsource=""):
- for element in tree.getiterator():
- idname = element.get("id")
- if idname:
- # store the old name if requested (for OVAL definitions)
- if store_defname and element.tag == ovalns + "definition":
- metadata = element.find(ovalns + "metadata")
- if metadata is None:
- metadata = ET.SubElement(element, "metadata")
- defnam = ET.SubElement(metadata, "reference",
ref_id=idname, source=refsource)
- # set the element to the new identifier
- element.set("id", self.assign_id(element.tag, idname))
- continue
- if element.tag == ovalns + "filter":
- element.text = self.assign_id("state", element.text)
- continue
- for attr in element.keys():
- if attr in refattr_to_keyword.keys():
- element.set(attr, self.assign_id(refattr_to_keyword[attr],
element.get(attr)))
- self.save()
- # note: the ini file is not tracked by git, see .gitignore
- return tree
+ def __init__(self, fname, content_id):
+ self.fname = fname
+ self.content_id = content_id
+ self.config = ConfigParser.ConfigParser()
+ f = self.config.read(fname)
+ if len(f) == 0:
+ self.__setup()
+
+ def __get_next_id(self):
+ i = self.config.getint("general", "next_id")
+ n = "%d" % (i + 1)
+ self.config.set("general", "next_id", n)
+ return i
+
+ def save(self):
+ fd = open(self.fname, "wb")
+ self.config.write(fd)
+
+ def __setup(self):
+ self.config.add_section("general")
+ self.config.set("general", "next_id", "100")
+ self.config.add_section("assigned")
+
+ def assign_id(self, tagname, name):
+ i = None
+ try:
+ i = self.config.getint("assigned", name)
+ except:
+ i = self.__get_next_id()
+ self.config.set("assigned", name, str(i))
+
+ str_id = "%s:%s:%s:%d" % (namespace_to_prefix(tagname), self.content_id,
tagname_to_abbrev(tagname), i)
+ return str_id
+
+ def translate(self, tree, store_defname=False):
+ for element in tree.getiterator():
+ idname = element.get("id")
+ if idname:
+ # store the old name if requested (for OVAL definitions)
+ if store_defname and element.tag == "{" + oval_ns +
"}definition":
+ metadata = element.find("{" + oval_ns + "}metadata")
+ if metadata is None:
+ metadata = ET.SubElement(element, "metadata")
+ defnam = ET.SubElement(metadata, "reference", ref_id=idname,
source=self.content_id)
+ # set the element to the new identifier
+ element.set("id", self.assign_id(element.tag, idname))
+ #continue
+ if element.tag == "{" + oval_ns + "}filter":
+ element.text = self.assign_id("{" + oval_ns + "}state",
element.text)
+ continue
+ for attr in element.keys():
+ if attr in ovalrefattr_to_tag.keys():
+ element.set(attr,self.assign_id( "{" + oval_ns + "}" +
ovalrefattr_to_tag[attr], element.get(attr)))
+ if attr in ocilrefattr_to_tag.keys():
+ element.set(attr, self.assign_id("{" + ocil_ns + "}" +
ocilrefattr_to_tag[attr], element.get(attr)))
+ if element.tag == "{" + ocil_ns + "}test_action_ref":
+ element.text = self.assign_id("{" + ocil_ns + "}action",
element.text)
+
+ self.save()
+ # note: the ini file is not tracked by git, see .gitignore
+ return tree
diff --git a/RHEL6/transforms/relabelids.py b/RHEL6/transforms/relabelids.py
index 966696c..7068437 100755
--- a/RHEL6/transforms/relabelids.py
+++ b/RHEL6/transforms/relabelids.py
@@ -5,81 +5,104 @@ import idtranslate
import lxml.etree as ET
# This script requires two arguments: an XCCDF file and an ID name scheme.
-# This script is designed to convert and synchronize all IDs referenced from the XCCDF
document.
-# These references would typically be inside OVAL documents, but we also looking to
OCIL.
-# The IDs are to be converted from strings to meaningless numbers.
+# This script is designed to convert and synchronize check IDs referenced from
+# the XCCDF document for the supported checksystems, which are currently OVAL
+# and OCIL. The IDs are to be converted from strings to meaningless numbers.
oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+oval_cs = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+
+ocil_ns = "http://scap.nist.gov/schema/ocil/2.0"
+ocil_cs = "http://scap.nist.gov/schema/ocil/2"
+
xccdf_ns = "http://checklists.nist.gov/xccdf/1.1"
def parse_xml_file(xmlfile):
- with open( xmlfile, 'r') as f:
- filestring = f.read()
- tree = ET.fromstring(filestring)
- #print filestring
- return tree
+ with open( xmlfile, 'r') as f:
+ filestring = f.read()
+ tree = ET.fromstring(filestring)
+ #print filestring
+ return tree
-def get_ovalfiles(checks):
- # iterate over all checks, grab the OVAL files referenced within
- ovalfiles = set()
- for check in checks:
- if check.get("system") == oval_ns:
- checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns)
- ovalfiles.add(checkcontentref.get("href"))
-# else:
-# print "Non-OVAL checking system found: " +
check.get("system")
- return ovalfiles
+def get_checkfiles(checks, checksystem):
+ # iterate over all checks, grab the OVAL files referenced within
+ checkfiles = set()
+ for check in checks:
+ if check.get("system") == checksystem:
+ checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns)
+ checkfiles.add(checkcontentref.get("href"))
+ return checkfiles
def main():
- if len(sys.argv) < 3:
- print "Provide an XCCDF file and an ID name scheme."
- print "This script finds check-content files (currently, OVAL) referenced
from XCCDF and synchronizes all IDs."
- sys.exit(1)
-
- xccdffile = sys.argv[1]
- idname = sys.argv[2]
-
- os.chdir("./output")
- # step over xccdf file, and find referenced oval files
- xccdftree = parse_xml_file(xccdffile)
-
- checks = xccdftree.findall(".//{%s}check" % xccdf_ns)
- ovalfiles = get_ovalfiles(checks)
-
- if len(ovalfiles) > 1:
- sys.exit("referencing more than one OVAL file is not yet supported by this
script.")
- ovalfile = ovalfiles.pop()
-
- # rename all IDs in the oval file
- ovaltree = parse_xml_file(ovalfile)
- translator = idtranslate.idtranslator(idname+".ini",
"oval:"+idname)
- ovaltree = translator.translate(ovaltree, store_defname=True,
refsource="scap-security-guide")
-
- newovalfile = ovalfile.replace(".xml", "-" + idname +
".xml")
- ET.ElementTree(ovaltree).write(newovalfile)
-
- # rename all IDs and file refs in the xccdf file
- for check in checks:
- checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns)
- if checkcontentref is None:
- continue
- checkid = translator.assign_id("definition",
checkcontentref.get("name"))
- checkcontentref.set("name", checkid)
- checkcontentref.set("href", newovalfile)
-
- checkexport = check.find("./{%s}check-export" % xccdf_ns)
- if checkexport is not None:
- newexportname = translator.assign_id("variable",
checkexport.get("export-name"))
- checkexport.set("export-name", newexportname)
-
- newxccdffile = xccdffile.replace(".xml", "-" + idname +
".xml")
- #ET.dump(xccdftree)
- ET.ElementTree(xccdftree).write(newxccdffile)
- sys.exit(0)
+ if len(sys.argv) < 3:
+ print "Provide an XCCDF file and an ID name scheme."
+ print "This script finds check-content files (currently, OVAL and OCIL) referenced
from XCCDF and synchronizes all IDs."
+ sys.exit(1)
+
+ xccdffile = sys.argv[1]
+ idname = sys.argv[2]
+
+ os.chdir("./output")
+ # step over xccdf file, and find referenced check files
+ xccdftree = parse_xml_file(xccdffile)
+
+ checks = xccdftree.findall(".//{%s}check" % xccdf_ns)
+ ovalfiles = get_checkfiles(checks, oval_cs)
+ ocilfiles = get_checkfiles(checks, ocil_cs)
+
+ if len(ovalfiles) > 1 or len(ocilfiles) > 1:
+ sys.exit("referencing more than one file per check system is not yet supported by
this script.")
+ ovalfile = ovalfiles.pop() if ovalfiles else None
+ ocilfile = ocilfiles.pop() if ocilfiles else None
+
+ translator = idtranslate.idtranslator(idname+".ini", idname)
+
+ # rename all IDs in the oval file
+ if ovalfile:
+ ovaltree = parse_xml_file(ovalfile)
+ ovaltree = translator.translate(ovaltree, store_defname=True)
+ newovalfile = ovalfile.replace(".xml", "-" + idname +
".xml")
+ ET.ElementTree(ovaltree).write(newovalfile)
+
+ # rename all IDs in the ocil file
+ if ocilfile:
+ ociltree = parse_xml_file(ocilfile)
+ ociltree = translator.translate(ociltree)
+ newocilfile = ocilfile.replace(".xml", "-" + idname +
".xml")
+ ET.ElementTree(ociltree).write(newocilfile)
+
+ # rename all IDs and file refs in the xccdf file
+ for check in checks:
+ checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns)
+ if checkcontentref is None:
+ continue
+
+ if check.get("system") == oval_cs:
+ checkid = translator.assign_id("{" + oval_ns + "}definition",
checkcontentref.get("name"))
+ checkcontentref.set("name", checkid)
+ checkcontentref.set("href", newovalfile)
+ checkexport = check.find("./{%s}check-export" % xccdf_ns)
+ if checkexport is not None:
+ newexportname = translator.assign_id("{"+ oval_ns + "}variable",
checkexport.get("export-name"))
+ checkexport.set("export-name", newexportname)
+
+ if check.get("system") == ocil_cs:
+ checkid = translator.assign_id("{" + ocil_ns + "}questionnaire",
checkcontentref.get("name"))
+ checkcontentref.set("name", checkid)
+ checkcontentref.set("href", newocilfile)
+ checkexport = check.find("./{%s}check-export" % xccdf_ns)
+ if checkexport is not None:
+ newexportname = translator.assign_id("{"+ oval_ns + "}variable",
checkexport.get("export-name"))
+ checkexport.set("export-name", newexportname)
+
+ newxccdffile = xccdffile.replace(".xml", "-" + idname +
".xml")
+ #ET.dump(xccdftree)
+ ET.ElementTree(xccdftree).write(newxccdffile)
+ sys.exit(0)
if __name__ == "__main__":
- main()
+ main()
--
1.7.1