Passed
Pull Request — master (#97)
by Jan
01:40
created

oval_graph.xml_parser.XmlParser.create_dict_form_criteria()   B

Complexity

Conditions 6

Size

Total Lines 24
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 19
nop 3
dl 0
loc 24
ccs 9
cts 9
cp 1
crap 6
rs 8.5166
c 0
b 0
f 0
1 1
import sys
2 1
import os
3
4 1
from lxml import etree as ET
5
6 1
from ._xml_parser_oval_scan_definitions import _XmlParserScanDefinitions
7 1
from ._builder_oval_graph import _BuilderOvalGraph
8
9 1
ns = {
10
    'XMLSchema': 'http://oval.mitre.org/XMLSchema/oval-results-5',
11
    'xccdf': 'http://checklists.nist.gov/xccdf/1.2',
12
    'arf': 'http://scap.nist.gov/schema/asset-reporting-format/1.1',
13
    'oval-definitions': 'http://oval.mitre.org/XMLSchema/oval-definitions-5',
14
    'scap': 'http://scap.nist.gov/schema/scap/source/1.2',
15
    'oval-characteristics': 'http://oval.mitre.org/XMLSchema/oval-system-characteristics-5',
16
}
17
18
19 1
class XmlParser:
20 1
    def __init__(self, src):
21 1
        self.src = src
22 1
        self.tree = ET.parse(self.src)
23 1
        self.root = self.tree.getroot()
24 1
        self.oval_graph_builder = _BuilderOvalGraph()
25
26 1
        if not self.validate(
27
                'schemas/arf/1.1/asset-reporting-format_1.1.0.xsd'):
28 1
            CRED = '\033[91m'
29 1
            CEND = '\033[0m'
30 1
            print(
31
                CRED +
32
                "Warning: This file is not valid arf report." +
33
                CEND,
34
                file=sys.stderr)
35 1
        try:
36 1
            self.used_rules = self._get_used_rules()
37 1
            self.report_data = self._get_report_data(
38
                self.used_rules[0]['href'])
39 1
            self.notselected_rules = self._get_notselected_rules()
40 1
            self.definitions = self._get_definitions()
41 1
            self.oval_definitions = self._get_oval_definitions()
42 1
            self.scan_definitions = _XmlParserScanDefinitions(
43
                self.definitions, self.oval_definitions, self.report_data).get_scan()
44 1
        except BaseException:
45 1
            raise ValueError("err- This is not arf report file.")
46
47 1
    def get_src(self, src):
48 1
        _dir = os.path.dirname(os.path.realpath(__file__))
49 1
        FIXTURE_DIR = os.path.join(_dir, src)
50 1
        return str(FIXTURE_DIR)
51
52 1
    def validate(self, xsd_path):
53 1
        xsd_path = self.get_src(xsd_path)
54 1
        xmlschema_doc = ET.parse(xsd_path)
55 1
        xmlschema = ET.XMLSchema(xmlschema_doc)
56
57 1
        xml_doc = self.tree
58 1
        result = xmlschema.validate(xml_doc)
59
60 1
        return result
61
62 1
    def _get_used_rules(self):
63 1
        rulesResults = self.root.findall(
64
            './/xccdf:TestResult/xccdf:rule-result', ns)
65 1
        rules = []
66 1
        for ruleResult in rulesResults:
67 1
            result = ruleResult.find('.//xccdf:result', ns)
68 1
            if result.text != "notselected":
69 1
                check_content_ref = ruleResult.find(
70
                    './/xccdf:check/xccdf:check-content-ref', ns)
71 1
                if check_content_ref is not None:
72 1
                    rules.append(dict(
73
                        id_rule=ruleResult.get('idref'),
74
                        id_def=check_content_ref.attrib.get('name'),
75
                        href=check_content_ref.attrib.get('href'),
76
                        result=result.text,
77
                    ))
78 1
        return rules
79
80 1
    def _get_report_data(self, href):
81 1
        report_data = None
82 1
        reports = self.root.find('.//arf:reports', ns)
83 1
        for report in reports:
84 1
            if "#" + str(report.get("id")) == href:
85 1
                report_data = report
86 1
        return report_data
87
88 1
    def _get_notselected_rules(self):
89 1
        rulesResults = self.root.findall(
90
            './/xccdf:TestResult/xccdf:rule-result', ns)
91 1
        rules = []
92 1
        for ruleResult in rulesResults:
93 1
            result = ruleResult.find('.//xccdf:result', ns)
94 1
            if result.text == "notselected":
95 1
                rules.append(dict(id_rule=ruleResult.get('idref')))
96 1
        return rules
97
98 1
    def _get_definitions(self):
99 1
        data = self.report_data.find(
100
            ('.//XMLSchema:oval_results/XMLSchema:results/'
101
             'XMLSchema:system/XMLSchema:definitions'), ns)
102 1
        return data
103
104 1
    def _get_oval_definitions(self):
105 1
        return self.root.find(
106
            './/arf:report-requests/arf:report-request/'
107
            'arf:content/scap:data-stream-collection/'
108
            'scap:component/oval-definitions:oval_definitions/'
109
            'oval-definitions:definitions', ns)
110
111 1
    def _get_definition_of_rule(self, rule_id):
112 1
        for definition in self.scan_definitions['definitions']:
113 1
            if self.get_def_id_by_rule_id(rule_id) == definition['id']:
114 1
                return dict(rule_id=rule_id, definition=definition)
115
116 1
    def get_def_id_by_rule_id(self, rule_id):
117 1
        for rule in self.notselected_rules:
118 1
            if rule['id_rule'] == rule_id:
119 1
                raise ValueError(
120
                    'err- rule "{}" was not selected, so there are no results.'
121
                    .format(rule_id))
122 1
        for rule in self.used_rules:
123 1
            if rule['id_rule'] == rule_id:
124 1
                return rule['id_def']
125 1
        raise ValueError('err- 404 rule not found!')
126
127 1
    def get_oval_tree(self, rule_id=None):
128 1
        return self.oval_graph_builder.get_oval_graph_from_dict_of_rule(
129
            self._get_definition_of_rule(rule_id))
130