From b63a98d49740feeeed489c16153dc2ef31d757c0 Mon Sep 17 00:00:00 2001 From: Luiz Carvalho Date: Wed, 18 Sep 2024 16:22:39 -0400 Subject: [PATCH] Allow subpaths to be excluded in disallowed pkgs There are certain repositories that defined multiple packages. These packages may have different attributes, e.g. different licenses. As such, it is desirable to disallow certain packages from those repos while still allowing others. A good example of this is the github.com/hashicorp/consul repo. The top-level license is quite restritive, but the one under the `/api` subpath is not. This commit changes the sbom_cyclonedx.allowed policy rule to take into account the subpath attribute. The objects in the list disallowed_packages array can now provide a list of `exclude_subpaths` in order to ignore certain subpaths. Ref: EC-870 Signed-off-by: Luiz Carvalho --- policy/release/sbom_cyclonedx.rego | 10 +++++++++ policy/release/sbom_cyclonedx_test.rego | 30 ++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/policy/release/sbom_cyclonedx.rego b/policy/release/sbom_cyclonedx.rego index c9b2acbaf..fb965f084 100644 --- a/policy/release/sbom_cyclonedx.rego +++ b/policy/release/sbom_cyclonedx.rego @@ -191,9 +191,14 @@ _contains(needle, haystack) if { needle_purl.type == hay_purl.type needle_purl.namespace == hay_purl.namespace needle_purl.name == hay_purl.name + _matches_subpath(needle_purl, hay) _matches_version(needle_purl.version, hay) } else := false +_matches_subpath(purl, disallowed) if { + not purl.subpath in object.get(disallowed, "exclude_subpaths", []) +} + _matches_version(version, matcher) if { matcher.format in {"semverv", "semver"} matcher.min != "" @@ -232,6 +237,11 @@ _rule_data_errors contains msg if { "format": {"enum": ["semver", "semverv"]}, "min": {"type": "string"}, "max": {"type": "string"}, + "exclude_subpaths": { + "type": "array", + "uniqueItems": true, + "items": {"type": "string"}, + }, }, "additionalProperties": false, "anyOf": [ diff --git a/policy/release/sbom_cyclonedx_test.rego b/policy/release/sbom_cyclonedx_test.rego index 229024bc0..2e4d6c02e 100644 --- a/policy/release/sbom_cyclonedx_test.rego +++ b/policy/release/sbom_cyclonedx_test.rego @@ -198,6 +198,29 @@ test_not_allowed_with_max if { assert_allowed("pkg:golang/k8s.io/client-go@v99.99.99", disallowed_packages) } +test_not_allowed_with_subpaths if { + disallowed_packages := [{ + "purl": "pkg:golang/github.com/hashicorp/consul", + "format": "semverv", + "min": "v1.29.2", + "exclude_subpaths": [ + "api", + "sdk", + ], + }] + + # Unkonwn subpath matches + assert_not_allowed("pkg:golang/github.com/hashicorp/consul@v1.29.2#spam", disallowed_packages) + + # Missing subpath matches + assert_not_allowed("pkg:golang/github.com/hashicorp/consul@v1.29.2#", disallowed_packages) + assert_not_allowed("pkg:golang/github.com/hashicorp/consul@v1.29.2", disallowed_packages) + + # Excluded subpaths do not match + assert_allowed("pkg:golang/github.com/hashicorp/consul@v1.29.2#api", disallowed_packages) + assert_allowed("pkg:golang/github.com/hashicorp/consul@v1.29.2#sdk", disallowed_packages) +} + test_not_allowed_with_min_max if { disallowed_packages := [{ "purl": "pkg:golang/k8s.io/client-go", @@ -264,7 +287,7 @@ test_rule_data_validation if { # Additional properties not allowed {"purl": "pkg:golang/k8s.io/client-go", "format": "semverv", "min": "v0.1.0", "blah": "foo"}, # Bad types everywhere - {"purl": 1, "format": 2, "min": 3, "max": 4}, + {"purl": 1, "format": 2, "min": 3, "max": 4, "exclude_subpaths": 5}, # Duplicated items {"purl": "pkg:golang/k8s.io/client-go", "format": "semverv", "min": "v0.1.0"}, {"purl": "pkg:golang/k8s.io/client-go", "format": "semverv", "min": "v0.1.0"}, @@ -405,6 +428,11 @@ test_rule_data_validation if { "code": "sbom_cyclonedx.disallowed_packages_provided", "msg": "Rule data disallowed_external_references has unexpected format: 1: url is required", }, + { + "code": "sbom_cyclonedx.disallowed_packages_provided", + # regal ignore:line-length + "msg": "Rule data disallowed_packages has unexpected format: 2.exclude_subpaths: Invalid type. Expected: array, given: integer", + }, } lib.assert_equal_results(sbom_cyclonedx.deny, expected) with input.attestations as [_sbom_attestation]