Passed
Pull Request — master (#40)
by Jan
05:49
created

oscap_report.scap_results_parser.rule_parser   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 112
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 91
dl 0
loc 112
ccs 72
cts 72
cp 1
rs 10
c 0
b 0
f 0
wmc 21

9 Methods

Rating   Name   Duplication   Size   Complexity  
A RuleParser._get_remediation_code() 0 6 1
A RuleParser._get_multi_check() 0 6 3
A RuleParser._get_warnings() 0 6 2
A RuleParser.__init__() 0 2 1
A RuleParser._get_identifiers() 0 10 2
B RuleParser.process_rule() 0 32 5
A RuleParser._get_remediations() 0 13 2
A RuleParser._get_references() 0 10 2
A RuleParser._get_check_content_refs_dict() 0 10 3
1 1
from lxml import etree
2
3 1
from .data_structures.data_structures import Remediation, Rule
4 1
from .description_parser import DescriptionParser
5 1
from .namespaces import NAMESPACES
6
7
8 1
class RuleParser():
9 1
    def __init__(self, ref_value):
10 1
        self.description_parser = DescriptionParser(ref_value)
11
12 1
    @staticmethod
13 1
    def _get_references(rule):
14 1
        references = []
15 1
        for referenc in rule.findall(".//xccdf:reference", NAMESPACES):
16 1
            ref = {
17
                "href": referenc.get("href"),
18
                "text": referenc.text,
19
            }
20 1
            references.append(ref)
21 1
        return references
22
23 1
    @staticmethod
24 1
    def _get_identifiers(rule):
25 1
        identifiers = []
26 1
        for identifier in rule.findall(".//xccdf:ident", NAMESPACES):
27 1
            ident = {
28
                "system": identifier.get("system"),
29
                "text": identifier.text,
30
            }
31 1
            identifiers.append(ident)
32 1
        return identifiers
33
34 1
    @staticmethod
35 1
    def _get_warnings(rule):
36 1
        warnings = []
37 1
        for warning in rule.findall(".//xccdf:warning", NAMESPACES):
38 1
            warnings.append(warning.text)
39 1
        return warnings
40
41 1
    def _get_remediation_code(self, fix):
42 1
        str_fix = etree.tostring(fix).decode()
43 1
        start_tag_fix = str_fix.find(">") + 1
44 1
        end_tag_fix = str_fix.rfind("</")
45 1
        fix_code = str_fix[start_tag_fix:end_tag_fix]
46 1
        return self.description_parser.performe_sub_tag(fix_code)
47
48 1
    def _get_remediations(self, rule):
49 1
        output = []
50 1
        for fix in rule.findall(".//xccdf:fix", NAMESPACES):
51 1
            fix_dict = {
52
                "remediation_id": fix.get("id"),
53
                "system": fix.get("system"),
54
                "complexity": fix.get("complexity", ""),
55
                "disruption": fix.get("disruption", ""),
56
                "strategy": fix.get("strategy", ""),
57
                "fix": self._get_remediation_code(fix),
58
            }
59 1
            output.append(Remediation(**fix_dict))
60 1
        return output
61
62 1
    @staticmethod
63 1
    def _get_multi_check(rule):
64 1
        for check in rule.findall(".//xccdf:check", NAMESPACES):
65 1
            if check.get("multi-check") == "true":
66 1
                return True
67 1
        return False
68
69 1
    @staticmethod
70 1
    def _get_check_content_refs_dict(rule):
71 1
        check_content_refs = rule.findall(".//xccdf:check-content-ref", NAMESPACES)
72 1
        check_content_refs_dict = {}
73 1
        if check_content_refs is not None:
74 1
            for check_ref in check_content_refs:
75 1
                name = check_ref.get("name", "")
76 1
                id_check = name[:name.find(":")]
77 1
                check_content_refs_dict[id_check] = name
78 1
        return check_content_refs_dict
79
80 1
    def process_rule(self, rule):
81 1
        rule_id = rule.get("id")
82
83 1
        rule_dict = {
84
            "rule_id": rule_id,
85
            "severity": rule.get("severity", "Unknown"),
86
            "description": self.description_parser.get_full_description(rule),
87
            "references": self._get_references(rule),
88
            "identifiers": self._get_identifiers(rule),
89
            "warnings": self._get_warnings(rule),
90
            "remediations": self._get_remediations(rule),
91
            "multi_check": self._get_multi_check(rule),
92
        }
93
94 1
        title = rule.find(".//xccdf:title", NAMESPACES)
95 1
        if title is not None:
96 1
            rule_dict["title"] = title.text
97
98 1
        rationale = rule.find(".//xccdf:rationale", NAMESPACES)
99 1
        if rationale is not None:
100 1
            rule_dict["rationale"] = rationale.text
101
102 1
        platforms = rule.findall(".//xccdf:platform", NAMESPACES)
103 1
        rule_dict["platforms"] = []
104 1
        if platforms is not None:
105 1
            for platform in platforms:
106 1
                rule_dict["platforms"].append(platform.get("idref"))
107
108 1
        check_content_refs_dict = self._get_check_content_refs_dict(rule)
109 1
        rule_dict["oval_definition_id"] = check_content_refs_dict.get("oval", "")
110
111
        return Rule(**rule_dict)
112