From 5f8282d59324171e9a07ad40e05d09c040e45e6b Mon Sep 17 00:00:00 2001 From: Mark Bestavros Date: Tue, 7 Nov 2023 09:57:41 -0500 Subject: [PATCH] Add support for SCAN_OUTPUT results Signed-off-by: Mark Bestavros --- policy/release/cve.rego | 60 +++++++++++++++- policy/release/cve_test.rego | 131 +++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 2 deletions(-) diff --git a/policy/release/cve.rego b/policy/release/cve.rego index a3769e79..e9364ec4 100644 --- a/policy/release/cve.rego +++ b/policy/release/cve.rego @@ -141,17 +141,73 @@ deny contains result if { result := lib.result_helper(rego.metadata.chain(), []) } +# METADATA +# title: Deprecated CVE result name +# description: >- +# The `CLAIR_SCAN_RESULT` result name has been deprecated, and has been +# replaced with `SCAN_OUTPUT`. If any task results with the old name are +# found, this rule will raise a warning. +# custom: +# short_name: deprecated_cve_result_name +# failure_msg: CVE scan uses deprecated result name +# solution: >- +# Use the newer `SCAN_OUTPUT` result name. +# collections: +# - minimal +# - redhat +# depends_on: +# - attestation_type.known_attestation_type +# +warn contains result if { + _vulnerabilities_deprecated + result := lib.result_helper(rego.metadata.chain(), []) +} + +# METADATA +# title: Deprecated CVE result name for unpatched vulnerabilities +# description: >- +# The `CLAIR_SCAN_RESULT` result name has been deprecated, and has been +# replaced with `SCAN_OUTPUT`. If any task results with the old name are +# found, this rule will raise a warning. +# custom: +# short_name: deprecated_unpatched_cve_result_name +# failure_msg: CVE scan uses deprecated result name +# solution: >- +# Use the newer `SCAN_OUTPUT` result name, including for unpached vulnerabilities. +# collections: +# - minimal +# - redhat +# depends_on: +# - attestation_type.known_attestation_type +# +warn contains result if { + _unpatched_vulnerabilities_deprecated + result := lib.result_helper(rego.metadata.chain(), []) +} + _vulnerabilities := vulnerabilities if { some result in lib.results_named(_result_name) vulnerabilities := result.value.vulnerabilities -} +} else := _vulnerabilities_deprecated _unpatched_vulnerabilities := vulnerabilities if { some result in lib.results_named(_result_name) vulnerabilities := result.value.unpatched_vulnerabilities +} else := _unpatched_vulnerabilities_deprecated + +_vulnerabilities_deprecated := vulnerabilities if { + some result in lib.results_named(_deprecated_result_name) + vulnerabilities := result.value.vulnerabilities +} + +_unpatched_vulnerabilities_deprecated := vulnerabilities if { + some result in lib.results_named(_deprecated_result_name) + vulnerabilities := result.value.unpatched_vulnerabilities } -_result_name := "CLAIR_SCAN_RESULT" +_result_name := "SCAN_OUTPUT" + +_deprecated_result_name := "CLAIR_SCAN_RESULT" _non_zero_vulnerabilities(key) := _non_zero_levels(key, _vulnerabilities) diff --git a/policy/release/cve_test.rego b/policy/release/cve_test.rego index 2feda23b..b475e2f8 100644 --- a/policy/release/cve_test.rego +++ b/policy/release/cve_test.rego @@ -36,6 +36,27 @@ test_success if { lib.assert_empty(cve.deny | cve.warn) with input.attestations as attestations } +test_success_deprecated_name if { + slsav1_task_with_result := tkn_test.slsav1_task_result_ref( + "clair-scan", + [{ + "name": cve._deprecated_result_name, + "type": "string", + "value": {"vulnerabilities": _dummy_counts_zero_high}, + }], + ) + attestations := [ + lib_test.att_mock_helper_ref( + cve._result_name, + {"vulnerabilities": _dummy_counts_zero_high}, + "clair-scan", + _bundle, + ), + lib_test.mock_slsav1_attestation_with_tasks([tkn_test.slsav1_task_bundle(slsav1_task_with_result, _bundle)]), + ] + lib.assert_empty(cve.deny) with input.attestations as attestations +} + test_success_with_rule_data if { slsav1_task_with_result := tkn_test.slsav1_task_result_ref( "clair-scan", @@ -65,6 +86,28 @@ test_success_with_rule_data if { with data.rule_data.warn_unpatched_cve_security_levels as ["spam"] } +test_success_with_rule_data_deprecated_name if { + slsav1_task_with_result := tkn_test.slsav1_task_result_ref( + "clair-scan", + [{ + "name": cve._deprecated_result_name, + "type": "string", + "value": {"vulnerabilities": _dummy_counts}, + }], + ) + attestations := [ + lib_test.att_mock_helper_ref( + cve._result_name, + {"vulnerabilities": _dummy_counts}, + "clair-scan", + _bundle, + ), + lib_test.mock_slsav1_attestation_with_tasks([tkn_test.slsav1_task_bundle(slsav1_task_with_result, _bundle)]), + ] + lib.assert_empty(cve.deny) with input.attestations as attestations + with data.rule_data.restrict_cve_security_levels as ["spam"] +} + test_failure if { slsav1_task_with_result := tkn_test.slsav1_task_result_ref( "clair-scan", @@ -104,6 +147,45 @@ test_failure if { lib.assert_equal_results(cve.deny, expected_deny) with input.attestations as attestations } +test_failure_deprecated_name if { + slsav1_task_with_result := tkn_test.slsav1_task_result_ref( + "clair-scan", + [{ + "name": cve._deprecated_result_name, + "type": "string", + "value": { + "vulnerabilities": _dummy_counts, + "unpatched_vulnerabilities": _dummy_counts, + }, + }], + ) + attestations := [ + lib_test.att_mock_helper_ref( + cve._deprecated_result_name, + { + "vulnerabilities": _dummy_counts, + "unpatched_vulnerabilities": _dummy_counts, + }, + "clair-scan", + _bundle, + ), + lib_test.mock_slsav1_attestation_with_tasks([tkn_test.slsav1_task_bundle(slsav1_task_with_result, _bundle)]), + ] + expected_deny := { + { + "code": "cve.cve_blockers", + "term": "critical", + "msg": "Found 1 CVE vulnerabilities of critical security level", + }, + { + "code": "cve.cve_blockers", + "term": "high", + "msg": "Found 10 CVE vulnerabilities of high security level", + }, + } + lib.assert_equal_results(cve.deny, expected_deny) with input.attestations as attestations +} + test_failure_with_rule_data if { _custom_counts := {"spam": 1, "bacon": 2, "eggs": 3} slsav1_task_with_result := tkn_test.slsav1_task_result_ref( @@ -195,6 +277,55 @@ test_warn if { lib.assert_equal_results(cve.warn, expected) with input.attestations as attestations } +test_warn_deprecated_name if { + slsav1_task_with_result := tkn_test.slsav1_task_result_ref( + "clair-scan", + [{ + "name": cve._deprecated_result_name, + "type": "string", + "value": { + "vulnerabilities": _dummy_counts, + "unpatched_vulnerabilities": _dummy_counts, + }, + }], + ) + attestations := [ + lib_test.att_mock_helper_ref( + cve._result_name, + { + "vulnerabilities": _dummy_counts, + "unpatched_vulnerabilities": _dummy_counts, + }, + "clair-scan", + _bundle, + ), + lib_test.mock_slsav1_attestation_with_tasks([tkn_test.slsav1_task_bundle(slsav1_task_with_result, _bundle)]), + ] + expected := { + { + "code": "cve.deprecated_cve_result_name", + "collections": ["minimal", "redhat"], + "effective_on": "2022-01-01T00:00:00Z", + "msg": "CVE scan uses deprecated result name", + }, + { + "code": "cve.deprecated_unpatched_cve_result_name", + "msg": "CVE scan uses deprecated result name", + }, + { + "code": "cve.unpatched_cve_warnings", + "msg": "Found 1 non-blocking unpatched CVE vulnerabilities of critical security level", + "term": "critical", + }, + { + "code": "cve.unpatched_cve_warnings", + "term": "high", + "msg": "Found 10 non-blocking unpatched CVE vulnerabilities of high security level", + }, + } + lib.assert_equal_results(cve.warn, expected) with input.attestations as attestations +} + test_warn_with_rule_data if { slsav1_task_with_result := tkn_test.slsav1_task_result_ref( "clair-scan",