Analysis produced from the following Copilot prompt:
Currently Tekton Chains does not appear to sign an OCI artifact even though it is included in an appropriate ARTIFACT_OUTPUTS with isBuildArtifact set to "true".
Can you explain what the cause of the artfact not being signed.
Root Cause
The OCIArtifact.ExtractObjects() method only recognizes specific result naming patterns and does NOT support the *ARTIFACT_OUTPUTS type-hint.
What OCIArtifact.ExtractObjects() Currently Looks For
The ExtractOCIImagesFromResults() function (called by OCIArtifact) only extracts images from:
-
*IMAGE_URL / *IMAGE_DIGEST pair - Results with suffixes IMAGE_URL and IMAGE_DIGEST
- Example:
image1_IMAGE_URL + image1_IMAGE_DIGEST
-
IMAGES result - A comma-separated string of images in format repo@sha256:digest
- Example:
gcr.io/foo/bar@sha256:abc123
What's Missing
The ExtractOCIImagesFromResults() function completely ignores results with the *ARTIFACT_OUTPUTS suffix, even when they have:
- A valid
uri field
- A valid
digest field
isBuildArtifact: "true"
The Code Evidence
From pkg/artifacts/signable.go:
func ExtractOCIImagesFromResults(ctx context.Context, results []objects.Result) []interface{} {
logger := logging.FromContext(ctx)
objs := []interface{}{}
// Only looks for IMAGE_URL/IMAGE_DIGEST pairs
extractor := structuredSignableExtractor{
uriSuffix: OCIImageURLResultName, // "IMAGE_URL"
digestSuffix: OCIImageDigestResultName, // "IMAGE_DIGEST"
isValid: hasImageRequirements,
}
for _, s := range extractor.extract(ctx, results) {
// Process IMAGE_URL/IMAGE_DIGEST pairs
}
// Only looks for IMAGES result
for _, key := range results {
if key.Name != OCIImagesResultName { // Only "IMAGES"
continue
}
// Process IMAGES result
}
return objs
}
Notice: There is NO code path that processes *ARTIFACT_OUTPUTS results.
The Disconnect
While the SLSA provenance generation code (in pkg/chains/formats/slsa/extract/extract.go) properly extracts artifacts from *ARTIFACT_OUTPUTS results for provenance subjects, the OCI signing code does not. This creates an asymmetry:
- ✅ Provenance:
*ARTIFACT_OUTPUTS artifacts are included in SLSA provenance subjects
- ❌ Signing:
*ARTIFACT_OUTPUTS artifacts are NOT extracted for OCI signing
Solution
The ExtractOCIImagesFromResults() function needs to be enhanced to also extract and sign OCI artifacts from *ARTIFACT_OUTPUTS results. This would involve:
- Adding support for
*ARTIFACT_OUTPUTS result type-hint in ExtractOCIImagesFromResults()
- Checking for the
isBuildArtifact: "true" flag (or processing all *ARTIFACT_OUTPUTS results)
- Extracting the
uri and digest fields just like the SLSA provenance extraction does
Analysis produced from the following Copilot prompt:
Root Cause
The
OCIArtifact.ExtractObjects()method only recognizes specific result naming patterns and does NOT support the*ARTIFACT_OUTPUTStype-hint.What
OCIArtifact.ExtractObjects()Currently Looks ForThe
ExtractOCIImagesFromResults()function (called byOCIArtifact) only extracts images from:*IMAGE_URL/*IMAGE_DIGESTpair - Results with suffixesIMAGE_URLandIMAGE_DIGESTimage1_IMAGE_URL+image1_IMAGE_DIGESTIMAGESresult - A comma-separated string of images in formatrepo@sha256:digestgcr.io/foo/bar@sha256:abc123What's Missing
The
ExtractOCIImagesFromResults()function completely ignores results with the*ARTIFACT_OUTPUTSsuffix, even when they have:urifielddigestfieldisBuildArtifact: "true"The Code Evidence
From
pkg/artifacts/signable.go:Notice: There is NO code path that processes
*ARTIFACT_OUTPUTSresults.The Disconnect
While the SLSA provenance generation code (in
pkg/chains/formats/slsa/extract/extract.go) properly extracts artifacts from*ARTIFACT_OUTPUTSresults for provenance subjects, the OCI signing code does not. This creates an asymmetry:*ARTIFACT_OUTPUTSartifacts are included in SLSA provenance subjects*ARTIFACT_OUTPUTSartifacts are NOT extracted for OCI signingSolution
The
ExtractOCIImagesFromResults()function needs to be enhanced to also extract and sign OCI artifacts from*ARTIFACT_OUTPUTSresults. This would involve:*ARTIFACT_OUTPUTSresult type-hint inExtractOCIImagesFromResults()isBuildArtifact: "true"flag (or processing all*ARTIFACT_OUTPUTSresults)urianddigestfields just like the SLSA provenance extraction does