Passed
Push — master ( 5534fc...ed6ab7 )
by Matěj
02:32 queued 14s
created

test_machine_only_rules.check_product()   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nop 3
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
#!/usr/bin/python3
2
3
import os
4
import argparse
5
import xml.etree.ElementTree as ET
6
import sys
7
import ssg.constants
8
import ssg.yaml
9
10
machine_cpe = "cpe:/a:machine"
11
12
13
def main():
14
    args = parse_command_line_args()
15
    for product in ssg.constants.product_directories:
16
        product_dir = os.path.join(args.source_dir, product)
17
        product_yaml_path = os.path.join(product_dir, "product.yml")
18
        product_yaml = ssg.yaml.open_raw(product_yaml_path)
19
        guide_dir = os.path.abspath(
20
            os.path.join(product_dir, product_yaml['benchmark_root']))
21
        if not check_product(args.build_dir, product, guide_dir):
22
            sys.exit(1)
23
24
25
def check_product(build_dir, product, guide_dir):
26
    input_groups, input_rules = scan_rules_groups(guide_dir, False)
27
    ds_path = os.path.join(build_dir, "ssg-" + product + "-ds.xml")
28
    if not check_ds(ds_path, "groups", input_groups):
29
        return False
30
    return True
31
32
33
def check_ds(ds_path, what, input_elems):
34
    try:
35
        tree = ET.parse(ds_path)
36
    except IOError as e:
37
        sys.stderr.write("The product datastream '%s' hasn't been build, "
38
                         "skipping the test." % (ds_path))
39
        return True
40
    root = tree.getroot()
41
    if what == "groups":
42
        replacement = "xccdf_org.ssgproject.content_group_"
43
        xpath_query = ".//{%s}Group" % ssg.constants.XCCDF12_NS
44
    if what == "rules":
45
        replacement = "xccdf_org.ssgproject.content_rule_"
46
        xpath_query = ".//{%s}Rule" % ssg.constants.XCCDF12_NS
47
    benchmark = root.find(".//{%s}Benchmark" % ssg.constants.XCCDF12_NS)
48
    for elem in benchmark.findall(xpath_query):
0 ignored issues
show
introduced by
The variable xpath_query does not seem to be defined in case what == "groups" on line 41 is False. Are you sure this can never be the case?
Loading history...
49
        elem_id = elem.get("id")
50
        elem_short_id = elem_id.replace(replacement, "")
0 ignored issues
show
introduced by
The variable replacement does not seem to be defined in case what == "groups" on line 41 is False. Are you sure this can never be the case?
Loading history...
51
        if elem_short_id not in input_elems:
52
            continue
53
        platforms = elem.findall("{%s}platform" % ssg.constants.XCCDF12_NS)
54
        machine_platform = False
55
        for p in platforms:
56
            idref = p.get("idref")
57
            if idref == machine_cpe:
58
                machine_platform = True
59
        if not machine_platform:
60
            sys.stderr.write("%s %s in %s is missing <platform> element" %
61
                             (what, elem_short_id, ds_path))
62
            return False
63
    return True
64
65
66
def parse_command_line_args():
67
    parser = argparse.ArgumentParser(
68
        description="Tests if 'machine' CPEs are "
69
                    "propagated to the built datastream")
70
    parser.add_argument("--source_dir", required=True,
71
                        help="Content source directory path")
72
    parser.add_argument("--build_dir", required=True,
73
                        help="Build directory containing built datastreams")
74
    args = parser.parse_args()
75
    return args
76
77
78
def check_if_machine_only(dirpath, name, is_machine_only_group):
79
    if name in os.listdir(dirpath):
80
        if is_machine_only_group:
81
            return True
82
        yml_path = os.path.join(dirpath, name)
83
        with open(yml_path, "r") as yml_file:
84
            yml_file_contents = yml_file.read()
85
            if "platform: machine" in yml_file_contents:
86
                return True
87
    return False
88
89
90
def scan_rules_groups(dirpath, parent_machine_only):
91
    groups = set()
92
    rules = set()
93
    name = os.path.basename(dirpath)
94
    is_machine_only = False
95
    if check_if_machine_only(dirpath, "group.yml", parent_machine_only):
96
        groups.add(name)
97
        is_machine_only = True
98
    if check_if_machine_only(dirpath, "rule.yml", parent_machine_only):
99
        rules.add(name)
100
    for dir_item in os.listdir(dirpath):
101
        subdir_path = os.path.join(dirpath, dir_item)
102
        if os.path.isdir(subdir_path):
103
            subdir_groups, subdir_rules = scan_rules_groups(
104
                subdir_path, is_machine_only)
105
            groups |= subdir_groups
106
            rules |= subdir_rules
107
    return groups, rules
108
109
110
if __name__ == "__main__":
111
    main()
112