Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration of the OVAL object model into the combine_ovals.py script #11236

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 68 additions & 65 deletions build-scripts/combine_ovals.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,105 +2,108 @@

import argparse
import sys
import logging
import os

import ssg.build_ovals
import ssg.constants
import ssg.utils
import ssg.xml
import ssg.environment
from ssg.oval_object_model import (
ExceptionDuplicateObjectReferenceInTest,
ExceptionDuplicateOVALEntity,
ExceptionEmptyNote,
ExceptionMissingObjectReferenceInTest,
)

MASSAGE_FORMAT = "%(levelname)s: %(message)s"
EXPECTED_ERRORS = (
ExceptionDuplicateObjectReferenceInTest,
ExceptionDuplicateOVALEntity,
ExceptionEmptyNote,
ExceptionMissingObjectReferenceInTest,
ValueError,
)


def parse_args():
p = argparse.ArgumentParser()
p.add_argument(
"--build-config-yaml", required=True, dest="build_config_yaml",
"--build-config-yaml",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the style updates surely make the code better, they also make the diff larger and therefore the PR becomes harder review. The reviewers when they see the diff they need to evaluate if the change is a code style change or actual behavior change. Next time, please don't do style updates unless necessary or requested by Code Climate. The best commits are small commits that do only necessary things.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I've moved these changes to at least a separate commit.

required=True,
dest="build_config_yaml",
help="YAML file with information about the build configuration. "
"e.g.: ~/scap-security-guide/build/build_config.yml"
"e.g.: ~/scap-security-guide/build/build_config.yml",
)
p.add_argument(
"--product-yaml", required=True, dest="product_yaml",
"--product-yaml",
required=True,
dest="product_yaml",
help="YAML file with information about the product we are building. "
"e.g.: ~/scap-security-guide/rhel7/product.yml"
"e.g.: ~/scap-security-guide/rhel7/product.yml",
)
p.add_argument(
"--build-ovals-dir", required=True, dest="build_ovals_dir",
help="Directory to store intermediate built OVAL files."
"--build-ovals-dir",
required=True,
dest="build_ovals_dir",
help="Directory to store intermediate built OVAL files.",
)
p.add_argument("--output", type=argparse.FileType("wb"), required=True)
p.add_argument(
"--include-benchmark", action="store_true",
"--include-benchmark",
action="store_true",
help="Include OVAL checks from rule directories in the benchmark "
"directory tree which is specified by product.yml "
"in the `benchmark_root` key.")
"in the `benchmark_root` key.",
)
p.add_argument(
"ovaldirs", metavar="OVAL_DIR", nargs="+",
"ovaldirs",
metavar="OVAL_DIR",
nargs="+",
help="Shared directory(ies) from which we will collect OVAL "
"definitions to combine. Order matters, latter directories override "
"former. If --include-benchmark is provided, these will be "
"overwritten by OVALs in the rule directory (which in turn preference "
"oval/{{{ product }}}.xml over oval/shared.xml for a given rule.")
"oval/{{{ product }}}.xml over oval/shared.xml for a given rule.",
)
p.add_argument(
"--log",
action="store",
default="WARNING",
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
help="write debug information to the log up to the LOG_LEVEL.",
)

return p.parse_args()


def setup_logging(log_level_str):
numeric_level = getattr(logging, log_level_str.upper(), None)
if not isinstance(numeric_level, int):
raise ValueError("Invalid log level: {}".format(log_level_str))
logging.basicConfig(format=MASSAGE_FORMAT, level=numeric_level)


def main():
args = parse_args()
setup_logging(args.log)

oval_ns = ssg.constants.oval_namespace
footer = ssg.constants.oval_footer
env_yaml = ssg.environment.open_environment(
args.build_config_yaml, args.product_yaml)

header = ssg.xml.oval_generated_header(
"combine_ovals.py",
ssg.utils.required_key(env_yaml, "target_oval_version_str"),
ssg.utils.required_key(env_yaml, "ssg_version"))
args.build_config_yaml, args.product_yaml
)

oval_builder = ssg.build_ovals.OVALBuilder(
env_yaml,
args.product_yaml,
args.ovaldirs,
args.build_ovals_dir)
body = oval_builder.build_shorthand(args.include_benchmark)

# parse new file(string) as an ssg.xml.ElementTree, so we can reorder elements
# appropriately
corrected_tree = ssg.xml.ElementTree.fromstring(
("%s%s%s" % (header, body, footer)).encode("utf-8"))
tree = ssg.build_ovals.finalize_affected_platforms(corrected_tree, env_yaml)
definitions = ssg.xml.ElementTree.Element("{%s}definitions" % oval_ns)
tests = ssg.xml.ElementTree.Element("{%s}tests" % oval_ns)
objects = ssg.xml.ElementTree.Element("{%s}objects" % oval_ns)
states = ssg.xml.ElementTree.Element("{%s}states" % oval_ns)
variables = ssg.xml.ElementTree.Element("{%s}variables" % oval_ns)

for childnode in tree.findall("./{%s}def-group/*" % oval_ns):
if childnode.tag is ssg.xml.ElementTree.Comment:
continue
elif childnode.tag.endswith("definition"):
ssg.build_ovals.append(definitions, childnode)
elif childnode.tag.endswith("_test"):
ssg.build_ovals.append(tests, childnode)
elif childnode.tag.endswith("_object"):
ssg.build_ovals.append(objects, childnode)
elif childnode.tag.endswith("_state"):
ssg.build_ovals.append(states, childnode)
elif childnode.tag.endswith("_variable"):
ssg.build_ovals.append(variables, childnode)
else:
sys.stderr.write("Warning: Unknown element '%s'\n"
% (childnode.tag))

root = ssg.xml.ElementTree.fromstring(("%s%s" % (header, footer)).encode("utf-8"))
root.append(definitions)
root.append(tests)
root.append(objects)
if list(states):
root.append(states)
if list(variables):
root.append(variables)

ssg.xml.ElementTree.ElementTree(root).write(args.output)
env_yaml, args.product_yaml, args.ovaldirs, args.build_ovals_dir
)
oval_builder.product_name = "Script {}".format(os.path.basename(__file__))

try:
oval_document = oval_builder.get_oval_document_from_shorthands(
args.include_benchmark
)
oval_document.finalize_affected_platforms(env_yaml)

oval_document.save_as_xml(args.output)
except EXPECTED_ERRORS as error:
logging.critical(error)

sys.exit(0)

Expand Down
Loading
Loading