On Tue, 2010-09-14 at 10:44 -0400, Josh Adams wrote:
Also added code to keep track of tempfiles and cleanup on exit.
Fixes bug #8096
---
src/bin/secstate | 49 +++++++++++++++++++++++++++++++------------------
src/secstate/main.py | 9 +++++----
src/secstate/util.py | 1 -
3 files changed, 36 insertions(+), 23 deletions(-)
diff --git a/src/bin/secstate b/src/bin/secstate
index ebaf9c8..c560510 100644
--- a/src/bin/secstate
+++ b/src/bin/secstate
@@ -24,6 +24,7 @@
import sys
import ConfigParser
import os
+import shutil
from optparse import OptionParser
import openscap_api as oscap
@@ -57,67 +58,79 @@ def main():
subcommand = sys.argv[1]
except IndexError, e:
usage()
- return -1
+ return_code = -1
arg_num = 2
if (subcommand == '-c') or (subcommand == '--config'):
if not sec_instance.setConfigFile(sys.argv[arg_num]):
usage()
- return -1
+ return_code = -1
arg_num += 2
try:
subcommand = sys.argv[arg_num - 1]
except IndexError:
usage()
- return -1
+ return_code = -1
if subcommand == 'help':
- return help(sys.argv[arg_num:])
+ return_code = help(sys.argv[arg_num:])
elif subcommand == 'export':
- return export(sys.argv[arg_num:])
+ return_code = export(sys.argv[arg_num:])
elif subcommand == 'search':
- return search(sys.argv[arg_num:])
+ return_code = search(sys.argv[arg_num:])
elif subcommand == 'list':
- return list_content(sys.argv[arg_num:])
+ return_code = list_content(sys.argv[arg_num:])
elif subcommand == 'show':
- return show(sys.argv[arg_num:])
+ return_code = show(sys.argv[arg_num:])
elif os.geteuid() != 0:
sys.stderr.write("secstate must be run as root!\n")
- return -1
+ return_code = -1
elif subcommand == 'import':
- return import_content(sys.argv[arg_num:])
+ return_code = import_content(sys.argv[arg_num:])
elif subcommand == 'remove':
- return remove_content(sys.argv[arg_num:])
+ return_code = remove_content(sys.argv[arg_num:])
elif subcommand == 'select':
- return select(sys.argv[arg_num:], True)
+ return_code = select(sys.argv[arg_num:], True)
elif subcommand == 'deselect':
- return select(sys.argv[arg_num:], False)
+ return_code = select(sys.argv[arg_num:], False)
elif subcommand == 'audit':
- return audit(sys.argv[arg_num:])
+ return_code = audit(sys.argv[arg_num:])
elif subcommand == 'remediate':
- return remediate(sys.argv[arg_num:])
+ return_code = remediate(sys.argv[arg_num:])
elif subcommand == 'mitigate':
- return mitigate(sys.argv[arg_num:])
+ return_code = mitigate(sys.argv[arg_num:])
elif subcommand == 'save':
- return save_profile(sys.argv[arg_num:])
+ return_code = save_profile(sys.argv[arg_num:])
else:
sys.stderr.write("Uknown subcommand: %(command)s" %
{'command':subcommand})
usage()
- return -1
+ return_code = -1
+
+ try:
+ for dir in sec_instance.tempfiles['dirs']:
+ shutil.rmtree(dir)
+
+ for tmpfile in sec_instance.tempfiles['files']:
+ os.remove(tmpfile)
+ except IOError,e:
+ sec_instance.log.error("Error cleaning up temporary files: %(err)s" %
{'err':e})
+ return_code = -1
This code should be moved into a cleanup method in the SecState class. Since the SecState
class is responsible for creating these files and directories, it should also be
responsible for cleaning them up. We might be able to have the __del__ method call the
cleanup function so there isn't a need to call it explicitly.
Marshall
+
+ return return_code
def help(arg):
if arg == []:
diff --git a/src/secstate/main.py b/src/secstate/main.py
index f2025cd..60bb864 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -54,6 +54,7 @@ class Secstate:
self.load_content()
self.log = self.getLogger()
self.benchmark_dir = self.config.get('secstate',
'benchmark_dir')
+ self.tempfiles = {'dirs':[], 'files':[]}
def setConfigFile(self, conf):
config = ConfigParser.ConfigParser()
@@ -349,6 +350,7 @@ class Secstate:
Output: Success of failure of the import
"""
extract_path = tempfile.mkdtemp()
+ self.tempfiles['dirs'].append(extract_path)
if type[0] == "application/x-tar":
tar_file = None
@@ -407,11 +409,8 @@ class Secstate:
if benchmark == None:
return None
- # Delete temporary directory now that we are done with it
- shutil.rmtree(extract_path)
return benchmark
-
def import_content(self, content, changes=True, save=False,
active_profile=NONE_PROFILE):
"""
Function: Validates XCCDF/OVAL content and optionally saves it to the data
store
@@ -474,6 +473,7 @@ class Secstate:
benchmark_file = self.content[benchmark_id]
else:
benchmark_file = tempfile.mktemp()
+ self.tempfiles['files'].append(benchmark_file)
benchmark = self.import_content(benchmark_id)
if benchmark.export(benchmark_file) == None:
self.log.error("Error exporting benchmark to %(file)s" %
{'file':new_file})
@@ -1049,6 +1049,7 @@ class Secstate:
site_pp = self.config.get('secstate', 'site_pp')
else:
(site_pp_buf, site_pp) = tempfile.mkstemp()
+ self.tempfiles['files'].append(site_pp)
for puppet in benchmark.puppet:
os.write(site_pp_buf, 'import "%(file)s"\n' %
{'file':puppet})
os.close(site_pp_buf)
@@ -1073,6 +1074,7 @@ class Secstate:
else:
handle, fname = tempfile.mkstemp(suffix='.yaml')
+ self.tempfiles['files'].append(fname)
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', site_pp]
@@ -1083,7 +1085,6 @@ class Secstate:
if verbose:
puppet_args.append('--verbose')
subprocess.call(puppet_args)
- os.unlink(fname)
return True
diff --git a/src/secstate/util.py b/src/secstate/util.py
index d30a169..1b208cd 100644
--- a/src/secstate/util.py
+++ b/src/secstate/util.py
@@ -27,7 +27,6 @@ import time
import re
import ConfigParser
import json
-import tempfile
import zipfile
import libxml2
import libxslt