Passed
Push — master ( 501dda...a99175 )
by Jan
03:06 queued 11s
created

oval_graph.client   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 173
Duplicated Lines 0 %

Test Coverage

Coverage 94%

Importance

Changes 0
Metric Value
eloc 147
dl 0
loc 173
ccs 94
cts 100
cp 0.94
rs 9.68
c 0
b 0
f 0
wmc 34

12 Methods

Rating   Name   Duplication   Size   Complexity  
A client._get_wanted_not_selected_rules() 0 4 1
B client.run_gui_and_return_answers() 0 19 6
A client.create_dict_of_rule() 0 7 2
A client.save_dict() 0 4 2
A client.prepare_data() 0 9 3
A client._get_wanted_rules() 0 4 1
A client.open_web_browser() 0 8 3
A client.search_rules_id() 0 16 5
A client.__init__() 0 16 3
A client.parse_arguments() 0 40 1
B client.get_questions() 0 21 5
A client.get_only_fail_rule() 0 2 2
1 1
from __future__ import print_function, unicode_literals
2 1
import re
3 1
import oval_graph.xml_parser
4 1
import oval_graph.oval_graph
5 1
import oval_graph.converter
6 1
import webbrowser
7 1
import json
8 1
import argparse
9
10
11 1
class client():
12 1
    def __init__(self, args):
13 1
        self.arg = self.parse_arguments(args)
14 1
        self.remove_pass_tests = self.arg.remove_pass_tests
15 1
        self.show_fail_rules = self.arg.show_fail_rules
16 1
        self.show_not_selected_rules = self.arg.show_not_selected_rules
17 1
        self.off_webbrowser = self.arg.off_web_browser
18 1
        self.source_filename = self.arg.source_filename
19 1
        self.tree = self.arg.tree
20 1
        self.rule_name = self.arg.rule_id
21 1
        self.xml_parser = oval_graph.xml_parser.xml_parser(self.source_filename)
22 1
        if self.tree:
23 1
            self.html_interpreter = 'tree_html_interpreter'
24
        else:
25 1
            self.html_interpreter = 'graph_html_interpreter'
26 1
        if self.remove_pass_tests:
27
            raise NotImplementedError('Not implemented!')
28
29 1
    def run_gui_and_return_answers(self):
30 1
        try:
31 1
            from PyInquirer import style_from_dict, Token, prompt, Separator
32
            return prompt(
33
                self.get_questions(
34
                    Separator('= The Rules IDs ='),
35
                    Separator('= The not selected rule IDs =')))
36 1
        except ImportError:
37 1
            print('== The Rule IDs ==')
38 1
            rules = self.search_rules_id()
39 1
            if self.show_fail_rules:
40 1
                rules = self.get_only_fail_rule(rules)
41 1
            for rule in rules:
42 1
                print(rule['id_rule'] + r'\b')
43 1
            if self.show_not_selected_rules:
44 1
                print('== The not selected rule IDs ==')
45 1
                for rule in self._get_wanted_not_selected_rules():
46 1
                    print(rule['id_rule'] + '(Not selected)')
47 1
            return None
48
49 1
    def get_questions(
50
            self,
51
            separator_rule_ids,
52
            separator_not_selected_rule_ids):
53 1
        rules = self.search_rules_id()
54 1
        if self.show_fail_rules:
55 1
            rules = self.get_only_fail_rule(rules)
56 1
        questions = [{
57
            'type': 'checkbox',
58
            'message': 'Select rule(s)',
59
            'name': 'rules',
60
            'choices': [separator_rule_ids]
61
        }]
62 1
        for rule in rules:
63 1
            questions[0]['choices'].append(dict(name=rule['id_rule']))
64 1
        if self.show_not_selected_rules:
65 1
            questions[0]['choices'].append(separator_not_selected_rule_ids)
66 1
            for rule in self._get_wanted_not_selected_rules():
67 1
                questions[0]['choices'].append(
68
                    dict(name=rule['id_rule'], disabled='Not selected'))
69 1
        return questions
70
71 1
    def get_only_fail_rule(self, rules):
72 1
        return list(filter(lambda rule: rule['result'] == 'fail', rules))
73
74 1
    def _get_wanted_rules(self):
75 1
        return [
76
            x for x in self.xml_parser.get_used_rules() if re.search(
77
                self.rule_name, x['id_rule'])]
78
79 1
    def _get_wanted_not_selected_rules(self):
80 1
        return [
81
            x for x in self.xml_parser.get_notselected_rules() if re.search(
82
                self.rule_name, x['id_rule'])]
83
84 1
    def search_rules_id(self):
85 1
        rules = self._get_wanted_rules()
86 1
        notselected_rules = self._get_wanted_not_selected_rules()
87 1
        if len(notselected_rules) and not rules:
88 1
            raise ValueError(
89
                ('err- rule(s) "{}" was not selected, '
90
                 "so there are no results. The rule is"
91
                 ' "notselected" because it'
92
                 " wasn't a part of the executed profile"
93
                 " and therefore it wasn't evaluated "
94
                 "during the scan.")
95
               .format(notselected_rules[0]['id_rule']))
96 1
        elif not notselected_rules and not rules:
97 1
            raise ValueError('err- 404 rule not found!')
98
        else:
99 1
            return rules
100
101 1
    def create_dict_of_rule(self, rule_id):
102 1
        converter = oval_graph.converter.converter(
103
            oval_graph.oval_graph.build_nodes_form_xml(
104
                self.source_filename, rule_id))
105 1
        if self.tree:
106 1
            return converter.to_JsTree_dict()
107 1
        return converter.to_sigma_dict(0, 0)
108
109 1
    def save_dict(self, dict):
110 1
        with open(self.xml_parser.get_src(self.html_interpreter + '/data.js'), "w+") as data_file:
111 1
            data_file.write("var data_json =" + str(json.dumps(
112
                dict, sort_keys=False, indent=4) + ";"))
113
114 1
    def prepare_data(self, rules):
115 1
        try:
116 1
            for rule in rules['rules']:
117 1
                oval_tree = self.create_dict_of_rule(rule)
118 1
                self.save_dict(oval_tree)
119 1
                self.open_web_browser()
120 1
                print('Rule "{}" done!'.format(rule))
121 1
        except Exception as error:
122 1
            raise ValueError('Rule: "{}" Error: "{}"'.format(rule, error))
123
124 1
    def open_web_browser(self):
125 1
        if not self.off_webbrowser:
126
            try:
127
                webbrowser.get('firefox').open_new_tab(self.xml_parser.get_src(
128
                    self.html_interpreter + '/index.html'))
129
            except BaseException:
130
                webbrowser.open_new_tab(self.xml_parser.get_src(
131
                    self.src_html_interpreter + '/index.html'))
132
133 1
    def parse_arguments(self, args):
134 1
        parser = argparse.ArgumentParser(
135
            description="Client for visualization of SCAP rule evaluation results")
136 1
        parser.add_argument(
137
            '--show-fail-rules',
138
            action="store_true",
139
            default=False,
140
            help="Show only FAIL rules")
141 1
        parser.add_argument(
142
            '--show-not-selected-rules',
143
            action="store_true",
144
            default=False,
145
            help="Show notselected rules. These rules will not be visualized.")
146 1
        parser.add_argument(
147
            '--off-web-browser',
148
            action="store_true",
149
            default=False,
150
            help="It does not start the web browser.")
151 1
        parser.add_argument(
152
            '--tree',
153
            action="store_true",
154
            default=False,
155
            help="Render the graph in a form of directory tree")
156 1
        parser.add_argument(
157
            '--remove-pass-tests',
158
            action="store_true",
159
            default=False,
160
            help=(
161
                "Do not display passing tests for better orientation in"
162
                " graphs that contain a large amount of nodes.(Not implemented)"))
163 1
        parser.add_argument("source_filename", help="ARF scan file")
164 1
        parser.add_argument(
165
            "rule_id", help=(
166
                "Rule ID to be visualized. A part from the full rule ID"
167
                " a part of the ID or a regular expression can be used."
168
                " If brackets are used in the regular expression "
169
                "the regular expression must be quoted."))
170 1
        args = parser.parse_args(args)
171
172
        return args
173