|
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
|
|
|
|