Test Failed
Pull Request — master (#173)
by Jan
02:32
created

oval_graph.xml_parser.XmlParser.__init__()   A

Complexity

Conditions 3

Size

Total Lines 26
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 26
ccs 0
cts 17
cp 0
rs 9.256
c 0
b 0
f 0
cc 3
nop 2
crap 12
1
'''
2
    This file contains a class for creating OVAL graph from XML source
3
'''
4
5
import os
6
import sys
7
8
from lxml import etree as ET
9
10
from .oval_node._builder_oval_tree import _BuilderOvalTree
11
from ._xml_parser_oval_scan_definitions import _XmlParserScanDefinitions
12
from .exceptions import NotChecked
13
14
ns = {
15
    'XMLSchema': 'http://oval.mitre.org/XMLSchema/oval-results-5',
16
    'xccdf': 'http://checklists.nist.gov/xccdf/1.2',
17
    'arf': 'http://scap.nist.gov/schema/asset-reporting-format/1.1',
18
    'oval-definitions': 'http://oval.mitre.org/XMLSchema/oval-definitions-5',
19
    'scap': 'http://scap.nist.gov/schema/scap/source/1.2',
20
    'oval-characteristics': 'http://oval.mitre.org/XMLSchema/oval-system-characteristics-5',
21
}
22
23
24
class XmlParser:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
best-practice introduced by
Too many instance attributes (9/7)
Loading history...
25
    def __init__(self, src):
26
        self.src = src
27
        self.tree = ET.parse(self.src)
0 ignored issues
show
introduced by
Module 'lxml.etree' has no 'parse' member, but source is unavailable. Consider adding this module to extension-pkg-whitelist if you want to perform analysis based on run-time introspection of living objects.
Loading history...
28
        self.root = self.tree.getroot()
29
        if not self.validate(
30
                'schemas/arf/1.1/asset-reporting-format_1.1.0.xsd'):
31
            CRED = '\033[91m'
0 ignored issues
show
Coding Style Naming introduced by
Variable name "CRED" doesn't conform to '[a-z_][a-z0-9_]2,30$' pattern ('[a-z_][a-z0-9_]2,30$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
32
            CEND = '\033[0m'
0 ignored issues
show
Coding Style Naming introduced by
Variable name "CEND" doesn't conform to '[a-z_][a-z0-9_]2,30$' pattern ('[a-z_][a-z0-9_]2,30$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
33
            print(
34
                CRED +
35
                "Warning: This file is not valid arf report." +
36
                CEND,
37
                file=sys.stderr)
38
        try:
39
            self.used_rules = self._get_used_rules()
40
            self.report_data = self._get_report_data(
41
                list(self.used_rules.values())[0]['href'])
42
            self.notselected_rules = self._get_notselected_rules()
43
            self.definitions = self._get_definitions()
44
            self.oval_definitions = self._get_oval_definitions()
45
            self.scan_definitions = _XmlParserScanDefinitions(
46
                self.definitions, self.oval_definitions, self.report_data).get_scan()
47
        except BaseException:
48
            raise ValueError(
0 ignored issues
show
introduced by
Consider explicitly re-raising using the 'from' keyword
Loading history...
49
                'This file "{}" is not arf report file or there are no results'.format(
50
                    self.src))
51
52
    def get_src(self, src):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
53
        _dir = os.path.dirname(os.path.realpath(__file__))
54
        FIXTURE_DIR = os.path.join(_dir, src)
0 ignored issues
show
Coding Style Naming introduced by
Variable name "FIXTURE_DIR" doesn't conform to '[a-z_][a-z0-9_]2,30$' pattern ('[a-z_][a-z0-9_]2,30$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
55
        return str(FIXTURE_DIR)
56
57
    def validate(self, xsd_path):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
58
        xsd_path = self.get_src(xsd_path)
59
        xmlschema_doc = ET.parse(xsd_path)
0 ignored issues
show
introduced by
Module 'lxml.etree' has no 'parse' member, but source is unavailable. Consider adding this module to extension-pkg-whitelist if you want to perform analysis based on run-time introspection of living objects.
Loading history...
60
        xmlschema = ET.XMLSchema(xmlschema_doc)
0 ignored issues
show
introduced by
Module 'lxml.etree' has no 'XMLSchema' member, but source is unavailable. Consider adding this module to extension-pkg-whitelist if you want to perform analysis based on run-time introspection of living objects.
Loading history...
61
62
        xml_doc = self.tree
63
        result = xmlschema.validate(xml_doc)
64
65
        return result
66
67
    def _get_used_rules(self):
68
        rulesResults = self.root.findall(
0 ignored issues
show
Coding Style Naming introduced by
Variable name "rulesResults" doesn't conform to '[a-z_][a-z0-9_]2,30$' pattern ('[a-z_][a-z0-9_]2,30$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
69
            './/xccdf:TestResult/xccdf:rule-result', ns)
70
        rules = {}
71
        for ruleResult in rulesResults:
0 ignored issues
show
Coding Style Naming introduced by
Variable name "ruleResult" doesn't conform to '[a-z_][a-z0-9_]2,30$' pattern ('[a-z_][a-z0-9_]2,30$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
72
            result = ruleResult.find('.//xccdf:result', ns)
73
            if result.text != "notselected":
74
                check_content_ref = ruleResult.find(
75
                    './/xccdf:check/xccdf:check-content-ref', ns)
76
                message = ruleResult.find(
77
                    './/xccdf:message', ns)
78
                rule_dict = {}
79
                if check_content_ref is not None:
80
                    rule_dict['id_def'] = check_content_ref.attrib.get('name')
81
                    rule_dict['href'] = check_content_ref.attrib.get('href')
82
                    rule_dict['result'] = result.text
83
                    if message is not None:
84
                        rule_dict['message'] = message.text
85
                    rules[ruleResult.get('idref')] = rule_dict
86
        return rules
87
88
    def _get_report_data(self, href):
89
        report_data = None
90
        reports = self.root.find('.//arf:reports', ns)
91
        for report in reports:
92
            if "#" + str(report.get("id")) == href:
93
                report_data = report
94
        return report_data
95
96
    def _get_notselected_rules(self):
97
        rulesResults = self.root.findall(
0 ignored issues
show
Coding Style Naming introduced by
Variable name "rulesResults" doesn't conform to '[a-z_][a-z0-9_]2,30$' pattern ('[a-z_][a-z0-9_]2,30$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
98
            './/xccdf:TestResult/xccdf:rule-result', ns)
99
        rules = []
100
        for ruleResult in rulesResults:
0 ignored issues
show
Coding Style Naming introduced by
Variable name "ruleResult" doesn't conform to '[a-z_][a-z0-9_]2,30$' pattern ('[a-z_][a-z0-9_]2,30$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
101
            result = ruleResult.find('.//xccdf:result', ns)
102
            if result.text == "notselected":
103
                rules.append(ruleResult.get('idref'))
104
        return rules
105
106
    def _get_definitions(self):
107
        data = self.report_data.find(
108
            ('.//XMLSchema:oval_results/XMLSchema:results/'
109
             'XMLSchema:system/XMLSchema:definitions'), ns)
110
        return data
111
112
    def _get_oval_definitions(self):
113
        return self.root.find(
114
            './/arf:report-requests/arf:report-request/'
115
            'arf:content/scap:data-stream-collection/'
116
            'scap:component/oval-definitions:oval_definitions/'
117
            'oval-definitions:definitions', ns)
118
119
    def _get_definition_of_rule(self, rule_id):
120
        if rule_id in self.used_rules:
0 ignored issues
show
unused-code introduced by
Unnecessary "elif" after "return"
Loading history...
121
            rule_info = self.used_rules[rule_id]
122
            if rule_info['id_def'] is None:
123
                raise NotChecked(
124
                    '"{}" is {}: {}'.format(
125
                        rule_id,
126
                        rule_info['result'],
127
                        rule_info['message']))
128
            return dict(rule_id=rule_id,
129
                        definition_id=rule_info['id_def'],
130
                        definition=self.scan_definitions[rule_info['id_def']])
131
        elif rule_id in self.notselected_rules:
132
            raise ValueError(
133
                'Rule "{}" was not selected, so there are no results.'
134
                .format(rule_id))
135
        else:
136
            raise ValueError('404 rule "{}" not found!'.format(rule_id))
137
138
    def get_oval_tree(self, rule_id):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
139
        return _BuilderOvalTree.get_oval_tree_from_dict_of_rule(
140
            self._get_definition_of_rule(rule_id))
141