Passed
Pull Request — master (#3368)
by Matěj
02:59 queued 24s
created

ssg.oval.applicable_platforms()   A

Complexity

Conditions 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 10
nop 1
dl 0
loc 16
ccs 10
cts 10
cp 1
crap 2
rs 9.9
c 0
b 0
f 0
1 2
from __future__ import absolute_import
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2 2
from __future__ import print_function
3
4 2
import sys
5 2
import os
6 2
import re
7 2
import argparse
8 2
import tempfile
9 2
import subprocess
10
11 2
from .constants import oval_footer as footer
12 2
from .constants import oval_namespace as ovalns
13 2
from .rules import get_rule_dir_id, get_rule_dir_ovals, find_rule_dirs
14 2
from .xml import ElementTree as ET
15 2
from .xml import oval_generated_header
16 2
from .id_translate import IDTranslator
17
18 2
SHARED_OVAL = re.sub(r'ssg/.*', 'shared', __file__) + '/checks/oval/'
19 2
LINUX_OS_GUIDE = re.sub(r'ssg/.*', 'linux_os', __file__) + '/guide/'
20
21
22
# globals, to make recursion easier in case we encounter extend_definition
23 2
try:
24 2
    ET.register_namespace("oval", ovalns)
25
except AttributeError:
26
    # Legacy Python 2.6 fix, see e.g.
27
    # https://www.programcreek.com/python/example/57552/xml.etree.ElementTree._namespace_map
28
    ET._namespace_map[ovalns] = "oval"
0 ignored issues
show
Bug introduced by
The Module cElementTree does not seem to have a member named _namespace_map.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Bug introduced by
The Module xml.etree.cElementTree does not seem to have a member named _namespace_map.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Coding Style Best Practice introduced by
It seems like _namespace_map was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
29
30 2
definitions = ET.Element("oval:definitions")
0 ignored issues
show
Coding Style Naming introduced by
The name definitions does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
31 2
tests = ET.Element("oval:tests")
0 ignored issues
show
Coding Style Naming introduced by
The name tests does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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 2
objects = ET.Element("oval:objects")
0 ignored issues
show
Coding Style Naming introduced by
The name objects does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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 2
states = ET.Element("oval:states")
0 ignored issues
show
Coding Style Naming introduced by
The name states does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
34 2
variables = ET.Element("oval:variables")
0 ignored issues
show
Coding Style Naming introduced by
The name variables does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
35 2
silent_mode = False
0 ignored issues
show
Coding Style Naming introduced by
The name silent_mode does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
36
37
38
# append new child ONLY if it's not a duplicate
39 2
def append(element, newchild):
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
40
    global silent_mode
0 ignored issues
show
Coding Style Naming introduced by
The name silent_mode does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
41
    newid = newchild.get("id")
42
    existing = element.find(".//*[@id='" + newid + "']")
43
    if existing is not None:
44
        if not silent_mode:
45
            sys.stderr.write("Notification: this ID is used more than once " +
46
                             "and should represent equivalent elements: " +
47
                             newid + "\n")
48
    else:
49
        element.append(newchild)
50
51
52 2
def _add_elements(body, header):
53
    """Add oval elements to the global Elements defined above"""
54
    global definitions
0 ignored issues
show
Coding Style Naming introduced by
The name definitions does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
55
    global tests
0 ignored issues
show
Coding Style Naming introduced by
The name tests does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
56
    global objects
0 ignored issues
show
Coding Style Naming introduced by
The name objects does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
57
    global states
0 ignored issues
show
Coding Style Naming introduced by
The name states does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
58
    global variables
0 ignored issues
show
Coding Style Naming introduced by
The name variables does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
59
60
    tree = ET.fromstring(header + body + footer)
61
    tree = replace_external_vars(tree)
62
    defname = None
63
    # parse new file(string) as an etree, so we can arrange elements
64
    # appropriately
65
    for childnode in tree.findall("./{%s}def-group/*" % ovalns):
66
        # print "childnode.tag is " + childnode.tag
67
        if childnode.tag is ET.Comment:
68
            continue
69
        if childnode.tag == ("{%s}definition" % ovalns):
70
            append(definitions, childnode)
71
            defname = childnode.get("id")
72
            # extend_definition is a special case:  must include a whole other
73
            # definition
74
            for defchild in childnode.findall(".//{%s}extend_definition"
75
                                              % ovalns):
76
                defid = defchild.get("definition_ref")
77
                extend_ref = find_testfile_or_exit(defid)
78
                includedbody = read_ovaldefgroup_file(extend_ref)
79
                # recursively add the elements in the other file
80
                _add_elements(includedbody, header)
81
        if childnode.tag.endswith("_test"):
82
            append(tests, childnode)
83
        if childnode.tag.endswith("_object"):
84
            append(objects, childnode)
85
        if childnode.tag.endswith("_state"):
86
            append(states, childnode)
87
        if childnode.tag.endswith("_variable"):
88
            append(variables, childnode)
89
    return defname
90
91
92 2
def applicable_platforms(oval_file):
93
    """
94
    Returns the applicable platforms for a given oval file
95
    """
96
97 2
    platforms = []
98 2
    header = oval_generated_header("applicable_platforms", "5.11", "0.0.1")
99 2
    body = read_ovaldefgroup_file(oval_file)
100 2
    oval_tree = ET.fromstring(header + body + footer)
101
102 2
    element_path = "./{%s}def-group/{%s}definition/{%s}metadata/{%s}affected/{%s}platform"
103 2
    element_ns_path = element_path % (ovalns, ovalns, ovalns, ovalns, ovalns)
104 2
    for node in oval_tree.findall(element_ns_path):
105 2
        platforms.append(node.text)
106
107 2
    return platforms
108
109
110 2
def parse_affected(oval_contents):
111
    """
112
    Returns the tuple (start_affected, end_affected, platform_indents) for
113
    the passed oval file contents. start_affected is the line number of
114
    starting tag of the <affected> element, end_affected is the line number of
115
    the closing tag of the </affected> element, and platform_indents is a
116
    string containing the indenting characters before the contents of the
117
    <affected> element.
118
    """
119
120
    start_affected = list(filter(lambda x: "<affected" in oval_contents[x],
121
                                 range(0, len(oval_contents))))
122
    if len(start_affected) != 1:
123
        raise ValueError("OVAL file does not contain a single <affected> "
124
                         "element; counted %d in:\n%s\n\n" %
125
                         (len(start_affected), "\n".join(oval_contents)))
126
127
    start_affected = start_affected[0]
128
129
    end_affected = list(filter(lambda x: "</affected" in oval_contents[x],
130
                               range(0, len(oval_contents))))
131
    if len(end_affected) != 1:
132
        raise ValueError("Malformed OVAL file does not contain a single "
133
                         "closing </affected>; counted %d in:\n%s\n\n" %
134
                         (len(start_affected), "\n".join(oval_contents)))
135
    end_affected = end_affected[0]
136
137
    if start_affected >= end_affected:
138
        raise ValueError("Malformed OVAL file: start affected tag begins "
139
                         "on the same line or after ending affected tag: "
140
                         "start:%d vs end:%d:\n%s\n\n" %
141
                         (start_affected, end_affected, oval_contents))
142
143
    # Validate that start_affected contains only a starting <affected> tag;
144
    # otherwise, using this information to update the <platform> subelements
145
    # would fail.
146
    start_line = oval_contents[start_affected]
147
    start_line = start_line.strip()
148
149
    if not start_line.startswith('<affected'):
150
        raise ValueError("Malformed OVAL file: line with starting affected "
151
                         "tag contains other elements: line:%s\n%s\n\n" %
152
                         (start_line, oval_contents))
153
    if '<' in start_line[1:]:
154
        raise ValueError("Malformed OVAL file: line with starting affected "
155
                         "tag contains other elements: line:%s\n%s\n\n" %
156
                         (start_line, oval_contents))
157
158
    # Validate that end_affected contains only an ending </affected> tag;
159
    # otherwise, using this information to update the <platform> subelements
160
    # would fail.
161
    end_line = oval_contents[end_affected]
162
    end_line = end_line.strip()
163
164
    if not end_line.startswith('</affected>'):
165
        raise ValueError("Malformed OVAL file: line with ending affected "
166
                         "tag contains other elements: line:%s\n%s\n\n" %
167
                         (end_line, oval_contents))
168
    if '<' in end_line[1:]:
169
        raise ValueError("Malformed OVAL file: line with ending affected "
170
                         "tag contains other elements: line:%s\n%s\n\n" %
171
                         (end_line, oval_contents))
172
173
    indents = ""
174
    if start_affected+1 == end_affected:
175
        # Since the affected element is present but empty, the indents should
176
        # be two more spaces than that of the starting <affected> element.
177
        start_index = oval_contents[start_affected].index('<')
178
        indents = oval_contents[start_affected][0:start_index]
179
        indents += "  "
180
    else:
181
        # Otherwise, grab the indents off the next line unmodified, as this is
182
        # likely a platform element tag. We don't validate here that this is
183
        # indeed the case, as other parts of the build infrastructure will
184
        # validate this for us.
185
        start_index = oval_contents[start_affected+1].index('<')
186
        indents = oval_contents[start_affected+1][0:start_index]
187
188
    return start_affected, end_affected, indents
189
190
191 2
def replace_external_vars(tree):
192
    """Replace external_variables with local_variables, so the definition can be
193
       tested independently of an XCCDF file"""
194
195
    # external_variable is a special case: we turn it into a local_variable so
196
    # we can test
197
    for node in tree.findall(".//{%s}external_variable" % ovalns):
198
        print("External_variable with id : " + node.get("id"))
199
        extvar_id = node.get("id")
200
        # for envkey, envval in os.environ.iteritems():
201
        #     print envkey + " = " + envval
202
        # sys.exit()
203
        if extvar_id not in os.environ.keys():
204
            print("External_variable specified, but no value provided via "
205
                  "environment variable", file=sys.stderr)
206
            sys.exit(2)
207
        # replace tag name: external -> local
208
        node.tag = "{%s}local_variable" % ovalns
209
        literal = ET.Element("oval:literal_component")
210
        literal.text = os.environ[extvar_id]
211
        node.append(literal)
212
        # TODO: assignment of external_variable via environment vars, for
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
213
        # testing
214
    return tree
215
216
217 2
def find_testfile_or_exit(testfile):
218
    """Find OVAL files in CWD or shared/oval and calls sys.exit if the file is not found"""
219
    _testfile = find_testfile(testfile)
220
    if _testfile is None:
221
        print("ERROR: %s does not exist! Please specify a valid OVAL file." % testfile,
222
              file=sys.stderr)
223
        sys.exit(1)
224
    else:
225
        return _testfile
226
227
228 2
def find_testfile(oval_id):
229
    """
230
    Find OVAL file by id in CWD, SHARED_OVAL, or LINUX_OS_GUIDE. Understands rule
231
    directories and defaults to returning shared.xml over {{{ product }}}.xml.
232
233
    Returns path to OVAL file or None if not found.
234
    """
235 2
    if os.path.isfile(os.path.abspath(oval_id)):
236
        return os.path.abspath(oval_id)
237
238 2
    if oval_id.endswith(".xml"):
239 2
        oval_id, _ = os.path.splitext(oval_id)
240 2
        oval_id = os.path.basename(oval_id)
241
242 2
    candidates = [oval_id, "%s.xml" % oval_id]
243
244 2
    found_file = None
245 2
    for path in ['.', SHARED_OVAL, LINUX_OS_GUIDE]:
246 2
        for root, _, _ in os.walk(path):
247 2
            for candidate in candidates:
248 2
                search_file = os.path.join(root, candidate).strip()
249 2
                if os.path.isfile(search_file):
250
                    found_file = search_file
251
                    break
252
253 2
        for rule_dir in find_rule_dirs(path):
254 2
            rule_id = get_rule_dir_id(rule_dir)
255 2
            if rule_id == oval_id:
256 2
                ovals = get_rule_dir_ovals(rule_dir, product="shared")
257 2
                if ovals:
258 2
                    found_file = ovals[0]
259 2
                    break
260
261 2
    return found_file
262
263
264 2
def read_ovaldefgroup_file(testfile):
265
    """Read oval files"""
266 2
    with open(testfile, 'r') as test_file:
267 2
        body = test_file.read()
268 2
    return body
269
270
271 2
def get_openscap_supported_oval_version():
0 ignored issues
show
Coding Style Naming introduced by
The name get_openscap_supported_oval_version does not conform to the function naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

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...
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
272
    try:
273
        from openscap import oscap_get_version
274
        if [int(x) for x in str(oscap_get_version()).split(".")] >= [1, 2, 0]:
275
            return "5.11"
276
    except ImportError:
277
        pass
278
279
    return "5.10"
280
281
282 2
def parse_options():
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
283
    usage = "usage: %(prog)s [options] definition_file.xml"
284
    parser = argparse.ArgumentParser(usage=usage)
285
    # only some options are on by default
286
287
    oscap_oval_version = get_openscap_supported_oval_version()
288
289
    parser.add_argument("--oval_version",
290
                        default=oscap_oval_version,
291
                        dest="oval_version", action="store",
292
                        help="OVAL version to use. Example: 5.11, 5.10, ... "
293
                             "If not supplied the highest version supported by "
294
                             "openscap will be used: %s" % (oscap_oval_version))
295
    parser.add_argument("-q", "--quiet", "--silent", default=False,
296
                        action="store_true", dest="silent_mode",
297
                        help="Don't show any output when testing OVAL files")
298
    parser.add_argument("xmlfile", metavar="XMLFILE", help="OVAL XML file")
299
    args = parser.parse_args()
300
301
    return args
302
303
304 2
def main():
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
305
    global definitions
0 ignored issues
show
Coding Style Naming introduced by
The name definitions does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
306
    global tests
0 ignored issues
show
Coding Style Naming introduced by
The name tests does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
307
    global objects
0 ignored issues
show
Coding Style Naming introduced by
The name objects does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
308
    global states
0 ignored issues
show
Coding Style Naming introduced by
The name states does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
309
    global variables
0 ignored issues
show
Coding Style Naming introduced by
The name variables does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
310
    global silent_mode
0 ignored issues
show
Coding Style Naming introduced by
The name silent_mode does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

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...
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
311
312
    args = parse_options()
313
    silent_mode = args.silent_mode
314
    oval_version = args.oval_version
315
316
    testfile = args.xmlfile
317
    header = oval_generated_header("testoval.py", oval_version, "0.0.1")
318
    testfile = find_testfile_or_exit(testfile)
319
    body = read_ovaldefgroup_file(testfile)
320
321
    defname = _add_elements(body, header)
322
    if defname is None:
323
        print("Error while evaluating oval: defname not set; missing "
324
              "definitions section?")
325
        sys.exit(1)
326
327
    ovaltree = ET.fromstring(header + footer)
328
329
    # append each major element type, if it has subelements
330
    for element in [definitions, tests, objects, states, variables]:
331
        if list(element):
332
            ovaltree.append(element)
333
334
    # re-map all the element ids from meaningful names to meaningless
335
    # numbers
336
    testtranslator = IDTranslator("scap-security-guide.testing")
337
    ovaltree = testtranslator.translate(ovaltree)
338
    (ovalfile, fname) = tempfile.mkstemp(prefix=defname, suffix=".xml")
339
    os.write(ovalfile, ET.tostring(ovaltree))
340
    os.close(ovalfile)
341
342
    cmd = ['oscap', 'oval', 'eval', '--results', fname + '-results', fname]
343
    if not silent_mode:
344
        print("Evaluating with OVAL tempfile: " + fname)
345
        print("OVAL Schema Version: %s" % oval_version)
346
        print("Writing results to: " + fname + "-results")
347
        print("Running command: %s\n" % " ".join(cmd))
348
349
    oscap_child = subprocess.Popen(cmd, stdout=subprocess.PIPE)
350
    cmd_out = oscap_child.communicate()[0]
351
352
    if isinstance(cmd_out, bytes):
353
        cmd_out = cmd_out.decode('utf-8')
354
355
    if not silent_mode:
356
        print(cmd_out, file=sys.stderr)
357
358
    if oscap_child.returncode != 0:
359
        if not silent_mode:
360
            print("Error launching 'oscap' command: return code %d" % oscap_child.returncode)
361
        sys.exit(2)
362
363
    if 'false' in cmd_out or 'error' in cmd_out:
364
        # at least one from the evaluated OVAL definitions evaluated to
365
        # 'false' result, exit with '1' to indicate OVAL scan FAIL result
366
        sys.exit(1)
367
368
    # perhaps delete tempfile?
369
    definitions = ET.Element("oval:definitions")
370
    tests = ET.Element("oval:tests")
371
    objects = ET.Element("oval:objects")
372
    states = ET.Element("oval:states")
373
    variables = ET.Element("oval:variables")
374
375
    # 'false' keyword wasn't found in oscap's command output
376
    # exit with '0' to indicate OVAL scan TRUE result
377
    sys.exit(0)
378