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