Passed
Push — master ( b25b04...24a582 )
by Jan
04:05 queued 11s
created

oval_graph.xml_parser.XmlParser._get_used_rules()   B

Complexity

Conditions 5

Size

Total Lines 20
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5

Importance

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