diff --git a/pkg/attestation/crafter/materials/evidence.go b/pkg/attestation/crafter/materials/evidence.go index 414afb21a..a3b71943f 100644 --- a/pkg/attestation/crafter/materials/evidence.go +++ b/pkg/attestation/crafter/materials/evidence.go @@ -42,7 +42,9 @@ type EvidenceCrafter struct { // customEvidence represents the expected structure of a custom Evidence JSON file type customEvidence struct { // ID is a unique identifier for the evidence - ID string `json:"id"` + // Deprecated: in favor of ChainloopID + ID string `json:"id"` + ChainloopID string `json:"chainloop.material.evidence.id"` // Schema is an optional schema reference for the evidence validation Schema string `json:"schema"` // Data contains the actual evidence content @@ -93,8 +95,14 @@ func (i *EvidenceCrafter) tryExtractAnnotations(m *api.Attestation_Material, art return } + chainloopID := evidence.ChainloopID + // fallback to deprecated id field + if chainloopID == "" { + chainloopID = evidence.ID + } + // Check if it has the required structure (id and data fields) - if evidence.ID == "" || len(evidence.Data) == 0 { + if chainloopID == "" || len(evidence.Data) == 0 { i.logger.Debug().Msg("evidence JSON does not have required id and data fields, skipping annotation extraction") return } @@ -105,7 +113,7 @@ func (i *EvidenceCrafter) tryExtractAnnotations(m *api.Attestation_Material, art } // Extract id and schema as annotations - m.Annotations[annotationEvidenceID] = evidence.ID + m.Annotations[annotationEvidenceID] = chainloopID if evidence.Schema != "" { m.Annotations[annotationEvidenceSchema] = evidence.Schema } diff --git a/pkg/attestation/crafter/materials/evidence_test.go b/pkg/attestation/crafter/materials/evidence_test.go index 8df8cd069..57577f489 100644 --- a/pkg/attestation/crafter/materials/evidence_test.go +++ b/pkg/attestation/crafter/materials/evidence_test.go @@ -166,7 +166,7 @@ func TestEvidenceCraftWithJSONAnnotations(t *testing.T) { expectedAnnotations map[string]string }{ { - name: "JSON with id, data and schema fields extracts annotations", + name: "JSON with deprecated id, data and schema fields extracts annotations", filePath: "./testdata/evidence-with-id-data-schema.json", expectedAnnotations: map[string]string{ "chainloop.material.evidence.id": "custom-evidence-123", @@ -180,6 +180,14 @@ func TestEvidenceCraftWithJSONAnnotations(t *testing.T) { "chainloop.material.evidence.id": "custom-evidence-456", }, }, + { + name: "JSON with new chainloop.material.evidence.id, data and schema fields extracts annotations", + filePath: "./testdata/evidence-with-new-id-data-schema.json", + expectedAnnotations: map[string]string{ + "chainloop.material.evidence.id": "custom-evidence-123", + "chainloop.material.evidence.schema": "https://example.com/schema/v1", + }, + }, { name: "JSON without required structure does not extract annotations", filePath: "./testdata/evidence-invalid-structure.json", diff --git a/pkg/attestation/crafter/materials/testdata/evidence-with-new-id-data-schema.json b/pkg/attestation/crafter/materials/testdata/evidence-with-new-id-data-schema.json new file mode 100644 index 000000000..b2b595cc6 --- /dev/null +++ b/pkg/attestation/crafter/materials/testdata/evidence-with-new-id-data-schema.json @@ -0,0 +1,13 @@ +{ + "chainloop.material.evidence.id": "custom-evidence-123", + "schema": "https://example.com/schema/v1", + "data": { + "status": "approved", + "approver": "john.doe@example.com", + "timestamp": "2025-10-30T10:00:00Z", + "details": { + "review_type": "security", + "findings": ["no issues found"] + } + } +}