Users can now specify args for benchmarks that have been imported or for
files that have not been imported, even in the same command.
---
src/secstate/main.py | 67 ++++++++++++++++++++++++++++++++------------------
1 files changed, 43 insertions(+), 24 deletions(-)
diff --git a/src/secstate/main.py b/src/secstate/main.py
index a4a6436..711d335 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -273,6 +273,11 @@ class Secstate:
benchmark.vals[refval.item] = value_instance_to_value(value.get_instance_by_selector(refval.selector))
puppet_files = get_puppet_files(benchmark)
+ if store_path == None:
+ if self.content.has_key(benchmark.id):
+ puppet_files = map(lambda x: os.path.join(self.config.get('secstate', 'puppet_dir'), x), puppet_files)
+ else:
+ puppet_files = map(lambda x: os.path.join(os.path.dirname(benchmark_file), x), puppet_files)
benchmark.__dict__['puppet'] = puppet_files
benchmark.config.set(benchmark.id, 'puppet', json.dumps(list(puppet_files)))
@@ -295,7 +300,7 @@ class Secstate:
for oval in list(set(oval_files)):
shutil.copy(os.path.join(oval_path, oval), directory)
- for puppet in puppet_files:
+ for puppet in benchmark.puppet:
new_puppet = os.path.join(os.path.dirname(benchmark_file), puppet)
puppet_dir = self.config.get('secstate', 'puppet_dir')
if not os.path.isdir(puppet_dir):
@@ -311,6 +316,7 @@ class Secstate:
continue
shutil.copy(os.path.join(os.path.dirname(benchmark_file), puppet), self.config.get('secstate', 'puppet_dir'))
+ puppet = os.path.join(puppet_dir, puppet)
except (IOError, OSError), e:
self.log.error("Error importing content: %(error)s" % {'error':e})
@@ -368,8 +374,9 @@ class Secstate:
directory = None
for extracted_file in os.listdir(extract_path):
print extracted_file
- if is_benchmark(os.path.join(extract_path, extracted_file)):
- xccdf = extracted_file
+ if mimetypes.guess_type(extracted_file)[0] == "text/xml":
+ if is_benchmark(os.path.join(extract_path, extracted_file)):
+ xccdf = extracted_file
if xccdf == None:
self.log.error("Could not find XCCDF benchmark in archive %(file)s", {'file':zip})
@@ -940,7 +947,11 @@ class Secstate:
ret = self.sublist(content, arg, recurse, show_all)
return ret
- def get_passed_result_ids(self, xccdf_results):
+ def get_passed_result_ids(self, xccdf_results, original_benchmarks):
+ if original_benchmarks == None:
+ self.log.error("Error importing original benchmark")
+ return (None, None)
+
if xccdf_results == None:
return ([], set())
@@ -961,50 +972,58 @@ class Secstate:
self.log.error("Error importing benchmark %(file)s" % {'file':result})
return None, None
- if not self.content.has_key(benchmark.id):
- self.log.error("Results file does not match any imported content")
- return None, None
+ if not original_benchmarks.has_key(benchmark.id):
+ self.log.info("Results file '%(file)s' does not match any remediation content, skipping" % {'file':result})
+ continue
- imported_benchmark = self.import_content(benchmark.id)
- if imported_benchmark == None:
- self.log.error("Error loading imported content: %(id)s" % {'id':benchmark.id})
- return None, None
-
result_ids.append(benchmark.id)
passing_ids = set()
for test_result in benchmark.results:
for rule_result in test_result.rule_results:
id = rule_result.idref
result = rule_result.result
- if result != oscap.xccdf.XCCDF_RESULT_FAIL or not imported_benchmark.selections[id]:
+ if result != oscap.xccdf.XCCDF_RESULT_FAIL or not original_benchmarks[benchmark.id].selections[id]:
passing_ids.add(id)
return (result_ids, passing_ids)
def remediate_puppet(self, args, xccdf_results=None, log_dest=None, noop=False, verbose=False, yes_all=False):
- (result_ids, passing_ids) = self.get_passed_result_ids(xccdf_results)
- if result_ids == None or passing_ids == None:
- return False
template = '%s\n'
if args == []:
args = self.content.keys()
+ benchmarks = {}
for arg in args:
- if arg not in result_ids and not yes_all:
- inpt = raw_input("No results file provided for %s, remediate anyway? " % arg)
- if inpt != 'y':
- continue
-
benchmark = self.import_content(arg)
if benchmark == None:
self.log.error("Error importing content: %s" % arg)
return False
if not benchmark.__dict__.has_key('oval'):
# OVAL Definition Model, so skip
+ self.log.info("Skipping OVAL File: '%(file)s'" % {'file':arg})
continue
+ benchmarks[benchmark.id] = benchmark
+
+ (result_ids, passing_ids) = self.get_passed_result_ids(xccdf_results, benchmarks)
+ if result_ids == None or passing_ids == None:
+ return False
+
+ for bench_id,benchmark in benchmarks.items():
+ if bench_id not in result_ids and not yes_all:
+ inpt = raw_input("No results file provided for %s, remediate anyway? " % bench_id)
+ if inpt != 'y':
+ continue
+
+ if self.content.has_key(bench_id):
+ site_pp = self.config.get('secstate', 'site_pp')
+ else:
+ (site_pp_buf, site_pp) = tempfile.mkstemp()
+ for puppet in benchmark.puppet:
+ os.write(site_pp_buf, 'import "%(file)s"\n' % {'file':puppet})
+ os.close(site_pp_buf)
- self.log.info("-- Remediating %(id)s --" % {'id':arg})
+ self.log.info("-- Remediating %(id)s --" % {'id':bench_id})
try:
ignore_ids = []
for key in benchmark.selections:
@@ -1019,13 +1038,13 @@ class Secstate:
if (puppet_content["classes"] == []) and (puppet_content["parameters"] == {}):
sys.stderr.write("No remediation to be done.\n")
if verbose:
- sys.stderr.write("Either results XCCDF did not report any failurse, or failures reported did not have a well formed <fix> element in the corresponding XCCDF benchmark.\n")
+ sys.stderr.write("Either results XCCDF did not report any failures, or failures reported did not have a well formed <fix> element in the corresponding XCCDF benchmark.\n")
else:
handle, fname = tempfile.mkstemp(suffix='.yaml')
os.write(handle, template % dict_to_external(puppet_content))
os.close(handle)
- puppet_args = ['/usr/bin/puppet', '--external_node', '/usr/libexec/secstate/secstate_external_node %s' % fname, '--node_terminus', 'exec', self.config.get('secstate', 'site_pp')]
+ puppet_args = ['/usr/bin/puppet', '--external_node', '/usr/libexec/secstate/secstate_external_node %s' % fname, '--node_terminus', 'exec', site_pp]
if noop:
puppet_args.append('--noop')
if log_dest:
--
1.7.2.2