Source code for ssg.oval

from __future__ import absolute_import
from __future__ import print_function

import sys
import os

from .constants import oval_footer as footer
from .constants import oval_namespace as ovalns
from .xml import ElementTree as ET
from .xml import oval_generated_header

from .jinja import process_file_with_macros
from .products import _get_implied_properties


ASSUMED_OVAL_VERSION_STRING = "5.11"
# globals, to make recursion easier in case we encounter extend_definition
try:
    ET.register_namespace("oval", ovalns)
except AttributeError:
    # Legacy Python 2.6 fix, see e.g.
    # https://www.programcreek.com/python/example/57552/xml.etree.ElementTree._namespace_map
    from xml.etree import ElementTree as ET
    ET._namespace_map[ovalns] = "oval"


[docs] def applicable_platforms(oval_file, oval_version_string=None): """ Returns the applicable platforms for a given oval file """ platforms = [] if not oval_version_string: oval_version_string = ASSUMED_OVAL_VERSION_STRING header = oval_generated_header("applicable_platforms", oval_version_string, "0.0.1") oval_version_list = [int(num) for num in oval_version_string.split(".")] subst_dict = dict(target_oval_version=oval_version_list) oval_filename_components = oval_file.split(os.path.sep) if len(oval_filename_components) > 3: subst_dict["rule_id"] = oval_filename_components[-3] else: msg = "Unable to get rule ID from OVAL path '{path}'".format(path=oval_file) print(msg, file=sys.stderr) subst_dict = _get_implied_properties(subst_dict) subst_dict['target_oval_version'] = [999, 999.999] body = process_file_with_macros(oval_file, subst_dict) try: oval_tree = ET.fromstring(header + body + footer) except Exception as e: msg = "Error while loading " + oval_file print(msg, file=sys.stderr) raise e element_path = "./{%s}def-group/{%s}definition/{%s}metadata/{%s}affected/{%s}platform" element_ns_path = element_path % (ovalns, ovalns, ovalns, ovalns, ovalns) for node in oval_tree.findall(element_ns_path): platforms.append(node.text) return platforms
[docs] def parse_affected(oval_contents): """ Returns the tuple (start_affected, end_affected, platform_indents) for the passed oval file contents. start_affected is the line number of starting tag of the <affected> element, end_affected is the line number of the closing tag of the </affected> element, and platform_indents is a string containing the indenting characters before the contents of the <affected> element. """ start_affected = list(filter(lambda x: "<affected" in oval_contents[x], range(0, len(oval_contents)))) if len(start_affected) != 1: raise ValueError("OVAL file does not contain a single <affected> " "element; counted %d in:\n%s\n\n" % (len(start_affected), "\n".join(oval_contents))) start_affected = start_affected[0] end_affected = list(filter(lambda x: "</affected" in oval_contents[x], range(0, len(oval_contents)))) if len(end_affected) != 1: raise ValueError("Malformed OVAL file does not contain a single " "closing </affected>; counted %d in:\n%s\n\n" % (len(start_affected), "\n".join(oval_contents))) end_affected = end_affected[0] if start_affected >= end_affected: raise ValueError("Malformed OVAL file: start affected tag begins " "on the same line or after ending affected tag: " "start:%d vs end:%d:\n%s\n\n" % (start_affected, end_affected, oval_contents)) # Validate that start_affected contains only a starting <affected> tag; # otherwise, using this information to update the <platform> subelements # would fail. start_line = oval_contents[start_affected] start_line = start_line.strip() if not start_line.startswith('<affected'): raise ValueError("Malformed OVAL file: line with starting affected " "tag contains other elements: line:%s\n%s\n\n" % (start_line, oval_contents)) if '<' in start_line[1:]: raise ValueError("Malformed OVAL file: line with starting affected " "tag contains other elements: line:%s\n%s\n\n" % (start_line, oval_contents)) # Validate that end_affected contains only an ending </affected> tag; # otherwise, using this information to update the <platform> subelements # would fail. end_line = oval_contents[end_affected] end_line = end_line.strip() if not end_line.startswith('</affected>'): raise ValueError("Malformed OVAL file: line with ending affected " "tag contains other elements: line:%s\n%s\n\n" % (end_line, oval_contents)) if '<' in end_line[1:]: raise ValueError("Malformed OVAL file: line with ending affected " "tag contains other elements: line:%s\n%s\n\n" % (end_line, oval_contents)) indents = "" if start_affected+1 == end_affected: # Since the affected element is present but empty, the indents should # be two more spaces than that of the starting <affected> element. start_index = oval_contents[start_affected].index('<') indents = oval_contents[start_affected][0:start_index] indents += " " else: # Otherwise, grab the indents off the next line unmodified, as this is # likely a platform element tag. We don't validate here that this is # indeed the case, as other parts of the build infrastructure will # validate this for us. start_index = oval_contents[start_affected+1].index('<') indents = oval_contents[start_affected+1][0:start_index] return start_affected, end_affected, indents