From d7c20af408b97feaf2a2b06688638294317e185b Mon Sep 17 00:00:00 2001 From: Simon Baird Date: Fri, 6 Oct 2023 17:05:50 -0400 Subject: [PATCH 1/2] Mention the 'unknown' CVE severity in descriptions Actually there's no functional change needed for EC to support the new CVE severity, but we mention in the documentation and commentary what the expected value for CVE severity are, so this patch updates that. Additionally I added 'unknown' to the dummy data in the tests, and added some test coverage so it includes some output for the 'unknown' results. It's also not really needed, but I think it helps communicate the intention for future readers of the code. Resolves: https://issues.redhat.com/browse/EC-36 --- policy/lib/rule_data.rego | 2 +- policy/release/cve.rego | 4 ++-- policy/release/cve_test.rego | 35 ++++++++++++++++++++--------------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/policy/lib/rule_data.rego b/policy/lib/rule_data.rego index f1f9b643..a65736fa 100644 --- a/policy/lib/rule_data.rego +++ b/policy/lib/rule_data.rego @@ -30,7 +30,7 @@ rule_data_defaults := { "warned_tests_results": ["WARNING"], # # Used in release/cve.go - # Valid levels: "critical", "high", "medium", and "low" + # Valid levels: "critical", "high", "medium", "low", and "unknown" "restrict_cve_security_levels": ["critical", "high"], "warn_cve_security_levels": [], # Used in policy/release/slsa_source_correlated.rego diff --git a/policy/release/cve.rego b/policy/release/cve.rego index 4c929297..a57db8a1 100644 --- a/policy/release/cve.rego +++ b/policy/release/cve.rego @@ -22,7 +22,7 @@ import data.lib # rule will fail. By default, only CVEs of critical and high security level # cause a failure. This is configurable by the rule data key # `restrict_cve_security_levels`. The available levels are critical, high, -# medium, and low. +# medium, low, and unknown. # custom: # short_name: cve_blockers # failure_msg: Found %d CVE vulnerabilities of %s security level @@ -48,7 +48,7 @@ deny contains result if { # rule will raise a warning. By default, the list of CVE security levels used # by this policy is empty. However, this is configurable by the rule data key # `warn_cve_security_levels`. The available levels are critical, high, -# medium, and low. +# medium, low, and unknown. # custom: # short_name: cve_warnings # failure_msg: Found %d non-blocking CVE vulnerabilities of %s security level diff --git a/policy/release/cve_test.rego b/policy/release/cve_test.rego index 68811e97..04405abf 100644 --- a/policy/release/cve_test.rego +++ b/policy/release/cve_test.rego @@ -15,13 +15,13 @@ test_success if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 0, "high": 0, "medium": 20, "low": 300}}, + "value": {"vulnerabilities": {"critical": 0, "high": 0, "medium": 20, "low": 300, "unknown": 2}}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 0, "high": 0, "medium": 20, "low": 300}}, + {"vulnerabilities": {"critical": 0, "high": 0, "medium": 20, "low": 300, "unknown": 2}}, "clair-scan", _bundle, ), @@ -36,13 +36,13 @@ test_success_with_rule_data if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300}}, + "value": {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300}}, + {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, "clair-scan", _bundle, ), @@ -58,13 +58,13 @@ test_failure if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300}}, + "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300}}, + {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, "clair-scan", _bundle, ), @@ -125,13 +125,13 @@ test_warn if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300}}, + "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300}}, + {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, "clair-scan", _bundle, ), @@ -146,13 +146,13 @@ test_warn_with_rule_data if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300}}, + "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300}}, + {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, "clair-scan", _bundle, ), @@ -169,9 +169,14 @@ test_warn_with_rule_data if { "term": "low", "msg": "Found 300 non-blocking CVE vulnerabilities of low security level", }, + { + "code": "cve.cve_warnings", + "term": "unknown", + "msg": "Found 2 non-blocking CVE vulnerabilities of unknown security level", + }, } lib.assert_equal_results(cve.warn, expected) with input.attestations as attestations - with data.rule_data.warn_cve_security_levels as ["medium", "low"] + with data.rule_data.warn_cve_security_levels as ["medium", "low", "unknown"] } test_missing_cve_scan_result if { @@ -180,13 +185,13 @@ test_missing_cve_scan_result if { [{ "name": "WRONG_RESULT_NAME", "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300}}, + "value": {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, }], ) attestations := [ lib_test.att_mock_helper_ref( "WRONG_RESULT_NAME", - {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300}}, + {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, "clair-scan", _bundle, ), @@ -205,13 +210,13 @@ test_missing_cve_scan_vulnerabilities if { [{ "name": cve._result_name, "type": "string", - "value": {"seitilibarenluv": {"critical": 1, "high": 1, "medium": 20, "low": 300}}, + "value": {"seitilibarenluv": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"seitilibarenluv": {"critical": 1, "high": 1, "medium": 20, "low": 300}}, + {"seitilibarenluv": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, "clair-scan", _bundle, ), From 6e6566f26a5616bcedc35db6e667166ffd28738c Mon Sep 17 00:00:00 2001 From: Simon Baird Date: Thu, 12 Oct 2023 17:07:01 -0400 Subject: [PATCH 2/2] Tidy up some dummy test data used for cve policy Use vars to remove some unnecessary repetition. References: https://issues.redhat.com/browse/EC-36 --- policy/release/cve_test.rego | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/policy/release/cve_test.rego b/policy/release/cve_test.rego index 04405abf..4f1b2df5 100644 --- a/policy/release/cve_test.rego +++ b/policy/release/cve_test.rego @@ -15,13 +15,13 @@ test_success if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 0, "high": 0, "medium": 20, "low": 300, "unknown": 2}}, + "value": {"vulnerabilities": _dummy_counts_zero_high}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 0, "high": 0, "medium": 20, "low": 300, "unknown": 2}}, + {"vulnerabilities": _dummy_counts_zero_high}, "clair-scan", _bundle, ), @@ -36,13 +36,13 @@ test_success_with_rule_data if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, + "value": {"vulnerabilities": _dummy_counts}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, + {"vulnerabilities": _dummy_counts}, "clair-scan", _bundle, ), @@ -58,13 +58,13 @@ test_failure if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, + "value": {"vulnerabilities": _dummy_counts}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, + {"vulnerabilities": _dummy_counts}, "clair-scan", _bundle, ), @@ -125,13 +125,13 @@ test_warn if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, + "value": {"vulnerabilities": _dummy_counts}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, + {"vulnerabilities": _dummy_counts}, "clair-scan", _bundle, ), @@ -146,13 +146,13 @@ test_warn_with_rule_data if { [{ "name": cve._result_name, "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, + "value": {"vulnerabilities": _dummy_counts}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"vulnerabilities": {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2}}, + {"vulnerabilities": _dummy_counts}, "clair-scan", _bundle, ), @@ -185,13 +185,13 @@ test_missing_cve_scan_result if { [{ "name": "WRONG_RESULT_NAME", "type": "string", - "value": {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, + "value": {"vulnerabilities": _dummy_counts}, }], ) attestations := [ lib_test.att_mock_helper_ref( "WRONG_RESULT_NAME", - {"vulnerabilities": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, + {"vulnerabilities": _dummy_counts}, "clair-scan", _bundle, ), @@ -210,13 +210,13 @@ test_missing_cve_scan_vulnerabilities if { [{ "name": cve._result_name, "type": "string", - "value": {"seitilibarenluv": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, + "value": {"seitilibarenluv": _dummy_counts}, }], ) attestations := [ lib_test.att_mock_helper_ref( cve._result_name, - {"seitilibarenluv": {"critical": 1, "high": 1, "medium": 20, "low": 300, "unknown": 2}}, + {"seitilibarenluv": _dummy_counts}, "clair-scan", _bundle, ), @@ -230,3 +230,7 @@ test_missing_cve_scan_vulnerabilities if { } _bundle := "registry.img/spam@sha256:4e388ab32b10dc8dbc7e28144f552830adc74787c1e2c0824032078a79f227fb" + +_dummy_counts := {"critical": 1, "high": 10, "medium": 20, "low": 300, "unknown": 2} + +_dummy_counts_zero_high := {"critical": 0, "high": 0, "medium": 20, "low": 300, "unknown": 2}