[PATCH 1/2] improved verify-references script to show if Profile does not include all Rules with certain references
Jeffrey Blank
blank at eclipse.ncsc.mil
Tue Jul 24 20:59:36 UTC 2012
Signed-off-by: Jeffrey Blank <blank at eclipse.ncsc.mil>
---
RHEL6/utils/verify-references.py | 63 ++++++++++++++++++++++++++++++++++---
1 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/RHEL6/utils/verify-references.py b/RHEL6/utils/verify-references.py
index d642ed6..e4ef43c 100755
--- a/RHEL6/utils/verify-references.py
+++ b/RHEL6/utils/verify-references.py
@@ -12,13 +12,16 @@ import lxml.etree as ET
xccdf_ns = "http://checklists.nist.gov/xccdf/1.1"
oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
-# we use this string to look for NIST references within the XCCDF rules
+# we use these strings to look for references within the XCCDF rules
nist_ref_href = "http://csrc.nist.gov/publications/nistpubs/800-53-Rev3/sp800-53-rev3-final.pdf"
+disa_ref_href = "http://iase.disa.mil/cci/index.html"
def parse_options():
usage = "usage: %prog [options] xccdf_file"
parser = optparse.OptionParser(usage=usage, version="%prog ")
# only some options are on by default
+ parser.add_option("-p", "--profile", default=False, action="store", dest="profile_name",
+ help="act on Rules from this XCCDF Profile only")
parser.add_option("--rules-with-invalid-checks", default=False, action="store_true", dest="rules_with_invalid_checks",
help="print XCCDF Rules that reference an invalid/nonexistent check")
parser.add_option("--rules-without-checks", default=False, action="store_true", dest="rules_without_checks",
@@ -27,6 +30,12 @@ def parse_options():
help="print XCCDF Rules that do not include a severity")
parser.add_option("--rules-without-nistrefs", default=False, action="store_true", dest="rules_without_nistrefs",
help="print XCCDF Rules which do not include any NIST 800-53 references")
+ parser.add_option("--rules-without-disarefs", default=False, action="store_true", dest="rules_without_disarefs",
+ help="print XCCDF Rules which do not include any DISA CCI references")
+ parser.add_option("--rules-with-nistrefs-outside-profile", default=False, action="store_true", dest="nistrefs_not_in_profile",
+ help="print XCCDF Rules which have a NIST reference, but are not part of the Profile specified")
+ parser.add_option("--rules-with-disarefs-outside-profile", default=False, action="store_true", dest="disarefs_not_in_profile",
+ help="print XCCDF Rules which have a DISA CCI reference, but are not part of the Profile specified")
parser.add_option("--ovaldefs-unused", default=False, action="store_true", dest="ovaldefs_unused",
help="print OVAL definitions which are not used by any XCCDF Rule")
parser.add_option("--all-checks", default=False, action="store_true", dest="all_checks",
@@ -49,6 +58,19 @@ def get_ovalfiles(checks):
return ovalfiles
+def get_profileruleids(xccdftree, profile_name):
+ ruleids = []
+
+ while profile_name:
+ profile = xccdftree.find(".//{%s}Profile[@id='%s']" % (xccdf_ns, profile_name))
+ if profile is None:
+ sys.exit("Specified XCCDF Profile %s was not found.")
+ for select in profile.findall(".//{%s}select" % xccdf_ns):
+ ruleids.append(select.get("idref"))
+ profile_name = profile.get("extends")
+
+ return ruleids
+
def main():
(options, args) = parse_options()
xccdffilename = args[0]
@@ -56,7 +78,16 @@ def main():
# extract all of the rules within the xccdf
xccdftree = ET.parse(xccdffilename)
rules = xccdftree.findall(".//{%s}Rule" % xccdf_ns)
-
+
+ # if a profile was specified, get rid of any Rules that aren't in it
+ if options.profile_name:
+ profile_ruleids = get_profileruleids(xccdftree, options.profile_name)
+ prunedrules = rules[:]
+ for rule in rules:
+ if rule.get("id") not in profile_ruleids:
+ prunedrules.remove(rule)
+ rules = prunedrules
+
# step over xccdf file, and find referenced oval files
checks = xccdftree.findall(".//{%s}check" % xccdf_ns)
ovalfiles = get_ovalfiles(checks)
@@ -91,18 +122,38 @@ def main():
if rule.get("severity") is None:
print "No severity assigned to XCCDF Rule: " + rule.get("id")
- if options.rules_without_nistrefs or options.all_checks:
+ if options.rules_without_nistrefs or options.rules_without_disarefs or options.all_checks:
for rule in rules:
# find all references in the current rule
refs = rule.findall(".//{%s}reference" % xccdf_ns)
if refs is None:
print "No reference assigned to XCCDF Rule: " + rule.get("id")
else:
- # loop through the references and make sure at least one of them is a NIST reference
+ # loop through the Rule's references and put their hrefs in a list
ref_href_list = [ref.get("href") for ref in refs]
- # print warning if rules does not have a NIST reference
- if (not nist_ref_href in ref_href_list):
+ # print warning if rule does not have a NIST reference
+ if (not nist_ref_href in ref_href_list) and options.rules_without_nistrefs:
print "No valid NIST reference in XCCDF Rule: " + rule.get("id")
+ # print warning if rule does not have a DISA reference
+ if (not disa_ref_href in ref_href_list) and options.rules_without_disarefs:
+ print "No valid DISA CCI reference in XCCDF Rule: " + rule.get("id")
+
+ if options.disarefs_not_in_profile or options.nistrefs_not_in_profile:
+ if options.profile_name is None:
+ sys.exit("The options for finding Rules with a reference, but which are not in a Profile, requires specifying a Profile.")
+ allrules = xccdftree.findall(".//{%s}Rule" % xccdf_ns)
+ for rule in allrules:
+ # find all references in the current rule
+ refs = rule.findall(".//{%s}reference" % xccdf_ns)
+ ref_href_list = [ref.get("href") for ref in refs]
+ # print warning if Rule is outside Profile and has a NIST reference
+ if options.nistrefs_not_in_profile:
+ if (nist_ref_href in ref_href_list) and (rule.get("id") not in profile_ruleids):
+ print "XCCDF Rule found with NIST reference outside Profile %s: " % options.profile_name + rule.get("id")
+ # print warning if Rule is outside Profile and has a DISA reference
+ if options.disarefs_not_in_profile:
+ if (disa_ref_href in ref_href_list) and (rule.get("id") not in profile_ruleids):
+ print "XCCDF Rule found with DISA CCI reference outside Profile %s: " % options.profile_name + rule.get("id")
if options.ovaldefs_unused or options.all_checks:
# create a list of all of the OVAL checks that are defined in the oval file
--
1.7.1
More information about the scap-security-guide
mailing list