blob: 126cdf8a24e67d76896ac2957e529f50b8ad8957 [file] [log] [blame]
from __future__ import absolute_import
from oscap.commands import xccdf, oval
import logging
import os
import salt.utils
import shutil
import stat
_OSCAP_XCCDF_EXIT_CODES_MAP = {
0: True, # all rules pass
1: False, # there is an error during evaluation
2: True # there is at least one rule with either fail or unknown result
}
DIR_MODE = '0750'
log = logging.getLogger(__name__)
def __virtual__():
if not salt.utils.which('oscap'):
return (False, 'oscap is required.')
return 'oscap'
def eval(evaltype,
benchmark,
profile='default',
xccdf_version='1.2',
tailoring_id=None,
cpe=None,
fetch_from_master=False,
benchmark_url=None,
benchmark_basepath='output',
saltenv='base',
results_dir=None):
'''
`oscap eval` wrapper
:param evaltype: what to evaluate, can be `xccdf` or `oval`
:param profile: xccdf profile (default 'default')
:param xccdf_version xccdf benchmark version (default 1.2)
:param tailoring_id id of your tailoring data (default None)
:param cpe CPE dictionary or language for applicability checks (default None)
:param fetch_from_master: fetch oscap input data from the master (default False)
:param benchmark_basepath: basepath where the benchmark will be searched (default 'output')
:param saltenv: saltenv, used for cached files (default 'base')
:param results_dir: directory for storing results (default {{__opts__[cachedir]}}/files/openscap/latest)
:return: success,returncode,results_dir, optionally stderr
Usage example:
salt MINION oscap.eval xccdf /tmp/myxccdf.xml tailoring_id=myenv_oscap_variables profile='anssi_nt28_high'
'''
success = False
stderr = None
returncode = None
pillar_data = None
latest_dir = os.path.join(__opts__['cachedir'], 'files', 'openscap', 'latest')
results_dir = os.path.normpath(results_dir) if results_dir else latest_dir
benchmark_url = benchmark_url if benchmark_url else \
'salt://{}/{}'.format(benchmark_basepath,
os.path.dirname(benchmark))
if fetch_from_master:
_ret_ = __salt__['cp.cache_dir'](benchmark_url)
benchmark = benchmark[1:] if os.path.isabs(benchmark) else benchmark
benchmark = os.path.join(__opts__['cachedir'], 'files',
saltenv, benchmark_basepath, benchmark)
if evaltype == 'xccdf':
if tailoring_id:
pillar_data = __salt__['pillar.get']('openscap:tailoring:{}'\
.format(tailoring_id))
(stdout, stderr, rc, temp_dir) = xccdf(benchmark,
profile=profile,
pillar_data=pillar_data,
tailoring_id=tailoring_id,
cpe=cpe,
xccdf_version=xccdf_version)
success = _OSCAP_XCCDF_EXIT_CODES_MAP[rc]
elif evaltype == 'oval':
(stdout, stderr, rc, temp_dir) = oval(benchmark)
success = not rc
else:
raise RuntimeError('Unsupported oscap command "{}"'.format(evaltype))
ret = {
'success': success,
'returncode': rc,
'results_dir': results_dir
}
if success:
mode = int(str(stat.S_IMODE(int(DIR_MODE))), 8)
base_dir = os.path.dirname(results_dir)
if os.path.isdir(results_dir):
shutil.rmtree(results_dir)
if not os.path.isdir(base_dir):
os.makedirs(base_dir)
os.chmod(base_dir, mode)
shutil.move(temp_dir, results_dir)
os.chmod(results_dir, mode)
if stderr:
ret['stderr'] = stderr
return ret