From 7bf6430d12f21d94e070278bf7809231b68b0371 Mon Sep 17 00:00:00 2001 From: Rob Nester Date: Fri, 5 Jun 2026 10:41:44 -0400 Subject: [PATCH 1/2] feat(EC-1824): add acceptance tests for multi-arch volatile exceptions Add two acceptance test scenarios verifying that volatile config componentNames excludes work correctly with multi-arch expanded component names (e.g., "foo-sha256:-arm64"). The tests use --images with an ApplicationSnapshot file to set component names to the expanded format, validating the originalComponentName() wiring in Criteria.get() end-to-end. Scenario A: exclude matches when expanded name's base matches componentNames Scenario B: exclude does NOT match when base name differs resolves: EC-1824 Co-Authored-By: Claude Opus 4.6 (1M context) --- features/__snapshots__/validate_image.snap | 225 +++++++++++++++++++++ features/validate_image.feature | 106 ++++++++++ 2 files changed, 331 insertions(+) diff --git a/features/__snapshots__/validate_image.snap b/features/__snapshots__/validate_image.snap index e5bc417ef..b51d9b6ab 100644 --- a/features/__snapshots__/validate_image.snap +++ b/features/__snapshots__/validate_image.snap @@ -5916,3 +5916,228 @@ time="${TIMESTAMP}" level=warning msg="Attestation signature check skipped, fetc time="${TIMESTAMP}" level=warning msg="Both --skip-image-sig-check and --skip-att-sig-check are active, all cryptographic verification is disabled" --- + +[TestFeatures/volatile config exclude matches multi-arch expanded component name:stdout - 1] +{ + "success": true, + "components": [ + { + "name": "multi-arch-test-sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2-arm64", + "containerImage": "${REGISTRY}/acceptance/multi-arch-volatile@sha256:${REGISTRY_acceptance/multi-arch-volatile:latest_DIGEST}", + "source": {}, + "successes": [ + { + "msg": "Pass", + "metadata": { + "code": "builtin.attestation.signature_check" + } + }, + { + "msg": "Pass", + "metadata": { + "code": "builtin.attestation.syntax_check" + } + }, + { + "msg": "Pass", + "metadata": { + "code": "builtin.image.signature_check" + } + }, + { + "msg": "Pass", + "metadata": { + "code": "filtering.always_pass" + } + }, + { + "msg": "Pass", + "metadata": { + "code": "filtering.always_pass_with_collection" + } + } + ], + "success": true, + "signatures": [ + { + "keyid": "", + "sig": "${IMAGE_SIGNATURE_acceptance/multi-arch-volatile}" + } + ], + "attestations": [ + { + "type": "https://in-toto.io/Statement/v0.1", + "predicateType": "https://slsa.dev/provenance/v0.2", + "predicateBuildType": "https://tekton.dev/attestations/chains/pipelinerun@v2", + "signatures": [ + { + "keyid": "", + "sig": "${ATTESTATION_SIGNATURE_acceptance/multi-arch-volatile}" + } + ] + } + ] + } + ], + "key": "${known_PUBLIC_KEY_JSON}", + "policy": { + "sources": [ + { + "policy": [ + "git::${GITHOST}/git/happy-day-policy.git?ref=${LATEST_COMMIT}" + ], + "config": { + "include": [ + "@stamps", + "filtering.always_pass", + "filtering.always_fail" + ] + }, + "volatileConfig": { + "exclude": [ + { + "value": "filtering.always_fail", + "componentNames": [ + "multi-arch-test" + ] + }, + { + "value": "filtering.always_fail_with_collection", + "componentNames": [ + "multi-arch-test" + ] + } + ] + } + } + ], + "publicKey": "${known_PUBLIC_KEY}" + }, + "ec-version": "${EC_VERSION}", + "effective-time": "${TIMESTAMP}" +} +--- + +[TestFeatures/volatile config exclude matches multi-arch expanded component name:stderr - 1] + +--- + +[TestFeatures/volatile config exclude does not match different multi-arch component:stdout - 1] +{ + "success": false, + "components": [ + { + "name": "other-component-sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2-amd64", + "containerImage": "${REGISTRY}/acceptance/multi-arch-volatile-neg@sha256:${REGISTRY_acceptance/multi-arch-volatile-neg:latest_DIGEST}", + "source": {}, + "violations": [ + { + "msg": "always fail", + "metadata": { + "code": "filtering.always_fail" + } + }, + { + "msg": "always fail with collection", + "metadata": { + "code": "filtering.always_fail_with_collection" + } + } + ], + "successes": [ + { + "msg": "Pass", + "metadata": { + "code": "builtin.attestation.signature_check" + } + }, + { + "msg": "Pass", + "metadata": { + "code": "builtin.attestation.syntax_check" + } + }, + { + "msg": "Pass", + "metadata": { + "code": "builtin.image.signature_check" + } + }, + { + "msg": "Pass", + "metadata": { + "code": "filtering.always_pass" + } + }, + { + "msg": "Pass", + "metadata": { + "code": "filtering.always_pass_with_collection" + } + } + ], + "success": false, + "signatures": [ + { + "keyid": "", + "sig": "${IMAGE_SIGNATURE_acceptance/multi-arch-volatile-neg}" + } + ], + "attestations": [ + { + "type": "https://in-toto.io/Statement/v0.1", + "predicateType": "https://slsa.dev/provenance/v0.2", + "predicateBuildType": "https://tekton.dev/attestations/chains/pipelinerun@v2", + "signatures": [ + { + "keyid": "", + "sig": "${ATTESTATION_SIGNATURE_acceptance/multi-arch-volatile-neg}" + } + ] + } + ] + } + ], + "key": "${known_PUBLIC_KEY_JSON}", + "policy": { + "sources": [ + { + "policy": [ + "git::${GITHOST}/git/happy-day-policy.git?ref=${LATEST_COMMIT}" + ], + "config": { + "include": [ + "@stamps", + "filtering.always_pass", + "filtering.always_fail" + ] + }, + "volatileConfig": { + "exclude": [ + { + "value": "filtering.always_fail", + "componentNames": [ + "multi-arch-test" + ] + }, + { + "value": "filtering.always_fail_with_collection", + "componentNames": [ + "multi-arch-test" + ] + } + ] + } + } + ], + "publicKey": "${known_PUBLIC_KEY}" + }, + "ec-version": "${EC_VERSION}", + "effective-time": "${TIMESTAMP}" +} +--- + +[TestFeatures/volatile config exclude does not match different multi-arch component:stderr - 1] +Error: success criteria not met + +--- diff --git a/features/validate_image.feature b/features/validate_image.feature index 05899bb12..f58e589da 100644 --- a/features/validate_image.feature +++ b/features/validate_image.feature @@ -1115,6 +1115,112 @@ Feature: evaluate enterprise contract Then the exit status should be 0 Then the output should match the snapshot + # Tests for EC-1824: multi-arch per-component volatile exceptions. + # When validate image encounters an image index, imageIndexWorker (input.go:264) expands + # the component name from "foo" to "foo-sha256:-". The fix in Criteria.get() + # uses originalComponentName() to strip that suffix so volatile config componentNames + # entries referencing the original name still match. + # These tests use --images with an ApplicationSnapshot file to set the component name + # to the expanded format directly, validating the originalComponentName() wiring. + + Scenario: volatile config exclude matches multi-arch expanded component name + Given a key pair named "known" + Given an image named "acceptance/multi-arch-volatile" + Given a valid image signature of "acceptance/multi-arch-volatile" image signed by the "known" key + Given a valid attestation of "acceptance/multi-arch-volatile" signed by the "known" key + Given a git repository named "happy-day-policy" with + | filtering.rego | examples/filtering.rego | + Given a file named "${TMPDIR}/multi-arch-images.json" containing + """ + { + "components": [ + { + "containerImage": "${REGISTRY}/acceptance/multi-arch-volatile", + "name": "multi-arch-test-sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2-arm64" + } + ] + } + """ + Given policy configuration named "ec-policy" with specification + """ + { + "sources": [ + { + "volatileConfig": { + "exclude": [ + { + "value": "filtering.always_fail", + "componentNames": ["multi-arch-test"] + }, + { + "value": "filtering.always_fail_with_collection", + "componentNames": ["multi-arch-test"] + } + ] + }, + "config": { + "include": ["@stamps", "filtering.always_pass", "filtering.always_fail"] + }, + "policy": [ + "git::https://${GITHOST}/git/happy-day-policy.git" + ] + } + ] + } + """ + When ec command is run with "validate image --images ${TMPDIR}/multi-arch-images.json --policy acceptance/ec-policy --public-key ${known_PUBLIC_KEY} --ignore-rekor --show-successes --output json" + Then the exit status should be 0 + Then the output should match the snapshot + + Scenario: volatile config exclude does not match different multi-arch component + Given a key pair named "known" + Given an image named "acceptance/multi-arch-volatile-neg" + Given a valid image signature of "acceptance/multi-arch-volatile-neg" image signed by the "known" key + Given a valid attestation of "acceptance/multi-arch-volatile-neg" signed by the "known" key + Given a git repository named "happy-day-policy" with + | filtering.rego | examples/filtering.rego | + Given a file named "${TMPDIR}/multi-arch-images-neg.json" containing + """ + { + "components": [ + { + "containerImage": "${REGISTRY}/acceptance/multi-arch-volatile-neg", + "name": "other-component-sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2-amd64" + } + ] + } + """ + Given policy configuration named "ec-policy" with specification + """ + { + "sources": [ + { + "volatileConfig": { + "exclude": [ + { + "value": "filtering.always_fail", + "componentNames": ["multi-arch-test"] + }, + { + "value": "filtering.always_fail_with_collection", + "componentNames": ["multi-arch-test"] + } + ] + }, + "config": { + "include": ["@stamps", "filtering.always_pass", "filtering.always_fail"] + }, + "policy": [ + "git::https://${GITHOST}/git/happy-day-policy.git" + ] + } + ] + } + """ + When ec command is run with "validate image --images ${TMPDIR}/multi-arch-images-neg.json --policy acceptance/ec-policy --public-key ${known_PUBLIC_KEY} --ignore-rekor --show-successes --output json" + Then the exit status should be 1 + Then the output should match the snapshot + Scenario: Unsupported policies Given a key pair named "known" Given an image named "acceptance/image" From 9817ee475fc57a9302de1e2d00537eb37f76b32f Mon Sep 17 00:00:00 2001 From: Rob Nester Date: Mon, 8 Jun 2026 13:26:14 -0400 Subject: [PATCH 2/2] fix(EC-1824): trim verbose comment block per reviewer feedback reference: EC-1824 Co-Authored-By: Claude Opus 4.6 (1M context) --- features/validate_image.feature | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/features/validate_image.feature b/features/validate_image.feature index f58e589da..c6c43d835 100644 --- a/features/validate_image.feature +++ b/features/validate_image.feature @@ -1115,13 +1115,8 @@ Feature: evaluate enterprise contract Then the exit status should be 0 Then the output should match the snapshot - # Tests for EC-1824: multi-arch per-component volatile exceptions. - # When validate image encounters an image index, imageIndexWorker (input.go:264) expands - # the component name from "foo" to "foo-sha256:-". The fix in Criteria.get() - # uses originalComponentName() to strip that suffix so volatile config componentNames - # entries referencing the original name still match. - # These tests use --images with an ApplicationSnapshot file to set the component name - # to the expanded format directly, validating the originalComponentName() wiring. + # EC-1824: verify volatile config componentNames excludes work with + # multi-arch expanded component names (e.g., "foo-sha256:-arm64"). Scenario: volatile config exclude matches multi-arch expanded component name Given a key pair named "known"