Test Failed
Push — master ( 6149c6...e6e408 )
by Matthew
02:55 queued 14s
created

compile_all.find_existing_rules()   A

Complexity

Conditions 4

Size

Total Lines 9
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 9
nop 1
dl 0
loc 9
ccs 0
cts 9
cp 0
crap 20
rs 9.95
c 0
b 0
f 0
1
from __future__ import print_function
2
3
import argparse
4
import os.path
5
from glob import glob
6
7
import ssg.build_profile
8
import ssg.build_yaml
9
import ssg.utils
10
import ssg.controls
11
import ssg.products
12
import ssg.environment
13
from ssg.build_cpe import ProductCPEs
14
from ssg.constants import BENCHMARKS
15
16
def create_parser():
17
    parser = argparse.ArgumentParser()
18
    parser.add_argument(
19
        "--build-config-yaml", required=True,
20
        help="YAML file with information about the build configuration. "
21
        "e.g.: ~/scap-security-guide/build/build_config.yml "
22
        "needed for autodetection of profile root"
23
    )
24
    parser.add_argument(
25
        "--product-yaml", required=True,
26
        help="YAML file with information about the product we are building. "
27
        "e.g.: ~/scap-security-guide/products/rhel7/product.yml "
28
        "needed for autodetection of profile root"
29
    )
30
    parser.add_argument(
31
        "--resolved-base", required=True,
32
        help="To which directory to put processed rule/group/value YAMLs.")
33
    parser.add_argument(
34
        "--project-root",
35
        help="Path to the repository ie. project root "
36
        "e.g.: ~/scap-security-guide/",
37
    )
38
    parser.add_argument(
39
        "--sce-metadata",
40
        help="Combined SCE metadata to read."
41
    )
42
    parser.add_argument(
43
        "--stig-references", help="DISA STIG Reference XCCDF file"
44
    )
45
    return parser
46
47
48
def get_env_yaml(build_config_yaml, product_yaml):
49
    if build_config_yaml is None or product_yaml is None:
50
        return None
51
52
    env_yaml = ssg.environment.open_environment(build_config_yaml, product_yaml)
53
    return env_yaml
54
55
56
def get_all_content_directories(env_yaml, product_yaml):
57
    relative_benchmark_root = ssg.utils.required_key(env_yaml, "benchmark_root")
58
    benchmark_root = os.path.join(product_yaml["product_dir"], relative_benchmark_root)
59
60
    add_content_dirs = get_additional_content_directories(env_yaml)
61
    return [benchmark_root] + add_content_dirs
62
63
64
def get_additional_content_directories(env_yaml):
65
    # we assume that the project root is one directory above build-scripts
66
    project_root = os.path.dirname(os.path.dirname(__file__))
67
    additional_content_directories = env_yaml.get("additional_content_directories", [])
68
69
    absolute_additional_content_dirs = []
70
    for dirname in additional_content_directories:
71
        if not os.path.isabs(dirname):
72
            dirname = os.path.join(project_root, dirname)
73
        absolute_additional_content_dirs.append(dirname)
74
    return absolute_additional_content_dirs
75
76
77
def load_benchmark_source_data_from_directory_tree(loader, env_yaml, product_yaml):
78
    relevant_benchmark_sources = get_all_content_directories(env_yaml, product_yaml)
79
    loader.process_directory_trees(relevant_benchmark_sources)
80
81
82
def dump_compiled_profile(base_dir, profile):
83
    dest = os.path.join(base_dir, "profiles", "{name}.profile".format(name=profile.id_))
84
    profile.dump_yaml(dest)
85
86
87
def get_all_resolved_profiles_by_id(
88
        env_yaml, product_yaml, loader, product_cpes, controls_manager, controls_dir=None):
89
    profile_files = ssg.products.get_profile_files_from_root(env_yaml, product_yaml)
90
    profiles_by_id = load_resolve_and_validate_profiles(
91
        env_yaml, profile_files, loader, controls_manager, product_cpes)
92
    return profiles_by_id
93
94
95
def load_resolve_and_validate_profiles(env_yaml, profile_files, loader, controls_manager, product_cpes):
96
    profiles_by_id = ssg.build_profile.make_name_to_profile_mapping(profile_files, env_yaml, product_cpes)
97
98
    for p in profiles_by_id.values():
99
        p.resolve(profiles_by_id, loader.all_rules, controls_manager)
100
101
        p.validate_variables(loader.all_values.values())
102
        p.validate_rules(loader.all_rules.values(), loader.all_groups.values())
103
        p.validate_refine_rules(loader.all_rules.values())
104
    return profiles_by_id
105
106
107
def save_everything(base_dir, loader, controls_manager, profiles):
108
    controls_manager.save_everything(os.path.join(base_dir, "controls"))
109
    loader.save_all_entities(base_dir)
110
    for p in profiles:
111
        dump_compiled_profile(base_dir, p)
112
113
114
def find_existing_rules(project_root):
115
    rules = set()
116
    for benchmark in BENCHMARKS:
117
        benchmark = os.path.join(project_root, benchmark)
118
        for dirpath, _, filenames in os.walk(benchmark):
119
            if "rule.yml" in filenames:
120
                rule_id = os.path.basename(dirpath)
121
                rules.add(rule_id)
122
    return rules
123
124
125
def main():
126
    parser = create_parser()
127
    args = parser.parse_args()
128
129
    env_yaml = get_env_yaml(args.build_config_yaml, args.product_yaml)
130
    product_yaml = ssg.products.Product(args.product_yaml)
131
    product_cpes = ProductCPEs()
132
    product_cpes.load_product_cpes(env_yaml)
133
    product_cpes.load_content_cpes(env_yaml)
134
135
    loader = ssg.build_yaml.BuildLoader(
136
        None, env_yaml, product_cpes, args.sce_metadata, args.stig_references)
137
    load_benchmark_source_data_from_directory_tree(loader, env_yaml, product_yaml)
138
139
    project_root_abspath = os.path.abspath(args.project_root)
140
    controls_dir = os.path.join(project_root_abspath, "controls")
141
142
    existing_rules = find_existing_rules(project_root_abspath)
143
144
    controls_manager = ssg.controls.ControlsManager(
145
        controls_dir, env_yaml, existing_rules)
146
    controls_manager.load()
147
    controls_manager.remove_selections_not_known(loader.all_rules)
148
149
    profiles_by_id = get_all_resolved_profiles_by_id(
150
        env_yaml, product_yaml, loader, product_cpes, controls_manager, controls_dir)
151
152
    save_everything(
153
        args.resolved_base, loader, controls_manager, profiles_by_id.values())
154
155
156
if __name__ == "__main__":
157
    main()
158