[PATCH] Add updated results2html.xsl to remove warning message when transforming oval results.
by Jason Dana
---
src/share/transforms/results2html.xsl | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/share/transforms/results2html.xsl b/src/share/transforms/results2html.xsl
index 27afb92..1d21f7a 100644
--- a/src/share/transforms/results2html.xsl
+++ b/src/share/transforms/results2html.xsl
@@ -85,9 +85,9 @@
<div id="results">
<ul id="tree">
<xsl:apply-templates select="*[local-name(.)='Index']/*[local-name(.)='file']"/>
- <!-- Will throw warning if applied to an OVAL results XML -->
- <xsl:apply-templates select="document(concat($path,$genOvalRes))//*[local-name(.)='interfaces']"/>
- <!-- -->
+ <xsl:if test="$genOval">
+ <xsl:apply-templates select="document(concat($path,$genOvalRes))//*[local-name(.)='interfaces']"/>
+ </xsl:if>
<xsl:apply-templates select="//*[local-name(.)='interfaces']"/>
<xsl:apply-templates select="*[local-name(.)='Benchmark']//*[local-name(.)='TestResult']"/>
<xsl:apply-templates select="*[local-name(.)='oval_results']"/>
--
1.7.2.1
13 years, 8 months
[PATCH] Added error message and return code for 'show'
by Josh Adams
Also fixed several other return codes for other sub-commands.
Fixes bug #7615
---
src/bin/secstate | 16 ++++++++--------
src/secstate/main.py | 3 +++
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/src/bin/secstate b/src/bin/secstate
index b4c484d..2962ad4 100644
--- a/src/bin/secstate
+++ b/src/bin/secstate
@@ -87,28 +87,28 @@ def main():
return remove_content(sys.argv[arg_num:])
elif subcommand == 'select':
- select(sys.argv[arg_num:], True)
+ return select(sys.argv[arg_num:], True)
elif subcommand == 'deselect':
- select(sys.argv[arg_num:], False)
+ return select(sys.argv[arg_num:], False)
elif subcommand == 'audit':
- audit(sys.argv[arg_num:])
+ return audit(sys.argv[arg_num:])
elif subcommand == 'search':
- search(sys.argv[arg_num:])
+ return search(sys.argv[arg_num:])
elif subcommand == 'list':
- list_content(sys.argv[arg_num:])
+ return list_content(sys.argv[arg_num:])
elif subcommand == 'show':
- show(sys.argv[arg_num:])
+ return show(sys.argv[arg_num:])
elif subcommand == 'remediate':
- remediate(sys.argv[arg_num:])
+ return remediate(sys.argv[arg_num:])
elif subcommand == 'save':
- save_profile(sys.argv[arg_num:])
+ return save_profile(sys.argv[arg_num:])
else:
sys.stderr.write("Uknown subcommand: %(command)s" % {'command':subcommand})
diff --git a/src/secstate/main.py b/src/secstate/main.py
index 9a77b16..712878b 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -752,6 +752,9 @@ class Secstate:
return True
+ self.log.error("Item '%(id)s' could not be found in the imported content" % {'id':item_id})
+ return False
+
def sublist(self, content, arg, recurse, show_all, tabs=0):
tabstr = "\t" * tabs
selected = ""
--
1.7.2.1
13 years, 8 months
[PATCH] Fixed issue when searching with no arguments
by Josh Adams
Also added an error message and proper return value when nothing is
found.
Fixes bug #7614
---
src/bin/secstate | 2 ++
src/secstate/main.py | 9 +++++++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/bin/secstate b/src/bin/secstate
index b4c484d..4588203 100644
--- a/src/bin/secstate
+++ b/src/bin/secstate
@@ -259,6 +259,8 @@ def remediate(arguments):
return -1
def search(arguments):
+ if arguments == []:
+ arguments.append('-h')
parser = OptionParser(usage="secstate search [options] <string>")
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
help="Show extra information from the search")
diff --git a/src/secstate/main.py b/src/secstate/main.py
index 9a77b16..e2f2351 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -634,6 +634,7 @@ class Secstate:
Output: None
Side Effects: Prints out the results of the search
"""
+ found_something = False
for key in self.content:
content = self.import_content(key)
if content == None:
@@ -649,6 +650,7 @@ class Secstate:
if defn == None:
continue
else:
+ found_something = True
rule_defs = rules_to_defs(content)
for k, v in rule_defs.iteritems():
if search_string in v:
@@ -668,11 +670,14 @@ class Secstate:
if (title != None) and (description != None):
if (search_string in title) or (search_string in description):
+ found_something = True
print "\t%(id)s:" % {'id':item.id}
print "\t\tTitle: '%(title)s'" % {'title':title}
print "\t\tDescription: %(description)s\n" % {'description':description}
-
- return True
+
+ if not found_something:
+ self.log.error("Could not find anything in the imported content that matches '%(string)s'" % {'string':search_string})
+ return found_something
def show(self, item_id=None, verbose=False):
for key in self.content:
--
1.7.2.1
13 years, 8 months
[PATCH] Check file existence when importing
by Josh Adams
Make sure the file being imported actually exists.
Fixes bug #7617
---
src/secstate/main.py | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/src/secstate/main.py b/src/secstate/main.py
index 9a77b16..b720cd1 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -386,6 +386,10 @@ class Secstate:
if save:
store_path = self.config.get('secstate', 'benchmark_dir')
+ if not os.path.isfile(content):
+ self.log.error("No such file: '%(file)s'" % {'file':content})
+ return None
+
file_type = mimetypes.guess_type(content)
if file_type[0] == "text/xml":
if is_benchmark(content):
--
1.7.2.1
13 years, 8 months
[PATCH] Changed usage string for (de)select command
by Josh Adams
Fixes bug #7589
---
src/bin/secstate | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/bin/secstate b/src/bin/secstate
index b4c484d..d55ac17 100644
--- a/src/bin/secstate
+++ b/src/bin/secstate
@@ -178,11 +178,15 @@ def remove_content(arguments):
return -1
def select(arguments, value):
- parser = OptionParser(usage="secstate select <benchmark> <all/id>")
+ sel = ""
+ if not value:
+ sel = "de"
+
+ parser = OptionParser(usage="secstate %(sel)sselect <benchmark> <all/id>" % {'sel':sel})
parser.add_option('-m', '--message', action='store', type='string', dest='message',
- default=None, help="Adds message about selection")
+ default=None, help="Adds message about %(sel)sselection" % {'sel':sel})
parser.add_option('-r', '--recurse', action='store_true', dest='recurse', default=False,
- help="Recursively select or deselect rules inside of groups or benchmarks")
+ help="Recursively %(sel)sselect rules inside of groups or benchmarks" % {'sel':sel})
(options, args) = parser.parse_args(arguments)
if len(args) == 1:
if not sec_instance.select(args[0], args[0], value, recurse=options.recurse, message=options.message):
--
1.7.2.1
13 years, 8 months
[PATCH] Fixed 'show' and 'search' commands
by Josh Adams
Forgot to update the search and show commands from when I changed how
benchmarks are imported in commit ce899011cfc6cda06bf189ed946ed4465c51b283
---
src/secstate/main.py | 103 +++++++++++++++++++++++++-------------------------
1 files changed, 52 insertions(+), 51 deletions(-)
diff --git a/src/secstate/main.py b/src/secstate/main.py
index 4ca6b18..8d4d6f7 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -621,53 +621,53 @@ class Secstate:
"""
for key in self.content:
content = self.import_content(key)
- if benchmark == None:
- if def_model == None:
- self.log.error("Error importing content: %(key)s" % {'key':key})
- return False
- else:
- continue
+ if content == None:
+ self.log.error("Error importing content: %(key)s" % {'key':key})
+ return False
print "In benchmark %(bench)s:" % {'bench':key}
if reverse:
- defn = def_model.get_definition(search_string)
- if defn == None:
- continue
- else:
- rule_defs = rules_to_defs(benchmark)
- for k, v in rule_defs.iteritems():
- if search_string in v:
- print "OVAL Definition %(id)s is used by %(rule_id)s" % {'id':search_string, 'rule_id':k}
- continue
-
- for item in xccdf_get_items(benchmark, oscap.xccdf.XCCDF_ITEM, benchmark.content):
- title = None
- description = None
-
- if len(item.title) > 0:
- title = item.title[0].text
-
- if len(item.description) > 0:
- description = item.description[0].text
-
- if (title != None) and (description != None):
- if (search_string in title) or (search_string in description):
- print "\t%(id)s:" % {'id':item.id}
- print "\t\tTitle: '%(title)s'" % {'title':title}
- print "\t\tDescription: %(description)s\n" % {'description':description}
+ if content.__dict__.has_key('oval'):
+ for def_model in content.oval.values():
+ defn = def_model.get_definition(search_string)
+ if defn == None:
+ continue
+ else:
+ rule_defs = rules_to_defs(content)
+ for k, v in rule_defs.iteritems():
+ if search_string in v:
+ print "OVAL Definition %(id)s is used by %(rule_id)s" % {'id':search_string, 'rule_id':k}
+ continue
+
+ if content.__dict__.has_key('oval'):
+ for item in xccdf_get_items(content, oscap.xccdf.XCCDF_ITEM, content.content):
+ title = None
+ description = None
+
+ if len(item.title) > 0:
+ title = item.title[0].text
+ if len(item.description) > 0:
+ description = item.description[0].text
+
+ if (title != None) and (description != None):
+ if (search_string in title) or (search_string in description):
+ print "\t%(id)s:" % {'id':item.id}
+ print "\t\tTitle: '%(title)s'" % {'title':title}
+ print "\t\tDescription: %(description)s\n" % {'description':description}
+
return True
def show(self, item_id=None, verbose=False):
for key in self.content:
content = self.import_content(key)
- if benchmark == None:
- if def_model == None:
- self.log.error("Error importing content: %(file)s" % {'file':key})
- return None
-
- defn = def_model.get_definition(item_id)
+ if content == None:
+ self.log.error("Error importing content: %(file)s" % {'file':key})
+ return None
+
+ if not content.__dict__.has_key('oval'):
+ defn = content.get_definition(item_id)
if defn == None:
continue
else:
@@ -676,20 +676,21 @@ class Secstate:
print "\tDescription: '%(desc)s'" % {'desc':defn.description}
return True
+ item = None
if item_id == key:
- item = benchmark.to_item()
+ item = content.to_item()
else:
- item = benchmark.get_item(item_id)
+ if content.__dict__.has_key('oval'):
+ item = content.get_item(item_id)
if item == None:
- defn = def_model.get_definition(item_id)
- if defn == None:
- continue
- else:
- print "%(id)s:" % {'id':item_id}
- print "\tTitle: '%(title)s'" % {'title':defn.title}
- print "\tDescription: '%(desc)s'" % {'desc':defn.description}
- return True
+ for def_model in content.oval.values():
+ defn = def_model.get_definition(item_id)
+ if defn != None:
+ print "%(id)s:" % {'id':item_id}
+ print "\tTitle: '%(title)s'" % {'title':defn.title}
+ print "\tDescription: '%(desc)s'" % {'desc':defn.description}
+ return True
else:
print "%(id)s:" % {'id':item.id}
@@ -704,11 +705,11 @@ class Secstate:
type = item.type
if type == oscap.xccdf.XCCDF_BENCHMARK:
active_profile = NONE_PROFILE
- if benchmark.config.has_option(key, 'profile'):
- active_profile = benchmark.config.get(key, 'profile')
- if len(benchmark.profiles) > 0:
+ if content.config.has_option(key, 'profile'):
+ active_profile = content.config.get(key, 'profile')
+ if len(content.profiles) > 0:
print "\tProfiles:"
- for profile in benchmark.profiles:
+ for profile in content.profiles:
selected = "[ ]"
title = ""
prof_id = profile.id
--
1.7.2.1
13 years, 8 months
[PATCH] Fixed OVAL output
by Josh Adams
Also cleaned up how results are passed to the output function for both
OVAL and XCCDF.
---
src/secstate/main.py | 3 ++-
src/secstate/util.py | 20 ++++++++------------
2 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/src/secstate/main.py b/src/secstate/main.py
index 4ca6b18..9cee13d 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -163,6 +163,7 @@ class Secstate:
return None
oval_id = os.path.splitext(os.path.basename(oval_file))[0]
+ def_model.__dict__['id'] = oval_id
if self.content.has_key(oval_id):
config = ConfigParser.ConfigParser()
@@ -172,7 +173,6 @@ class Secstate:
return None
def_model.__dict__['config'] = config
- def_model.__dict__['id'] = oval_id
if store_path:
if not os.path.isdir(store_path):
@@ -600,6 +600,7 @@ class Secstate:
else:
sess = oscap.oval.agent_new_session(scanned_content, scanned_content.id)
+ sess.__dict__['filename'] = scanned_content.id
(res_benchmark, res_models) = evaluate_oval(sess, verbose)
if (res_benchmark == None) and (res_models == None):
diff --git a/src/secstate/util.py b/src/secstate/util.py
index 647eaf7..5c1336d 100644
--- a/src/secstate/util.py
+++ b/src/secstate/util.py
@@ -107,6 +107,7 @@ def evaluate_xccdf(benchmark, url_XCCDF, s_profile=None, all=False, verbose=Fals
sessions = []
for oval_file,def_model in benchmark.oval.items():
tmp_sess = oscap.oval.agent.new_session(def_model, oval_file)
+ tmp_sess.__dict__['filename'] = oval_file
policy_model.register_engine_oval(tmp_sess)
sessions.append(tmp_sess)
@@ -142,10 +143,8 @@ def evaluate_xccdf(benchmark, url_XCCDF, s_profile=None, all=False, verbose=Fals
results_benchmark = benchmark.clone()
results_benchmark.add_result(oscap.xccdf.result_clone(ritem))
- results_benchmark.__dict__['oval'] = benchmark.oval
- res_models = dict(zip(benchmark.oval.keys(), sessions))
- return (results_benchmark, res_models)
+ return (results_benchmark, sessions)
def oval_reporter(msg, usr):
result = msg.user2num
@@ -169,7 +168,6 @@ def oval_reporter(msg, usr):
return 0
def evaluate_oval(sess, verbose=True):
-
usr = {'false':0,
'true':0,
'err':0,
@@ -197,10 +195,9 @@ def evaluate_oval(sess, verbose=True):
"Not Evaluated:\t%(neval)s\n" \
"Not Applicable:\t%(na)s\n" % usr
- res_model = oscap.oval.agent_get_results_model(sess)
- return (None, {None:res_model})
+ return (None, [sess])
-def export_results(results_dir, id, benchmark=None, res_models=None, xml=True, html=True, xccdf_ss=None, oval_ss=None):
+def export_results(results_dir, id, benchmark=None, sessions=None, xml=True, html=True, xccdf_ss=None, oval_ss=None):
if not xml and not html:
return True
@@ -225,11 +222,10 @@ def export_results(results_dir, id, benchmark=None, res_models=None, xml=True, h
if html and (xccdf_ss != None):
result_to_html(xccdf_xml, xccdf_ss, os.path.join(results_dir, id + ".xccdf.html"))
- if res_models != None:
- for oval_file,session in res_models.items():
- res_model = oscap.oval.agent.results_model(session)
- if benchmark != None:
- id = os.path.splitext(oval_file)[0]
+ if sessions != None:
+ for sess in sessions:
+ res_model = oscap.oval.agent.results_model(sess)
+ id = os.path.splitext(sess.filename)[0]
if xml:
oval_xml = os.path.join(results_dir, id + ".oval.xml")
--
1.7.2.1
13 years, 8 months
[PATCH] Add proper support for values in profiles
by Josh Adams
Handle set-values and refine-values in profiles.
Fixes bug #7582
---
src/secstate/main.py | 16 ++++++++++++++++
src/secstate/util.py | 32 +++++++++++++++++---------------
2 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/src/secstate/main.py b/src/secstate/main.py
index 4ca6b18..058f33c 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -251,12 +251,28 @@ class Secstate:
for item in xccdf_get_items(benchmark, oscap.xccdf.XCCDF_ITEM, benchmark.content):
benchmark.selections[item.id] = item.selected
+ benchmark.__dict__['vals'] = {}
+ for val in xccdf_get_values(benchmark):
+ val_instance = val.instances[0]
+ benchmark.vals[val.id] = value_instance_to_value(val_instance)
+
current_profile = benchmark.config.get(benchmark.id, 'profile')
profile = benchmark.get_item(current_profile).to_profile()
prof_sel = get_profile_selections(benchmark, profile)
for key,val in prof_sel.items():
benchmark.selections[key] = val
+ for setval in profile.setvalues:
+ if not benchmark.get_item(setval.item).prohibit_changes:
+ benchmark.vals[setval.item] = setval.value
+
+ for refval in profile.refine_values:
+ value = benchmark.get_item(refval.item).to_value()
+ if not value.prohibit_changes:
+ benchmark.vals[refval.item] = value_instance_to_value(value.get_instance_by_selector(refval.selector))
+
+ print benchmark.vals
+
if store_path != None:
id = get_benchmark_id(benchmark_file)
directory = os.path.join(bench_dir, id)
diff --git a/src/secstate/util.py b/src/secstate/util.py
index 647eaf7..9067990 100644
--- a/src/secstate/util.py
+++ b/src/secstate/util.py
@@ -320,6 +320,14 @@ def xccdf_get_items(template, type, items=None):
return result
+def xccdf_get_values(benchmark):
+ result = []
+ result.extend(benchmark.values)
+ for group in xccdf_get_items(benchmark, oscap.xccdf.XCCDF_GROUP, benchmark.content):
+ result.extend(group.values)
+
+ return result
+
def xccdf_get_refs(benchmark):
"""
Function: Get all referenced OVAL files from an XCCDF document
@@ -425,6 +433,14 @@ def item_get_type_str(item):
else:
return "Item"
+def value_instance_to_value(val_instance):
+ if val_instance.type == oscap.xccdf.XCCDF_TYPE_NUMBER:
+ return val_instance.value_number
+ elif val_instance.type == oscap.xccdf.XCCDF_TYPE_STRING:
+ return val_instance.value_string
+ elif val_instance.type == oscap.xccdf.XCCDF_TYPE_BOOLEAN:
+ return str(val_instance.value_boolean).lower()
+
def parse_puppet_fixes(benchmark, ignore_ids=[]):
fixes = xccdf_get_fixes(benchmark, ignore_ids)
all_puppet = {'classes' : set(), 'environment' : "", 'parameters' : {}}
@@ -491,21 +507,7 @@ def dereference_sub_elements(fix, benchmark):
ids = [m.group(1) for m in re.finditer(sub_element_re, content)]
for id in ids:
#lookup the actual value the id points too
- value_obj = benchmark.get_item(id).to_value()
- value_instance = value_obj.instances[0]
-
- type = value_instance.type
- if type == oscap.xccdf.XCCDF_TYPE_NUMBER:
- numeric_value = value_instance.value_number
- # turn float into int if they are equal to remove unnecessary decimal component
- if numeric_value == int(numeric_value):
- numeric_value = int(numeric_value)
- value = str(numeric_value)
- elif type == oscap.xccdf.XCCDF_TYPE_STRING:
- value = value_instance.value_string
- elif type == oscap.xccdf.XCCDF_TYPE_BOOLEAN:
- value = str(value_instance.value_boolean).lower()
-
+ value = benchmark.vals[id]
content = re.sub(replacement_re % id, re.escape(value), content)
return content
--
1.7.2.1
13 years, 8 months
[PATCH] Fixed typo and issue with selection
by Josh Adams
Selecting a previously deselected item will now also select all of its
parents, as well as the benchmark itself.
---
src/secstate/main.py | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/secstate/main.py b/src/secstate/main.py
index 86da593..c9f637c 100644
--- a/src/secstate/main.py
+++ b/src/secstate/main.py
@@ -497,10 +497,11 @@ class Secstate:
if selected:
parent = item.parent
while parent.id != benchmark_id:
- benchmark.config.set(active_profile, parent_id, json.dumps(sel_dict))
- self.log.debug("Setting %(id)s to %(val)s" % {'id':parent_id,
+ benchmark.config.set(active_profile, parent.id, json.dumps(sel_dict))
+ self.log.debug("Setting %(id)s to %(val)s" % {'id':parent.id,
'val':selected})
parent = parent.parent
+ benchmark.config.set(benchmark.id, "selected", selected)
benchmark.config.set(benchmark_id, 'profile', active_profile)
if recurse:
--
1.7.2.1
13 years, 8 months
[PATCH] Got rid of colons in unique directory name
by Josh Adams
Apparently Windows does not like :'s in directory names.
Fixes bug #7384
---
src/secstate/util.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/secstate/util.py b/src/secstate/util.py
index de3d811..ea7ca84 100644
--- a/src/secstate/util.py
+++ b/src/secstate/util.py
@@ -202,7 +202,7 @@ def evaluate_oval(sess, verbose=True):
def export_results(results_dir, id, benchmark=None, res_models=None, xccdf_ss=None, oval_ss=None, html_dir=None):
unique = "audit-%(hostname)s-%(date)s" % {'hostname':os.uname()[1],
- 'date':time.strftime("%a-%B-%d-%H:%M:%S-%Y")}
+ 'date':time.strftime("%a-%B-%d-%H_%M_%S-%Y")}
if not os.path.isdir(os.path.join(results_dir, unique)):
try:
os.makedirs(os.path.join(results_dir, unique))
--
1.7.2.1
13 years, 8 months