Create openscap formula
This formula allows to install openscap schemas and utils.
Also, here is a simple oscap execution module.
Change-Id: Ib113f9a739deafbc4cf85c97b071636d0161cb54
Closes-PROD: https://mirantis.jira.com/browse/PROD-20392
diff --git a/_modules/oscap/__init__.py b/_modules/oscap/__init__.py
new file mode 100644
index 0000000..88cdcba
--- /dev/null
+++ b/_modules/oscap/__init__.py
@@ -0,0 +1,106 @@
+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,
+ 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 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,
+ 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)
+ os.rename(temp_dir, latest_dir)
+ os.chmod(latest_dir, mode)
+
+ if stderr:
+ ret['stderr'] = stderr
+
+ return ret