|
1
|
|
|
#!/usr/bin/python3 |
|
2
|
|
|
|
|
3
|
|
|
from glob import glob |
|
4
|
|
|
import collections |
|
5
|
|
|
import os |
|
6
|
|
|
import re |
|
7
|
|
|
import pathlib |
|
8
|
|
|
|
|
9
|
|
|
import argparse |
|
10
|
|
|
|
|
11
|
|
|
import ssg.build_yaml |
|
12
|
|
|
import ssg.controls |
|
13
|
|
|
import ssg.yaml |
|
14
|
|
|
import ssg.jinja |
|
15
|
|
|
import template_renderer |
|
16
|
|
|
|
|
17
|
|
|
|
|
18
|
|
|
class HtmlOutput(template_renderer.Renderer): |
|
19
|
|
|
TEMPLATE_NAME = "rules-template.html" |
|
20
|
|
|
|
|
21
|
|
|
def _get_all_compiled_profiles(self): |
|
22
|
|
|
compiled_profiles = glob(str(self.built_content_path / "profiles" / "*.profile")) |
|
23
|
|
|
profiles = [] |
|
24
|
|
|
for p in compiled_profiles: |
|
25
|
|
|
profiles.append(ssg.build_yaml.Profile.from_yaml(p)) |
|
26
|
|
|
return profiles |
|
27
|
|
|
|
|
28
|
|
|
def _set_rule_profiles_membership(self, rule, profiles): |
|
29
|
|
|
rule.in_profiles = [p for p in profiles if rule.id_ in p.selected] |
|
30
|
|
|
|
|
31
|
|
|
def _resolve_var_substitutions(self, rule): |
|
32
|
|
|
# The <sub .../> here is not the HTML subscript element <sub>...</sub>, |
|
33
|
|
|
# and therefore is invalid HTML. |
|
34
|
|
|
# so this code substitutes the whole sub element with contents of its idref prefixed by $ |
|
35
|
|
|
# as occurrence of sub with idref implies that substitution of XCCDF values takes place |
|
36
|
|
|
rule.description = re.sub( |
|
37
|
|
|
r'<sub\s+idref="([^"]*)"\s*/>', r"<tt>$\1</tt>", rule.description) |
|
38
|
|
|
|
|
39
|
|
|
def process_rules(self, rule_files): |
|
40
|
|
|
rules = [] |
|
41
|
|
|
profiles = self._get_all_compiled_profiles() |
|
42
|
|
|
|
|
43
|
|
|
for r_file in rule_files: |
|
44
|
|
|
rule = ssg.build_yaml.Rule.from_yaml(r_file, self.env_yaml) |
|
45
|
|
|
self._set_rule_relative_definition_location(rule) |
|
46
|
|
|
self._set_rule_profiles_membership(rule, profiles) |
|
47
|
|
|
self._resolve_var_substitutions(rule) |
|
48
|
|
|
rules.append(rule) |
|
49
|
|
|
|
|
50
|
|
|
self.template_data["rules"] = rules |
|
51
|
|
|
|
|
52
|
|
|
|
|
53
|
|
|
def parse_args(): |
|
54
|
|
|
parser = HtmlOutput.create_parser( |
|
55
|
|
|
"Pass a list of rule YAMLs, and the script will " |
|
56
|
|
|
"render their summary as an HTML along with links to the usage of these rules in profiles " |
|
57
|
|
|
"and with links to the upstream rule source.") |
|
58
|
|
|
parser.add_argument( |
|
59
|
|
|
"rule", metavar="FILENAME", nargs="+", help="The rule YAML files") |
|
60
|
|
|
return parser.parse_args() |
|
61
|
|
|
|
|
62
|
|
|
|
|
63
|
|
|
if __name__ == "__main__": |
|
64
|
|
|
args = parse_args() |
|
65
|
|
|
renderer = HtmlOutput(args.product, args.build_dir) |
|
66
|
|
|
renderer.process_rules(args.rule) |
|
67
|
|
|
renderer.output_results(args) |
|
68
|
|
|
|