Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add allowed package sources policy #1212

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions antora/docs/modules/ROOT/pages/release_policy.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Rules included:
* xref:release_policy.adoc#rpm_repos__rule_data_provided[RPM Repos: Known repo id list provided]
* xref:release_policy.adoc#rpm_signature__rule_data_provided[RPM Signature: Rule data provided]
* xref:release_policy.adoc#sbom_cyclonedx__allowed_package_external_references[SBOM CycloneDX: Allowed package external references]
* xref:release_policy.adoc#sbom_cyclonedx__allowed_package_sources[SBOM CycloneDX: Allowed package sources]
* xref:release_policy.adoc#sbom_cyclonedx__disallowed_package_attributes[SBOM CycloneDX: Disallowed package attributes]
* xref:release_policy.adoc#sbom_cyclonedx__disallowed_package_external_references[SBOM CycloneDX: Disallowed package external references]
* xref:release_policy.adoc#sbom__disallowed_packages_provided[SBOM: Disallowed packages list is provided]
Expand Down Expand Up @@ -142,6 +143,7 @@ Rules included:
* xref:release_policy.adoc#rpm_signature__rule_data_provided[RPM Signature: Rule data provided]
* xref:release_policy.adoc#sbom_cyclonedx__allowed[SBOM CycloneDX: Allowed]
* xref:release_policy.adoc#sbom_cyclonedx__allowed_package_external_references[SBOM CycloneDX: Allowed package external references]
* xref:release_policy.adoc#sbom_cyclonedx__allowed_package_sources[SBOM CycloneDX: Allowed package sources]
* xref:release_policy.adoc#sbom_cyclonedx__disallowed_package_attributes[SBOM CycloneDX: Disallowed package attributes]
* xref:release_policy.adoc#sbom_cyclonedx__disallowed_package_external_references[SBOM CycloneDX: Disallowed package external references]
* xref:release_policy.adoc#sbom_cyclonedx__valid[SBOM CycloneDX: Valid]
Expand Down Expand Up @@ -1111,6 +1113,19 @@ Confirm the CycloneDX SBOM contains only packages with explicitly allowed extern
* Code: `sbom_cyclonedx.allowed_package_external_references`
* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/sbom_cyclonedx/sbom_cyclonedx.rego#L89[Source, window="_blank"]

[#sbom_cyclonedx__allowed_package_sources]
=== link:#sbom_cyclonedx__allowed_package_sources[Allowed package sources]

For each of the components fetched by Cachi2 which define externalReferences of type distribution, verify they are allowed based on the allowed_package_sources rule data key. By default, allowed_package_sources is empty which means no components with such references are allowed.

*Solution*: Update the image to not use a package from a disallowed source.

* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Package %s fetched by cachi2 was sourced from %q which is not allowed`
* Code: `sbom_cyclonedx.allowed_package_sources`
* Effective from: `2024-12-15T00:00:00Z`
* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/sbom_cyclonedx/sbom_cyclonedx.rego#L151[Source, window="_blank"]

[#sbom_cyclonedx__disallowed_package_attributes]
=== link:#sbom_cyclonedx__disallowed_package_attributes[Disallowed package attributes]

Expand Down
1 change: 1 addition & 0 deletions antora/docs/modules/ROOT/partials/release_policy_nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
*** xref:release_policy.adoc#sbom_cyclonedx_package[SBOM CycloneDX]
**** xref:release_policy.adoc#sbom_cyclonedx__allowed[Allowed]
**** xref:release_policy.adoc#sbom_cyclonedx__allowed_package_external_references[Allowed package external references]
**** xref:release_policy.adoc#sbom_cyclonedx__allowed_package_sources[Allowed package sources]
**** xref:release_policy.adoc#sbom_cyclonedx__disallowed_package_attributes[Disallowed package attributes]
**** xref:release_policy.adoc#sbom_cyclonedx__disallowed_package_external_references[Disallowed package external references]
**** xref:release_policy.adoc#sbom_cyclonedx__valid[Valid]
Expand Down
2 changes: 2 additions & 0 deletions policy/lib/sbom/sbom.rego
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,5 @@ rule_data_attributes_key := "disallowed_attributes"
rule_data_allowed_external_references_key := "allowed_external_references"

rule_data_disallowed_external_references_key := "disallowed_external_references"

rule_data_allowed_package_sources_key := "allowed_package_sources"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the rule_data_errors rules above. Let's add a new one that verifies the consistency of this new rule data key. This helps us determine if the rule data provided has any problems.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holding out on this until the the comment about rule data format is settled.

55 changes: 55 additions & 0 deletions policy/release/sbom_cyclonedx/sbom_cyclonedx.rego
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,61 @@ deny contains result if {
result := lib.result_helper_with_term(rego.metadata.chain(), [id, reference.url, reference.type, msg], id)
}

# METADATA
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need corresponding changes in sbom_spdx.rego 😭

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cachi2 currently does not produce an SPDX SBOM, so there's not yet anything to latch onto (as in to the externalReference of type distribution in CycloneDX). Holding out on this until the the comment about rule data format is settled.

# title: Allowed package sources
# description: >-
# For each of the components fetched by Cachi2 which define externalReferences of type
# distribution, verify they are allowed based on the allowed_package_sources rule data
# key. By default, allowed_package_sources is empty which means no components with such
# references are allowed.
# custom:
# short_name: allowed_package_sources
# failure_msg: Package %s fetched by cachi2 was sourced from %q which is not allowed
# solution: Update the image to not use a package from a disallowed source.
# collections:
# - redhat
# - policy_data
# effective_on: 2024-12-15T00:00:00Z
deny contains result if {
some s in sbom.cyclonedx_sboms
some component in s.components

# only look at components that define an externalReferences of type `distribution`
some reference in component.externalReferences
reference.type == "distribution"

# only look at components fetched by cachi2
some properties in component.properties
properties.name == "cachi2:found_by"
properties.value == "cachi2"

purl := component.purl
parsed_purl := ec.purl.parse(purl)

# patterns are either those defined by the rule for a give purl type, or empty by default
allowed_data := lib.rule_data(sbom.rule_data_allowed_package_sources_key)
patterns := _get_purl_allowed_patterns(parsed_purl.type, allowed_data)
distribution_url := object.get(reference, "url", "")

# only progress past this point if no matches were found
not _url_matches_any_pattern(distribution_url, patterns)

result := lib.result_helper_with_term(rego.metadata.chain(), [purl, distribution_url], purl)
}

# get allowed pattens for given purl type, or empty list if not defined
_get_purl_allowed_patterns(purl_type, allowed_rule_data) := patterns if {
some allowed in allowed_rule_data
purl_type == allowed.type
patterns := allowed.patterns
} else := []

# see if any pattern matches given url
_url_matches_any_pattern(url, patterns) if {
some pattern in patterns
regex.match(pattern, url)
}

# _with_effective_on annotates the result with the item's effective_on attribute. If the item does
# not have the attribute, result is returned unmodified.
_with_effective_on(result, item) := new_result if {
Expand Down
95 changes: 95 additions & 0 deletions policy/release/sbom_cyclonedx/sbom_cyclonedx_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,101 @@ test_external_references_disallowed_no_purl if {
}]}
}

test_allowed_package_sources if {
expected := {{
"code": "sbom_cyclonedx.allowed_package_sources",
"term": "pkg:generic/[email protected]?download_url=https://openssl.org/source/openssl-1.1.0g.tar.gz",
# regal ignore:line-length
"msg": `Package pkg:generic/[email protected]?download_url=https://openssl.org/source/openssl-1.1.0g.tar.gz fetched by cachi2 was sourced from "https://openssl.org/source/openssl-1.1.0g.tar.gz" which is not allowed`,
}}

att := json.patch(_sbom_attestation, [
{
"op": "add",
"path": "/statement/predicate/components/-",
"value": {
"type": "file",
"name": "openssl",
"purl": "pkg:generic/[email protected]?download_url=https://openssl.org/source/openssl-1.1.0g.tar.gz",
"properties": [{
"name": "cachi2:found_by",
"value": "cachi2",
}],
"externalReferences": [{"type": "distribution", "url": "https://openssl.org/source/openssl-1.1.0g.tar.gz"}],
},
},
{
"op": "add",
"path": "/statement/predicate/components/-",
"value": {
"type": "library",
"name": "batik-anim",
"purl": "pkg:maven/org.apache.xmlgraphics/[email protected]?type=pom",
"properties": [{
"name": "cachi2:found_by",
"value": "cachi2",
}],
# regal ignore:line-length
"externalReferences": [{"type": "distribution", "url": "https://repo.maven.apache.org/maven2/org/apache/xmlgraphics/batik-anim/1.9.1/batik-anim-1.9.1.pom"}],
},
},
{
"op": "add",
"path": "/statement/predicate/components/-",
"value": {
"type": "file",
"name": "unrelated",
"purl": "pkg:generic/unrelated",
"externalReferences": [{"type": "distribution", "url": "https://irrelevant.org"}],
},
},
])

lib.assert_equal_results(expected, sbom_cyclonedx.deny) with input.attestations as [att]
with data.rule_data as {sbom.rule_data_allowed_package_sources_key: [
{
"type": "maven",
"patterns": [".*apache.org.*", ".*example.com.*"],
},
{
"type": "generic",
"patterns": [".*apache.org.*", ".*example.com.*"],
},
]}
}

test_allowed_package_sources_no_rule_defined if {
expected := {{
"code": "sbom_cyclonedx.allowed_package_sources",
"term": "pkg:maven/org.apache.xmlgraphics/[email protected]?type=pom",
# regal ignore:line-length
"msg": `Package pkg:maven/org.apache.xmlgraphics/[email protected]?type=pom fetched by cachi2 was sourced from "https://repo.maven.apache.org/maven2/org/apache/xmlgraphics/batik-anim/1.9.1/batik-anim-1.9.1.pom" which is not allowed`,
}}

att := json.patch(_sbom_attestation, [{
"op": "add",
"path": "/statement/predicate/components/-",
"value": {
"type": "library",
"name": "batik-anim",
"purl": "pkg:maven/org.apache.xmlgraphics/[email protected]?type=pom",
"properties": [{
"name": "cachi2:found_by",
"value": "cachi2",
}],
# regal ignore:line-length
"externalReferences": [{"type": "distribution", "url": "https://repo.maven.apache.org/maven2/org/apache/xmlgraphics/batik-anim/1.9.1/batik-anim-1.9.1.pom"}],
},
}])

# rule data is defined only for purl of type generic
lib.assert_equal_results(expected, sbom_cyclonedx.deny) with input.attestations as [att]
with data.rule_data as {sbom.rule_data_allowed_package_sources_key: [{
"type": "generic",
"patterns": [".*example.com.*"],
}]}
}

test_attributes_not_allowed_no_properties if {
att := json.patch(_sbom_attestation, [{
"op": "remove",
Expand Down