blob: 88cdcbad2899aeff8c0d81e9469352d10080f005 [file] [log] [blame]
Ivan Suzdal184c4e32018-06-06 13:55:30 +04001from __future__ import absolute_import
2from oscap.commands import xccdf, oval
3import logging
4import os
5import salt.utils
6import shutil
7import stat
8
9_OSCAP_XCCDF_EXIT_CODES_MAP = {
10 0: True, # all rules pass
11 1: False, # there is an error during evaluation
12 2: True # there is at least one rule with either fail or unknown result
13}
14
15DIR_MODE = '0750'
16
17log = logging.getLogger(__name__)
18
19def __virtual__():
20 if not salt.utils.which('oscap'):
21 return (False, 'oscap is required.')
22 return 'oscap'
23
24def eval(evaltype,
25 benchmark,
26 profile='default',
27 xccdf_version='1.2',
28 tailoring_id=None,
29 fetch_from_master=False,
30 benchmark_url=None,
31 benchmark_basepath='output',
32 saltenv='base',
33 results_dir=None):
34 '''
35 `oscap eval` wrapper
36 :param evaltype: what to evaluate, can be `xccdf` or `oval`
37 :param profile: xccdf profile (default 'default')
38 :param xccdf_version xccdf benchmark version (default 1.2)
39 :param tailoring_id id of your tailoring data (default None)
40 :param fetch_from_master: fetch oscap input data from the master (default False)
41 :param benchmark_basepath: basepath where the benchmark will be searched (default 'output')
42 :param saltenv: saltenv, used for cached files (default 'base')
43 :param results_dir: directory for storing results (default {{__opts__[cachedir]}}/files/openscap/latest)
44
45 :return: success,returncode,results_dir, optionally stderr
46
47 Usage example:
48
49 salt MINION oscap.eval xccdf /tmp/myxccdf.xml tailoring_id=myenv_oscap_variables profile='anssi_nt28_high'
50 '''
51 success = False
52 stderr = None
53 returncode = None
54 pillar_data = None
55
56 latest_dir = os.path.join(__opts__['cachedir'], 'files', 'openscap', 'latest')
57 results_dir = os.path.normpath(results_dir) if results_dir else latest_dir
58
59 benchmark_url = benchmark_url if benchmark_url else \
60 'salt://{}/{}'.format(benchmark_basepath,
61 os.path.dirname(benchmark))
62
63 if fetch_from_master:
64 _ret_ = __salt__['cp.cache_dir'](benchmark_url)
65 benchmark = benchmark[1:] if os.path.isabs(benchmark) else benchmark
66 benchmark = os.path.join(__opts__['cachedir'], 'files',
67 saltenv, benchmark_basepath, benchmark)
68
69 if evaltype == 'xccdf':
70 if tailoring_id:
71 pillar_data = __salt__['pillar.get']('openscap:tailoring:{}'\
72 .format(tailoring_id))
73 (stdout, stderr, rc, temp_dir) = xccdf(benchmark,
74 profile=profile,
75 pillar_data=pillar_data,
76 tailoring_id=tailoring_id,
77 xccdf_version=xccdf_version)
78
79 success = _OSCAP_XCCDF_EXIT_CODES_MAP[rc]
80 elif evaltype == 'oval':
81 (stdout, stderr, rc, temp_dir) = oval(benchmark)
82 success = not rc
83 else:
84 raise RuntimeError('Unsupported oscap command "{}"'.format(evaltype))
85
86 ret = {
87 'success': success,
88 'returncode': rc,
89 'results_dir': results_dir
90 }
91
92 if success:
93 mode = int(str(stat.S_IMODE(int(DIR_MODE))), 8)
94 base_dir = os.path.dirname(results_dir)
95 if os.path.isdir(results_dir):
96 shutil.rmtree(results_dir)
97 if not os.path.isdir(base_dir):
98 os.makedirs(base_dir)
99 os.chmod(base_dir, mode)
100 os.rename(temp_dir, latest_dir)
101 os.chmod(latest_dir, mode)
102
103 if stderr:
104 ret['stderr'] = stderr
105
106 return ret