Feature/improve pre commit (#119)
This commit is contained in:
@@ -5,6 +5,15 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
|
|
||||||
|
- id: check-yaml
|
||||||
|
exclude: \.j2.(yaml|yml)$|\.(yaml|yml).j2$
|
||||||
|
args: [--unsafe] # see https://github.com/pre-commit/pre-commit-hooks/issues/273
|
||||||
|
|
||||||
|
- id: check-toml
|
||||||
|
- id: check-json
|
||||||
|
- id: check-symlinks
|
||||||
|
|
||||||
- repo: https://github.com/ansible/ansible-lint.git
|
- repo: https://github.com/ansible/ansible-lint.git
|
||||||
# get latest release tag from https://github.com/ansible/ansible-lint/releases/
|
# get latest release tag from https://github.com/ansible/ansible-lint/releases/
|
||||||
rev: v6.20.3
|
rev: v6.20.3
|
||||||
@@ -13,4 +22,8 @@ repos:
|
|||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- jmespath
|
- jmespath
|
||||||
|
|
||||||
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||||
|
rev: 23.11.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
@@ -14,61 +15,65 @@ import xml.dom.minidom
|
|||||||
|
|
||||||
role = "iosxeSTIG"
|
role = "iosxeSTIG"
|
||||||
|
|
||||||
|
|
||||||
class CallbackModule(CallbackBase):
|
class CallbackModule(CallbackBase):
|
||||||
CALLBACK_VERSION = 2.0
|
CALLBACK_VERSION = 2.0
|
||||||
CALLBACK_TYPE = 'xml'
|
CALLBACK_TYPE = "xml"
|
||||||
CALLBACK_NAME = 'stig_xml'
|
CALLBACK_NAME = "stig_xml"
|
||||||
|
|
||||||
CALLBACK_NEEDS_WHITELIST = True
|
CALLBACK_NEEDS_WHITELIST = True
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(CallbackModule, self).__init__()
|
super(CallbackModule, self).__init__()
|
||||||
self.rules = {}
|
self.rules = {}
|
||||||
self.stig_path = os.environ.get('STIG_PATH')
|
self.stig_path = os.environ.get("STIG_PATH")
|
||||||
self.XML_path = os.environ.get('XML_PATH')
|
self.XML_path = os.environ.get("XML_PATH")
|
||||||
if self.stig_path is None:
|
if self.stig_path is None:
|
||||||
self.stig_path = os.path.join(os.getcwd(), "roles", role, "files")
|
self.stig_path = os.path.join(os.getcwd(), "roles", role, "files")
|
||||||
self._display.display('Using STIG_PATH: {}'.format(self.stig_path))
|
self._display.display("Using STIG_PATH: {}".format(self.stig_path))
|
||||||
if self.XML_path is None:
|
if self.XML_path is None:
|
||||||
self.XML_path = os.getcwd()
|
self.XML_path = os.getcwd()
|
||||||
self._display.display('Using XML_PATH: {}'.format(self.XML_path))
|
self._display.display("Using XML_PATH: {}".format(self.XML_path))
|
||||||
|
|
||||||
print("Writing: {}".format(self.XML_path))
|
print("Writing: {}".format(self.XML_path))
|
||||||
STIG_name = os.path.basename(self.stig_path)
|
STIG_name = os.path.basename(self.stig_path)
|
||||||
ET.register_namespace('cdf', 'http://checklists.nist.gov/xccdf/1.2')
|
ET.register_namespace("cdf", "http://checklists.nist.gov/xccdf/1.2")
|
||||||
self.tr = ET.Element('{http://checklists.nist.gov/xccdf/1.2}TestResult')
|
self.tr = ET.Element("{http://checklists.nist.gov/xccdf/1.2}TestResult")
|
||||||
self.tr.set('id', 'xccdf_mil.disa.stig_testresult_scap_mil.disa_comp_{}'.format(STIG_name))
|
self.tr.set(
|
||||||
|
"id",
|
||||||
|
"xccdf_mil.disa.stig_testresult_scap_mil.disa_comp_{}".format(STIG_name),
|
||||||
|
)
|
||||||
endtime = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
endtime = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
||||||
self.tr.set('end-time', endtime)
|
self.tr.set("end-time", endtime)
|
||||||
tg = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}target')
|
tg = ET.SubElement(self.tr, "{http://checklists.nist.gov/xccdf/1.2}target")
|
||||||
tg.text = platform.node()
|
tg.text = platform.node()
|
||||||
|
|
||||||
def __get_rev(self, nid):
|
def __get_rev(self, nid):
|
||||||
rev = '0'
|
rev = "0"
|
||||||
# Check all files for the rule number.
|
# Check all files for the rule number.
|
||||||
for file in os.listdir(self.stig_path):
|
for file in os.listdir(self.stig_path):
|
||||||
with open(os.path.join(self.stig_path, file), 'r') as f:
|
with open(os.path.join(self.stig_path, file), "r") as f:
|
||||||
r = 'SV-{}r(?P<rev>\d)_rule'.format(nid)
|
r = "SV-{}r(?P<rev>\d)_rule".format(nid)
|
||||||
m = re.search(r, f.read())
|
m = re.search(r, f.read())
|
||||||
if m:
|
if m:
|
||||||
rev = m.group('rev')
|
rev = m.group("rev")
|
||||||
break
|
break
|
||||||
return rev
|
return rev
|
||||||
|
|
||||||
def v2_runner_on_ok(self, result):
|
def v2_runner_on_ok(self, result):
|
||||||
name = result._task.get_name()
|
name = result._task.get_name()
|
||||||
m = re.search('stigrule_(?P<id>\d+)', name)
|
m = re.search("stigrule_(?P<id>\d+)", name)
|
||||||
if m:
|
if m:
|
||||||
nid = m.group('id')
|
nid = m.group("id")
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
rev = self.__get_rev(nid)
|
rev = self.__get_rev(nid)
|
||||||
key = "{}r{}".format(nid, rev)
|
key = "{}r{}".format(nid, rev)
|
||||||
if self.rules.get(key, 'Unknown') != False:
|
if self.rules.get(key, "Unknown") != False:
|
||||||
self.rules[key] = result.is_changed()
|
self.rules[key] = result.is_changed()
|
||||||
|
|
||||||
def __set_duplicates(self):
|
def __set_duplicates(self):
|
||||||
with open(os.path.join(self.stig_path, 'duplicates.json')) as f:
|
with open(os.path.join(self.stig_path, "duplicates.json")) as f:
|
||||||
dups = json.load(f)
|
dups = json.load(f)
|
||||||
for d in dups:
|
for d in dups:
|
||||||
dup_of = str(dups[d][0])
|
dup_of = str(dups[d][0])
|
||||||
@@ -82,17 +87,19 @@ class CallbackModule(CallbackBase):
|
|||||||
def v2_playbook_on_stats(self, stats):
|
def v2_playbook_on_stats(self, stats):
|
||||||
self.__set_duplicates()
|
self.__set_duplicates()
|
||||||
for rule, changed in self.rules.items():
|
for rule, changed in self.rules.items():
|
||||||
state = 'fail' if changed else 'pass'
|
state = "fail" if changed else "pass"
|
||||||
rr = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}rule-result')
|
rr = ET.SubElement(
|
||||||
rr.set('idref', 'xccdf_mil.disa.stig_rule_SV-{}_rule'.format(rule))
|
self.tr, "{http://checklists.nist.gov/xccdf/1.2}rule-result"
|
||||||
rs = ET.SubElement(rr, '{http://checklists.nist.gov/xccdf/1.2}result')
|
)
|
||||||
|
rr.set("idref", "xccdf_mil.disa.stig_rule_SV-{}_rule".format(rule))
|
||||||
|
rs = ET.SubElement(rr, "{http://checklists.nist.gov/xccdf/1.2}result")
|
||||||
rs.text = state
|
rs.text = state
|
||||||
passing = len(self.rules) - sum(self.rules.values())
|
passing = len(self.rules) - sum(self.rules.values())
|
||||||
sc = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}score')
|
sc = ET.SubElement(self.tr, "{http://checklists.nist.gov/xccdf/1.2}score")
|
||||||
sc.set('maximum', str(len(self.rules)))
|
sc.set("maximum", str(len(self.rules)))
|
||||||
sc.set('system', 'urn:xccdf:scoring:flat-unweighted')
|
sc.set("system", "urn:xccdf:scoring:flat-unweighted")
|
||||||
sc.text = str(passing)
|
sc.text = str(passing)
|
||||||
with open(os.path.join(self.XML_path, "xccdf-results.xml"), 'w') as f:
|
with open(os.path.join(self.XML_path, "xccdf-results.xml"), "w") as f:
|
||||||
out = ET.tostring(self.tr)
|
out = ET.tostring(self.tr)
|
||||||
pretty = xml.dom.minidom.parseString(out).toprettyxml(encoding='utf-8')
|
pretty = xml.dom.minidom.parseString(out).toprettyxml(encoding="utf-8")
|
||||||
f.write(pretty)
|
f.write(pretty)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
@@ -11,76 +12,82 @@ import os
|
|||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
|
|
||||||
|
|
||||||
class CallbackModule(CallbackBase):
|
class CallbackModule(CallbackBase):
|
||||||
CALLBACK_VERSION = 2.0
|
CALLBACK_VERSION = 2.0
|
||||||
CALLBACK_TYPE = 'xml'
|
CALLBACK_TYPE = "xml"
|
||||||
CALLBACK_NAME = 'stig_xml'
|
CALLBACK_NAME = "stig_xml"
|
||||||
|
|
||||||
CALLBACK_NEEDS_WHITELIST = True
|
CALLBACK_NEEDS_WHITELIST = True
|
||||||
|
|
||||||
def _get_STIG_path(self):
|
def _get_STIG_path(self):
|
||||||
cwd = os.path.abspath('.')
|
cwd = os.path.abspath(".")
|
||||||
for dirpath, dirs, files in os.walk(cwd):
|
for dirpath, dirs, files in os.walk(cwd):
|
||||||
if os.path.sep + 'files' in dirpath and '.xml' in files[0]:
|
if os.path.sep + "files" in dirpath and ".xml" in files[0]:
|
||||||
return os.path.join(cwd, dirpath, files[0])
|
return os.path.join(cwd, dirpath, files[0])
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(CallbackModule, self).__init__()
|
super(CallbackModule, self).__init__()
|
||||||
self.rules = {}
|
self.rules = {}
|
||||||
self.stig_path = os.environ.get('STIG_PATH')
|
self.stig_path = os.environ.get("STIG_PATH")
|
||||||
self.XML_path = os.environ.get('XML_PATH')
|
self.XML_path = os.environ.get("XML_PATH")
|
||||||
if self.stig_path is None:
|
if self.stig_path is None:
|
||||||
self.stig_path = self._get_STIG_path()
|
self.stig_path = self._get_STIG_path()
|
||||||
self._display.display('Using STIG_PATH: {}'.format(self.stig_path))
|
self._display.display("Using STIG_PATH: {}".format(self.stig_path))
|
||||||
if self.XML_path is None:
|
if self.XML_path is None:
|
||||||
self.XML_path = tempfile.mkdtemp() + "/xccdf-results.xml"
|
self.XML_path = tempfile.mkdtemp() + "/xccdf-results.xml"
|
||||||
self._display.display('Using XML_PATH: {}'.format(self.XML_path))
|
self._display.display("Using XML_PATH: {}".format(self.XML_path))
|
||||||
|
|
||||||
print("Writing: {}".format(self.XML_path))
|
print("Writing: {}".format(self.XML_path))
|
||||||
STIG_name = os.path.basename(self.stig_path)
|
STIG_name = os.path.basename(self.stig_path)
|
||||||
ET.register_namespace('cdf', 'http://checklists.nist.gov/xccdf/1.2')
|
ET.register_namespace("cdf", "http://checklists.nist.gov/xccdf/1.2")
|
||||||
self.tr = ET.Element('{http://checklists.nist.gov/xccdf/1.2}TestResult')
|
self.tr = ET.Element("{http://checklists.nist.gov/xccdf/1.2}TestResult")
|
||||||
self.tr.set('id', 'xccdf_mil.disa.stig_testresult_scap_mil.disa_comp_{}'.format(STIG_name))
|
self.tr.set(
|
||||||
|
"id",
|
||||||
|
"xccdf_mil.disa.stig_testresult_scap_mil.disa_comp_{}".format(STIG_name),
|
||||||
|
)
|
||||||
endtime = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
endtime = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
||||||
self.tr.set('end-time', endtime)
|
self.tr.set("end-time", endtime)
|
||||||
tg = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}target')
|
tg = ET.SubElement(self.tr, "{http://checklists.nist.gov/xccdf/1.2}target")
|
||||||
tg.text = platform.node()
|
tg.text = platform.node()
|
||||||
|
|
||||||
def _get_rev(self, nid):
|
def _get_rev(self, nid):
|
||||||
with open(self.stig_path, 'r') as f:
|
with open(self.stig_path, "r") as f:
|
||||||
r = 'SV-{}r(?P<rev>\d+)_rule'.format(nid)
|
r = "SV-{}r(?P<rev>\d+)_rule".format(nid)
|
||||||
m = re.search(r, f.read())
|
m = re.search(r, f.read())
|
||||||
if m:
|
if m:
|
||||||
rev = m.group('rev')
|
rev = m.group("rev")
|
||||||
else:
|
else:
|
||||||
rev = '0'
|
rev = "0"
|
||||||
return rev
|
return rev
|
||||||
|
|
||||||
def v2_runner_on_ok(self, result):
|
def v2_runner_on_ok(self, result):
|
||||||
name = result._task.get_name()
|
name = result._task.get_name()
|
||||||
m = re.search('stigrule_(?P<id>\d+)', name)
|
m = re.search("stigrule_(?P<id>\d+)", name)
|
||||||
if m:
|
if m:
|
||||||
nid = m.group('id')
|
nid = m.group("id")
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
rev = self._get_rev(nid)
|
rev = self._get_rev(nid)
|
||||||
key = "{}r{}".format(nid, rev)
|
key = "{}r{}".format(nid, rev)
|
||||||
if self.rules.get(key, 'Unknown') != False:
|
if self.rules.get(key, "Unknown") != False:
|
||||||
self.rules[key] = result.is_changed()
|
self.rules[key] = result.is_changed()
|
||||||
|
|
||||||
def v2_playbook_on_stats(self, stats):
|
def v2_playbook_on_stats(self, stats):
|
||||||
for rule, changed in self.rules.items():
|
for rule, changed in self.rules.items():
|
||||||
state = 'fail' if changed else 'pass'
|
state = "fail" if changed else "pass"
|
||||||
rr = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}rule-result')
|
rr = ET.SubElement(
|
||||||
rr.set('idref', 'xccdf_mil.disa.stig_rule_SV-{}_rule'.format(rule))
|
self.tr, "{http://checklists.nist.gov/xccdf/1.2}rule-result"
|
||||||
rs = ET.SubElement(rr, '{http://checklists.nist.gov/xccdf/1.2}result')
|
)
|
||||||
|
rr.set("idref", "xccdf_mil.disa.stig_rule_SV-{}_rule".format(rule))
|
||||||
|
rs = ET.SubElement(rr, "{http://checklists.nist.gov/xccdf/1.2}result")
|
||||||
rs.text = state
|
rs.text = state
|
||||||
passing = len(self.rules) - sum(self.rules.values())
|
passing = len(self.rules) - sum(self.rules.values())
|
||||||
sc = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}score')
|
sc = ET.SubElement(self.tr, "{http://checklists.nist.gov/xccdf/1.2}score")
|
||||||
sc.set('maximum', str(len(self.rules)))
|
sc.set("maximum", str(len(self.rules)))
|
||||||
sc.set('system', 'urn:xccdf:scoring:flat-unweighted')
|
sc.set("system", "urn:xccdf:scoring:flat-unweighted")
|
||||||
sc.text = str(passing)
|
sc.text = str(passing)
|
||||||
with open(self.XML_path, 'wb') as f:
|
with open(self.XML_path, "wb") as f:
|
||||||
out = ET.tostring(self.tr)
|
out = ET.tostring(self.tr)
|
||||||
pretty = xml.dom.minidom.parseString(out).toprettyxml(encoding='utf-8')
|
pretty = xml.dom.minidom.parseString(out).toprettyxml(encoding="utf-8")
|
||||||
f.write(pretty)
|
f.write(pretty)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
@@ -11,76 +12,82 @@ import os
|
|||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
|
|
||||||
|
|
||||||
class CallbackModule(CallbackBase):
|
class CallbackModule(CallbackBase):
|
||||||
CALLBACK_VERSION = 2.0
|
CALLBACK_VERSION = 2.0
|
||||||
CALLBACK_TYPE = 'xml'
|
CALLBACK_TYPE = "xml"
|
||||||
CALLBACK_NAME = 'stig_xml'
|
CALLBACK_NAME = "stig_xml"
|
||||||
|
|
||||||
CALLBACK_NEEDS_WHITELIST = True
|
CALLBACK_NEEDS_WHITELIST = True
|
||||||
|
|
||||||
def _get_STIG_path(self):
|
def _get_STIG_path(self):
|
||||||
cwd = os.path.abspath('.')
|
cwd = os.path.abspath(".")
|
||||||
for dirpath, dirs, files in os.walk(cwd):
|
for dirpath, dirs, files in os.walk(cwd):
|
||||||
if os.path.sep + 'files' in dirpath and '.xml' in files[0]:
|
if os.path.sep + "files" in dirpath and ".xml" in files[0]:
|
||||||
return os.path.join(cwd, dirpath, files[0])
|
return os.path.join(cwd, dirpath, files[0])
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(CallbackModule, self).__init__()
|
super(CallbackModule, self).__init__()
|
||||||
self.rules = {}
|
self.rules = {}
|
||||||
self.stig_path = os.environ.get('STIG_PATH')
|
self.stig_path = os.environ.get("STIG_PATH")
|
||||||
self.XML_path = os.environ.get('XML_PATH')
|
self.XML_path = os.environ.get("XML_PATH")
|
||||||
if self.stig_path is None:
|
if self.stig_path is None:
|
||||||
self.stig_path = self._get_STIG_path()
|
self.stig_path = self._get_STIG_path()
|
||||||
self._display.display('Using STIG_PATH: {}'.format(self.stig_path))
|
self._display.display("Using STIG_PATH: {}".format(self.stig_path))
|
||||||
if self.XML_path is None:
|
if self.XML_path is None:
|
||||||
self.XML_path = tempfile.mkdtemp() + "/xccdf-results.xml"
|
self.XML_path = tempfile.mkdtemp() + "/xccdf-results.xml"
|
||||||
self._display.display('Using XML_PATH: {}'.format(self.XML_path))
|
self._display.display("Using XML_PATH: {}".format(self.XML_path))
|
||||||
|
|
||||||
print("Writing: {}".format(self.XML_path))
|
print("Writing: {}".format(self.XML_path))
|
||||||
STIG_name = os.path.basename(self.stig_path)
|
STIG_name = os.path.basename(self.stig_path)
|
||||||
ET.register_namespace('cdf', 'http://checklists.nist.gov/xccdf/1.2')
|
ET.register_namespace("cdf", "http://checklists.nist.gov/xccdf/1.2")
|
||||||
self.tr = ET.Element('{http://checklists.nist.gov/xccdf/1.2}TestResult')
|
self.tr = ET.Element("{http://checklists.nist.gov/xccdf/1.2}TestResult")
|
||||||
self.tr.set('id', 'xccdf_mil.disa.stig_testresult_scap_mil.disa_comp_{}'.format(STIG_name))
|
self.tr.set(
|
||||||
|
"id",
|
||||||
|
"xccdf_mil.disa.stig_testresult_scap_mil.disa_comp_{}".format(STIG_name),
|
||||||
|
)
|
||||||
endtime = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
endtime = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
||||||
self.tr.set('end-time', endtime)
|
self.tr.set("end-time", endtime)
|
||||||
tg = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}target')
|
tg = ET.SubElement(self.tr, "{http://checklists.nist.gov/xccdf/1.2}target")
|
||||||
tg.text = platform.node()
|
tg.text = platform.node()
|
||||||
|
|
||||||
def _get_rev(self, nid):
|
def _get_rev(self, nid):
|
||||||
with open(self.stig_path, 'r') as f:
|
with open(self.stig_path, "r") as f:
|
||||||
r = 'SV-{}r(?P<rev>\d+)_rule'.format(nid)
|
r = "SV-{}r(?P<rev>\d+)_rule".format(nid)
|
||||||
m = re.search(r, f.read())
|
m = re.search(r, f.read())
|
||||||
if m:
|
if m:
|
||||||
rev = m.group('rev')
|
rev = m.group("rev")
|
||||||
else:
|
else:
|
||||||
rev = '0'
|
rev = "0"
|
||||||
return rev
|
return rev
|
||||||
|
|
||||||
def v2_runner_on_ok(self, result):
|
def v2_runner_on_ok(self, result):
|
||||||
name = result._task.get_name()
|
name = result._task.get_name()
|
||||||
m = re.search('stigrule_(?P<id>\d+)', name)
|
m = re.search("stigrule_(?P<id>\d+)", name)
|
||||||
if m:
|
if m:
|
||||||
nid = m.group('id')
|
nid = m.group("id")
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
rev = self._get_rev(nid)
|
rev = self._get_rev(nid)
|
||||||
key = "{}r{}".format(nid, rev)
|
key = "{}r{}".format(nid, rev)
|
||||||
if self.rules.get(key, 'Unknown') != False:
|
if self.rules.get(key, "Unknown") != False:
|
||||||
self.rules[key] = result.is_changed()
|
self.rules[key] = result.is_changed()
|
||||||
|
|
||||||
def v2_playbook_on_stats(self, stats):
|
def v2_playbook_on_stats(self, stats):
|
||||||
for rule, changed in self.rules.items():
|
for rule, changed in self.rules.items():
|
||||||
state = 'fail' if changed else 'pass'
|
state = "fail" if changed else "pass"
|
||||||
rr = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}rule-result')
|
rr = ET.SubElement(
|
||||||
rr.set('idref', 'xccdf_mil.disa.stig_rule_SV-{}_rule'.format(rule))
|
self.tr, "{http://checklists.nist.gov/xccdf/1.2}rule-result"
|
||||||
rs = ET.SubElement(rr, '{http://checklists.nist.gov/xccdf/1.2}result')
|
)
|
||||||
|
rr.set("idref", "xccdf_mil.disa.stig_rule_SV-{}_rule".format(rule))
|
||||||
|
rs = ET.SubElement(rr, "{http://checklists.nist.gov/xccdf/1.2}result")
|
||||||
rs.text = state
|
rs.text = state
|
||||||
passing = len(self.rules) - sum(self.rules.values())
|
passing = len(self.rules) - sum(self.rules.values())
|
||||||
sc = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}score')
|
sc = ET.SubElement(self.tr, "{http://checklists.nist.gov/xccdf/1.2}score")
|
||||||
sc.set('maximum', str(len(self.rules)))
|
sc.set("maximum", str(len(self.rules)))
|
||||||
sc.set('system', 'urn:xccdf:scoring:flat-unweighted')
|
sc.set("system", "urn:xccdf:scoring:flat-unweighted")
|
||||||
sc.text = str(passing)
|
sc.text = str(passing)
|
||||||
with open(self.XML_path, 'wb') as f:
|
with open(self.XML_path, "wb") as f:
|
||||||
out = ET.tostring(self.tr)
|
out = ET.tostring(self.tr)
|
||||||
pretty = xml.dom.minidom.parseString(out).toprettyxml(encoding='utf-8')
|
pretty = xml.dom.minidom.parseString(out).toprettyxml(encoding="utf-8")
|
||||||
f.write(pretty)
|
f.write(pretty)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
@@ -11,76 +12,82 @@ import os
|
|||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
|
|
||||||
|
|
||||||
class CallbackModule(CallbackBase):
|
class CallbackModule(CallbackBase):
|
||||||
CALLBACK_VERSION = 2.0
|
CALLBACK_VERSION = 2.0
|
||||||
CALLBACK_TYPE = 'xml'
|
CALLBACK_TYPE = "xml"
|
||||||
CALLBACK_NAME = 'stig_xml'
|
CALLBACK_NAME = "stig_xml"
|
||||||
|
|
||||||
CALLBACK_NEEDS_WHITELIST = True
|
CALLBACK_NEEDS_WHITELIST = True
|
||||||
|
|
||||||
def _get_STIG_path(self):
|
def _get_STIG_path(self):
|
||||||
cwd = os.path.abspath('.')
|
cwd = os.path.abspath(".")
|
||||||
for dirpath, dirs, files in os.walk(cwd):
|
for dirpath, dirs, files in os.walk(cwd):
|
||||||
if os.path.sep + 'files' in dirpath and '.xml' in files[0]:
|
if os.path.sep + "files" in dirpath and ".xml" in files[0]:
|
||||||
return os.path.join(cwd, dirpath, files[0])
|
return os.path.join(cwd, dirpath, files[0])
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(CallbackModule, self).__init__()
|
super(CallbackModule, self).__init__()
|
||||||
self.rules = {}
|
self.rules = {}
|
||||||
self.stig_path = os.environ.get('STIG_PATH')
|
self.stig_path = os.environ.get("STIG_PATH")
|
||||||
self.XML_path = os.environ.get('XML_PATH')
|
self.XML_path = os.environ.get("XML_PATH")
|
||||||
if self.stig_path is None:
|
if self.stig_path is None:
|
||||||
self.stig_path = self._get_STIG_path()
|
self.stig_path = self._get_STIG_path()
|
||||||
self._display.display('Using STIG_PATH: {}'.format(self.stig_path))
|
self._display.display("Using STIG_PATH: {}".format(self.stig_path))
|
||||||
if self.XML_path is None:
|
if self.XML_path is None:
|
||||||
self.XML_path = tempfile.mkdtemp() + "/xccdf-results.xml"
|
self.XML_path = tempfile.mkdtemp() + "/xccdf-results.xml"
|
||||||
self._display.display('Using XML_PATH: {}'.format(self.XML_path))
|
self._display.display("Using XML_PATH: {}".format(self.XML_path))
|
||||||
|
|
||||||
print("Writing: {}".format(self.XML_path))
|
print("Writing: {}".format(self.XML_path))
|
||||||
STIG_name = os.path.basename(self.stig_path)
|
STIG_name = os.path.basename(self.stig_path)
|
||||||
ET.register_namespace('cdf', 'http://checklists.nist.gov/xccdf/1.2')
|
ET.register_namespace("cdf", "http://checklists.nist.gov/xccdf/1.2")
|
||||||
self.tr = ET.Element('{http://checklists.nist.gov/xccdf/1.2}TestResult')
|
self.tr = ET.Element("{http://checklists.nist.gov/xccdf/1.2}TestResult")
|
||||||
self.tr.set('id', 'xccdf_mil.disa.stig_testresult_scap_mil.disa_comp_{}'.format(STIG_name))
|
self.tr.set(
|
||||||
|
"id",
|
||||||
|
"xccdf_mil.disa.stig_testresult_scap_mil.disa_comp_{}".format(STIG_name),
|
||||||
|
)
|
||||||
endtime = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
endtime = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
||||||
self.tr.set('end-time', endtime)
|
self.tr.set("end-time", endtime)
|
||||||
tg = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}target')
|
tg = ET.SubElement(self.tr, "{http://checklists.nist.gov/xccdf/1.2}target")
|
||||||
tg.text = platform.node()
|
tg.text = platform.node()
|
||||||
|
|
||||||
def _get_rev(self, nid):
|
def _get_rev(self, nid):
|
||||||
with open(self.stig_path, 'r') as f:
|
with open(self.stig_path, "r") as f:
|
||||||
r = 'SV-{}r(?P<rev>\d+)_rule'.format(nid)
|
r = "SV-{}r(?P<rev>\d+)_rule".format(nid)
|
||||||
m = re.search(r, f.read())
|
m = re.search(r, f.read())
|
||||||
if m:
|
if m:
|
||||||
rev = m.group('rev')
|
rev = m.group("rev")
|
||||||
else:
|
else:
|
||||||
rev = '0'
|
rev = "0"
|
||||||
return rev
|
return rev
|
||||||
|
|
||||||
def v2_runner_on_ok(self, result):
|
def v2_runner_on_ok(self, result):
|
||||||
name = result._task.get_name()
|
name = result._task.get_name()
|
||||||
m = re.search('stigrule_(?P<id>\d+)', name)
|
m = re.search("stigrule_(?P<id>\d+)", name)
|
||||||
if m:
|
if m:
|
||||||
nid = m.group('id')
|
nid = m.group("id")
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
rev = self._get_rev(nid)
|
rev = self._get_rev(nid)
|
||||||
key = "{}r{}".format(nid, rev)
|
key = "{}r{}".format(nid, rev)
|
||||||
if self.rules.get(key, 'Unknown') != False:
|
if self.rules.get(key, "Unknown") != False:
|
||||||
self.rules[key] = result.is_changed()
|
self.rules[key] = result.is_changed()
|
||||||
|
|
||||||
def v2_playbook_on_stats(self, stats):
|
def v2_playbook_on_stats(self, stats):
|
||||||
for rule, changed in self.rules.items():
|
for rule, changed in self.rules.items():
|
||||||
state = 'fail' if changed else 'pass'
|
state = "fail" if changed else "pass"
|
||||||
rr = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}rule-result')
|
rr = ET.SubElement(
|
||||||
rr.set('idref', 'xccdf_mil.disa.stig_rule_SV-{}_rule'.format(rule))
|
self.tr, "{http://checklists.nist.gov/xccdf/1.2}rule-result"
|
||||||
rs = ET.SubElement(rr, '{http://checklists.nist.gov/xccdf/1.2}result')
|
)
|
||||||
|
rr.set("idref", "xccdf_mil.disa.stig_rule_SV-{}_rule".format(rule))
|
||||||
|
rs = ET.SubElement(rr, "{http://checklists.nist.gov/xccdf/1.2}result")
|
||||||
rs.text = state
|
rs.text = state
|
||||||
passing = len(self.rules) - sum(self.rules.values())
|
passing = len(self.rules) - sum(self.rules.values())
|
||||||
sc = ET.SubElement(self.tr, '{http://checklists.nist.gov/xccdf/1.2}score')
|
sc = ET.SubElement(self.tr, "{http://checklists.nist.gov/xccdf/1.2}score")
|
||||||
sc.set('maximum', str(len(self.rules)))
|
sc.set("maximum", str(len(self.rules)))
|
||||||
sc.set('system', 'urn:xccdf:scoring:flat-unweighted')
|
sc.set("system", "urn:xccdf:scoring:flat-unweighted")
|
||||||
sc.text = str(passing)
|
sc.text = str(passing)
|
||||||
with open(self.XML_path, 'wb') as f:
|
with open(self.XML_path, "wb") as f:
|
||||||
out = ET.tostring(self.tr)
|
out = ET.tostring(self.tr)
|
||||||
pretty = xml.dom.minidom.parseString(out).toprettyxml(encoding='utf-8')
|
pretty = xml.dom.minidom.parseString(out).toprettyxml(encoding="utf-8")
|
||||||
f.write(pretty)
|
f.write(pretty)
|
||||||
|
|||||||
Reference in New Issue
Block a user