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

utils.refchecker.reference_check()   B

Complexity

Conditions 5

Size

Total Lines 25
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 20
nop 8
dl 0
loc 25
ccs 0
cts 19
cp 0
crap 30
rs 8.9332
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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