Issues (70)

tests/run_scapval.py (1 issue)

Severity
1
#!/usr/bin/python3
2
from __future__ import print_function
3
4
import argparse
5
import subprocess
6
import os
7
import xml.etree.ElementTree as ET
8
import sys
9
10
scapval_results_ns = "http://csrc.nist.gov/ns/decima/results/1.0"
11
oval_unix_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5#unix"
12
xccdf_ns = "http://checklists.nist.gov/xccdf/1.2"
13
14
XML_SCHEMA_REQUIREMENT = "SRC-329"
15
16
K8S_PRODUCTS = set((
17
    "ocp4",
18
    "eks",
19
))
20
21
22
def parse_args():
23
    parser = argparse.ArgumentParser(
24
        description="Runs SCAP Validation of our data streams using SCAP"
25
        "Validation Tool (SCAPVal)")
26
    parser.add_argument(
27
        "--scap-version",
28
        help="SCAP Version (Only 1.2 and 1.3 supported)",
29
        choices=["1.2", "1.3"], required=True)
30
    parser.add_argument(
31
        "--scapval-path",
32
        help="Full path to the SCAPVal JAR archive", required=True)
33
    input_group = parser.add_mutually_exclusive_group(required=True)
34
    input_group.add_argument(
35
        "--build-dir",
36
        help="Full path to the ComplianceAsCode build directory")
37
    input_group.add_argument("--datastream", help="Full path to the ComplianceAsCode data stream")
38
    return parser.parse_args()
39
40
41
def ds_is_k8s_related(result_path):
42
    for prodname in K8S_PRODUCTS:
43
        ds_basename_stem = "ssg-{prodname}-ds".format(prodname=prodname)
44
        if ds_basename_stem in result_path:
45
            return True
46
    return False
47
48
49
def print_requirement_feedback(req_id, message):
50
    print("    %s: %s" % (req_id, message))
51
52
53
def process_results(result_path):
54
    ret_val = True
55
    tree = ET.parse(result_path)
56
    root = tree.getroot()
57
    results = root.find("./{%s}results" % scapval_results_ns)
58
    for base_req in results.findall(
59
            "./{%s}base-requirement" % scapval_results_ns):
60
        scapval_requirement_id = base_req.get("id")
61
        status = base_req.find("./{%s}status" % scapval_results_ns).text
62
        if status == "FAIL":
63
            if ds_is_k8s_related(result_path) and scapval_requirement_id == XML_SCHEMA_REQUIREMENT:
64
                warning = "WARNING (Contains non-standardized yamlfilecontent_test)"
65
                print_requirement_feedback(scapval_requirement_id, warning)
66
            else:
67
                print_requirement_feedback(scapval_requirement_id, status)
68
                ret_val = False
69
        if status == "PASS":
70
            if ds_is_k8s_related(result_path) and scapval_requirement_id == XML_SCHEMA_REQUIREMENT:
71
                msg = ("FAIL (yamlfilecontent_test is probably standardized by now."
72
                       "You should update the waiver.)")
73
                print_requirement_feedback(scapval_requirement_id, msg)
74
    return ret_val
75
76
77
def test_datastream(datastream_path,  scapval_path, scap_version):
78
    result_path = datastream_path + ".result.xml"
79
    report_path = datastream_path + ".report.html"
80
    scapval_command = [
81
            "java",
82
            "-Xmx1024m",
83
            "-Djava.protocol.handler.pkgs=sun.net.www.protocol",
84
            "-jar", scapval_path,
85
            "-scapversion", scap_version,
86
            "-file", datastream_path,
87
            "-valresultfile", result_path,
88
            "-valreportfile", report_path
89
            ]
90
    try:
91
        subprocess.check_output(scapval_command, stderr=subprocess.STDOUT)
92
    except subprocess.CalledProcessError as e:
93
        scapval_output = e.output.decode("utf-8")
94
        # Workaround: SCAPVal 1.3.2 can't generate HTML report because
95
        # it throws a NullPointerException, but we don't need the HTML
96
        # report for this test, so we can ignore this error.
97
        # TODO: Remove this when this is fixed in SCAPVal
98
        last_line = scapval_output.splitlines()[-1]
99
        if not last_line.endswith(
100
                "ERROR SCAPVal has encountered a problem and cannot continue "
101
                "with this validation. - java.lang.NullPointerException: "
102
                "XSLTemplateExtension cannot be null"):
103
            sys.stderr.write("Command '{0}' returned {1}:\n{2}\n".format(
104
                " ".join(e.cmd), e.returncode, scapval_output))
105
            sys.exit(1)
106
    return process_results(result_path)
107
108
109
def main():
110
    overall_result = True
111
    args = parse_args()
112
    if args.datastream is not None:
113
        build_dir = os.path.dirname(args.datastream)
114
        files = [os.path.basename(args.datastream), ]
115
    else:
116
        build_dir = args.build_dir
117
        files = os.listdir(build_dir)
118
    print("Build dir: %s" % build_dir)
119
    if args.scap_version == "1.2":
120
        ds_suffix = "-ds-1.2.xml"
121
    elif args.scap_version == "1.3":
122
        ds_suffix = "-ds.xml"
123
124
    for filename in files:
125
        if filename.endswith(ds_suffix):
0 ignored issues
show
The variable ds_suffix does not seem to be defined for all execution paths.
Loading history...
126
            print("Testing %s ..." % filename)
127
            datastream_path = os.path.join(build_dir, filename)
128
            datastream_result = test_datastream(
129
                    datastream_path, args.scapval_path, args.scap_version)
130
            if datastream_result:
131
                print("%s: PASS" % filename)
132
            else:
133
                print("%s: FAIL" % filename)
134
                overall_result = False
135
    if overall_result:
136
        sys.exit(0)
137
    else:
138
        sys.exit(1)
139
140
141
if __name__ == "__main__":
142
    main()
143