Test Failed
Push — master ( 00964b...f887a2 )
by Jan
02:30 queued 12s
created

utils.refchecker.main()   B

Complexity

Conditions 6

Size

Total Lines 38
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
eloc 31
nop 0
dl 0
loc 38
ccs 0
cts 30
cp 0
crap 42
rs 8.2026
c 0
b 0
f 0
1
#!/usr/bin/env python
2
3
import sys
4
import os
5
import argparse
6
import json
7
8
import ssg.build_profile
9
import ssg.build_yaml
10
import ssg.controls
11
import ssg.environment
12
import ssg.products
13
import ssg.rules
14
import ssg.rule_yaml
15
import ssg.yaml
16
import ssg.utils
17
18
SSG_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
19
20
21
def parse_args():
22
    parser = argparse.ArgumentParser(description="Check all rule.yml referenced in a given"
23
                                     "profile for a required reference identifier")
24
    parser.add_argument("-j", "--json", type=str, action="store",
25
                        default="build/rule_dirs.json", help="File to read "
26
                        "json output of rule_dir_json from (defaults to "
27
                        "build/rule_dirs.json")
28
    parser.add_argument("-c", "--build-config-yaml", default="build/build_config.yml",
29
                        help="YAML file with information about the build configuration. "
30
                        "Defaults to build/build_config.yml")
31
    parser.add_argument("--controls", default="controls",
32
                        help="Directory that contains control files with policy controls.")
33
    parser.add_argument("-p", "--profiles-root",
34
                        help="Override where to look for profile files.")
35
    parser.add_argument("product", type=str, help="Product to check has required references")
36
    parser.add_argument("profile", type=str, help="Profile to iterate over")
37
    parser.add_argument("reference", type=str, help="Required reference system to check for")
38
39
    return parser.parse_args()
40
41
42
def load(rule_obj, env_yaml=None):
43
    """
44
    From the given rule_dir object, load the build_yaml.Rule associated with
45
    it.
46
    """
47
48
    yaml_file = ssg.rules.get_rule_dir_yaml(rule_obj['dir'])
49
    return ssg.build_yaml.Rule.from_yaml(yaml_file, env_yaml=env_yaml)
50
51
52
def load_for_product(rule_obj, product, env_yaml=None):
53
    """
54
    From the given rule_dir object, load the build_yaml.Rule associated with
55
    it, normalizing for the given product.
56
    """
57
58
    rule = load(rule_obj, env_yaml=env_yaml)
59
    rule.normalize(product)
60
    return rule
61
62
63
def reference_check(env_yaml, rule_dirs, profile_path, product, product_yaml, reference,
64
                    profiles_root, controls_manager=None):
65
    profile = ssg.build_yaml.ProfileWithInlinePolicies.from_yaml(profile_path, env_yaml)
66
67
    if controls_manager:
68
        profile_files = ssg.products.get_profile_files_from_root(env_yaml, product_yaml)
69
        all_profiles = ssg.build_profile.make_name_to_profile_mapping(profile_files, env_yaml)
70
        profile.resolve(all_profiles, controls_manager)
71
72
    ok = True
73
    for rule_id in profile.selected + profile.unselected:
74
        if rule_id not in rule_dirs:
75
            msg = "Unable to find rule in rule_dirs.json: {0}"
76
            msg = msg.format(rule_id)
77
            raise ValueError(msg)
78
79
        rule = load_for_product(rule_dirs[rule_id], product, env_yaml=env_yaml)
80
81
        if reference not in rule.references:
82
            ok = False
83
            msg = "Rule {0} lacks required reference {1} or {1}@{2}"
84
            msg = msg.format(rule_id, reference, product)
85
            print(msg, file=sys.stderr)
86
87
    return ok
88
89
90
def main():
91
    args = parse_args()
92
93
    json_file = open(args.json, 'r')
94
    all_rules = json.load(json_file)
95
96
    linux_products, other_products = ssg.products.get_all(SSG_ROOT)
97
    all_products = linux_products.union(other_products)
98
    if args.product not in all_products:
99
        msg = "Unknown product {0}: check SSG_ROOT and try again"
100
        msg = msg.format(args.product)
101
        raise ValueError(msg)
102
103
    product_base = os.path.join(SSG_ROOT, args.product)
104
    product_yaml = os.path.join(product_base, "product.yml")
105
    env_yaml = ssg.environment.open_environment(args.build_config_yaml, product_yaml)
106
107
    controls_manager = None
108
    if os.path.exists(args.controls):
109
        controls_manager = ssg.controls.ControlsManager(args.controls, env_yaml)
110
        controls_manager.load()
111
112
    profiles_root = os.path.join(product_base, "profiles")
113
    if args.profiles_root:
114
        profiles_root = args.profiles_root
115
116
    profile_filename = args.profile + ".profile"
117
    profile_path = os.path.join(profiles_root, profile_filename)
118
    if not os.path.exists(profile_path):
119
        msg = "Unknown profile {0}: check profile, --profiles-root, and try again. "
120
        msg = "Note that the '.profile' suffix shouldn't be included."
121
        msg = msg.format(args.profile)
122
        raise ValueError(msg)
123
124
    ok = reference_check(env_yaml, all_rules, profile_path, args.product, product_yaml,
125
                         args.reference, profiles_root, controls_manager)
126
    if not ok:
127
        sys.exit(1)
128
129
130
if __name__ == "__main__":
131
    main()
132