1
|
|
|
from __future__ import absolute_import |
|
|
|
|
2
|
|
|
from __future__ import print_function |
3
|
|
|
|
4
|
|
|
import os |
5
|
|
|
import re |
|
|
|
|
6
|
|
|
|
7
|
|
|
from .build_remediations import parse_from_file |
8
|
|
|
from .constants import XCCDF11_NS |
|
|
|
|
9
|
|
|
from .rule_yaml import parse_prodtype |
10
|
|
|
from .utils import read_file_list |
11
|
|
|
|
12
|
|
|
from .build_remediations import REMEDIATION_TO_EXT_MAP as REMEDIATION_MAP |
13
|
|
|
|
14
|
|
|
|
15
|
|
|
def get_fix_path(rule_obj, lang, fix_id): |
16
|
|
|
""" |
17
|
|
|
For the given fix_id or product, return the full path to the fix of the |
18
|
|
|
given language in the rule described by the given rule_obj. |
19
|
|
|
""" |
20
|
|
|
|
21
|
|
|
if not fix_id.endswith(REMEDIATION_MAP[lang]): |
22
|
|
|
fix_id += REMEDIATION_MAP[lang] |
23
|
|
|
|
24
|
|
|
if ('dir' not in rule_obj or 'id' not in rule_obj or |
25
|
|
|
'remediations' not in rule_obj or lang not in rule_obj['remediations']): |
|
|
|
|
26
|
|
|
raise ValueError("Malformed rule_obj") |
27
|
|
|
|
28
|
|
|
if fix_id not in rule_obj['remediations'][lang]: |
29
|
|
|
raise ValueError("Unknown fix_id:%s for rule_id:%s and lang:%s" % |
30
|
|
|
(fix_id, rule_obj['id'], lang)) |
31
|
|
|
|
32
|
|
|
return os.path.join(rule_obj['dir'], lang, fix_id) |
33
|
|
|
|
34
|
|
|
|
35
|
|
|
def get_fix_contents(rule_obj, lang, fix_id): |
36
|
|
|
""" |
37
|
|
|
Returns the tuple (path, contents) of the fix described by the given |
38
|
|
|
fix_id or product. |
39
|
|
|
""" |
40
|
|
|
|
41
|
|
|
fix_path = get_fix_path(rule_obj, lang, fix_id) |
42
|
|
|
fix_contents = read_file_list(fix_path) |
43
|
|
|
|
44
|
|
|
return fix_path, fix_contents |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
def applicable_platforms(fix_path): |
|
|
|
|
48
|
|
|
_, config = parse_from_file(fix_path, {}) |
49
|
|
|
|
50
|
|
|
if not 'platform' in config: |
51
|
|
|
raise ValueError("Malformed fix: missing platform" % fix_path) |
52
|
|
|
|
53
|
|
|
return parse_prodtype(config['platform']) |
54
|
|
|
|
55
|
|
|
|
56
|
|
|
def parse_platform(fix_contents): |
57
|
|
|
""" |
58
|
|
|
Parses the platform configuration item to determine the line number that |
59
|
|
|
the platforms configuration option is on. If this key is not found, None |
60
|
|
|
is returned instead. |
61
|
|
|
|
62
|
|
|
Note that this performs no validation on the contents of the file besides |
63
|
|
|
this and does not return the current value of the platform. |
64
|
|
|
|
65
|
|
|
If the configuration specification changes any, please update the |
66
|
|
|
corresponding parsing in ssg.build_remediations.parse_from_file(...). |
67
|
|
|
""" |
68
|
|
|
|
69
|
|
|
matched_line = None |
70
|
|
|
for line_num in range(0, len(fix_contents)): |
71
|
|
|
line = fix_contents[line_num] |
72
|
|
|
if line.startswith('#') and '=' in line: |
73
|
|
|
key, value = line.strip('#').split('=', 1) |
|
|
|
|
74
|
|
|
if key.strip() == 'platform': |
75
|
|
|
matched_line = line_num |
76
|
|
|
|
77
|
|
|
return matched_line |
78
|
|
|
|
79
|
|
|
def set_applicable_platforms(fix_contents, new_platforms): |
80
|
|
|
""" |
81
|
|
|
Returns a modified contents which updates the platforms to the new |
82
|
|
|
platforms. |
83
|
|
|
""" |
84
|
|
|
|
85
|
|
|
platform_line = parse_platform(fix_contents) |
86
|
|
|
if platform_line is None: |
87
|
|
|
raise ValueError("When parsing config file, unable to find platform " |
88
|
|
|
"line!\n\n%s" % "\n".join(fix_contents)) |
89
|
|
|
|
90
|
|
|
new_platforms_str = "# platform = " + ",".join(sorted(new_platforms)) |
91
|
|
|
|
92
|
|
|
new_contents = fix_contents[0:platform_line] |
93
|
|
|
new_contents.extend([new_platforms_str]) |
94
|
|
|
new_contents.extend(fix_contents[platform_line+1:]) |
95
|
|
|
|
96
|
|
|
return new_contents |
97
|
|
|
|
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.