diff --git a/antora/docs/modules/ROOT/pages/release_policy.adoc b/antora/docs/modules/ROOT/pages/release_policy.adoc index f6f993ff..1aa79361 100644 --- a/antora/docs/modules/ROOT/pages/release_policy.adoc +++ b/antora/docs/modules/ROOT/pages/release_policy.adoc @@ -211,8 +211,8 @@ a| A set of policy rules to validate artifacts built using RHTAP Jenkins pipelin Rules included: -* xref:release_policy.adoc#rhtap_jenkins__invocation_id_found[RHTAP Jenkins: RHTAP Jenkins SLSA Invocation ID present] -* xref:release_policy.adoc#rhtap_jenkins__attestation_found[RHTAP Jenkins: RHTAP Jenkins SLSA Provenance Attestation Found] +* xref:release_policy.adoc#rhtap_multi_ci__attestation_format[RHTAP Multi-CI: SLSA Provenance Attestation Format] +* xref:release_policy.adoc#rhtap_multi_ci__attestation_found[RHTAP Multi-CI: SLSA Provenance Attestation Found] | [#slsa3]`slsa3` a| Includes policy rules required to meet SLSA Level 3. @@ -959,74 +959,36 @@ Check the image metadata for the presence of a "quay.expires-after" label. If it * Code: `quay_expiration.expires_label` * https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/quay_expiration/quay_expiration.rego#L16[Source, window="_blank"] -[#rhtap_github_package] -== link:#rhtap_github_package[RHTAP GitHub] +[#rhtap_multi_ci_package] +== link:#rhtap_multi_ci_package[RHTAP Multi-CI] -Some initial checks for images built using an RHTAP GitHub build pipeline. Note that the RHTAP GitHub pipeline is WIP currently, but will be shipped in an upcoming release of RHTAP. It's expected more useful checks will be added in future. RHTAP GitHub pipelines are defined under https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci +Checks for images built using an RHTAP build pipeline in either Jenkins, GitLab or GitHub. RHTAP pipelines are defined under https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci -* Package name: `rhtap_github` +* Package name: `rhtap_multi_ci` -[#rhtap_github__attestation_found] -=== link:#rhtap_github__attestation_found[RHTAP GitHub SLSA Provenance Attestation Found] +[#rhtap_multi_ci__attestation_format] +=== link:#rhtap_multi_ci__attestation_format[SLSA Provenance Attestation Format] -Verify an attestation created by the RHTAP GitHub build pipeline is present. +Confirm the attestation created by the RHTAP Multi-CI build pipeline matches the expected format. -*Solution*: It appears the build pipeline did not create a SLSA provenance attestation. Check the logs in GitHub for the cosign-sign-attest stage to see if you can find out why. +*Solution*: This check looks for some fields expected to be present in the SLSA attestation. Modifying the scripts that produce the attestation predicate might cause this to fail. See also the `att-predicate-*.sh` scripts at https://github.com/redhat-appstudio/tssc-dev-multi-ci/tree/main/rhtap * Rule type: [rule-type-indicator failure]#FAILURE# -* FAILURE message: `The expected SLSA v1.0 provenance with build type %s was not found.` -* Code: `rhtap_github.attestation_found` -* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/rhtap_github/rhtap_github.rego#L17[Source, window="_blank"] +* FAILURE message: `RHTAP %s attestation problem: %s` +* Code: `rhtap_multi_ci.attestation_format` +* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/rhtap_multi_ci/rhtap_multi_ci.rego#L40[Source, window="_blank"] -[#rhtap_gitlab_package] -== link:#rhtap_gitlab_package[RHTAP GitLab] +[#rhtap_multi_ci__attestation_found] +=== link:#rhtap_multi_ci__attestation_found[SLSA Provenance Attestation Found] -Some initial checks for images built using an RHTAP GitLab build pipeline. Note that the RHTAP GitLab pipeline is WIP currently, but will be shipped in an upcoming release of RHTAP. It's expected more useful checks will be added in future. RHTAP GitLab pipelines are defined under https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci +Verify an attestation created by the RHTAP Multi-CI build pipeline is present. -* Package name: `rhtap_gitlab` - -[#rhtap_gitlab__attestation_found] -=== link:#rhtap_gitlab__attestation_found[RHTAP GitLab SLSA Provenance Attestation Found] - -Verify an attestation created by the RHTAP GitLab build pipeline is present. - -*Solution*: It appears the build pipeline did not create a SLSA provenance attestation. Check the logs in GitLab for the cosign-sign-attest stage to see if you can find out why. - -* Rule type: [rule-type-indicator failure]#FAILURE# -* FAILURE message: `The expected SLSA v1.0 provenance with build type %s was not found.` -* Code: `rhtap_gitlab.attestation_found` -* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/rhtap_gitlab/rhtap_gitlab.rego#L17[Source, window="_blank"] - -[#rhtap_jenkins_package] -== link:#rhtap_jenkins_package[RHTAP Jenkins] - -Some initial checks for images built using an RHTAP Jenkins build pipeline. Note that the RHTAP Jenkins pipeline is WIP currently, but will be shipped in an upcoming release of RHTAP. It's expected more useful checks will be added in future. RHTAP Jenkins pipelines are defined under https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci - -* Package name: `rhtap_jenkins` - -[#rhtap_jenkins__invocation_id_found] -=== link:#rhtap_jenkins__invocation_id_found[RHTAP Jenkins SLSA Invocation ID present] - -Confirm that an invocation ID was found in the attestation in the expected location. - -*Solution*: For some reason the invocation id was missing or empty in the build provenance. It should be located at `predicate.runDetails.metadata.invocationID` in the attestation statement. - -* Rule type: [rule-type-indicator failure]#FAILURE# -* FAILURE message: `The build provenance metadata did not contain an invocation id.` -* Code: `rhtap_jenkins.invocation_id_found` -* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/rhtap_jenkins/rhtap_jenkins.rego#L36[Source, window="_blank"] - -[#rhtap_jenkins__attestation_found] -=== link:#rhtap_jenkins__attestation_found[RHTAP Jenkins SLSA Provenance Attestation Found] - -Verify an attestation created by the RHTAP Jenkins build pipeline is present. - -*Solution*: It appears the build pipeline did not create a SLSA provenance attestation. Check the logs in Jenkins for the cosign-sign-attest stage to see if you can find out why. +*Solution*: It appears the build pipeline did not create the expected SLSA provenance attestation. Check for relevant error messages in the 'cosign-sign-attest' pipeline step logs. * Rule type: [rule-type-indicator failure]#FAILURE# -* FAILURE message: `The expected SLSA v1.0 provenance with build type %s was not found.` -* Code: `rhtap_jenkins.attestation_found` -* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/rhtap_jenkins/rhtap_jenkins.rego#L17[Source, window="_blank"] +* FAILURE message: `A SLSA v1.0 provenance with one of the following RHTAP Multi-CI build types was not found: %s.` +* Code: `rhtap_multi_ci.attestation_found` +* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/release/rhtap_multi_ci/rhtap_multi_ci.rego#L16[Source, window="_blank"] [#rpm_repos_package] == link:#rpm_repos_package[RPM Repos] diff --git a/antora/docs/modules/ROOT/partials/release_policy_nav.adoc b/antora/docs/modules/ROOT/partials/release_policy_nav.adoc index 91708388..4f7ec9c8 100644 --- a/antora/docs/modules/ROOT/partials/release_policy_nav.adoc +++ b/antora/docs/modules/ROOT/partials/release_policy_nav.adoc @@ -71,13 +71,9 @@ **** xref:release_policy.adoc#provenance_materials__git_clone_task_found[Git clone task found] *** xref:release_policy.adoc#quay_expiration_package[Quay expiration] **** xref:release_policy.adoc#quay_expiration__expires_label[Expires label] -*** xref:release_policy.adoc#rhtap_github_package[RHTAP GitHub] -**** xref:release_policy.adoc#rhtap_github__attestation_found[RHTAP GitHub SLSA Provenance Attestation Found] -*** xref:release_policy.adoc#rhtap_gitlab_package[RHTAP GitLab] -**** xref:release_policy.adoc#rhtap_gitlab__attestation_found[RHTAP GitLab SLSA Provenance Attestation Found] -*** xref:release_policy.adoc#rhtap_jenkins_package[RHTAP Jenkins] -**** xref:release_policy.adoc#rhtap_jenkins__invocation_id_found[RHTAP Jenkins SLSA Invocation ID present] -**** xref:release_policy.adoc#rhtap_jenkins__attestation_found[RHTAP Jenkins SLSA Provenance Attestation Found] +*** xref:release_policy.adoc#rhtap_multi_ci_package[RHTAP Multi-CI] +**** xref:release_policy.adoc#rhtap_multi_ci__attestation_format[SLSA Provenance Attestation Format] +**** xref:release_policy.adoc#rhtap_multi_ci__attestation_found[SLSA Provenance Attestation Found] *** xref:release_policy.adoc#rpm_repos_package[RPM Repos] **** xref:release_policy.adoc#rpm_repos__ids_known[All rpms have known repo ids] **** xref:release_policy.adoc#rpm_repos__rule_data_provided[Known repo id list provided] diff --git a/policy/release/lib/attestations.rego b/policy/release/lib/attestations.rego index fd99c7b1..cb0feb05 100644 --- a/policy/release/lib/attestations.rego +++ b/policy/release/lib/attestations.rego @@ -84,22 +84,6 @@ taskrun_attestations := [att | att.statement.predicate.buildType in taskrun_att_build_types ] -# For attestations created using an RHTAP build pipeline. See also: -# - https://github.com/redhat-appstudio/tssc-sample-jenkins -# - https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci/source-repo/jenkins -# - https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci/gitops-template/jenkins -# - https://github.com/redhat-appstudio/tssc-dev-multi-ci/blob/main/rhtap/att-predicate-jenkins.sh -# - https://github.com/redhat-appstudio/tssc-dev-multi-ci/blob/main/rhtap/att-predicate-github.sh -# - https://github.com/redhat-appstudio/tssc-dev-multi-ci/blob/main/rhtap/att-predicate-gitlab.sh -# -rhtap_build_type(rhtap_ci_type) := sprintf("https://redhat.com/rhtap/slsa-build-types/%s-build/v1", [rhtap_ci_type]) - -rhtap_attestations(rhtap_ci_type) := [att | - some att in input.attestations - att.statement.predicateType == slsa_provenance_predicate_type_v1 - att.statement.predicate.buildDefinition.buildType == rhtap_build_type(rhtap_ci_type) -] - tasks_from_pipelinerun := [task | some att in pipelinerun_attestations some task in tekton.tasks(att) diff --git a/policy/release/lib/attestations_test.rego b/policy/release/lib/attestations_test.rego index 199f4248..0bb441ba 100644 --- a/policy/release/lib/attestations_test.rego +++ b/policy/release/lib/attestations_test.rego @@ -416,10 +416,3 @@ test_result_values if { not lib.result_values(123) } - -test_rhtap_build_type if { - lib.assert_equal( - "https://redhat.com/rhtap/slsa-build-types/bacon-build/v1", - lib.rhtap_build_type("bacon"), - ) -} diff --git a/policy/release/rhtap_github/rhtap_github.rego b/policy/release/rhtap_github/rhtap_github.rego deleted file mode 100644 index bd4c05d2..00000000 --- a/policy/release/rhtap_github/rhtap_github.rego +++ /dev/null @@ -1,40 +0,0 @@ -# -# METADATA -# title: RHTAP GitHub -# description: >- -# Some initial checks for images built using an RHTAP GitHub build pipeline. Note -# that the RHTAP GitHub pipeline is WIP currently, but will be shipped in an upcoming -# release of RHTAP. It's expected more useful checks will be added in future. RHTAP -# GitHub pipelines are defined under -# https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci -# -package rhtap_github - -import rego.v1 - -import data.lib - -# METADATA -# title: RHTAP GitHub SLSA Provenance Attestation Found -# description: >- -# Verify an attestation created by the RHTAP GitHub build pipeline is present. -# custom: -# short_name: attestation_found -# failure_msg: The expected SLSA v1.0 provenance with build type %s was not found. -# solution: >- -# It appears the build pipeline did not create a SLSA provenance attestation. -# Check the logs in GitHub for the cosign-sign-attest stage to see if you can -# find out why. -# collections: -# - rhtap-github -# -deny contains result if { - count(_rhtap_attestations) < 1 - result := lib.result_helper(rego.metadata.chain(), [_rhtap_build_type]) -} - -_rhtap_attestations := lib.rhtap_attestations(_rhtap_ci_type) - -_rhtap_build_type := lib.rhtap_build_type(_rhtap_ci_type) - -_rhtap_ci_type := "github" diff --git a/policy/release/rhtap_github/rhtap_github_test.rego b/policy/release/rhtap_github/rhtap_github_test.rego deleted file mode 100644 index 3ae4ca3a..00000000 --- a/policy/release/rhtap_github/rhtap_github_test.rego +++ /dev/null @@ -1,36 +0,0 @@ -package rhtap_github_test - -import rego.v1 - -import data.lib -import data.rhtap_github - -test_github_atts_happy_path if { - lib.assert_empty(rhtap_github.deny) with input.attestations as [good_att] - lib.assert_empty(rhtap_github.deny) with input.attestations as [bad_att, good_att] -} - -test_github_atts_missing if { - expected := { - "code": "rhtap_github.attestation_found", - # regal ignore:line-length - "msg": "The expected SLSA v1.0 provenance with build type https://redhat.com/rhtap/slsa-build-types/github-build/v1 was not found.", - } - - lib.assert_equal_results({expected}, rhtap_github.deny) with input.attestations as [] - lib.assert_equal_results({expected}, rhtap_github.deny) with input.attestations as [bad_att] -} - -good_build_type := "https://redhat.com/rhtap/slsa-build-types/github-build/v1" - -good_att := mock_att(good_build_type, {}) - -bad_att := mock_att("https://bogus/build/type/v1", {}) - -mock_att(build_type, run_details) := {"statement": { - "predicateType": "https://slsa.dev/provenance/v1", - "predicate": { - "buildDefinition": {"buildType": build_type}, - "runDetails": run_details, - }, -}} diff --git a/policy/release/rhtap_gitlab/rhtap_gitlab.rego b/policy/release/rhtap_gitlab/rhtap_gitlab.rego deleted file mode 100644 index c6319486..00000000 --- a/policy/release/rhtap_gitlab/rhtap_gitlab.rego +++ /dev/null @@ -1,40 +0,0 @@ -# -# METADATA -# title: RHTAP GitLab -# description: >- -# Some initial checks for images built using an RHTAP GitLab build pipeline. Note -# that the RHTAP GitLab pipeline is WIP currently, but will be shipped in an upcoming -# release of RHTAP. It's expected more useful checks will be added in future. RHTAP -# GitLab pipelines are defined under -# https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci -# -package rhtap_gitlab - -import rego.v1 - -import data.lib - -# METADATA -# title: RHTAP GitLab SLSA Provenance Attestation Found -# description: >- -# Verify an attestation created by the RHTAP GitLab build pipeline is present. -# custom: -# short_name: attestation_found -# failure_msg: The expected SLSA v1.0 provenance with build type %s was not found. -# solution: >- -# It appears the build pipeline did not create a SLSA provenance attestation. -# Check the logs in GitLab for the cosign-sign-attest stage to see if you can -# find out why. -# collections: -# - rhtap-gitlab -# -deny contains result if { - count(_rhtap_attestations) < 1 - result := lib.result_helper(rego.metadata.chain(), [_rhtap_build_type]) -} - -_rhtap_attestations := lib.rhtap_attestations(_rhtap_ci_type) - -_rhtap_build_type := lib.rhtap_build_type(_rhtap_ci_type) - -_rhtap_ci_type := "gitlab" diff --git a/policy/release/rhtap_gitlab/rhtap_gitlab_test.rego b/policy/release/rhtap_gitlab/rhtap_gitlab_test.rego deleted file mode 100644 index aadab677..00000000 --- a/policy/release/rhtap_gitlab/rhtap_gitlab_test.rego +++ /dev/null @@ -1,36 +0,0 @@ -package rhtap_gitlab_test - -import rego.v1 - -import data.lib -import data.rhtap_gitlab - -test_gitlab_atts_happy_path if { - lib.assert_empty(rhtap_gitlab.deny) with input.attestations as [good_att] - lib.assert_empty(rhtap_gitlab.deny) with input.attestations as [bad_att, good_att] -} - -test_gitlab_atts_missing if { - expected := { - "code": "rhtap_gitlab.attestation_found", - # regal ignore:line-length - "msg": "The expected SLSA v1.0 provenance with build type https://redhat.com/rhtap/slsa-build-types/gitlab-build/v1 was not found.", - } - - lib.assert_equal_results({expected}, rhtap_gitlab.deny) with input.attestations as [] - lib.assert_equal_results({expected}, rhtap_gitlab.deny) with input.attestations as [bad_att] -} - -good_build_type := "https://redhat.com/rhtap/slsa-build-types/gitlab-build/v1" - -good_att := mock_att(good_build_type, {}) - -bad_att := mock_att("https://bogus/build/type/v1", {}) - -mock_att(build_type, run_details) := {"statement": { - "predicateType": "https://slsa.dev/provenance/v1", - "predicate": { - "buildDefinition": {"buildType": build_type}, - "runDetails": run_details, - }, -}} diff --git a/policy/release/rhtap_jenkins/rhtap_jenkins.rego b/policy/release/rhtap_jenkins/rhtap_jenkins.rego deleted file mode 100644 index 1c2b0a7f..00000000 --- a/policy/release/rhtap_jenkins/rhtap_jenkins.rego +++ /dev/null @@ -1,71 +0,0 @@ -# -# METADATA -# title: RHTAP Jenkins -# description: >- -# Some initial checks for images built using an RHTAP Jenkins build pipeline. Note -# that the RHTAP Jenkins pipeline is WIP currently, but will be shipped in an upcoming -# release of RHTAP. It's expected more useful checks will be added in future. RHTAP -# Jenkins pipelines are defined under -# https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci -# -package rhtap_jenkins - -import rego.v1 - -import data.lib - -# METADATA -# title: RHTAP Jenkins SLSA Provenance Attestation Found -# description: >- -# Verify an attestation created by the RHTAP Jenkins build pipeline is present. -# custom: -# short_name: attestation_found -# failure_msg: The expected SLSA v1.0 provenance with build type %s was not found. -# solution: >- -# It appears the build pipeline did not create a SLSA provenance attestation. -# Check the logs in Jenkins for the cosign-sign-attest stage to see if you can -# find out why. -# collections: -# - rhtap-jenkins -# -deny contains result if { - count(_rhtap_attestations) < 1 - result := lib.result_helper(rego.metadata.chain(), [_rhtap_build_type]) -} - -# METADATA -# title: RHTAP Jenkins SLSA Invocation ID present -# description: >- -# Confirm that an invocation ID was found in the attestation in the expected location. -# custom: -# short_name: invocation_id_found -# failure_msg: The build provenance metadata did not contain an invocation id. -# solution: >- -# For some reason the invocation id was missing or empty in the build provenance. -# It should be located at `predicate.runDetails.metadata.invocationID` in the -# attestation statement. -# collections: -# - rhtap-jenkins -# depends_on: -# - rhtap_jenkins.attestation_found -# -deny contains result if { - attestations_with_invocation_id := {att | - some att in _rhtap_attestations - invocation_id := att.statement.predicate.runDetails.metadata.invocationID - trim_space(invocation_id) != "" - } - - # We're expecting just one attestation, but if there are multiple let's apply this check - # to all of them. Note that we don't produce a violation if _rhtap_attestations - # has zero length. (The 'attestation_found' violation defined above would be produced.) - count(attestations_with_invocation_id) != count(_rhtap_attestations) - - result := lib.result_helper(rego.metadata.chain(), []) -} - -_rhtap_attestations := lib.rhtap_attestations(_rhtap_ci_type) - -_rhtap_build_type := lib.rhtap_build_type(_rhtap_ci_type) - -_rhtap_ci_type := "jenkins" diff --git a/policy/release/rhtap_jenkins/rhtap_jenkins_test.rego b/policy/release/rhtap_jenkins/rhtap_jenkins_test.rego deleted file mode 100644 index 992eba3c..00000000 --- a/policy/release/rhtap_jenkins/rhtap_jenkins_test.rego +++ /dev/null @@ -1,50 +0,0 @@ -package rhtap_jenkins_test - -import rego.v1 - -import data.lib -import data.rhtap_jenkins - -test_jenkins_atts_happy_path if { - lib.assert_empty(rhtap_jenkins.deny) with input.attestations as [good_att] - lib.assert_empty(rhtap_jenkins.deny) with input.attestations as [bad_att, good_att] -} - -test_jenkins_atts_missing if { - # Note we don't get the "invocation_id_required" deny when there are no attestations found - expected := { - "code": "rhtap_jenkins.attestation_found", - # regal ignore:line-length - "msg": "The expected SLSA v1.0 provenance with build type https://redhat.com/rhtap/slsa-build-types/jenkins-build/v1 was not found.", - } - - lib.assert_equal_results({expected}, rhtap_jenkins.deny) with input.attestations as [] - lib.assert_equal_results({expected}, rhtap_jenkins.deny) with input.attestations as [bad_att] -} - -test_invocation_id_missing if { - expected := { - "code": "rhtap_jenkins.invocation_id_found", - "msg": "The build provenance metadata did not contain an invocation id.", - } - lib.assert_equal_results({expected}, rhtap_jenkins.deny) with input.attestations as [bad_invocation_1] - lib.assert_equal_results({expected}, rhtap_jenkins.deny) with input.attestations as [bad_invocation_2] -} - -good_build_type := "https://redhat.com/rhtap/slsa-build-types/jenkins-build/v1" - -good_att := mock_att(good_build_type, {"metadata": {"invocationID": "hello"}}) - -bad_att := mock_att("https://bogus/build/type/v1", {}) - -bad_invocation_1 := mock_att(good_build_type, {"metadata": {}}) - -bad_invocation_2 := mock_att(good_build_type, {"metadata": {"invocationID": " "}}) - -mock_att(build_type, run_details) := {"statement": { - "predicateType": "https://slsa.dev/provenance/v1", - "predicate": { - "buildDefinition": {"buildType": build_type}, - "runDetails": run_details, - }, -}} diff --git a/policy/release/rhtap_multi_ci/rhtap_multi_ci.rego b/policy/release/rhtap_multi_ci/rhtap_multi_ci.rego new file mode 100644 index 00000000..ec49de07 --- /dev/null +++ b/policy/release/rhtap_multi_ci/rhtap_multi_ci.rego @@ -0,0 +1,135 @@ +# +# METADATA +# title: RHTAP Multi-CI +# description: >- +# Checks for images built using an RHTAP build pipeline in either Jenkins, +# GitLab or GitHub. RHTAP pipelines are defined under +# https://github.com/redhat-appstudio/tssc-sample-templates/tree/main/skeleton/ci +# +package rhtap_multi_ci + +import rego.v1 + +import data.lib +import data.lib.json as j + +# METADATA +# title: SLSA Provenance Attestation Found +# description: >- +# Verify an attestation created by the RHTAP Multi-CI build pipeline is present. +# custom: +# short_name: attestation_found +# failure_msg: "A SLSA v1.0 provenance with one of the following RHTAP Multi-CI +# build types was not found: %s." +# solution: >- +# It appears the build pipeline did not create the expected SLSA provenance +# attestation. Check for relevant error messages in the 'cosign-sign-attest' +# pipeline step logs. +# collections: +# - rhtap-multi-ci +# # For compatibility. These will be removed these soon. +# - rhtap-github +# - rhtap-gitlab +# - rhtap-jenkins +# +deny contains result if { + count(_attestations) < 1 + result := lib.result_helper(rego.metadata.chain(), [lib.quoted_values_string(_known_build_types)]) +} + +# METADATA +# title: SLSA Provenance Attestation Format +# description: >- +# Confirm the attestation created by the RHTAP Multi-CI build pipeline matches the +# expected format. +# custom: +# short_name: attestation_format +# failure_msg: "RHTAP %s attestation problem: %s" +# solution: >- +# This check looks for some fields expected to be present in the SLSA attestation. Modifying +# the scripts that produce the attestation predicate might cause this to fail. See also +# the `att-predicate-*.sh` scripts at https://github.com/redhat-appstudio/tssc-dev-multi-ci/tree/main/rhtap +# collections: +# - rhtap-multi-ci +# # For compatibility. These will be removed these soon. +# - rhtap-github +# - rhtap-gitlab +# - rhtap-jenkins +# depends_on: +# - rhtap_multi_ci.attestation_found +# +deny contains result if { + some att in _attestations + some ci_type in _known_ci_types + att.statement.predicate.buildDefinition.buildType == _build_type(ci_type) + some schema_error in j.validate_schema(att.statement.predicate, _predicate_schema(ci_type)) + result := lib.result_helper(rego.metadata.chain(), [ci_type, schema_error.message]) +} + +# ----------------------------------------------------------------------------- + +# Common to each ci type +_predicate_schema_base := { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["runDetails"], + "properties": {"runDetails": { + "type": "object", + "required": ["builder", "metadata"], + "properties": { + "metadata": { + "type": "object", + "required": ["invocationID"], + "properties": {"invocationID": {"type": "string", "minLength": 1}}, + }, + "builder": { + "type": "object", + "required": ["id"], + "properties": {"id": {"type": "string", "minLength": 1}}, + }, + }, + }}, +} + +# See https://github.com/redhat-appstudio/tssc-dev-multi-ci/blob/main/rhtap/att-predicate-jenkins.sh +_predicate_schema("jenkins") := json.patch(_predicate_schema_base, [ + # Check runDetails.builder.version is present and is an object + {"op": "add", "path": "/properties/runDetails/properties/builder/required/1", "value": "version"}, + {"op": "add", "path": "/properties/runDetails/properties/builder/properties/version", "value": {"type": "object"}}, +]) + +# See https://github.com/redhat-appstudio/tssc-dev-multi-ci/blob/main/rhtap/att-predicate-github.sh +# (Currently no extra schema checks other than the common checks) +_predicate_schema("github") := json.patch(_predicate_schema_base, []) + +# See https://github.com/redhat-appstudio/tssc-dev-multi-ci/blob/main/rhtap/att-predicate-gitlab.sh +# (Currently no extra schema checks other than the common checks) +_predicate_schema("gitlab") := json.patch(_predicate_schema_base, []) + +# ----------------------------------------------------------------------------- + +_known_build_types := [_build_type(known_ci_type) | some known_ci_type in _known_ci_types] + +_build_type(ci_type) := sprintf("https://redhat.com/rhtap/slsa-build-types/%s-build/v1", [ci_type]) + +# RHTAP Multi-CI currently supports these environments: +_known_ci_types := ["jenkins", "github", "gitlab"] + +# Just the potentially relevant attestations +_attestations := [att | + some att in _all_attestations + + # Beware we are not supporting SLSA formats other than v1.0 here + att.statement.predicateType == _slsa_provenance_predicate_type_v1 + + # Just the RHTAP Multi-CI build types + some known_build_type in _known_build_types + att.statement.predicate.buildDefinition.buildType == known_build_type +] + +# Standard predicate type for SLSA V1.0 +_slsa_provenance_predicate_type_v1 := "https://slsa.dev/provenance/v1" + +# The actual raw attestation is found under the 'statement' key. +# See https://enterprisecontract.dev/docs/ec-cli/policy_input.html#_validate_image +_all_attestations := input.attestations diff --git a/policy/release/rhtap_multi_ci/rhtap_multi_ci_test.rego b/policy/release/rhtap_multi_ci/rhtap_multi_ci_test.rego new file mode 100644 index 00000000..94161d5a --- /dev/null +++ b/policy/release/rhtap_multi_ci/rhtap_multi_ci_test.rego @@ -0,0 +1,77 @@ +package rhtap_multi_ci_test + +import rego.v1 + +import data.lib +import data.rhtap_multi_ci + +test_atts_happy_path if { + lib.assert_empty(rhtap_multi_ci.deny) with input.attestations as [good_att] + lib.assert_empty(rhtap_multi_ci.deny) with input.attestations as [ignored_att, good_att] +} + +test_atts_missing if { + expected := { + "code": "rhtap_multi_ci.attestation_found", + "msg": sprintf("%s%s%s%s", [ + "A SLSA v1.0 provenance with one of the following RHTAP Multi-CI build types was not found:", + " 'https://redhat.com/rhtap/slsa-build-types/jenkins-build/v1',", + " 'https://redhat.com/rhtap/slsa-build-types/github-build/v1',", + " 'https://redhat.com/rhtap/slsa-build-types/gitlab-build/v1'.", + ]), + } + + lib.assert_equal_results({expected}, rhtap_multi_ci.deny) with input.attestations as [] + lib.assert_equal_results({expected}, rhtap_multi_ci.deny) with input.attestations as [ignored_att] +} + +test_fields_missing if { + expected = { + { + "code": "rhtap_multi_ci.attestation_format", + "msg": "RHTAP jenkins attestation problem: runDetails.metadata: invocationID is required", + }, + { + "code": "rhtap_multi_ci.attestation_format", + "msg": "RHTAP jenkins attestation problem: runDetails.builder: id is required", + }, + } + lib.assert_equal_results(expected, rhtap_multi_ci.deny) with input.attestations as [missing_fields_att] +} + +# Not very useful except to get 100% coverage +# (I don't feel like repeating the above tests with the other two build types) +test_schema_sanity if { + lib.assert_not_equal(rhtap_multi_ci._predicate_schema_base, rhtap_multi_ci._predicate_schema("jenkins")) + lib.assert_equal(rhtap_multi_ci._predicate_schema_base, rhtap_multi_ci._predicate_schema("github")) + lib.assert_equal(rhtap_multi_ci._predicate_schema_base, rhtap_multi_ci._predicate_schema("gitlab")) +} + +good_build_type := "https://redhat.com/rhtap/slsa-build-types/jenkins-build/v1" + +good_att := mock_att(good_build_type, { + "metadata": {"invocationID": "foo"}, + "builder": {"id": "42", "version": {}}, +}) + +missing_fields_att := mock_att(good_build_type, { + "metadata": {"vacationID": "foo"}, + "builder": {"name": "Bob", "version": {}}, +}) + +ignored_att := mock_att("https://other/build/type/v1", {}) + +mock_att(build_type, run_details) := {"statement": { + "predicateType": "https://slsa.dev/provenance/v1", + "predicate": { + "buildDefinition": {"buildType": build_type}, + "runDetails": run_details, + }, +}} + +test_rhtap_build_type if { + lib.assert_equal( + "https://redhat.com/rhtap/slsa-build-types/bacon-build/v1", + rhtap_multi_ci._build_type("bacon"), + ) +}