1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
import os
import logging
from . import utils, products
from .rules import get_rule_dir_ovals, find_rule_dirs_in_paths
from .oval_object_model import OVALDocument
from .build_yaml import Rule, DocumentationNotComplete
from .jinja import process_file_with_macros
from .id_translate import IDTranslator
from .xml import ElementTree
def expand_shorthand(shorthand_path, oval_path, env_yaml):
oval_document = OVALDocument()
oval_document.ssg_version = env_yaml.get("ssg_version", "Unknown ssg_version")
oval_document.product_name = "test"
oval_document.schema_version = env_yaml.get("target_oval_version_str", "5.11")
shorthand_file_content = process_file_with_macros(shorthand_path, env_yaml)
oval_document.load_shorthand(shorthand_file_content)
root = oval_document.get_xml_element()
id_translator = IDTranslator("test")
root_translated = id_translator.translate(root)
ElementTree.ElementTree(root_translated).write(oval_path)
class OVALBuildException(Exception):
pass
class OVALBuilder:
def __init__(
self,
env_yaml,
product_yaml_path,
shared_directories,
build_ovals_dir,
):
self.env_yaml = env_yaml
self.product_yaml = products.Product(product_yaml_path)
self.product = utils.required_key(env_yaml, "product")
self.shared_directories = shared_directories
self.build_ovals_dir = build_ovals_dir
self.oval_document = OVALDocument()
self.oval_document.ssg_version = env_yaml.get(
"ssg_version", "Unknown ssg_version"
)
self.oval_document.schema_version = utils.required_key(
env_yaml, "target_oval_version_str"
)
self.already_processed = []
@property
def product_name(self):
return self.oval_document.product_name
@product_name.setter
def product_name(self, __value):
self.oval_document.product_name = __value
def get_oval_document_from_shorthands(self, include_benchmark):
if self.build_ovals_dir:
utils.mkdir_p(self.build_ovals_dir)
if include_benchmark:
self._load_checks_from_benchmark()
self._load_checks_from_shared_directories()
return self.oval_document
def _get_dirs_rules_from_benchmark(self):
product_dir = self.product_yaml["product_dir"]
relative_guide_dir = utils.required_key(self.env_yaml, "benchmark_root")
guide_dir = os.path.abspath(os.path.join(product_dir, relative_guide_dir))
additional_content_directories = self.env_yaml.get(
"additional_content_directories", []
)
dirs_to_scan = [guide_dir]
for rd in additional_content_directories:
abspath = os.path.abspath(os.path.join(product_dir, rd))
dirs_to_scan.append(abspath)
return list(find_rule_dirs_in_paths(dirs_to_scan))
def _load_checks_from_benchmark(self):
rule_dirs = self._get_dirs_rules_from_benchmark()
self._process_directories(rule_dirs, True)
def _load_checks_from_shared_directories(self):
# earlier directory has higher priority
reversed_dirs = self.shared_directories[::-1]
self._process_directories(reversed_dirs, False)
def _process_directories(self, directories, from_benchmark):
for directory in directories:
if not os.path.exists(directory):
continue
self._process_directory(directory, from_benchmark)
def _process_directory(self, directory, from_benchmark):
try:
context = self._get_context(directory, from_benchmark)
except DocumentationNotComplete:
return
for file_path in self._get_list_of_oval_files(directory, from_benchmark):
self._process_oval_file(file_path, from_benchmark, context)
def _get_context(self, directory, from_benchmark):
if from_benchmark:
rule_path = os.path.join(directory, "rule.yml")
rule = Rule.from_yaml(rule_path, self.env_yaml)
local_env_yaml = dict(**self.env_yaml)
local_env_yaml["rule_id"] = rule.id_
local_env_yaml["rule_title"] = rule.title
local_env_yaml["products"] = {self.product}
return local_env_yaml
return self.env_yaml
def _get_list_of_oval_files(self, directory, from_benchmark):
if from_benchmark:
return get_rule_dir_ovals(directory, self.product)
return sorted([os.path.join(directory, x) for x in os.listdir(directory)])
def _create_key(self, file_path, from_benchmark):
if from_benchmark:
rule_id = self._get_rule_id(file_path)
oval_key = "%s.xml" % rule_id
else:
oval_key = os.path.basename(file_path)
return oval_key
def _get_rule_id(self, file_path):
return os.path.basename(os.path.dirname(os.path.dirname(file_path)))
def _process_oval_file(self, file_path, from_benchmark, context):
oval_key = self._create_key(file_path, from_benchmark)
if oval_key in self.already_processed:
return
xml_content = self._read_oval_file(file_path, context, from_benchmark)
rule_id = None
if from_benchmark:
rule_id = self._get_rule_id(file_path)
self._store_intermediate_file(rule_id, xml_content)
if self.oval_document.load_shorthand(xml_content, self.product, rule_id):
self.already_processed.append(oval_key)
def _read_oval_file(self, file_path, context, from_benchmark):
if not file_path.endswith(".xml"):
logging.critical("File name '{}' doesn't end with '.xml'.".format(file_path))
if from_benchmark or "checks_from_templates" not in file_path:
return process_file_with_macros(file_path, context)
with open(file_path, "r") as f:
return f.read()
def _store_intermediate_file(self, rule_id, xml_content):
if not self.build_ovals_dir:
return
output_file_name = rule_id + ".xml"
output_filepath = os.path.join(self.build_ovals_dir, output_file_name)
with open(output_filepath, "w") as f:
f.write(xml_content)
|