diff --git a/app/cli/api/attestation/v1/crafting_state.go b/app/cli/api/attestation/v1/crafting_state.go index 1b948098e..cd0899c97 100644 --- a/app/cli/api/attestation/v1/crafting_state.go +++ b/app/cli/api/attestation/v1/crafting_state.go @@ -20,21 +20,22 @@ import ( ) type NormalizedMaterialOutput struct { - Value, Digest string - IsOutput bool + Name, Digest string + IsOutput bool + Content []byte } func (m *Attestation_Material) NormalizedOutput() *NormalizedMaterialOutput { switch m.MaterialType { case schemaapi.CraftingSchema_Material_ARTIFACT, schemaapi.CraftingSchema_Material_SBOM_CYCLONEDX_JSON, schemaapi.CraftingSchema_Material_SBOM_SPDX_JSON: a := m.GetArtifact() - return &NormalizedMaterialOutput{a.Name, a.Digest, a.IsSubject} + return &NormalizedMaterialOutput{a.Name, a.Digest, a.IsSubject, a.Content} case schemaapi.CraftingSchema_Material_CONTAINER_IMAGE: a := m.GetContainerImage() - return &NormalizedMaterialOutput{a.Name, a.Digest, a.IsSubject} + return &NormalizedMaterialOutput{a.Name, a.Digest, a.IsSubject, nil} case schemaapi.CraftingSchema_Material_STRING: a := m.GetString_() - return &NormalizedMaterialOutput{Value: a.Value} + return &NormalizedMaterialOutput{Content: []byte(a.Value)} } return nil diff --git a/app/cli/api/attestation/v1/crafting_state.pb.go b/app/cli/api/attestation/v1/crafting_state.pb.go index b2c3e44fc..2d944fd43 100644 --- a/app/cli/api/attestation/v1/crafting_state.pb.go +++ b/app/cli/api/attestation/v1/crafting_state.pb.go @@ -300,6 +300,9 @@ type Attestation_Material struct { MaterialType v1.CraftingSchema_Material_MaterialType `protobuf:"varint,6,opt,name=material_type,json=materialType,proto3,enum=workflowcontract.v1.CraftingSchema_Material_MaterialType" json:"material_type,omitempty"` // Whether the material has been uploaded to the CAS UploadedToCas bool `protobuf:"varint,7,opt,name=uploaded_to_cas,json=uploadedToCas,proto3" json:"uploaded_to_cas,omitempty"` + // If the material content has been injected inline in the attestation + // leveraging a form of inline CAS + InlineCas bool `protobuf:"varint,8,opt,name=inline_cas,json=inlineCas,proto3" json:"inline_cas,omitempty"` } func (x *Attestation_Material) Reset() { @@ -383,6 +386,13 @@ func (x *Attestation_Material) GetUploadedToCas() bool { return false } +func (x *Attestation_Material) GetInlineCas() bool { + if x != nil { + return x.InlineCas + } + return false +} + type isAttestation_Material_M interface { isAttestation_Material_M() } @@ -544,6 +554,9 @@ type Attestation_Material_Artifact struct { // which also has annotated the fileName Digest string `protobuf:"bytes,3,opt,name=digest,proto3" json:"digest,omitempty"` IsSubject bool `protobuf:"varint,4,opt,name=is_subject,json=isSubject,proto3" json:"is_subject,omitempty"` + // Inline content of the artifact. + // This is optional and is used for small artifacts that can be stored inline in the attestation + Content []byte `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"` } func (x *Attestation_Material_Artifact) Reset() { @@ -606,6 +619,13 @@ func (x *Attestation_Material_Artifact) GetIsSubject() bool { return false } +func (x *Attestation_Material_Artifact) GetContent() []byte { + if x != nil { + return x.Content + } + return nil +} + var File_attestation_v1_crafting_state_proto protoreflect.FileDescriptor var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ @@ -618,7 +638,7 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x0b, 0x0a, 0x0b, 0x41, + 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd1, 0x0b, 0x0a, 0x0b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, @@ -655,7 +675,7 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x90, 0x06, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xc9, 0x06, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x45, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, @@ -683,62 +703,65 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x52, 0x0c, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, - 0x64, 0x54, 0x6f, 0x43, 0x61, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, - 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x86, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x17, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x1a, 0x80, 0x01, 0x0a, 0x08, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x17, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x64, - 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x42, 0x03, 0x0a, 0x01, 0x6d, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, - 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, - 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, - 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, - 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, - 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0xe1, 0x01, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, - 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0f, 0x73, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0e, 0x73, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x3f, 0x5a, 0x3d, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, - 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, - 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x54, 0x6f, 0x43, 0x61, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x5f, 0x63, 0x61, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x43, 0x61, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x12, + 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x86, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x1a, 0x9a, 0x01, 0x0a, 0x08, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x17, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x64, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x03, 0x0a, + 0x01, 0x6d, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaf, + 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x46, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, + 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0b, 0x69, 0x6e, 0x70, + 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, + 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, + 0x22, 0xe1, 0x01, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x65, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, + 0x12, 0x28, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, + 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, + 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, + 0x6c, 0x69, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/cli/api/attestation/v1/crafting_state.pb.validate.go b/app/cli/api/attestation/v1/crafting_state.pb.validate.go index b71771f2f..1c59a6d83 100644 --- a/app/cli/api/attestation/v1/crafting_state.pb.validate.go +++ b/app/cli/api/attestation/v1/crafting_state.pb.validate.go @@ -624,6 +624,8 @@ func (m *Attestation_Material) validate(all bool) error { // no validation rules for UploadedToCas + // no validation rules for InlineCas + switch v := m.M.(type) { case *Attestation_Material_String_: if v == nil { @@ -1154,6 +1156,8 @@ func (m *Attestation_Material_Artifact) validate(all bool) error { // no validation rules for IsSubject + // no validation rules for Content + if len(errors) > 0 { return Attestation_Material_ArtifactMultiError(errors) } diff --git a/app/cli/api/attestation/v1/crafting_state.proto b/app/cli/api/attestation/v1/crafting_state.proto index 02deb81a8..8db8fd020 100644 --- a/app/cli/api/attestation/v1/crafting_state.proto +++ b/app/cli/api/attestation/v1/crafting_state.proto @@ -43,6 +43,9 @@ message Attestation { // Whether the material has been uploaded to the CAS bool uploaded_to_cas = 7; + // If the material content has been injected inline in the attestation + // leveraging a form of inline CAS + bool inline_cas = 8; message KeyVal { string id = 1 [(validate.rules).string.min_len = 1]; @@ -65,6 +68,9 @@ message Attestation { // which also has annotated the fileName string digest = 3 [(validate.rules).string.min_len = 1]; bool is_subject = 4; + // Inline content of the artifact. + // This is optional and is used for small artifacts that can be stored inline in the attestation + bytes content = 5; } } diff --git a/app/cli/internal/action/attestation_add.go b/app/cli/internal/action/attestation_add.go index 8b141eaeb..3cd58ed79 100644 --- a/app/cli/internal/action/attestation_add.go +++ b/app/cli/internal/action/attestation_add.go @@ -81,7 +81,21 @@ func (action *AttestationAdd) Run(k, v string) error { cc := casclient.New(artifactCASConn, casclient.WithLogger(action.Logger)) - if err := action.c.AddMaterial(k, v, cc); err != nil { + // // TODO: retrieve this information from backend + backend := &casclient.CASBackend{ + Uploader: cc, + Name: "OCI", + // 100MB max size + MaxSize: 100 * 1024 * 1024, + } + + // backend := &casclient.CASBackend{ + // Name: "INLINE", + // // 500KB max size + // MaxSize: 500 * 1024, + // } + + if err := action.c.AddMaterial(k, v, backend); err != nil { action.Logger.Err(err).Msg("adding material") return err } diff --git a/app/controlplane/internal/service/attestation.go b/app/controlplane/internal/service/attestation.go index ddc8ccb07..9e5af724f 100644 --- a/app/controlplane/internal/service/attestation.go +++ b/app/controlplane/internal/service/attestation.go @@ -298,10 +298,15 @@ func bizAttestationToPb(att *biz.Attestation) (*cpAPI.AttestationItem, error) { return nil, fmt.Errorf("error extracting predicate from attestation: %w", err) } + materials, err := extractMaterials(predicate.GetMaterials()) + if err != nil { + return nil, fmt.Errorf("error extracting materials from attestation: %w", err) + } + return &cpAPI.AttestationItem{ Envelope: encodedAttestation, EnvVars: extractEnvVariables(predicate.GetEnvVars()), - Materials: extractMaterials(predicate.GetMaterials()), + Materials: materials, }, nil } @@ -319,18 +324,23 @@ func extractEnvVariables(in map[string]string) []*cpAPI.AttestationItem_EnvVaria return res } -func extractMaterials(in []*chainloop.NormalizedMaterial) []*cpAPI.AttestationItem_Material { +func extractMaterials(in []*chainloop.NormalizedMaterial) ([]*cpAPI.AttestationItem_Material, error) { res := make([]*cpAPI.AttestationItem_Material, 0, len(in)) for _, m := range in { // Initialize simply with the value displayValue := m.Value // Override if there is a hash attached if m.Hash != nil { - displayValue = fmt.Sprintf("%s@%s", m.Value, m.Hash) + name := m.Value + if m.EmbeddedInline || m.UploadedToCAS { + name = m.Filename + } + + displayValue = fmt.Sprintf("%s@%s", name, m.Hash) } res = append(res, &cpAPI.AttestationItem_Material{Name: m.Name, Value: displayValue, Type: m.Type}) } - return res + return res, nil } diff --git a/app/controlplane/internal/service/attestation_test.go b/app/controlplane/internal/service/attestation_test.go index 38b38ad3e..c1d047f65 100644 --- a/app/controlplane/internal/service/attestation_test.go +++ b/app/controlplane/internal/service/attestation_test.go @@ -44,6 +44,12 @@ func TestExtractMaterials(t *testing.T) { Value: "bar", Hash: &crv1.Hash{Algorithm: "sha256", Hex: "deadbeef"}, }, + { + Name: "image", + Type: "CONTAINER_IMAGE", + Value: "docker.io/nginx", + Hash: &crv1.Hash{Algorithm: "sha256", Hex: "deadbeef"}, + }, }, want: []*cpAPI.AttestationItem_Material{ { @@ -56,14 +62,20 @@ func TestExtractMaterials(t *testing.T) { Type: "ARTIFACT", Value: "bar@sha256:deadbeef", }, + { + Name: "image", + Type: "CONTAINER_IMAGE", + Value: "docker.io/nginx@sha256:deadbeef", + }, }, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - got := extractMaterials(tc.input) - assert.Equal(t, got, tc.want) + got, err := extractMaterials(tc.input) + assert.NoError(t, err) + assert.Equal(t, tc.want, got) }) } } diff --git a/app/controlplane/plugins/core/guac/v1/guac.go b/app/controlplane/plugins/core/guac/v1/guac.go index 4db5ffad7..72ac6b372 100644 --- a/app/controlplane/plugins/core/guac/v1/guac.go +++ b/app/controlplane/plugins/core/guac/v1/guac.go @@ -159,7 +159,7 @@ func (i *Integration) Execute(ctx context.Context, req *sdk.ExecutionRequest) er // 2 - Upload all the materials, in our case they are SBOMs for _, sbom := range req.Input.Materials { - filename := uniqueFilename(pathPrefix, sbom.Value, sbom.Hash.Hex) + filename := uniqueFilename(pathPrefix, sbom.Filename, sbom.Hash.Hex) if err := uploadToBucket(ctx, bucket, filename, sbom.Content, req.ChainloopMetadata, i.Logger); err != nil { return fmt.Errorf("uploading the SBOM to the bucket: %w", err) } diff --git a/app/controlplane/plugins/sdk/v1/plugin/api/fanout.pb.go b/app/controlplane/plugins/sdk/v1/plugin/api/fanout.pb.go index f04b177ac..4717762ec 100644 --- a/app/controlplane/plugins/sdk/v1/plugin/api/fanout.pb.go +++ b/app/controlplane/plugins/sdk/v1/plugin/api/fanout.pb.go @@ -941,6 +941,7 @@ type ExecuteRequest_NormalizedMaterial struct { Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"` Hash string `protobuf:"bytes,5,opt,name=hash,proto3" json:"hash,omitempty"` UploadedToCas bool `protobuf:"varint,6,opt,name=uploaded_to_cas,json=uploadedToCas,proto3" json:"uploaded_to_cas,omitempty"` + FileName string `protobuf:"bytes,7,opt,name=file_name,json=fileName,proto3" json:"file_name,omitempty"` } func (x *ExecuteRequest_NormalizedMaterial) Reset() { @@ -1017,6 +1018,13 @@ func (x *ExecuteRequest_NormalizedMaterial) GetUploadedToCas() bool { return false } +func (x *ExecuteRequest_NormalizedMaterial) GetFileName() string { + if x != nil { + return x.FileName + } + return "" +} + type ExecuteRequest_Metadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1157,7 +1165,7 @@ var file_fanout_proto_rawDesc = []byte{ 0x22, 0x36, 0x0a, 0x0e, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xff, 0x04, 0x0a, 0x0e, 0x45, 0x78, 0x65, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9c, 0x05, 0x0a, 0x0e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x11, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x67, @@ -1176,7 +1184,7 @@ var file_fanout_proto_rawDesc = []byte{ 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, - 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0xa8, 0x01, 0x0a, 0x12, 0x4e, 0x6f, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0xc5, 0x01, 0x0a, 0x12, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, @@ -1187,66 +1195,67 @@ var file_fanout_proto_rawDesc = []byte{ 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x54, - 0x6f, 0x43, 0x61, 0x73, 0x1a, 0xa3, 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, - 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x0a, - 0x15, 0x49, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0x38, 0x0a, 0x16, 0x49, - 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x64, 0x32, 0x9c, 0x04, 0x0a, 0x0d, 0x46, 0x61, 0x6e, 0x6f, 0x75, 0x74, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x62, 0x65, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x5b, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, - 0x12, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, - 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x12, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0e, 0x49, 0x73, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x49, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x73, 0x53, 0x75, + 0x6f, 0x43, 0x61, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x1a, 0xa3, 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, + 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, + 0x23, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x0a, 0x15, 0x49, 0x73, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x74, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0x38, 0x0a, 0x16, 0x49, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x14, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x41, - 0x74, 0x74, 0x61, 0x63, 0x68, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x74, 0x74, 0x61, - 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, - 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, - 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x70, 0x6c, 0x75, 0x67, - 0x69, 0x6e, 0x73, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x64, 0x32, 0x9c, 0x04, 0x0a, 0x0d, 0x46, 0x61, 0x6e, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, + 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x12, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x31, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0e, 0x49, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x73, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x62, 0x65, 0x64, 0x54, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x37, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x14, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x41, 0x74, 0x74, 0x61, + 0x63, 0x68, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x74, 0x74, + 0x61, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x07, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, + 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x61, + 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/controlplane/plugins/sdk/v1/plugin/api/fanout.proto b/app/controlplane/plugins/sdk/v1/plugin/api/fanout.proto index 2a1620859..c55924296 100644 --- a/app/controlplane/plugins/sdk/v1/plugin/api/fanout.proto +++ b/app/controlplane/plugins/sdk/v1/plugin/api/fanout.proto @@ -110,6 +110,7 @@ message ExecuteRequest { string value = 4; string hash = 5; bool uploaded_to_cas = 6; + string file_name = 7; } message Metadata { diff --git a/app/controlplane/plugins/sdk/v1/plugin/api/translation.go b/app/controlplane/plugins/sdk/v1/plugin/api/translation.go index 8de0d3cee..a170aca8e 100644 --- a/app/controlplane/plugins/sdk/v1/plugin/api/translation.go +++ b/app/controlplane/plugins/sdk/v1/plugin/api/translation.go @@ -132,6 +132,7 @@ func MaterialSDKToProto(in *sdk.ExecuteMaterial) *ExecuteRequest_NormalizedMater Name: in.Name, Type: in.Type, Value: in.Value, + FileName: in.Filename, Hash: in.Hash.String(), UploadedToCas: in.UploadedToCAS, } @@ -150,6 +151,7 @@ func MaterialProtoToSDK(in *ExecuteRequest_NormalizedMaterial) *sdk.ExecuteMater Name: in.Name, Type: in.Type, Value: in.Value, + Filename: in.FileName, UploadedToCAS: in.UploadedToCas, Hash: &hash, }, diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index cae331fc0..01ad6a0fd 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -326,7 +326,7 @@ func notResolvedVars(resolved map[string]string, wantList []string) []string { } // Inject material to attestation state -func (c *Crafter) AddMaterial(key, value string, uploader casclient.Uploader) error { +func (c *Crafter) AddMaterial(key, value string, casBackend *casclient.CASBackend) error { if err := c.requireStateLoaded(); err != nil { return err } @@ -349,7 +349,7 @@ func (c *Crafter) AddMaterial(key, value string, uploader casclient.Uploader) er } // 3 - Craft resulting material - mt, err := materials.Craft(context.Background(), m, value, uploader, c.logger) + mt, err := materials.Craft(context.Background(), m, value, casBackend, c.logger) if err != nil { return err } diff --git a/internal/attestation/crafter/materials/artifact.go b/internal/attestation/crafter/materials/artifact.go index 704387791..4497e5fdb 100644 --- a/internal/attestation/crafter/materials/artifact.go +++ b/internal/attestation/crafter/materials/artifact.go @@ -27,19 +27,19 @@ import ( type ArtifactCrafter struct { *crafterCommon - uploader casclient.Uploader + backend *casclient.CASBackend } -func NewArtifactCrafter(schema *schemaapi.CraftingSchema_Material, uploader casclient.Uploader, l *zerolog.Logger) (*ArtifactCrafter, error) { +func NewArtifactCrafter(schema *schemaapi.CraftingSchema_Material, backend *casclient.CASBackend, l *zerolog.Logger) (*ArtifactCrafter, error) { if schema.Type != schemaapi.CraftingSchema_Material_ARTIFACT { return nil, fmt.Errorf("material type is not artifact") } craftCommon := &crafterCommon{logger: l, input: schema} - return &ArtifactCrafter{uploader: uploader, crafterCommon: craftCommon}, nil + return &ArtifactCrafter{backend: backend, crafterCommon: craftCommon}, nil } // Craft will calculate the digest of the artifact, simulate an upload and return the material definition func (i *ArtifactCrafter) Craft(ctx context.Context, artifactPath string) (*api.Attestation_Material, error) { - return uploadAndCraft(ctx, i.input, i.uploader, artifactPath) + return uploadAndCraft(ctx, i.input, i.backend, artifactPath, i.logger) } diff --git a/internal/attestation/crafter/materials/artifact_test.go b/internal/attestation/crafter/materials/artifact_test.go index e6adf616c..d3db175ec 100644 --- a/internal/attestation/crafter/materials/artifact_test.go +++ b/internal/attestation/crafter/materials/artifact_test.go @@ -20,6 +20,7 @@ import ( "testing" "time" + "code.cloudfoundry.org/bytefmt" attestationApi "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" contractAPI "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter/materials" @@ -75,16 +76,18 @@ func TestArtifactCraft(t *testing.T) { // Mock uploader uploader := mUploader.NewUploader(t) - uploader.On("UploadFile", context.TODO(), "file.txt"). + uploader.On("UploadFile", context.TODO(), "./testdata/simple.txt"). Return(&casclient.UpDownStatus{ Digest: "deadbeef", - Filename: "file.txt", + Filename: "simple.txt", }, nil) - crafter, err := materials.NewArtifactCrafter(schema, uploader, &l) + backend := &casclient.CASBackend{Uploader: uploader} + + crafter, err := materials.NewArtifactCrafter(schema, backend, &l) require.NoError(t, err) - got, err := crafter.Craft(context.TODO(), "file.txt") + got, err := crafter.Craft(context.TODO(), "./testdata/simple.txt") assert.NoError(err) assert.Equal(contractAPI.CraftingSchema_Material_ARTIFACT.String(), got.MaterialType.String()) assert.True(got.UploadedToCas) @@ -92,6 +95,63 @@ func TestArtifactCraft(t *testing.T) { // The result includes the digest reference assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ - Id: "test", Digest: "deadbeef", Name: "file.txt", + Id: "test", Digest: "sha256:54181dfe59340b318253e59f7695f547c5c10d071cb75001170a389061349918", Name: "simple.txt", + }) +} + +func TestArtifactCraftInline(t *testing.T) { + assert := assert.New(t) + schema := &contractAPI.CraftingSchema_Material{ + Name: "test", + Type: contractAPI.CraftingSchema_Material_ARTIFACT, + } + l := zerolog.Nop() + + t.Run("inline without size limit", func(t *testing.T) { + backend := &casclient.CASBackend{} + + crafter, err := materials.NewArtifactCrafter(schema, backend, &l) + require.NoError(t, err) + + got, err := crafter.Craft(context.TODO(), "./testdata/simple.txt") + assert.NoError(err) + assertMaterial(t, got) + }) + + t.Run("backend with size limit", func(t *testing.T) { + backend := &casclient.CASBackend{ + MaxSize: 100 * bytefmt.BYTE, + } + + crafter, err := materials.NewArtifactCrafter(schema, backend, &l) + require.NoError(t, err) + + got, err := crafter.Craft(context.TODO(), "./testdata/simple.txt") + assert.NoError(err) + assertMaterial(t, got) + }) + + t.Run("backend with size limit too small", func(t *testing.T) { + backend := &casclient.CASBackend{ + MaxSize: bytefmt.BYTE, + } + + crafter, err := materials.NewArtifactCrafter(schema, backend, &l) + require.NoError(t, err) + + _, err = crafter.Craft(context.TODO(), "./testdata/simple.txt") + assert.Error(err) + }) +} + +func assertMaterial(t *testing.T, got *attestationApi.Attestation_Material) { + assert := assert.New(t) + // Not uploaded to CAS + assert.False(got.UploadedToCas) + // The result includes the digest and inline content + assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ + Id: "test", Digest: "sha256:54181dfe59340b318253e59f7695f547c5c10d071cb75001170a389061349918", Name: "simple.txt", + // Inline content + Content: []byte("txt file"), }) } diff --git a/internal/attestation/crafter/materials/cyclonedxjson.go b/internal/attestation/crafter/materials/cyclonedxjson.go index d441225c7..b3c5cb736 100644 --- a/internal/attestation/crafter/materials/cyclonedxjson.go +++ b/internal/attestation/crafter/materials/cyclonedxjson.go @@ -28,17 +28,17 @@ import ( ) type CyclonedxJSONCrafter struct { - uploader casclient.Uploader + backend *casclient.CASBackend *crafterCommon } -func NewCyclonedxJSONCrafter(materialSchema *schemaapi.CraftingSchema_Material, uploader casclient.Uploader, l *zerolog.Logger) (*CyclonedxJSONCrafter, error) { +func NewCyclonedxJSONCrafter(materialSchema *schemaapi.CraftingSchema_Material, backend *casclient.CASBackend, l *zerolog.Logger) (*CyclonedxJSONCrafter, error) { if materialSchema.Type != schemaapi.CraftingSchema_Material_SBOM_CYCLONEDX_JSON { return nil, fmt.Errorf("material type is not cyclonedx json") } return &CyclonedxJSONCrafter{ - uploader: uploader, + backend: backend, crafterCommon: &crafterCommon{logger: l, input: materialSchema}, }, nil } @@ -62,5 +62,5 @@ func (i *CyclonedxJSONCrafter) Craft(ctx context.Context, filePath string) (*api return nil, fmt.Errorf("invalid cyclonedx sbom file: %w", ErrInvalidMaterialType) } - return uploadAndCraft(ctx, i.input, i.uploader, filePath) + return uploadAndCraft(ctx, i.input, i.backend, filePath, i.logger) } diff --git a/internal/attestation/crafter/materials/cyclonedxjson_test.go b/internal/attestation/crafter/materials/cyclonedxjson_test.go index 391241c81..ce415f66e 100644 --- a/internal/attestation/crafter/materials/cyclonedxjson_test.go +++ b/internal/attestation/crafter/materials/cyclonedxjson_test.go @@ -109,7 +109,8 @@ func TestCyclonedxJSONCraft(t *testing.T) { }, nil) } - crafter, err := materials.NewCyclonedxJSONCrafter(schema, uploader, &l) + backend := &casclient.CASBackend{Uploader: uploader} + crafter, err := materials.NewCyclonedxJSONCrafter(schema, backend, &l) require.NoError(t, err) got, err := crafter.Craft(context.TODO(), tc.filePath) @@ -125,7 +126,7 @@ func TestCyclonedxJSONCraft(t *testing.T) { // The result includes the digest reference assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ - Id: "test", Digest: "deadbeef", Name: "sbom.cyclonedx.json", + Id: "test", Digest: "sha256:16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c", Name: "sbom.cyclonedx.json", }) }) } diff --git a/internal/attestation/crafter/materials/junit_xml.go b/internal/attestation/crafter/materials/junit_xml.go index be2fe820a..e24c98ef5 100644 --- a/internal/attestation/crafter/materials/junit_xml.go +++ b/internal/attestation/crafter/materials/junit_xml.go @@ -32,15 +32,15 @@ import ( type JUnitXMLCrafter struct { *crafterCommon - uploader casclient.Uploader + backend *casclient.CASBackend } -func NewJUnitXMLCrafter(schema *schemaapi.CraftingSchema_Material, uploader casclient.Uploader, l *zerolog.Logger) (*JUnitXMLCrafter, error) { +func NewJUnitXMLCrafter(schema *schemaapi.CraftingSchema_Material, backend *casclient.CASBackend, l *zerolog.Logger) (*JUnitXMLCrafter, error) { if schema.Type != schemaapi.CraftingSchema_Material_JUNIT_XML { return nil, fmt.Errorf("material type is not JUnit XML") } craftCommon := &crafterCommon{logger: l, input: schema} - return &JUnitXMLCrafter{uploader: uploader, crafterCommon: craftCommon}, nil + return &JUnitXMLCrafter{backend: backend, crafterCommon: craftCommon}, nil } func (i *JUnitXMLCrafter) Craft(ctx context.Context, filePath string) (*api.Attestation_Material, error) { @@ -48,7 +48,7 @@ func (i *JUnitXMLCrafter) Craft(ctx context.Context, filePath string) (*api.Atte return nil, err } - return uploadAndCraft(ctx, i.input, i.uploader, filePath) + return uploadAndCraft(ctx, i.input, i.backend, filePath, i.logger) } func (i *JUnitXMLCrafter) validate(filePath string) error { diff --git a/internal/attestation/crafter/materials/junit_xml_test.go b/internal/attestation/crafter/materials/junit_xml_test.go index 8a47b597d..4860c22cd 100644 --- a/internal/attestation/crafter/materials/junit_xml_test.go +++ b/internal/attestation/crafter/materials/junit_xml_test.go @@ -111,7 +111,8 @@ func TestJUnitXMLCraft(t *testing.T) { }, nil) } - crafter, err := materials.NewJUnitXMLCrafter(schema, uploader, &l) + backend := &casclient.CASBackend{Uploader: uploader} + crafter, err := materials.NewJUnitXMLCrafter(schema, backend, &l) require.NoError(t, err) got, err := crafter.Craft(context.TODO(), tc.filePath) @@ -127,7 +128,7 @@ func TestJUnitXMLCraft(t *testing.T) { // The result includes the digest reference assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ - Id: "test", Digest: "deadbeef", Name: "test.xml", + Id: "test", Digest: "sha256:e9c941b25c06d8bd98205122cbc827504c6d03d37b7f4afd7ed03b3eeec789e2", Name: "junit.xml", }) }) } diff --git a/internal/attestation/crafter/materials/materials.go b/internal/attestation/crafter/materials/materials.go index 40883232f..b4f449313 100644 --- a/internal/attestation/crafter/materials/materials.go +++ b/internal/attestation/crafter/materials/materials.go @@ -18,11 +18,16 @@ package materials import ( "context" "fmt" + "io" + "io/ioutil" + "os" "time" + "code.cloudfoundry.org/bytefmt" api "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/casclient" + cr_v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/rs/zerolog" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -38,34 +43,100 @@ type crafterCommon struct { // uploadAndCraft uploads the artifact to CAS and crafts the material // this function is used by all the uploadable artifacts crafters (SBOMs, JUnit, and more in the future) -func uploadAndCraft(ctx context.Context, input *schemaapi.CraftingSchema_Material, uploader casclient.Uploader, artifactPath string) (*api.Attestation_Material, error) { - result, err := uploader.UploadFile(ctx, artifactPath) +func uploadAndCraft(ctx context.Context, input *schemaapi.CraftingSchema_Material, backend *casclient.CASBackend, artifactPath string, l *zerolog.Logger) (*api.Attestation_Material, error) { + // 1 - Check the file can be stored in the provided CAS backend + result, err := fileStats(artifactPath) if err != nil { - return nil, fmt.Errorf("uploading material: %w", err) + return nil, fmt.Errorf("getting file stats: %w", err) } + defer result.r.Close() - res := &api.Attestation_Material{ - AddedAt: timestamppb.New(time.Now()), - MaterialType: input.Type, - UploadedToCas: true, + l.Debug().Str("filename", result.filename).Str("digest", result.digest).Str("path", artifactPath). + Str("size", bytefmt.ByteSize(uint64(result.size))). + Str("max_size", bytefmt.ByteSize(uint64(backend.MaxSize))). + Str("backend", backend.Name).Msg("crafting file") + + // If there is a max size set and the file is bigger than that, return an error + if backend.MaxSize > 0 && result.size > backend.MaxSize { + return nil, fmt.Errorf("file too big to be processed by the %s CAS backend: %s > %s", backend.Name, bytefmt.ByteSize(uint64(result.size)), bytefmt.ByteSize(uint64(backend.MaxSize))) + } + + material := &api.Attestation_Material{ + AddedAt: timestamppb.New(time.Now()), + MaterialType: input.Type, M: &api.Attestation_Material_Artifact_{ Artifact: &api.Attestation_Material_Artifact{ Id: input.Name, - Name: result.Filename, - Digest: result.Digest, + Name: result.filename, + Digest: result.digest, IsSubject: input.Output, }, }, } - return res, nil + // 2 - Upload the file to CAS + if backend.Uploader != nil { + l.Debug().Str("backend", backend.Name).Msg("uploading") + + _, err = backend.Uploader.UploadFile(ctx, artifactPath) + if err != nil { + return nil, fmt.Errorf("uploading material: %w", err) + } + + material.UploadedToCas = true + } else { + l.Debug().Str("backend", backend.Name).Msg("storing inline") + // or store it inline if no uploader is provided + content, err := ioutil.ReadAll(result.r) + if err != nil { + return nil, fmt.Errorf("reading file: %w", err) + } + + material.InlineCas = true + material.GetArtifact().Content = content + } + + return material, nil +} + +type fileInfo struct { + filename, digest string + size int64 + r io.ReadCloser +} + +// Returns the sha256 hash of the file, its size and an error +func fileStats(filepath string) (*fileInfo, error) { + stat, err := os.Stat(filepath) + if err != nil { + return nil, err + } + + f, err := os.Open(filepath) + if err != nil { + return nil, fmt.Errorf("can't open file to upload: %w", err) + } + + hash, _, err := cr_v1.SHA256(f) + if err != nil { + return nil, fmt.Errorf("generating digest: %w", err) + } + + // Since we have already iterated on the file to calculate the digest + // we need to rewind the file pointer + _, err = f.Seek(0, io.SeekStart) + if err != nil { + return nil, fmt.Errorf("rewinding file pointer: %w", err) + } + + return &fileInfo{filename: stat.Name(), digest: hash.String(), size: stat.Size(), r: f}, nil } type Craftable interface { Craft(ctx context.Context, value string) (*api.Attestation_Material, error) } -func Craft(ctx context.Context, materialSchema *schemaapi.CraftingSchema_Material, value string, uploader casclient.Uploader, logger *zerolog.Logger) (*api.Attestation_Material, error) { +func Craft(ctx context.Context, materialSchema *schemaapi.CraftingSchema_Material, value string, casBackend *casclient.CASBackend, logger *zerolog.Logger) (*api.Attestation_Material, error) { var crafter Craftable var err error @@ -75,13 +146,13 @@ func Craft(ctx context.Context, materialSchema *schemaapi.CraftingSchema_Materia case schemaapi.CraftingSchema_Material_CONTAINER_IMAGE: crafter, err = NewOCIImageCrafter(materialSchema, logger) case schemaapi.CraftingSchema_Material_ARTIFACT: - crafter, err = NewArtifactCrafter(materialSchema, uploader, logger) + crafter, err = NewArtifactCrafter(materialSchema, casBackend, logger) case schemaapi.CraftingSchema_Material_SBOM_CYCLONEDX_JSON: - crafter, err = NewCyclonedxJSONCrafter(materialSchema, uploader, logger) + crafter, err = NewCyclonedxJSONCrafter(materialSchema, casBackend, logger) case schemaapi.CraftingSchema_Material_SBOM_SPDX_JSON: - crafter, err = NewSPDXJSONCrafter(materialSchema, uploader, logger) + crafter, err = NewSPDXJSONCrafter(materialSchema, casBackend, logger) case schemaapi.CraftingSchema_Material_JUNIT_XML: - crafter, err = NewJUnitXMLCrafter(materialSchema, uploader, logger) + crafter, err = NewJUnitXMLCrafter(materialSchema, casBackend, logger) default: return nil, fmt.Errorf("material of type %q not supported yet", materialSchema.Type) } diff --git a/internal/attestation/crafter/materials/spdxjson.go b/internal/attestation/crafter/materials/spdxjson.go index b18525efd..2a6648b4f 100644 --- a/internal/attestation/crafter/materials/spdxjson.go +++ b/internal/attestation/crafter/materials/spdxjson.go @@ -29,17 +29,17 @@ import ( ) type SPDXJSONCrafter struct { - uploader casclient.Uploader *crafterCommon + backend *casclient.CASBackend } -func NewSPDXJSONCrafter(materialSchema *schemaapi.CraftingSchema_Material, uploader casclient.Uploader, l *zerolog.Logger) (*SPDXJSONCrafter, error) { +func NewSPDXJSONCrafter(materialSchema *schemaapi.CraftingSchema_Material, backend *casclient.CASBackend, l *zerolog.Logger) (*SPDXJSONCrafter, error) { if materialSchema.Type != schemaapi.CraftingSchema_Material_SBOM_SPDX_JSON { return nil, fmt.Errorf("material type is not spdx json") } return &SPDXJSONCrafter{ - uploader: uploader, + backend: backend, crafterCommon: &crafterCommon{logger: l, input: materialSchema}, }, nil } @@ -58,5 +58,5 @@ func (i *SPDXJSONCrafter) Craft(ctx context.Context, filePath string) (*api.Atte return nil, fmt.Errorf("invalid spdx sbom file: %w", ErrInvalidMaterialType) } - return uploadAndCraft(ctx, i.input, i.uploader, filePath) + return uploadAndCraft(ctx, i.input, i.backend, filePath, i.logger) } diff --git a/internal/attestation/crafter/materials/spdxjson_test.go b/internal/attestation/crafter/materials/spdxjson_test.go index a814fed49..4cd415bae 100644 --- a/internal/attestation/crafter/materials/spdxjson_test.go +++ b/internal/attestation/crafter/materials/spdxjson_test.go @@ -110,7 +110,8 @@ func TestSPDXJSONCraft(t *testing.T) { }, nil) } - crafter, err := materials.NewSPDXJSONCrafter(schema, uploader, &l) + backend := &casclient.CASBackend{Uploader: uploader} + crafter, err := materials.NewSPDXJSONCrafter(schema, backend, &l) require.NoError(t, err) got, err := crafter.Craft(context.TODO(), tc.filePath) @@ -126,7 +127,7 @@ func TestSPDXJSONCraft(t *testing.T) { // // The result includes the digest reference assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ - Id: "test", Digest: "deadbeef", Name: "sbom.spdx.json", + Id: "test", Digest: "sha256:fe2636fb6c698a29a315278b762b2000efd5959afe776ee4f79f1ed523365a33", Name: "sbom.spdx.json", }) }) } diff --git a/internal/attestation/renderer/chainloop/chainloop.go b/internal/attestation/renderer/chainloop/chainloop.go index db05ce8df..e2ef2f25f 100644 --- a/internal/attestation/renderer/chainloop/chainloop.go +++ b/internal/attestation/renderer/chainloop/chainloop.go @@ -45,12 +45,16 @@ type NormalizedMaterial struct { Name string // Type of the Material Type string - // Either the fileName or the actual string content + // filename of the artifact that was either uploaded or injected inline in "value" + Filename string + // Inline content for an artifact or string material Value string // Hash of the Material Hash *crv1.Hash // Whether the Material was uploaded and available for download from CAS UploadedToCAS bool + // Whether the Material was embedded inline in the attestation + EmbeddedInline bool } type ProvenancePredicateCommon struct { diff --git a/internal/attestation/renderer/chainloop/chainloop_test.go b/internal/attestation/renderer/chainloop/chainloop_test.go index b5f2fb23a..12668feb6 100644 --- a/internal/attestation/renderer/chainloop/chainloop_test.go +++ b/internal/attestation/renderer/chainloop/chainloop_test.go @@ -63,8 +63,9 @@ func TestExtractPredicate(t *testing.T) { materials: []*NormalizedMaterial{ { Name: "binary", Type: "ARTIFACT", - Value: "main.go", - Hash: &crv1.Hash{Algorithm: "sha256", Hex: "8fce0203a4efaac3b08ee3ad769233039faa762a3da0777c45b315f398f0c150"}, + Filename: "main.go", + Hash: &crv1.Hash{Algorithm: "sha256", Hex: "8fce0203a4efaac3b08ee3ad769233039faa762a3da0777c45b315f398f0c150"}, + UploadedToCAS: true, }, { Name: "image", Type: "CONTAINER_IMAGE", @@ -73,8 +74,16 @@ func TestExtractPredicate(t *testing.T) { }, { Name: "sbom", Type: "SBOM_CYCLONEDX_JSON", - Value: "sbom.cyclonedx.json", - Hash: &crv1.Hash{Algorithm: "sha256", Hex: "16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c"}, + Filename: "sbom.cyclonedx.json", + Hash: &crv1.Hash{Algorithm: "sha256", Hex: "16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c"}, + UploadedToCAS: true, + }, + { + Name: "sbom", Type: "SBOM_CYCLONEDX_JSON", + Filename: "inline-sbom.json", + Hash: &crv1.Hash{Algorithm: "sha256", Hex: "16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c"}, + EmbeddedInline: true, + Value: "hello inline!", }, { Name: "stringvar", Type: "STRING", diff --git a/internal/attestation/renderer/chainloop/testdata/valid.envelope.v2.json b/internal/attestation/renderer/chainloop/testdata/valid.envelope.v2.json index dbbf1317c..dcac30516 100644 --- a/internal/attestation/renderer/chainloop/testdata/valid.envelope.v2.json +++ b/internal/attestation/renderer/chainloop/testdata/valid.envelope.v2.json @@ -1,6 +1,6 @@ { "payloadType": "application/vnd.in-toto+json", - "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJjaGFpbmxvb3AuZGV2L2F0dGVzdGF0aW9uL3YwLjIiLCJzdWJqZWN0IjpbeyJuYW1lIjoiY2hhaW5sb29wLmRldi93b3JrZmxvdy9vbGQiLCJkaWdlc3QiOnsic2hhMjU2IjoiMDQwN2EyYjAxZmJkODk4YmNjMTEwNjVmNzYxMDhkMTY5OTg2MjA2MzBmZmM0NTNkMjE2MmNmNTc5YjQyZGUwMyJ9fSx7Im5hbWUiOiJpbmRleC5kb2NrZXIuaW8vYml0bmFtaS9uZ2lueCIsImRpZ2VzdCI6eyJzaGEyNTYiOiI3NDdlZjMzNWVhMjdhMmZhZjA4YWEyOTJhNWJjNTQ5MWFmZjUwYzZhOTRlZTRlYmNiYmNkNDNjZGVjY2NjYWYxIn19XSwicHJlZGljYXRlIjp7Im1ldGFkYXRhIjp7Im5hbWUiOiJvbGQiLCJwcm9qZWN0Ijoib2xkIiwidGVhbSI6IiIsImluaXRpYWxpemVkQXQiOiIyMDIzLTA1LTA5VDExOjUxOjQwLjI3NzU2NzQ4NFoiLCJmaW5pc2hlZEF0IjoiMjAyMy0wNS0wOVQxMzo1MjoxNC4zMzc3NjgwODcrMDI6MDAiLCJ3b3JrZmxvd1J1bklEIjoiMDAzYzZkNGYtMTkwNy00NWE3LWE1OTYtNTdjMzhlZjFmZGMzIiwid29ya2Zsb3dJRCI6ImYyZmI1MzM4LWY3OWItNDRiOC05YTYxLTYxNmY1MTBjMDE5YiJ9LCJidWlsZGVyIjp7ImlkIjoiY2hhaW5sb29wLmRldi9jbGkvZGV2QHNoYTI1Njo1ODkyZWUwYTNhZjJhMDU3NzAzZjM2YmM0ZDY4MjQxMGQzNzA5YTgzOTNjMGIwYjc5MTYyOTUxZTFjZDVlZWJiIn0sImJ1aWxkVHlwZSI6ImNoYWlubG9vcC5kZXYvd29ya2Zsb3dydW4vdjAuMSIsImVudiI6eyJDVVNUT01fVkFSIjoiZm9vYmFyIn0sInJ1bm5lclR5cGUiOiJSVU5ORVJfVFlQRV9VTlNQRUNJRklFRCIsIm1hdGVyaWFscyI6W3siZGlnZXN0Ijp7InNoYTI1NiI6IjhmY2UwMjAzYTRlZmFhYzNiMDhlZTNhZDc2OTIzMzAzOWZhYTc2MmEzZGEwNzc3YzQ1YjMxNWYzOThmMGMxNTAifSwibmFtZSI6Im1haW4uZ28iLCJhbm5vdGF0aW9ucyI6eyJjaGFpbmxvb3AubWF0ZXJpYWwubmFtZSI6ImJpbmFyeSIsImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjoiQVJUSUZBQ1QifX0seyJkaWdlc3QiOnsic2hhMjU2IjoiNzQ3ZWYzMzVlYTI3YTJmYWYwOGFhMjkyYTViYzU0OTFhZmY1MGM2YTk0ZWU0ZWJjYmJjZDQzY2RlY2NjY2FmMSJ9LCJuYW1lIjoiaW5kZXguZG9ja2VyLmlvL2JpdG5hbWkvbmdpbngiLCJhbm5vdGF0aW9ucyI6eyJjaGFpbmxvb3AubWF0ZXJpYWwubmFtZSI6ImltYWdlIiwiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiJDT05UQUlORVJfSU1BR0UifX0seyJkaWdlc3QiOnsic2hhMjU2IjoiMTYxNTliYjg4MWViNGFiN2ViNWQ4YWZjNTM1MGIwZmVlZWQxZTMxYzBhMjY4ZTM1NWU3NGY5Y2NiZTg4NWUwYyJ9LCJuYW1lIjoic2JvbS5jeWNsb25lZHguanNvbiIsImFubm90YXRpb25zIjp7ImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjoic2JvbSIsImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjoiU0JPTV9DWUNMT05FRFhfSlNPTiJ9fSx7ImNvbnRlbnQiOiJhR1ZzYkc5M2IzSnNaQT09IiwiYW5ub3RhdGlvbnMiOnsiY2hhaW5sb29wLm1hdGVyaWFsLm5hbWUiOiJzdHJpbmd2YXIiLCJjaGFpbmxvb3AubWF0ZXJpYWwudHlwZSI6IlNUUklORyJ9fV19fQ==", + "payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImNoYWlubG9vcC5kZXYvYXR0ZXN0YXRpb24vdjAuMiIsCiAgInN1YmplY3QiOiBbCiAgICB7CiAgICAgICJuYW1lIjogImNoYWlubG9vcC5kZXYvd29ya2Zsb3cvb2xkIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhMjU2IjogIjA0MDdhMmIwMWZiZDg5OGJjYzExMDY1Zjc2MTA4ZDE2OTk4NjIwNjMwZmZjNDUzZDIxNjJjZjU3OWI0MmRlMDMiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJuYW1lIjogImluZGV4LmRvY2tlci5pby9iaXRuYW1pL25naW54IiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhMjU2IjogIjc0N2VmMzM1ZWEyN2EyZmFmMDhhYTI5MmE1YmM1NDkxYWZmNTBjNmE5NGVlNGViY2JiY2Q0M2NkZWNjY2NhZjEiCiAgICAgIH0KICAgIH0KICBdLAogICJwcmVkaWNhdGUiOiB7CiAgICAibWV0YWRhdGEiOiB7CiAgICAgICJuYW1lIjogIm9sZCIsCiAgICAgICJwcm9qZWN0IjogIm9sZCIsCiAgICAgICJ0ZWFtIjogIiIsCiAgICAgICJpbml0aWFsaXplZEF0IjogIjIwMjMtMDUtMDlUMTE6NTE6NDAuMjc3NTY3NDg0WiIsCiAgICAgICJmaW5pc2hlZEF0IjogIjIwMjMtMDUtMDlUMTM6NTI6MTQuMzM3NzY4MDg3KzAyOjAwIiwKICAgICAgIndvcmtmbG93UnVuSUQiOiAiMDAzYzZkNGYtMTkwNy00NWE3LWE1OTYtNTdjMzhlZjFmZGMzIiwKICAgICAgIndvcmtmbG93SUQiOiAiZjJmYjUzMzgtZjc5Yi00NGI4LTlhNjEtNjE2ZjUxMGMwMTliIgogICAgfSwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiY2hhaW5sb29wLmRldi9jbGkvZGV2QHNoYTI1Njo1ODkyZWUwYTNhZjJhMDU3NzAzZjM2YmM0ZDY4MjQxMGQzNzA5YTgzOTNjMGIwYjc5MTYyOTUxZTFjZDVlZWJiIgogICAgfSwKICAgICJidWlsZFR5cGUiOiAiY2hhaW5sb29wLmRldi93b3JrZmxvd3J1bi92MC4xIiwKICAgICJlbnYiOiB7ICJDVVNUT01fVkFSIjogImZvb2JhciIgfSwKICAgICJydW5uZXJUeXBlIjogIlJVTk5FUl9UWVBFX1VOU1BFQ0lGSUVEIiwKICAgICJtYXRlcmlhbHMiOiBbCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTI1NiI6ICI4ZmNlMDIwM2E0ZWZhYWMzYjA4ZWUzYWQ3NjkyMzMwMzlmYWE3NjJhM2RhMDc3N2M0NWIzMTVmMzk4ZjBjMTUwIgogICAgICAgIH0sCiAgICAgICAgIm5hbWUiOiAibWFpbi5nbyIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogImJpbmFyeSIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiAiQVJUSUZBQ1QiLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5jYXMiOiB0cnVlCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGEyNTYiOiAiNzQ3ZWYzMzVlYTI3YTJmYWYwOGFhMjkyYTViYzU0OTFhZmY1MGM2YTk0ZWU0ZWJjYmJjZDQzY2RlY2NjY2FmMSIKICAgICAgICB9LAogICAgICAgICJuYW1lIjogImluZGV4LmRvY2tlci5pby9iaXRuYW1pL25naW54IiwKICAgICAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLm5hbWUiOiAiaW1hZ2UiLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIkNPTlRBSU5FUl9JTUFHRSIKICAgICAgICB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTI1NiI6ICIxNjE1OWJiODgxZWI0YWI3ZWI1ZDhhZmM1MzUwYjBmZWVlZDFlMzFjMGEyNjhlMzU1ZTc0ZjljY2JlODg1ZTBjIgogICAgICAgIH0sCiAgICAgICAgIm5hbWUiOiAic2JvbS5jeWNsb25lZHguanNvbiIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogInNib20iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIlNCT01fQ1lDTE9ORURYX0pTT04iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5jYXMiOiB0cnVlCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGEyNTYiOiAiMTYxNTliYjg4MWViNGFiN2ViNWQ4YWZjNTM1MGIwZmVlZWQxZTMxYzBhMjY4ZTM1NWU3NGY5Y2NiZTg4NWUwYyIKICAgICAgICB9LAogICAgICAgICJuYW1lIjogImlubGluZS1zYm9tLmpzb24iLAogICAgICAgICJjb250ZW50IjogImFHVnNiRzhnYVc1c2FXNWxJUT09IiwKICAgICAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLm5hbWUiOiAic2JvbSIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiAiU0JPTV9DWUNMT05FRFhfSlNPTiIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLmNhcy5pbmxpbmUiOiB0cnVlCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImNvbnRlbnQiOiAiYUdWc2JHOTNiM0pzWkE9PSIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogInN0cmluZ3ZhciIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiAiU1RSSU5HIgogICAgICAgIH0KICAgICAgfQogICAgXQogIH0KfQo=", "signatures": [ { "keyid": "", diff --git a/internal/attestation/renderer/chainloop/v01.go b/internal/attestation/renderer/chainloop/v01.go index 894062ef5..94b829e04 100644 --- a/internal/attestation/renderer/chainloop/v01.go +++ b/internal/attestation/renderer/chainloop/v01.go @@ -125,12 +125,12 @@ func outputChainloopMaterials(att *v1.Attestation, onlyOutput bool) []*Provenanc material := &ProvenanceM{} if artifactType == schemaapi.CraftingSchema_Material_STRING { - material.StringVal = nMaterial.Value + material.StringVal = string(nMaterial.Content) } else if nMaterial.Digest != "" { parts := strings.Split(nMaterial.Digest, ":") material.SLSA = &SLSACommonProvenanceMaterial{ &slsacommon.ProvenanceMaterial{ - URI: nMaterial.Value, + URI: nMaterial.Name, Digest: map[string]string{ parts[0]: parts[1], }, diff --git a/internal/attestation/renderer/chainloop/v02.go b/internal/attestation/renderer/chainloop/v02.go index 4a4eae33b..f83957fcc 100644 --- a/internal/attestation/renderer/chainloop/v02.go +++ b/internal/attestation/renderer/chainloop/v02.go @@ -90,6 +90,7 @@ func (r *RendererV02) Header() (*in_toto.StatementHeader, error) { const AnnotationMaterialType = "chainloop.material.type" const AnnotationMaterialName = "chainloop.material.name" const AnnotationMaterialCAS = "chainloop.material.cas" +const AnnotationMaterialInlineCAS = "chainloop.material.cas.inline" func outputMaterials(att *v1.Attestation, onlyOutput bool) []*slsa_v1.ResourceDescriptor { // Sort material keys to stabilize output @@ -115,7 +116,7 @@ func outputMaterials(att *v1.Attestation, onlyOutput bool) []*slsa_v1.ResourceDe material := &slsa_v1.ResourceDescriptor{} if artifactType == schemaapi.CraftingSchema_Material_STRING { - material.Content = []byte(nMaterial.Value) + material.Content = nMaterial.Content } if digest := nMaterial.Digest; digest != "" { @@ -123,7 +124,8 @@ func outputMaterials(att *v1.Attestation, onlyOutput bool) []*slsa_v1.ResourceDe material.Digest = map[string]string{ parts[0]: parts[1], } - material.Name = nMaterial.Value + material.Name = nMaterial.Name + material.Content = nMaterial.Content } material.Annotations = map[string]interface{}{ @@ -133,6 +135,8 @@ func outputMaterials(att *v1.Attestation, onlyOutput bool) []*slsa_v1.ResourceDe if mdef.UploadedToCas { material.Annotations[AnnotationMaterialCAS] = true + } else if mdef.InlineCas { + material.Annotations[AnnotationMaterialInlineCAS] = true } res = append(res, material) @@ -195,15 +199,32 @@ func normalizeMaterial(material *slsa_v1.ResourceDescriptor) (*NormalizedMateria } m.Hash = &crv1.Hash{Algorithm: "sha256", Hex: d} + // material.Name in a container image is the path to the image + // in an artifact type or derivative means the name of the file if material.Name == "" { return nil, fmt.Errorf("material name not found") } + // In the case of container images for example the value is in the name field + m.Value = material.Name + if v, ok := material.Annotations[AnnotationMaterialCAS]; ok && v.(bool) { m.UploadedToCAS = true } - m.Value = material.Name + if v, ok := material.Annotations[AnnotationMaterialInlineCAS]; ok && v.(bool) { + m.EmbeddedInline = true + } + + // In the case of an artifact type or derivative the filename is set and the inline content if any + if m.EmbeddedInline || m.UploadedToCAS { + m.Filename = material.Name + m.Value = "" + } + + if m.EmbeddedInline { + m.Value = string(material.Content) + } return m, nil } diff --git a/internal/attestation/renderer/chainloop/v02_test.go b/internal/attestation/renderer/chainloop/v02_test.go index 27145dfe9..dc06c9ded 100644 --- a/internal/attestation/renderer/chainloop/v02_test.go +++ b/internal/attestation/renderer/chainloop/v02_test.go @@ -159,11 +159,34 @@ func TestNormalizeMaterial(t *testing.T) { want: &NormalizedMaterial{ Name: "foo", Type: "ARTIFACT", - Value: "artifact.tgz", + Filename: "artifact.tgz", Hash: &crv1.Hash{Algorithm: "sha256", Hex: "deadbeef"}, UploadedToCAS: true, }, }, + { + name: "valid artifact material, inline content", + input: &slsa_v1.ResourceDescriptor{ + Annotations: map[string]interface{}{ + "chainloop.material.name": "foo", + "chainloop.material.type": "ARTIFACT", + "chainloop.material.cas.inline": true, + }, + Digest: map[string]string{ + "sha256": "deadbeef", + }, + Name: "artifact.tgz", + Content: []byte("this is an inline material"), + }, + want: &NormalizedMaterial{ + Name: "foo", + Type: "ARTIFACT", + Filename: "artifact.tgz", + Value: "this is an inline material", + Hash: &crv1.Hash{Algorithm: "sha256", Hex: "deadbeef"}, + EmbeddedInline: true, + }, + }, { name: "invalid artifact material, missing file name", input: &slsa_v1.ResourceDescriptor{ diff --git a/internal/casclient/casclient.go b/internal/casclient/casclient.go index 44657d319..1db5557ce 100644 --- a/internal/casclient/casclient.go +++ b/internal/casclient/casclient.go @@ -52,6 +52,14 @@ type DownloaderUploader interface { Uploader } +type CASBackend struct { + Uploader Uploader + // Max number of bytes this backend can store per artifact + MaxSize int64 + // CAS backend name + Name string +} + type ProgressStatusChan chan (*UpDownStatus) type Client struct { conn *grpc.ClientConn