On 6/6/14, 8:20 AM, Jan Lieskovsky wrote:
Currently */utils/verify-references.py script(s) (thus make validate for that
product) always return zero (success) status regardless if some of the underlying
internal checks failed or not.

This is not good for subsequent automated processing e.g. via shell scripts.

Therefore if some of the verify-references.py check caused a warning to be
printed, return non-zero / 1 exit status to indicate failure (not to actually
need to parse the warning).

This is just cosmetic change which doesn't have impact if the RPM package will be
built successfully or not (make validate isn't part of the RPM package build),
but will simplify the testing / life for those actually running 'make validate'
after each commit for that product.

Please review.

Thank you && Regards, Jan.
--
Jan iankko Lieskovsky / Red Hat Security Technologies Team

0001-utils-verify-references.py-Return-non-zero-status-to.patch

From 53fd3f4be3ca47a1d16f1d1ae9b68cd2d98c9dee Mon Sep 17 00:00:00 2001
From: Jan Lieskovsky <jlieskov@redhat.com>
Date: Fri, 6 Jun 2014 17:09:17 +0200
Subject: [PATCH] [*/utils/verify-references.py] Return non-zero status (to
 indicate failure) if some warning message was printed (some of the checks
 didn't pass)

Signed-off-by: Jan Lieskovsky <jlieskov@redhat.com>
---
 Fedora/utils/verify-references.py    | 17 ++++++++++++++++-
 OpenStack/utils/verify-references.py | 17 ++++++++++++++++-
 RHEL/6/utils/verify-references.py    | 17 ++++++++++++++++-
 RHEL/7/utils/verify-references.py    | 17 ++++++++++++++++-
 RHEVM3/utils/verify-references.py    | 17 ++++++++++++++++-
 5 files changed, 80 insertions(+), 5 deletions(-)

diff --git a/Fedora/utils/verify-references.py b/Fedora/utils/verify-references.py
index bac9723..d5a5c90 100755
--- a/Fedora/utils/verify-references.py
+++ b/Fedora/utils/verify-references.py
@@ -18,6 +18,9 @@ oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
 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"
 
+# default exit value - success
+exit_value = 0
+
 def parse_options():
 	usage = "usage: %prog [options] xccdf_file"
 	parser = optparse.OptionParser(usage=usage, version="%prog ")
@@ -49,6 +52,7 @@ def parse_options():
 	return (options, args)
 
 def get_ovalfiles(checks):
+	global exit_value
 	# iterate over all checks, grab the OVAL files referenced within
 	ovalfiles = set()
 	for check in checks:
@@ -57,6 +61,7 @@ def get_ovalfiles(checks):
 			ovalfiles.add(checkcontentref.get("href"))
 		elif check.get("system") != "ocil-transitional":
 			print "Non-OVAL checking system found: " + check.get("system")
+			exit_value = 1
 	return ovalfiles
 
 
@@ -74,6 +79,7 @@ def get_profileruleids(xccdftree, profile_name):
 	return ruleids
 
 def main():
+	global exit_value
 	(options, args) = parse_options()
 	xccdffilename = args[0]
 
@@ -118,17 +124,20 @@ def main():
 			if refname not in ovaldef_ids:
 				rule = check_content_ref.getparent().getparent() 
 				print "Invalid OVAL definition referenced by XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_checks or options.all_checks:
 		for rule in rules:
 			check = rule.find("./{%s}check" % xccdf_ns) 
 			if check is None:
 				print "No reference to OVAL definition in XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_severity or options.all_checks:
 		for rule in rules:
 			if rule.get("severity") is None:
 				print "No severity assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_nistrefs or options.rules_without_disarefs or options.all_checks:
 		for rule in rules:
@@ -136,15 +145,18 @@ def main():
 			refs = rule.findall(".//{%s}reference" % xccdf_ns)
 			if refs is None:
 				print "No reference assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 			else:
 				# 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 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")
+					exit_value = 1
 				# 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")
+					exit_value = 1
 
 	if options.disarefs_not_in_profile or options.nistrefs_not_in_profile:
 		if options.profile_name is None:
@@ -158,10 +170,12 @@ def main():
 			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")
+					exit_value = 1
 			# 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")
+					exit_value = 1
 
 	if options.ovaldefs_unused or options.all_checks:
 		# create a list of all of the OVAL compliance check ids that are defined in the oval file
@@ -177,8 +191,9 @@ def main():
 			# don't print out the OVAL defs that are extended by others, as they're not unused
 			if oval_id not in ovaldef_ids_extended:
 				print "OVAL Check is not referenced by XCCDF: %s" % oval_id
+				exit_value = 1
 
-	sys.exit(0)
+	sys.exit(exit_value)
 
 if __name__ == "__main__":
 	main()
diff --git a/OpenStack/utils/verify-references.py b/OpenStack/utils/verify-references.py
index 75a2ce9..91ae1ee 100755
--- a/OpenStack/utils/verify-references.py
+++ b/OpenStack/utils/verify-references.py
@@ -18,6 +18,9 @@ oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
 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"
 
+# default exit value - success
+exit_value = 0
+
 def parse_options():
 	usage = "usage: %prog [options] xccdf_file"
 	parser = optparse.OptionParser(usage=usage, version="%prog ")
@@ -49,6 +52,7 @@ def parse_options():
 	return (options, args)
 
 def get_ovalfiles(checks):
+	global exit_value
 	# iterate over all checks, grab the OVAL files referenced within
 	ovalfiles = set()
 	for check in checks:
@@ -57,6 +61,7 @@ def get_ovalfiles(checks):
 			ovalfiles.add(checkcontentref.get("href"))
 		elif check.get("system") != "ocil-transitional":
 			print "Non-OVAL checking system found: " + check.get("system")
+			exit_value = 1
 	return ovalfiles
 
 
@@ -74,6 +79,7 @@ def get_profileruleids(xccdftree, profile_name):
 	return ruleids
 
 def main():
+	global exit_value
 	(options, args) = parse_options()
 	xccdffilename = args[0]
 
@@ -112,17 +118,20 @@ def main():
 			if refname not in ovaldef_ids:
 				rule = check_content_ref.getparent().getparent() 
 				print "Invalid OVAL definition referenced by XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_checks or options.all_checks:
 		for rule in rules:
 			check = rule.find("./{%s}check" % xccdf_ns) 
 			if check is None:
 				print "No reference to OVAL definition in XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_severity or options.all_checks:
 		for rule in rules:
 			if rule.get("severity") is None:
 				print "No severity assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_nistrefs or options.rules_without_disarefs or options.all_checks:
 		for rule in rules:
@@ -130,15 +139,18 @@ def main():
 			refs = rule.findall(".//{%s}reference" % xccdf_ns)
 			if refs is None:
 				print "No reference assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 			else:
 				# 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 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")
+					exit_value = 1
 				# 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")
+					exit_value = 1
 
 	if options.disarefs_not_in_profile or options.nistrefs_not_in_profile:
 		if options.profile_name is None:
@@ -152,10 +164,12 @@ def main():
 			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")
+					exit_value = 1
 			# 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")
+					exit_value = 1
 
 	if options.ovaldefs_unused or options.all_checks:
 		# create a list of all of the OVAL checks that are defined in the oval file
@@ -169,8 +183,9 @@ def main():
 		oval_checks_list.sort()
 		for oval_id in oval_checks_list:
 			print "XCCDF does not reference OVAL Check: %s" % oval_id
+			exit_value = 1
 
-	sys.exit(0)
+	sys.exit(exit_value)
 
 if __name__ == "__main__":
 	main()
diff --git a/RHEL/6/utils/verify-references.py b/RHEL/6/utils/verify-references.py
index bac9723..d5a5c90 100755
--- a/RHEL/6/utils/verify-references.py
+++ b/RHEL/6/utils/verify-references.py
@@ -18,6 +18,9 @@ oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
 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"
 
+# default exit value - success
+exit_value = 0
+
 def parse_options():
 	usage = "usage: %prog [options] xccdf_file"
 	parser = optparse.OptionParser(usage=usage, version="%prog ")
@@ -49,6 +52,7 @@ def parse_options():
 	return (options, args)
 
 def get_ovalfiles(checks):
+	global exit_value
 	# iterate over all checks, grab the OVAL files referenced within
 	ovalfiles = set()
 	for check in checks:
@@ -57,6 +61,7 @@ def get_ovalfiles(checks):
 			ovalfiles.add(checkcontentref.get("href"))
 		elif check.get("system") != "ocil-transitional":
 			print "Non-OVAL checking system found: " + check.get("system")
+			exit_value = 1
 	return ovalfiles
 
 
@@ -74,6 +79,7 @@ def get_profileruleids(xccdftree, profile_name):
 	return ruleids
 
 def main():
+	global exit_value
 	(options, args) = parse_options()
 	xccdffilename = args[0]
 
@@ -118,17 +124,20 @@ def main():
 			if refname not in ovaldef_ids:
 				rule = check_content_ref.getparent().getparent() 
 				print "Invalid OVAL definition referenced by XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_checks or options.all_checks:
 		for rule in rules:
 			check = rule.find("./{%s}check" % xccdf_ns) 
 			if check is None:
 				print "No reference to OVAL definition in XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_severity or options.all_checks:
 		for rule in rules:
 			if rule.get("severity") is None:
 				print "No severity assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_nistrefs or options.rules_without_disarefs or options.all_checks:
 		for rule in rules:
@@ -136,15 +145,18 @@ def main():
 			refs = rule.findall(".//{%s}reference" % xccdf_ns)
 			if refs is None:
 				print "No reference assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 			else:
 				# 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 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")
+					exit_value = 1
 				# 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")
+					exit_value = 1
 
 	if options.disarefs_not_in_profile or options.nistrefs_not_in_profile:
 		if options.profile_name is None:
@@ -158,10 +170,12 @@ def main():
 			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")
+					exit_value = 1
 			# 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")
+					exit_value = 1
 
 	if options.ovaldefs_unused or options.all_checks:
 		# create a list of all of the OVAL compliance check ids that are defined in the oval file
@@ -177,8 +191,9 @@ def main():
 			# don't print out the OVAL defs that are extended by others, as they're not unused
 			if oval_id not in ovaldef_ids_extended:
 				print "OVAL Check is not referenced by XCCDF: %s" % oval_id
+				exit_value = 1
 
-	sys.exit(0)
+	sys.exit(exit_value)
 
 if __name__ == "__main__":
 	main()
diff --git a/RHEL/7/utils/verify-references.py b/RHEL/7/utils/verify-references.py
index bac9723..d5a5c90 100755
--- a/RHEL/7/utils/verify-references.py
+++ b/RHEL/7/utils/verify-references.py
@@ -18,6 +18,9 @@ oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
 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"
 
+# default exit value - success
+exit_value = 0
+
 def parse_options():
 	usage = "usage: %prog [options] xccdf_file"
 	parser = optparse.OptionParser(usage=usage, version="%prog ")
@@ -49,6 +52,7 @@ def parse_options():
 	return (options, args)
 
 def get_ovalfiles(checks):
+	global exit_value
 	# iterate over all checks, grab the OVAL files referenced within
 	ovalfiles = set()
 	for check in checks:
@@ -57,6 +61,7 @@ def get_ovalfiles(checks):
 			ovalfiles.add(checkcontentref.get("href"))
 		elif check.get("system") != "ocil-transitional":
 			print "Non-OVAL checking system found: " + check.get("system")
+			exit_value = 1
 	return ovalfiles
 
 
@@ -74,6 +79,7 @@ def get_profileruleids(xccdftree, profile_name):
 	return ruleids
 
 def main():
+	global exit_value
 	(options, args) = parse_options()
 	xccdffilename = args[0]
 
@@ -118,17 +124,20 @@ def main():
 			if refname not in ovaldef_ids:
 				rule = check_content_ref.getparent().getparent() 
 				print "Invalid OVAL definition referenced by XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_checks or options.all_checks:
 		for rule in rules:
 			check = rule.find("./{%s}check" % xccdf_ns) 
 			if check is None:
 				print "No reference to OVAL definition in XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_severity or options.all_checks:
 		for rule in rules:
 			if rule.get("severity") is None:
 				print "No severity assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_nistrefs or options.rules_without_disarefs or options.all_checks:
 		for rule in rules:
@@ -136,15 +145,18 @@ def main():
 			refs = rule.findall(".//{%s}reference" % xccdf_ns)
 			if refs is None:
 				print "No reference assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 			else:
 				# 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 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")
+					exit_value = 1
 				# 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")
+					exit_value = 1
 
 	if options.disarefs_not_in_profile or options.nistrefs_not_in_profile:
 		if options.profile_name is None:
@@ -158,10 +170,12 @@ def main():
 			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")
+					exit_value = 1
 			# 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")
+					exit_value = 1
 
 	if options.ovaldefs_unused or options.all_checks:
 		# create a list of all of the OVAL compliance check ids that are defined in the oval file
@@ -177,8 +191,9 @@ def main():
 			# don't print out the OVAL defs that are extended by others, as they're not unused
 			if oval_id not in ovaldef_ids_extended:
 				print "OVAL Check is not referenced by XCCDF: %s" % oval_id
+				exit_value = 1
 
-	sys.exit(0)
+	sys.exit(exit_value)
 
 if __name__ == "__main__":
 	main()
diff --git a/RHEVM3/utils/verify-references.py b/RHEVM3/utils/verify-references.py
index 75a2ce9..91ae1ee 100755
--- a/RHEVM3/utils/verify-references.py
+++ b/RHEVM3/utils/verify-references.py
@@ -18,6 +18,9 @@ oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
 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"
 
+# default exit value - success
+exit_value = 0
+
 def parse_options():
 	usage = "usage: %prog [options] xccdf_file"
 	parser = optparse.OptionParser(usage=usage, version="%prog ")
@@ -49,6 +52,7 @@ def parse_options():
 	return (options, args)
 
 def get_ovalfiles(checks):
+	global exit_value
 	# iterate over all checks, grab the OVAL files referenced within
 	ovalfiles = set()
 	for check in checks:
@@ -57,6 +61,7 @@ def get_ovalfiles(checks):
 			ovalfiles.add(checkcontentref.get("href"))
 		elif check.get("system") != "ocil-transitional":
 			print "Non-OVAL checking system found: " + check.get("system")
+			exit_value = 1
 	return ovalfiles
 
 
@@ -74,6 +79,7 @@ def get_profileruleids(xccdftree, profile_name):
 	return ruleids
 
 def main():
+	global exit_value
 	(options, args) = parse_options()
 	xccdffilename = args[0]
 
@@ -112,17 +118,20 @@ def main():
 			if refname not in ovaldef_ids:
 				rule = check_content_ref.getparent().getparent() 
 				print "Invalid OVAL definition referenced by XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_checks or options.all_checks:
 		for rule in rules:
 			check = rule.find("./{%s}check" % xccdf_ns) 
 			if check is None:
 				print "No reference to OVAL definition in XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_severity or options.all_checks:
 		for rule in rules:
 			if rule.get("severity") is None:
 				print "No severity assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 
 	if options.rules_without_nistrefs or options.rules_without_disarefs or options.all_checks:
 		for rule in rules:
@@ -130,15 +139,18 @@ def main():
 			refs = rule.findall(".//{%s}reference" % xccdf_ns)
 			if refs is None:
 				print "No reference assigned to XCCDF Rule: " + rule.get("id")
+				exit_value = 1
 			else:
 				# 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 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")
+					exit_value = 1
 				# 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")
+					exit_value = 1
 
 	if options.disarefs_not_in_profile or options.nistrefs_not_in_profile:
 		if options.profile_name is None:
@@ -152,10 +164,12 @@ def main():
 			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")
+					exit_value = 1
 			# 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")
+					exit_value = 1
 
 	if options.ovaldefs_unused or options.all_checks:
 		# create a list of all of the OVAL checks that are defined in the oval file
@@ -169,8 +183,9 @@ def main():
 		oval_checks_list.sort()
 		for oval_id in oval_checks_list:
 			print "XCCDF does not reference OVAL Check: %s" % oval_id
+			exit_value = 1
 
-	sys.exit(0)
+	sys.exit(exit_value)
 
 if __name__ == "__main__":
 	main()
-- 1.8.3.1


ack