diff --git a/antora/docs/modules/ROOT/pages/task_policy.adoc b/antora/docs/modules/ROOT/pages/task_policy.adoc index 2777f4577..546b10ed5 100644 --- a/antora/docs/modules/ROOT/pages/task_policy.adoc +++ b/antora/docs/modules/ROOT/pages/task_policy.adoc @@ -4,8 +4,27 @@ These rules are applied to Tekton task definitions. +[#step_images_package] +== link:#step_images_package[Tekton Task Step image policies] + +This package ensures that a Task definition contains valid values for the image references used by the Task's steps. + +* Package name: `step_images` + +[#step_images__step_images_accessible] +=== link:#step_images__step_images_accessible[Step images are valid] + +Confirm that each step in the Task uses a container image that is accessible. + +*Solution*: Make sure the container image used in each step of the Task is pushed to the registry and that it can be fetched. + +* Rule type: [rule-type-indicator failure]#FAILURE# +* FAILURE message: `Step %d uses inaccessible image ref '%s'` +* Code: `step_images.step_images_accessible` +* https://github.com/enterprise-contract/ec-policies/blob/{page-origin-refhash}/policy/task/step_images/step_images.rego#L14[Source, window="_blank"] + [#step_image_registries_package] -== link:#step_image_registries_package[Tekton Task Step image policies] +== link:#step_image_registries_package[Tekton Task Step image registry policies] This package ensures that a Task definition contains expected values for the image references used by the Task's steps. diff --git a/antora/docs/modules/ROOT/partials/task_policy_nav.adoc b/antora/docs/modules/ROOT/partials/task_policy_nav.adoc index a220af20e..e3e399f0a 100644 --- a/antora/docs/modules/ROOT/partials/task_policy_nav.adoc +++ b/antora/docs/modules/ROOT/partials/task_policy_nav.adoc @@ -1,5 +1,7 @@ * xref:task_policy.adoc[Task Policy] -** xref:task_policy.adoc#step_image_registries_package[Tekton Task Step image policies] +** xref:task_policy.adoc#step_images_package[Tekton Task Step image policies] +*** xref:task_policy.adoc#step_images__step_images_accessible[Step images are valid] +** xref:task_policy.adoc#step_image_registries_package[Tekton Task Step image registry policies] *** xref:task_policy.adoc#step_image_registries__step_image_registry_prefix_list_provided[Permitted step image registry prefix list provided] *** xref:task_policy.adoc#step_image_registries__step_images_permitted[Step images come from permitted registry] ** xref:task_policy.adoc#annotations_package[Tekton Task annotations] diff --git a/policy/task/step_image_registries/step_image_registries.rego b/policy/task/step_image_registries/step_image_registries.rego index 169b6253c..7f16ca416 100644 --- a/policy/task/step_image_registries/step_image_registries.rego +++ b/policy/task/step_image_registries/step_image_registries.rego @@ -1,6 +1,6 @@ # # METADATA -# title: Tekton Task Step image policies +# title: Tekton Task Step image registry policies # description: >- # This package ensures that a Task definition contains expected values for the image references # used by the Task's steps. diff --git a/policy/task/step_images/step_images.rego b/policy/task/step_images/step_images.rego new file mode 100644 index 000000000..825de45c1 --- /dev/null +++ b/policy/task/step_images/step_images.rego @@ -0,0 +1,37 @@ +# +# METADATA +# title: Tekton Task Step image policies +# description: >- +# This package ensures that a Task definition contains valid values for the image references +# used by the Task's steps. +# +package step_images + +import rego.v1 + +import data.lib + +# METADATA +# title: Step images are valid +# description: >- +# Confirm that each step in the Task uses a container image that is accessible. +# custom: +# short_name: step_images_accessible +# failure_msg: Step %d uses inaccessible image ref '%s' +# solution: >- +# Make sure the container image used in each step of the Task is pushed to the +# registry and that it can be fetched. +# +deny contains result if { + input.kind == "Task" + + some step_index, step in input.spec.steps + image_ref := step.image + is_null(ec.oci.image_manifest(image_ref)) + + result := lib.result_helper_with_term( + rego.metadata.chain(), + [step_index, image_ref], + image_ref, + ) +} diff --git a/policy/task/step_images/step_images_test.rego b/policy/task/step_images/step_images_test.rego new file mode 100644 index 000000000..0991f8d6b --- /dev/null +++ b/policy/task/step_images/step_images_test.rego @@ -0,0 +1,68 @@ +package step_images_test + +import rego.v1 + +import data.lib +import data.step_images + +test_looks_at_tasks_only if { + pipeline := { + "kind": "Pipeline", + "spec": {"steps": [{"image": "registry.io/repository/not_ok"}]}, + } + + lib.assert_empty(step_images.deny) with input as pipeline +} + +test_task_with_no_steps if { + task := {"kind": "Task"} + + lib.assert_empty(step_images.deny) with input as task +} + +test_task_with_valid_steps if { + task := { + "kind": "Task", + "spec": {"steps": [ + {"image": "registry.io/repository/ok:1"}, + {"image": "registry.io/repository/ok:2"}, + {"image": "registry.io/repository/ok:3"}, + ]}, + } + + lib.assert_empty(step_images.deny) with input as task with ec.oci.image_manifest as mock_image_manifest +} + +test_task_with_invalid_steps if { + task := { + "kind": "Task", + "spec": {"steps": [ + {"image": "registry.io/repository/ok:1"}, + {"image": "registry.io/repository/not_ok:2"}, + {"image": "registry.io/repository/ok:3"}, + {"image": "registry.io/repository/not_ok:4"}, + {"image": "registry.io/repository/ok:5"}, + ]}, + } + + expected := { + { + "code": "step_images.step_images_accessible", + "msg": "Step 1 uses inaccessible image ref 'registry.io/repository/not_ok:2'", + "term": "registry.io/repository/not_ok:2", + }, + { + "code": "step_images.step_images_accessible", + "msg": "Step 3 uses inaccessible image ref 'registry.io/repository/not_ok:4'", + "term": "registry.io/repository/not_ok:4", + }, + } + + lib.assert_equal_results(expected, step_images.deny) with input as task + with ec.oci.image_manifest as mock_image_manifest +} + +mock_image_manifest(ref) := m if { + startswith(ref, "registry.io/repository/ok") + m := {} +} else := null