File: stats.py

package info (click to toggle)
scap-security-guide 0.1.76-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 110,644 kB
  • sloc: xml: 241,883; sh: 73,777; python: 32,527; makefile: 27
file content (121 lines) | stat: -rw-r--r-- 3,772 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import os
import json

from ssg.build_profile import XCCDFBenchmark
from ssg.utils import mkdir_p


OFF_JSON_TO_HTML = False

try:
    from json2html import json2html
except ImportError:
    OFF_JSON_TO_HTML = True


def _process_stats_content(profile, bash_fixes_count, content, content_filepath):
    link = """<a href="{}"><div style="height:100%;width:100%">{}</div></a>"""
    count = len(profile[content])
    if content == "ansible_parity":
        # custom text link for ansible parity
        count = link.format(
            content_filepath,
            "{} out of {} ({}%)".format(
                bash_fixes_count - count,
                bash_fixes_count,
                int(((bash_fixes_count - count) / bash_fixes_count) * 100),
            ),
        )
    count_href_element = link.format(content_filepath, count)
    profile["{}_count".format(content)] = count_href_element


def _filter_profile_for_html_stats(profile, filtered_output, content_path):
    content_list = [
        "rules",
        "missing_stigid_refs",
        "missing_stigref_refs",
        "missing_ccn_refs",
        "missing_cis_refs",
        "missing_hipaa_refs",
        "missing_anssi_refs",
        "missing_ospp_refs",
        "missing_pcidss4_refs",
        "missing_cui_refs",
        "missing_ovals",
        "missing_sces",
        "missing_bash_fixes",
        "missing_ansible_fixes",
        "missing_ignition_fixes",
        "missing_kubernetes_fixes",
        "missing_puppet_fixes",
        "missing_anaconda_fixes",
        "missing_cces",
        "ansible_parity",
        "implemented_checks",
        "implemented_fixes",
        "missing_checks",
        "missing_fixes",
    ]

    bash_fixes_count = profile["rules_count"] - profile["missing_bash_fixes_count"]

    for content in content_list:
        content_file = "{}_{}.txt".format(profile["profile_id"], content)
        content_filepath = os.path.join("content", content_file)
        count = len(profile[content])
        if count > 0:
            _process_stats_content(profile, bash_fixes_count, content, content_filepath)
            with open(os.path.join(content_path, content_file), "w+") as f:
                f.write("\n".join(profile[content]))
        else:
            profile["{}_count".format(content)] = count
        del profile[content]
    filtered_output.append(profile)


def _get_profiles(args):
    benchmark = XCCDFBenchmark(args.benchmark, args.product)
    ret = []
    if args.profile:
        ret.append(benchmark.show_profile_stats(args.profile, args))
    else:
        ret.extend(benchmark.show_all_profile_stats(args))
    return ret


def _generate_html_stats(args, profiles):
    filtered_output = []
    output_path = "./"
    if args.output:
        output_path = args.output
        mkdir_p(output_path)

    content_path = os.path.join(output_path, "content")
    mkdir_p(content_path)

    for profile in profiles:
        _filter_profile_for_html_stats(profile, filtered_output, content_path)

    with open(os.path.join(output_path, "statistics.html"), "w+") as f:
        f.write(json2html.convert(json=json.dumps(filtered_output), escape=False))


def command_stats(args):
    profiles = _get_profiles(args)

    if args.format == "json":
        print(json.dumps(profiles, indent=4))

    elif args.format == "html":
        if OFF_JSON_TO_HTML:
            print("No module named 'json2html'. Please install module to enable this function.")
            return
        _generate_html_stats(args, profiles)

    elif args.format == "csv":
        # we can assume ret has at least one element
        # CSV header
        print(",".join(profiles[0].keys()))
        for line in profiles:
            print(",".join([str(value) for value in line.values()]))