From 9075abfb59f1dcb59325fa65e65001e4b05b0ffd Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 12:07:15 +0200 Subject: [PATCH 1/9] feat: add annotations Signed-off-by: Miguel Martinez Trivino --- .../api/attestation/v1/crafting_state.pb.go | 210 +++++++------ .../v1/crafting_state.pb.validate.go | 28 ++ .../api/attestation/v1/crafting_state.proto | 3 + app/cli/cmd/workflow_workflow_run_describe.go | 16 +- .../internal/action/workflow_run_describe.go | 36 ++- .../controlplane/v1/response_messages.pb.go | 286 ++++++++++-------- .../v1/response_messages.pb.validate.go | 2 + .../controlplane/v1/response_messages.proto | 1 + .../controlplane/v1/response_messages.ts | 118 +++++++- .../workflowcontract/v1/crafting_schema.ts | 105 ++++++- .../workflowcontract/v1/crafting_schema.pb.go | 158 +++++++--- .../v1/crafting_schema.pb.validate.go | 148 +++++++++ .../workflowcontract/v1/crafting_schema.proto | 9 + .../internal/service/attestation.go | 7 +- internal/attestation/crafter/crafter_test.go | 6 + .../crafter/materials/materials.go | 19 +- .../crafter/materials/oci_image.go | 3 - .../attestation/crafter/materials/string.go | 3 - .../contracts/with_material_annotations.yaml | 9 + .../renderer/chainloop/chainloop.go | 2 + .../attestation/renderer/chainloop/v02.go | 35 ++- 21 files changed, 920 insertions(+), 284 deletions(-) create mode 100644 internal/attestation/crafter/testdata/contracts/with_material_annotations.yaml diff --git a/app/cli/api/attestation/v1/crafting_state.pb.go b/app/cli/api/attestation/v1/crafting_state.pb.go index 2d944fd43..a0ac3364a 100644 --- a/app/cli/api/attestation/v1/crafting_state.pb.go +++ b/app/cli/api/attestation/v1/crafting_state.pb.go @@ -303,6 +303,8 @@ type Attestation_Material struct { // 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"` + // Annotations for the material + Annotations map[string]string `protobuf:"bytes,9,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Attestation_Material) Reset() { @@ -393,6 +395,13 @@ func (x *Attestation_Material) GetInlineCas() bool { return false } +func (x *Attestation_Material) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + type isAttestation_Material_M interface { isAttestation_Material_M() } @@ -427,7 +436,7 @@ type Attestation_Material_KeyVal struct { func (x *Attestation_Material_KeyVal) Reset() { *x = Attestation_Material_KeyVal{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[6] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -440,7 +449,7 @@ func (x *Attestation_Material_KeyVal) String() string { func (*Attestation_Material_KeyVal) ProtoMessage() {} func (x *Attestation_Material_KeyVal) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[6] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -453,7 +462,7 @@ func (x *Attestation_Material_KeyVal) ProtoReflect() protoreflect.Message { // Deprecated: Use Attestation_Material_KeyVal.ProtoReflect.Descriptor instead. func (*Attestation_Material_KeyVal) Descriptor() ([]byte, []int) { - return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{0, 1, 0} + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{0, 1, 1} } func (x *Attestation_Material_KeyVal) GetId() string { @@ -484,7 +493,7 @@ type Attestation_Material_ContainerImage struct { func (x *Attestation_Material_ContainerImage) Reset() { *x = Attestation_Material_ContainerImage{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[7] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -497,7 +506,7 @@ func (x *Attestation_Material_ContainerImage) String() string { func (*Attestation_Material_ContainerImage) ProtoMessage() {} func (x *Attestation_Material_ContainerImage) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[7] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -510,7 +519,7 @@ func (x *Attestation_Material_ContainerImage) ProtoReflect() protoreflect.Messag // Deprecated: Use Attestation_Material_ContainerImage.ProtoReflect.Descriptor instead. func (*Attestation_Material_ContainerImage) Descriptor() ([]byte, []int) { - return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{0, 1, 1} + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{0, 1, 2} } func (x *Attestation_Material_ContainerImage) GetId() string { @@ -562,7 +571,7 @@ type Attestation_Material_Artifact struct { func (x *Attestation_Material_Artifact) Reset() { *x = Attestation_Material_Artifact{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[8] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -575,7 +584,7 @@ func (x *Attestation_Material_Artifact) String() string { func (*Attestation_Material_Artifact) ProtoMessage() {} func (x *Attestation_Material_Artifact) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[8] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -588,7 +597,7 @@ func (x *Attestation_Material_Artifact) ProtoReflect() protoreflect.Message { // Deprecated: Use Attestation_Material_Artifact.ProtoReflect.Descriptor instead. func (*Attestation_Material_Artifact) Descriptor() ([]byte, []int) { - return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{0, 1, 2} + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{0, 1, 3} } func (x *Attestation_Material_Artifact) GetId() string { @@ -638,7 +647,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, 0xd1, 0x0b, 0x0a, 0x0b, 0x41, + 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf8, 0x0c, 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, @@ -675,7 +684,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, 0xc9, 0x06, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xf0, 0x07, 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, @@ -705,63 +714,74 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 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, + 0x6e, 0x65, 0x43, 0x61, 0x73, 0x12, 0x65, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 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, + 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x42, 0x0c, 0xfa, 0x42, 0x09, 0x9a, 0x01, 0x06, 0x2a, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, + 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 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 ( @@ -776,7 +796,7 @@ func file_attestation_v1_crafting_state_proto_rawDescGZIP() []byte { return file_attestation_v1_crafting_state_proto_rawDescData } -var file_attestation_v1_crafting_state_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_attestation_v1_crafting_state_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_attestation_v1_crafting_state_proto_goTypes = []interface{}{ (*Attestation)(nil), // 0: attestation.v1.Attestation (*CraftingState)(nil), // 1: attestation.v1.CraftingState @@ -784,34 +804,36 @@ var file_attestation_v1_crafting_state_proto_goTypes = []interface{}{ nil, // 3: attestation.v1.Attestation.MaterialsEntry (*Attestation_Material)(nil), // 4: attestation.v1.Attestation.Material nil, // 5: attestation.v1.Attestation.EnvVarsEntry - (*Attestation_Material_KeyVal)(nil), // 6: attestation.v1.Attestation.Material.KeyVal - (*Attestation_Material_ContainerImage)(nil), // 7: attestation.v1.Attestation.Material.ContainerImage - (*Attestation_Material_Artifact)(nil), // 8: attestation.v1.Attestation.Material.Artifact - (*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp - (v1.CraftingSchema_Runner_RunnerType)(0), // 10: workflowcontract.v1.CraftingSchema.Runner.RunnerType - (*v1.CraftingSchema)(nil), // 11: workflowcontract.v1.CraftingSchema - (v1.CraftingSchema_Material_MaterialType)(0), // 12: workflowcontract.v1.CraftingSchema.Material.MaterialType + nil, // 6: attestation.v1.Attestation.Material.AnnotationsEntry + (*Attestation_Material_KeyVal)(nil), // 7: attestation.v1.Attestation.Material.KeyVal + (*Attestation_Material_ContainerImage)(nil), // 8: attestation.v1.Attestation.Material.ContainerImage + (*Attestation_Material_Artifact)(nil), // 9: attestation.v1.Attestation.Material.Artifact + (*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp + (v1.CraftingSchema_Runner_RunnerType)(0), // 11: workflowcontract.v1.CraftingSchema.Runner.RunnerType + (*v1.CraftingSchema)(nil), // 12: workflowcontract.v1.CraftingSchema + (v1.CraftingSchema_Material_MaterialType)(0), // 13: workflowcontract.v1.CraftingSchema.Material.MaterialType } var file_attestation_v1_crafting_state_proto_depIdxs = []int32{ - 9, // 0: attestation.v1.Attestation.initialized_at:type_name -> google.protobuf.Timestamp - 9, // 1: attestation.v1.Attestation.finished_at:type_name -> google.protobuf.Timestamp + 10, // 0: attestation.v1.Attestation.initialized_at:type_name -> google.protobuf.Timestamp + 10, // 1: attestation.v1.Attestation.finished_at:type_name -> google.protobuf.Timestamp 2, // 2: attestation.v1.Attestation.workflow:type_name -> attestation.v1.WorkflowMetadata 3, // 3: attestation.v1.Attestation.materials:type_name -> attestation.v1.Attestation.MaterialsEntry 5, // 4: attestation.v1.Attestation.env_vars:type_name -> attestation.v1.Attestation.EnvVarsEntry - 10, // 5: attestation.v1.Attestation.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType - 11, // 6: attestation.v1.CraftingState.input_schema:type_name -> workflowcontract.v1.CraftingSchema + 11, // 5: attestation.v1.Attestation.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 12, // 6: attestation.v1.CraftingState.input_schema:type_name -> workflowcontract.v1.CraftingSchema 0, // 7: attestation.v1.CraftingState.attestation:type_name -> attestation.v1.Attestation 4, // 8: attestation.v1.Attestation.MaterialsEntry.value:type_name -> attestation.v1.Attestation.Material - 6, // 9: attestation.v1.Attestation.Material.string:type_name -> attestation.v1.Attestation.Material.KeyVal - 7, // 10: attestation.v1.Attestation.Material.container_image:type_name -> attestation.v1.Attestation.Material.ContainerImage - 8, // 11: attestation.v1.Attestation.Material.artifact:type_name -> attestation.v1.Attestation.Material.Artifact - 9, // 12: attestation.v1.Attestation.Material.added_at:type_name -> google.protobuf.Timestamp - 12, // 13: attestation.v1.Attestation.Material.material_type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 7, // 9: attestation.v1.Attestation.Material.string:type_name -> attestation.v1.Attestation.Material.KeyVal + 8, // 10: attestation.v1.Attestation.Material.container_image:type_name -> attestation.v1.Attestation.Material.ContainerImage + 9, // 11: attestation.v1.Attestation.Material.artifact:type_name -> attestation.v1.Attestation.Material.Artifact + 10, // 12: attestation.v1.Attestation.Material.added_at:type_name -> google.protobuf.Timestamp + 13, // 13: attestation.v1.Attestation.Material.material_type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 6, // 14: attestation.v1.Attestation.Material.annotations:type_name -> attestation.v1.Attestation.Material.AnnotationsEntry + 15, // [15:15] is the sub-list for method output_type + 15, // [15:15] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_attestation_v1_crafting_state_proto_init() } @@ -868,7 +890,7 @@ func file_attestation_v1_crafting_state_proto_init() { return nil } } - file_attestation_v1_crafting_state_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_attestation_v1_crafting_state_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Attestation_Material_KeyVal); i { case 0: return &v.state @@ -880,7 +902,7 @@ func file_attestation_v1_crafting_state_proto_init() { return nil } } - file_attestation_v1_crafting_state_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_attestation_v1_crafting_state_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Attestation_Material_ContainerImage); i { case 0: return &v.state @@ -892,7 +914,7 @@ func file_attestation_v1_crafting_state_proto_init() { return nil } } - file_attestation_v1_crafting_state_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_attestation_v1_crafting_state_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Attestation_Material_Artifact); i { case 0: return &v.state @@ -916,7 +938,7 @@ func file_attestation_v1_crafting_state_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_attestation_v1_crafting_state_proto_rawDesc, NumEnums: 0, - NumMessages: 9, + NumMessages: 10, NumExtensions: 0, NumServices: 0, }, 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 1c59a6d83..4ee7912d6 100644 --- a/app/cli/api/attestation/v1/crafting_state.pb.validate.go +++ b/app/cli/api/attestation/v1/crafting_state.pb.validate.go @@ -626,6 +626,34 @@ func (m *Attestation_Material) validate(all bool) error { // no validation rules for InlineCas + { + sorted_keys := make([]string, len(m.GetAnnotations())) + i := 0 + for key := range m.GetAnnotations() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetAnnotations()[key] + _ = val + + // no validation rules for Annotations[key] + + if utf8.RuneCountInString(val) < 1 { + err := Attestation_MaterialValidationError{ + field: fmt.Sprintf("Annotations[%v]", key), + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + } + } + switch v := m.M.(type) { case *Attestation_Material_String_: if v == nil { diff --git a/app/cli/api/attestation/v1/crafting_state.proto b/app/cli/api/attestation/v1/crafting_state.proto index 8db8fd020..6165bb0c0 100644 --- a/app/cli/api/attestation/v1/crafting_state.proto +++ b/app/cli/api/attestation/v1/crafting_state.proto @@ -47,6 +47,9 @@ message Attestation { // leveraging a form of inline CAS bool inline_cas = 8; + // Annotations for the material + map annotations = 9 [(validate.rules).map.values.string.min_len = 1]; + message KeyVal { string id = 1 [(validate.rules).string.min_len = 1]; string value = 2 [(validate.rules).string.min_len = 1]; diff --git a/app/cli/cmd/workflow_workflow_run_describe.go b/app/cli/cmd/workflow_workflow_run_describe.go index 9efc8d504..be704df06 100644 --- a/app/cli/cmd/workflow_workflow_run_describe.go +++ b/app/cli/cmd/workflow_workflow_run_describe.go @@ -24,6 +24,7 @@ import ( "github.com/chainloop-dev/chainloop/app/cli/internal/action" "github.com/jedib0t/go-pretty/v6/table" "github.com/jedib0t/go-pretty/v6/text" + "github.com/muesli/reflow/wrap" "github.com/spf13/cobra" ) @@ -134,12 +135,17 @@ func predicateV1Table(att *action.WorkflowRunAttestationItem) { mt := newTableWriter() mt.SetTitle("Materials") - header := table.Row{"Name", "Type", "Value"} - mt.AppendHeader(header) - for _, m := range materials { - row := table.Row{m.Name, m.Type, m.Value} - mt.AppendRow(row) + mt.AppendRow(table.Row{"Name", m.Name}) + mt.AppendRow(table.Row{"Type", m.Type}) + mt.AppendRow(table.Row{"Value", wrap.String(m.Value, 100)}) + if len(m.Annotations) > 0 { + mt.AppendRow(table.Row{"Annotations", "------"}) + for _, a := range m.Annotations { + mt.AppendRow(table.Row{"", fmt.Sprintf("%s: %s", a.Name, a.Value)}) + } + } + mt.AppendSeparator() } mt.Render() diff --git a/app/cli/internal/action/workflow_run_describe.go b/app/cli/internal/action/workflow_run_describe.go index 3ee346c71..6885d0c1a 100644 --- a/app/cli/internal/action/workflow_run_describe.go +++ b/app/cli/internal/action/workflow_run_describe.go @@ -19,6 +19,7 @@ import ( "context" "errors" "fmt" + "sort" "time" pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" @@ -51,12 +52,18 @@ type WorkflowRunAttestationItem struct { } type Material struct { + Name string `json:"name"` + Value string `json:"value"` + Type string `json:"type"` + Annotations []*Annotation `json:"annotations,omitempty"` +} + +type EnvVar struct { Name string `json:"name"` Value string `json:"value"` - Type string `json:"type"` } -type EnvVar struct { +type Annotation struct { Name string `json:"name"` Value string `json:"value"` } @@ -120,7 +127,7 @@ func (action *WorkflowRunDescribe) Run(runID string, verify bool, publicKey stri materials := make([]*Material, 0, len(attestation.GetMaterials())) for _, v := range attestation.GetMaterials() { - materials = append(materials, &Material{Name: v.Name, Value: v.Value, Type: v.Type}) + materials = append(materials, materialPBToAction(v)) } item.Attestation = &WorkflowRunAttestationItem{ @@ -134,6 +141,29 @@ func (action *WorkflowRunDescribe) Run(runID string, verify bool, publicKey stri return item, nil } +func materialPBToAction(in *pb.AttestationItem_Material) *Material { + m := &Material{ + Name: in.Name, + Value: in.Value, + Type: in.Type, + } + + // append annotations sorted + if in.Annotations != nil { + keys := make([]string, 0, len(in.Annotations)) + for k := range in.Annotations { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + m.Annotations = append(m.Annotations, &Annotation{Name: k, Value: in.Annotations[k]}) + } + } + + return m +} + func verifyEnvelope(ctx context.Context, e *dsse.Envelope, publicKey string) error { // Currently we only support basic cosign public key check // TODO: Add more verification methods diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.go b/app/controlplane/api/controlplane/v1/response_messages.pb.go index ca0bcaa13..e837cb70f 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.go @@ -993,7 +993,8 @@ type AttestationItem_Material struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` // Material type, i.e ARTIFACT - Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + Annotations map[string]string `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *AttestationItem_Material) Reset() { @@ -1049,6 +1050,13 @@ func (x *AttestationItem_Material) GetType() string { return "" } +func (x *AttestationItem_Material) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + type CASBackendItem_Limits struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1061,7 +1069,7 @@ type CASBackendItem_Limits struct { func (x *CASBackendItem_Limits) Reset() { *x = CASBackendItem_Limits{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[11] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1074,7 +1082,7 @@ func (x *CASBackendItem_Limits) String() string { func (*CASBackendItem_Limits) ProtoMessage() {} func (x *CASBackendItem_Limits) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[11] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1156,7 +1164,7 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x8d, 0x03, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xac, 0x04, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, @@ -1176,113 +1184,123 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x6c, 0x73, 0x1a, 0x37, 0x0a, 0x0b, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x48, 0x0a, 0x08, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x27, 0x0a, - 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x22, 0xc7, 0x01, 0x0a, 0x1b, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x12, 0x35, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x04, 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, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, 0x0a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x61, 0x63, 0x74, 0x22, 0x67, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, - 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, - 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xe6, 0x01, 0x0a, 0x08, + 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x5c, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4d, 0x61, + 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 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, 0xc1, 0x01, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xdb, 0x01, 0x0a, - 0x11, 0x4f, 0x72, 0x67, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x49, 0x74, - 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x26, 0x0a, 0x03, 0x6f, 0x72, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x52, 0x03, 0x6f, 0x72, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x27, 0x0a, 0x0f, + 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x22, 0xc7, 0x01, 0x0a, 0x1b, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, - 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x64, 0x0a, 0x03, 0x4f, 0x72, - 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x22, 0xe1, 0x04, 0x0a, 0x0e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, - 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3d, 0x0a, 0x0c, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x35, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x04, 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, + 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, 0x0a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x22, 0x67, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, + 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, + 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xdb, 0x01, 0x0a, 0x11, + 0x4f, 0x72, 0x67, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x49, 0x74, 0x65, + 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x26, 0x0a, 0x03, 0x6f, 0x72, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x4f, 0x72, 0x67, 0x52, 0x03, 0x6f, 0x72, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, + 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5d, 0x0a, 0x11, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, - 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x12, 0x3e, 0x0a, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, - 0x6d, 0x2e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, - 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x1a, 0x25, 0x0a, - 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x42, - 0x79, 0x74, 0x65, 0x73, 0x22, 0x6e, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x41, 0x4c, 0x49, - 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, - 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, - 0x49, 0x44, 0x10, 0x02, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, - 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, - 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, - 0x5f, 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, - 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 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, 0x61, 0x70, - 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, - 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x64, 0x0a, 0x03, 0x4f, 0x72, 0x67, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, + 0xe1, 0x04, 0x0a, 0x0e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, + 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5d, 0x0a, 0x11, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, + 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, + 0x3e, 0x0a, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, + 0x2e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x1a, 0x25, 0x0a, 0x06, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x22, 0x6e, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x41, 0x4c, 0x49, 0x44, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x41, + 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, + 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, + 0x44, 0x10, 0x02, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, + 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, + 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, + 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, + 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 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, 0x61, 0x70, 0x69, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, + 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1298,7 +1316,7 @@ func file_controlplane_v1_response_messages_proto_rawDescGZIP() []byte { } var file_controlplane_v1_response_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_controlplane_v1_response_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_controlplane_v1_response_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_controlplane_v1_response_messages_proto_goTypes = []interface{}{ (AllowListError)(0), // 0: controlplane.v1.AllowListError (CASBackendItem_ValidationStatus)(0), // 1: controlplane.v1.CASBackendItem.ValidationStatus @@ -1313,39 +1331,41 @@ var file_controlplane_v1_response_messages_proto_goTypes = []interface{}{ (*CASBackendItem)(nil), // 10: controlplane.v1.CASBackendItem (*AttestationItem_EnvVariable)(nil), // 11: controlplane.v1.AttestationItem.EnvVariable (*AttestationItem_Material)(nil), // 12: controlplane.v1.AttestationItem.Material - (*CASBackendItem_Limits)(nil), // 13: controlplane.v1.CASBackendItem.Limits - (*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp - (v1.CraftingSchema_Runner_RunnerType)(0), // 15: workflowcontract.v1.CraftingSchema.Runner.RunnerType - (*v1.CraftingSchema)(nil), // 16: workflowcontract.v1.CraftingSchema + nil, // 13: controlplane.v1.AttestationItem.Material.AnnotationsEntry + (*CASBackendItem_Limits)(nil), // 14: controlplane.v1.CASBackendItem.Limits + (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp + (v1.CraftingSchema_Runner_RunnerType)(0), // 16: workflowcontract.v1.CraftingSchema.Runner.RunnerType + (*v1.CraftingSchema)(nil), // 17: workflowcontract.v1.CraftingSchema } var file_controlplane_v1_response_messages_proto_depIdxs = []int32{ - 14, // 0: controlplane.v1.WorkflowItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 0: controlplane.v1.WorkflowItem.created_at:type_name -> google.protobuf.Timestamp 3, // 1: controlplane.v1.WorkflowItem.last_run:type_name -> controlplane.v1.WorkflowRunItem - 14, // 2: controlplane.v1.WorkflowRunItem.created_at:type_name -> google.protobuf.Timestamp - 14, // 3: controlplane.v1.WorkflowRunItem.finished_at:type_name -> google.protobuf.Timestamp + 15, // 2: controlplane.v1.WorkflowRunItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 3: controlplane.v1.WorkflowRunItem.finished_at:type_name -> google.protobuf.Timestamp 2, // 4: controlplane.v1.WorkflowRunItem.workflow:type_name -> controlplane.v1.WorkflowItem - 15, // 5: controlplane.v1.WorkflowRunItem.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 16, // 5: controlplane.v1.WorkflowRunItem.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType 6, // 6: controlplane.v1.WorkflowRunItem.contract_version:type_name -> controlplane.v1.WorkflowContractVersionItem - 14, // 7: controlplane.v1.AttestationItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 7: controlplane.v1.AttestationItem.created_at:type_name -> google.protobuf.Timestamp 11, // 8: controlplane.v1.AttestationItem.env_vars:type_name -> controlplane.v1.AttestationItem.EnvVariable 12, // 9: controlplane.v1.AttestationItem.materials:type_name -> controlplane.v1.AttestationItem.Material - 14, // 10: controlplane.v1.WorkflowContractItem.created_at:type_name -> google.protobuf.Timestamp - 14, // 11: controlplane.v1.WorkflowContractVersionItem.created_at:type_name -> google.protobuf.Timestamp - 16, // 12: controlplane.v1.WorkflowContractVersionItem.v1:type_name -> workflowcontract.v1.CraftingSchema - 14, // 13: controlplane.v1.User.created_at:type_name -> google.protobuf.Timestamp + 15, // 10: controlplane.v1.WorkflowContractItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 11: controlplane.v1.WorkflowContractVersionItem.created_at:type_name -> google.protobuf.Timestamp + 17, // 12: controlplane.v1.WorkflowContractVersionItem.v1:type_name -> workflowcontract.v1.CraftingSchema + 15, // 13: controlplane.v1.User.created_at:type_name -> google.protobuf.Timestamp 9, // 14: controlplane.v1.OrgMembershipItem.org:type_name -> controlplane.v1.Org - 14, // 15: controlplane.v1.OrgMembershipItem.created_at:type_name -> google.protobuf.Timestamp - 14, // 16: controlplane.v1.OrgMembershipItem.updated_at:type_name -> google.protobuf.Timestamp - 14, // 17: controlplane.v1.Org.created_at:type_name -> google.protobuf.Timestamp - 14, // 18: controlplane.v1.CASBackendItem.created_at:type_name -> google.protobuf.Timestamp - 14, // 19: controlplane.v1.CASBackendItem.validated_at:type_name -> google.protobuf.Timestamp + 15, // 15: controlplane.v1.OrgMembershipItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 16: controlplane.v1.OrgMembershipItem.updated_at:type_name -> google.protobuf.Timestamp + 15, // 17: controlplane.v1.Org.created_at:type_name -> google.protobuf.Timestamp + 15, // 18: controlplane.v1.CASBackendItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 19: controlplane.v1.CASBackendItem.validated_at:type_name -> google.protobuf.Timestamp 1, // 20: controlplane.v1.CASBackendItem.validation_status:type_name -> controlplane.v1.CASBackendItem.ValidationStatus - 13, // 21: controlplane.v1.CASBackendItem.limits:type_name -> controlplane.v1.CASBackendItem.Limits - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 14, // 21: controlplane.v1.CASBackendItem.limits:type_name -> controlplane.v1.CASBackendItem.Limits + 13, // 22: controlplane.v1.AttestationItem.Material.annotations:type_name -> controlplane.v1.AttestationItem.Material.AnnotationsEntry + 23, // [23:23] is the sub-list for method output_type + 23, // [23:23] is the sub-list for method input_type + 23, // [23:23] is the sub-list for extension type_name + 23, // [23:23] is the sub-list for extension extendee + 0, // [0:23] is the sub-list for field type_name } func init() { file_controlplane_v1_response_messages_proto_init() } @@ -1486,7 +1506,7 @@ func file_controlplane_v1_response_messages_proto_init() { return nil } } - file_controlplane_v1_response_messages_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_response_messages_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CASBackendItem_Limits); i { case 0: return &v.state @@ -1508,7 +1528,7 @@ func file_controlplane_v1_response_messages_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controlplane_v1_response_messages_proto_rawDesc, NumEnums: 2, - NumMessages: 12, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go b/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go index 7c151d766..7bbcec6a1 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go @@ -1745,6 +1745,8 @@ func (m *AttestationItem_Material) validate(all bool) error { // no validation rules for Type + // no validation rules for Annotations + if len(errors) > 0 { return AttestationItem_MaterialMultiError(errors) } diff --git a/app/controlplane/api/controlplane/v1/response_messages.proto b/app/controlplane/api/controlplane/v1/response_messages.proto index e953a20ed..d9dec7df7 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.proto +++ b/app/controlplane/api/controlplane/v1/response_messages.proto @@ -68,6 +68,7 @@ message AttestationItem { string value = 2; // Material type, i.e ARTIFACT string type = 3; + map annotations = 4; } } diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts index eab257e34..c67cf969a 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts @@ -88,6 +88,12 @@ export interface AttestationItem_Material { value: string; /** Material type, i.e ARTIFACT */ type: string; + annotations: { [key: string]: string }; +} + +export interface AttestationItem_Material_AnnotationsEntry { + key: string; + value: string; } export interface WorkflowContractItem { @@ -728,7 +734,7 @@ export const AttestationItem_EnvVariable = { }; function createBaseAttestationItem_Material(): AttestationItem_Material { - return { name: "", value: "", type: "" }; + return { name: "", value: "", type: "", annotations: {} }; } export const AttestationItem_Material = { @@ -742,6 +748,9 @@ export const AttestationItem_Material = { if (message.type !== "") { writer.uint32(26).string(message.type); } + Object.entries(message.annotations).forEach(([key, value]) => { + AttestationItem_Material_AnnotationsEntry.encode({ key: key as any, value }, writer.uint32(34).fork()).ldelim(); + }); return writer; }, @@ -773,6 +782,16 @@ export const AttestationItem_Material = { message.type = reader.string(); continue; + case 4: + if (tag !== 34) { + break; + } + + const entry4 = AttestationItem_Material_AnnotationsEntry.decode(reader, reader.uint32()); + if (entry4.value !== undefined) { + message.annotations[entry4.key] = entry4.value; + } + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -787,6 +806,12 @@ export const AttestationItem_Material = { name: isSet(object.name) ? String(object.name) : "", value: isSet(object.value) ? String(object.value) : "", type: isSet(object.type) ? String(object.type) : "", + annotations: isObject(object.annotations) + ? Object.entries(object.annotations).reduce<{ [key: string]: string }>((acc, [key, value]) => { + acc[key] = String(value); + return acc; + }, {}) + : {}, }; }, @@ -795,6 +820,12 @@ export const AttestationItem_Material = { message.name !== undefined && (obj.name = message.name); message.value !== undefined && (obj.value = message.value); message.type !== undefined && (obj.type = message.type); + obj.annotations = {}; + if (message.annotations) { + Object.entries(message.annotations).forEach(([k, v]) => { + obj.annotations[k] = v; + }); + } return obj; }, @@ -807,6 +838,87 @@ export const AttestationItem_Material = { message.name = object.name ?? ""; message.value = object.value ?? ""; message.type = object.type ?? ""; + message.annotations = Object.entries(object.annotations ?? {}).reduce<{ [key: string]: string }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[key] = String(value); + } + return acc; + }, + {}, + ); + return message; + }, +}; + +function createBaseAttestationItem_Material_AnnotationsEntry(): AttestationItem_Material_AnnotationsEntry { + return { key: "", value: "" }; +} + +export const AttestationItem_Material_AnnotationsEntry = { + encode(message: AttestationItem_Material_AnnotationsEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.key !== "") { + writer.uint32(10).string(message.key); + } + if (message.value !== "") { + writer.uint32(18).string(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): AttestationItem_Material_AnnotationsEntry { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseAttestationItem_Material_AnnotationsEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.key = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.value = reader.string(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): AttestationItem_Material_AnnotationsEntry { + return { key: isSet(object.key) ? String(object.key) : "", value: isSet(object.value) ? String(object.value) : "" }; + }, + + toJSON(message: AttestationItem_Material_AnnotationsEntry): unknown { + const obj: any = {}; + message.key !== undefined && (obj.key = message.key); + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + create, I>>( + base?: I, + ): AttestationItem_Material_AnnotationsEntry { + return AttestationItem_Material_AnnotationsEntry.fromPartial(base ?? {}); + }, + + fromPartial, I>>( + object: I, + ): AttestationItem_Material_AnnotationsEntry { + const message = createBaseAttestationItem_Material_AnnotationsEntry(); + message.key = object.key ?? ""; + message.value = object.value ?? ""; return message; }, }; @@ -1637,6 +1749,10 @@ if (_m0.util.Long !== Long) { _m0.configure(); } +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + function isSet(value: any): boolean { return value !== null && value !== undefined; } diff --git a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts index a585d9940..1b5c88953 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -65,6 +65,11 @@ export interface CraftingSchema_Material { optional: boolean; /** If a material is set as output it will get added to the subject in the statement */ output: boolean; + /** + * List of annotations that can be used to add metadata to the material + * this metadata can be used later on by the integrations engine to filter and interpolate data + */ + annotations: Annotation[]; } export enum CraftingSchema_Material_MaterialType { @@ -131,6 +136,16 @@ export function craftingSchema_Material_MaterialTypeToJSON(object: CraftingSchem } } +export interface Annotation { + /** Single word optionally separated with _ or - */ + name: string; + /** + * The value can be set in the contract or during the attestation process + * that's why its value is optional + */ + value: string; +} + function createBaseCraftingSchema(): CraftingSchema { return { schemaVersion: "", materials: [], envAllowList: [], runner: undefined }; } @@ -298,7 +313,7 @@ export const CraftingSchema_Runner = { }; function createBaseCraftingSchema_Material(): CraftingSchema_Material { - return { type: 0, name: "", optional: false, output: false }; + return { type: 0, name: "", optional: false, output: false, annotations: [] }; } export const CraftingSchema_Material = { @@ -315,6 +330,9 @@ export const CraftingSchema_Material = { if (message.output === true) { writer.uint32(32).bool(message.output); } + for (const v of message.annotations) { + Annotation.encode(v!, writer.uint32(42).fork()).ldelim(); + } return writer; }, @@ -353,6 +371,13 @@ export const CraftingSchema_Material = { message.output = reader.bool(); continue; + case 5: + if (tag !== 42) { + break; + } + + message.annotations.push(Annotation.decode(reader, reader.uint32())); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -368,6 +393,7 @@ export const CraftingSchema_Material = { name: isSet(object.name) ? String(object.name) : "", optional: isSet(object.optional) ? Boolean(object.optional) : false, output: isSet(object.output) ? Boolean(object.output) : false, + annotations: Array.isArray(object?.annotations) ? object.annotations.map((e: any) => Annotation.fromJSON(e)) : [], }; }, @@ -377,6 +403,11 @@ export const CraftingSchema_Material = { message.name !== undefined && (obj.name = message.name); message.optional !== undefined && (obj.optional = message.optional); message.output !== undefined && (obj.output = message.output); + if (message.annotations) { + obj.annotations = message.annotations.map((e) => e ? Annotation.toJSON(e) : undefined); + } else { + obj.annotations = []; + } return obj; }, @@ -390,6 +421,78 @@ export const CraftingSchema_Material = { message.name = object.name ?? ""; message.optional = object.optional ?? false; message.output = object.output ?? false; + message.annotations = object.annotations?.map((e) => Annotation.fromPartial(e)) || []; + return message; + }, +}; + +function createBaseAnnotation(): Annotation { + return { name: "", value: "" }; +} + +export const Annotation = { + encode(message: Annotation, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.name !== "") { + writer.uint32(10).string(message.name); + } + if (message.value !== "") { + writer.uint32(18).string(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Annotation { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseAnnotation(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.name = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.value = reader.string(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Annotation { + return { + name: isSet(object.name) ? String(object.name) : "", + value: isSet(object.value) ? String(object.value) : "", + }; + }, + + toJSON(message: Annotation): unknown { + const obj: any = {}; + message.name !== undefined && (obj.name = message.name); + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + create, I>>(base?: I): Annotation { + return Annotation.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Annotation { + const message = createBaseAnnotation(); + message.name = object.name ?? ""; + message.value = object.value ?? ""; return message; }, }; diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index 557b9ef45..d7d6f3080 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -220,6 +220,63 @@ func (x *CraftingSchema) GetRunner() *CraftingSchema_Runner { return nil } +type Annotation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Single word optionally separated with _ or - + // The value can be set in the contract or during the attestation process + // that's why its value is optional + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Annotation) Reset() { + *x = Annotation{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Annotation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Annotation) ProtoMessage() {} + +func (x *Annotation) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Annotation.ProtoReflect.Descriptor instead. +func (*Annotation) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{1} +} + +func (x *Annotation) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Annotation) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + type CraftingSchema_Runner struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -231,7 +288,7 @@ type CraftingSchema_Runner struct { func (x *CraftingSchema_Runner) Reset() { *x = CraftingSchema_Runner{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[1] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -244,7 +301,7 @@ func (x *CraftingSchema_Runner) String() string { func (*CraftingSchema_Runner) ProtoMessage() {} func (x *CraftingSchema_Runner) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[1] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -277,12 +334,15 @@ type CraftingSchema_Material struct { Optional bool `protobuf:"varint,3,opt,name=optional,proto3" json:"optional,omitempty"` // If a material is set as output it will get added to the subject in the statement Output bool `protobuf:"varint,4,opt,name=output,proto3" json:"output,omitempty"` + // List of annotations that can be used to add metadata to the material + // this metadata can be used later on by the integrations engine to filter and interpolate data + Annotations []*Annotation `protobuf:"bytes,5,rep,name=annotations,proto3" json:"annotations,omitempty"` } func (x *CraftingSchema_Material) Reset() { *x = CraftingSchema_Material{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[2] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -295,7 +355,7 @@ func (x *CraftingSchema_Material) String() string { func (*CraftingSchema_Material) ProtoMessage() {} func (x *CraftingSchema_Material) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[2] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -339,6 +399,13 @@ func (x *CraftingSchema_Material) GetOutput() bool { return false } +func (x *CraftingSchema_Material) GetAnnotations() []*Annotation { + if x != nil { + return x.Annotations + } + return nil +} + var File_workflowcontract_v1_crafting_schema_proto protoreflect.FileDescriptor var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ @@ -347,7 +414,7 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 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, 0x22, 0x86, 0x06, 0x0a, 0x0e, 0x43, 0x72, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x06, 0x0a, 0x0e, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x30, 0x0a, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x09, 0xfa, 0x42, 0x06, 0x72, 0x04, 0x0a, 0x02, 0x76, 0x31, 0x52, @@ -374,7 +441,7 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x49, 0x54, 0x4c, 0x41, 0x42, 0x5f, 0x50, 0x49, 0x50, - 0x45, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x1a, 0xd8, 0x02, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, + 0x45, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x1a, 0x9b, 0x03, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x57, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 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, @@ -386,22 +453,31 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x0c, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x41, 0x54, 0x45, - 0x52, 0x49, 0x41, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, - 0x47, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, - 0x5f, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x52, 0x54, 0x49, - 0x46, 0x41, 0x43, 0x54, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x43, - 0x59, 0x43, 0x4c, 0x4f, 0x4e, 0x45, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x04, 0x12, - 0x12, 0x0a, 0x0e, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x53, 0x50, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, - 0x4e, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x55, 0x4e, 0x49, 0x54, 0x5f, 0x58, 0x4d, 0x4c, - 0x10, 0x06, 0x42, 0x4d, 0x5a, 0x4b, 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, 0x61, 0x70, 0x69, 0x2f, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x0c, 0x4d, + 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x4d, + 0x41, 0x54, 0x45, 0x52, 0x49, 0x41, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, + 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, + 0x4e, 0x45, 0x52, 0x5f, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x41, + 0x52, 0x54, 0x49, 0x46, 0x41, 0x43, 0x54, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x42, 0x4f, + 0x4d, 0x5f, 0x43, 0x59, 0x43, 0x4c, 0x4f, 0x4e, 0x45, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, + 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x53, 0x50, 0x44, 0x58, 0x5f, + 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x55, 0x4e, 0x49, 0x54, 0x5f, + 0x58, 0x4d, 0x4c, 0x10, 0x06, 0x22, 0x48, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x72, 0x0b, 0x32, 0x09, 0x5e, 0x5b, 0x5c, 0x77, 0x7c, 0x2d, + 0x5d, 0x2b, 0x24, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, + 0x4d, 0x5a, 0x4b, 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, 0x61, 0x70, 0x69, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -417,24 +493,26 @@ func file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP() []byte { } var file_workflowcontract_v1_crafting_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_workflowcontract_v1_crafting_schema_proto_goTypes = []interface{}{ (CraftingSchema_Runner_RunnerType)(0), // 0: workflowcontract.v1.CraftingSchema.Runner.RunnerType (CraftingSchema_Material_MaterialType)(0), // 1: workflowcontract.v1.CraftingSchema.Material.MaterialType (*CraftingSchema)(nil), // 2: workflowcontract.v1.CraftingSchema - (*CraftingSchema_Runner)(nil), // 3: workflowcontract.v1.CraftingSchema.Runner - (*CraftingSchema_Material)(nil), // 4: workflowcontract.v1.CraftingSchema.Material + (*Annotation)(nil), // 3: workflowcontract.v1.Annotation + (*CraftingSchema_Runner)(nil), // 4: workflowcontract.v1.CraftingSchema.Runner + (*CraftingSchema_Material)(nil), // 5: workflowcontract.v1.CraftingSchema.Material } var file_workflowcontract_v1_crafting_schema_proto_depIdxs = []int32{ - 4, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material - 3, // 1: workflowcontract.v1.CraftingSchema.runner:type_name -> workflowcontract.v1.CraftingSchema.Runner + 5, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material + 4, // 1: workflowcontract.v1.CraftingSchema.runner:type_name -> workflowcontract.v1.CraftingSchema.Runner 0, // 2: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType 1, // 3: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 3, // 4: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_workflowcontract_v1_crafting_schema_proto_init() } @@ -456,7 +534,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CraftingSchema_Runner); i { + switch v := v.(*Annotation); i { case 0: return &v.state case 1: @@ -468,6 +546,18 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CraftingSchema_Runner); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_workflowcontract_v1_crafting_schema_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CraftingSchema_Material); i { case 0: return &v.state @@ -486,7 +576,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_workflowcontract_v1_crafting_schema_proto_rawDesc, NumEnums: 2, - NumMessages: 3, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go index 264bd75e4..2bba91baf 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go @@ -209,6 +209,120 @@ var _ interface { ErrorName() string } = CraftingSchemaValidationError{} +// Validate checks the field values on Annotation with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *Annotation) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on Annotation with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in AnnotationMultiError, or +// nil if none found. +func (m *Annotation) ValidateAll() error { + return m.validate(true) +} + +func (m *Annotation) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if !_Annotation_Name_Pattern.MatchString(m.GetName()) { + err := AnnotationValidationError{ + field: "Name", + reason: "value does not match regex pattern \"^[\\\\w|-]+$\"", + } + if !all { + return err + } + errors = append(errors, err) + } + + // no validation rules for Value + + if len(errors) > 0 { + return AnnotationMultiError(errors) + } + + return nil +} + +// AnnotationMultiError is an error wrapping multiple validation errors +// returned by Annotation.ValidateAll() if the designated constraints aren't met. +type AnnotationMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m AnnotationMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m AnnotationMultiError) AllErrors() []error { return m } + +// AnnotationValidationError is the validation error returned by +// Annotation.Validate if the designated constraints aren't met. +type AnnotationValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e AnnotationValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e AnnotationValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e AnnotationValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e AnnotationValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e AnnotationValidationError) ErrorName() string { return "AnnotationValidationError" } + +// Error satisfies the builtin error interface +func (e AnnotationValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAnnotation.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = AnnotationValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = AnnotationValidationError{} + +var _Annotation_Name_Pattern = regexp.MustCompile("^[\\w|-]+$") + // Validate checks the field values on CraftingSchema_Runner with the rules // defined in the proto definition for this message. If any rules are // violated, the first error encountered is returned, or nil if there are no violations. @@ -374,6 +488,40 @@ func (m *CraftingSchema_Material) validate(all bool) error { // no validation rules for Output + for idx, item := range m.GetAnnotations() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, CraftingSchema_MaterialValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, CraftingSchema_MaterialValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CraftingSchema_MaterialValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + if len(errors) > 0 { return CraftingSchema_MaterialMultiError(errors) } diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index cdfd227d6..c560008de 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -46,6 +46,9 @@ message CraftingSchema { bool optional = 3; // If a material is set as output it will get added to the subject in the statement bool output = 4; + // List of annotations that can be used to add metadata to the material + // this metadata can be used later on by the integrations engine to filter and interpolate data + repeated Annotation annotations = 5; enum MaterialType { MATERIAL_TYPE_UNSPECIFIED = 0; @@ -60,3 +63,9 @@ message CraftingSchema { } } +message Annotation { + string name = 1 [(validate.rules).string.pattern = "^[\\w|-]+$"]; // Single word optionally separated with _ or - + // The value can be set in the contract or during the attestation process + // that's why its value is optional + string value = 2; +} \ No newline at end of file diff --git a/app/controlplane/internal/service/attestation.go b/app/controlplane/internal/service/attestation.go index 502402976..7875d99ac 100644 --- a/app/controlplane/internal/service/attestation.go +++ b/app/controlplane/internal/service/attestation.go @@ -346,7 +346,12 @@ func extractMaterials(in []*chainloop.NormalizedMaterial) ([]*cpAPI.AttestationI displayValue = fmt.Sprintf("%s@%s", name, m.Hash) } - res = append(res, &cpAPI.AttestationItem_Material{Name: m.Name, Value: displayValue, Type: m.Type}) + res = append(res, &cpAPI.AttestationItem_Material{ + Name: m.Name, + Value: displayValue, + Type: m.Type, + Annotations: m.Annotations, + }) } return res, nil diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 51d3f1e11..7a3b297b1 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -68,6 +68,12 @@ func (s *crafterSuite) TestInit() { wantErr: false, dryRun: true, }, + { + name: "with annotations", + contractPath: "testdata/contracts/with_material_annotations.yaml", + workflowMetadata: s.workflowMetadata, + dryRun: true, + }, } for _, tc := range testCases { diff --git a/internal/attestation/crafter/materials/materials.go b/internal/attestation/crafter/materials/materials.go index 3df67998f..0cdbbe72d 100644 --- a/internal/attestation/crafter/materials/materials.go +++ b/internal/attestation/crafter/materials/materials.go @@ -62,7 +62,6 @@ func uploadAndCraft(ctx context.Context, input *schemaapi.CraftingSchema_Materia } material := &api.Attestation_Material{ - AddedAt: timestamppb.New(time.Now()), MaterialType: input.Type, M: &api.Attestation_Material_Artifact_{ Artifact: &api.Attestation_Material_Artifact{ @@ -140,6 +139,10 @@ func Craft(ctx context.Context, materialSchema *schemaapi.CraftingSchema_Materia var crafter Craftable var err error + if err := materialSchema.ValidateAll(); err != nil { + return nil, fmt.Errorf("validating material: %w", err) + } + switch materialSchema.Type { case schemaapi.CraftingSchema_Material_STRING: crafter, err = NewStringCrafter(materialSchema) @@ -161,5 +164,17 @@ func Craft(ctx context.Context, materialSchema *schemaapi.CraftingSchema_Materia return nil, err } - return crafter.Craft(ctx, value) + m, err := crafter.Craft(ctx, value) + if err != nil { + return nil, fmt.Errorf("crafting material: %w", err) + } + + m.AddedAt = timestamppb.New(time.Now()) + m.Annotations = make(map[string]string) + + for _, annotation := range materialSchema.Annotations { + m.Annotations[annotation.Name] = annotation.Value + } + + return m, nil } diff --git a/internal/attestation/crafter/materials/oci_image.go b/internal/attestation/crafter/materials/oci_image.go index 46012f261..d0d213af1 100644 --- a/internal/attestation/crafter/materials/oci_image.go +++ b/internal/attestation/crafter/materials/oci_image.go @@ -18,7 +18,6 @@ package materials import ( "context" "fmt" - "time" api "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" @@ -26,7 +25,6 @@ import ( "github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/v1/remote" "github.com/rs/zerolog" - "google.golang.org/protobuf/types/known/timestamppb" ) type OCIImageCrafter struct { @@ -62,7 +60,6 @@ func (i *OCIImageCrafter) Craft(_ context.Context, imageRef string) (*api.Attest i.logger.Debug().Str("name", repoName).Str("digest", remoteRef.DigestStr()).Msg("container image resolved") return &api.Attestation_Material{ - AddedAt: timestamppb.New(time.Now()), MaterialType: i.input.Type, M: &api.Attestation_Material_ContainerImage_{ ContainerImage: &api.Attestation_Material_ContainerImage{ diff --git a/internal/attestation/crafter/materials/string.go b/internal/attestation/crafter/materials/string.go index cdbae5734..c19163ca6 100644 --- a/internal/attestation/crafter/materials/string.go +++ b/internal/attestation/crafter/materials/string.go @@ -18,11 +18,9 @@ package materials import ( "context" "fmt" - "time" api "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" - "google.golang.org/protobuf/types/known/timestamppb" ) type StringCrafter struct { @@ -41,7 +39,6 @@ func NewStringCrafter(materialSchema *schemaapi.CraftingSchema_Material) (*Strin func (i *StringCrafter) Craft(_ context.Context, value string) (*api.Attestation_Material, error) { return &api.Attestation_Material{ - AddedAt: timestamppb.New(time.Now()), MaterialType: i.input.Type, M: &api.Attestation_Material_String_{ String_: &api.Attestation_Material_KeyVal{ diff --git a/internal/attestation/crafter/testdata/contracts/with_material_annotations.yaml b/internal/attestation/crafter/testdata/contracts/with_material_annotations.yaml new file mode 100644 index 000000000..6aa26d9c2 --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/with_material_annotations.yaml @@ -0,0 +1,9 @@ +schemaVersion: "v1" +materials: + - name: "string" + type: "STRING" + annotations: + - name: "with-default-val" + value: "val1" + - name: "without-default-val" + value: "boom" diff --git a/internal/attestation/renderer/chainloop/chainloop.go b/internal/attestation/renderer/chainloop/chainloop.go index e2ef2f25f..68f67c941 100644 --- a/internal/attestation/renderer/chainloop/chainloop.go +++ b/internal/attestation/renderer/chainloop/chainloop.go @@ -55,6 +55,8 @@ type NormalizedMaterial struct { UploadedToCAS bool // Whether the Material was embedded inline in the attestation EmbeddedInline bool + // Custom annotations + Annotations map[string]string } type ProvenancePredicateCommon struct { diff --git a/internal/attestation/renderer/chainloop/v02.go b/internal/attestation/renderer/chainloop/v02.go index f83957fcc..9cc5e549c 100644 --- a/internal/attestation/renderer/chainloop/v02.go +++ b/internal/attestation/renderer/chainloop/v02.go @@ -87,10 +87,16 @@ func (r *RendererV02) Header() (*in_toto.StatementHeader, error) { }, nil } -const AnnotationMaterialType = "chainloop.material.type" -const AnnotationMaterialName = "chainloop.material.name" -const AnnotationMaterialCAS = "chainloop.material.cas" -const AnnotationMaterialInlineCAS = "chainloop.material.cas.inline" +const builtInAnnotationPrefix = "chainloop." + +var AnnotationMaterialType = builtInAnnotation("material.type") +var AnnotationMaterialName = builtInAnnotation("material.name") +var AnnotationMaterialCAS = builtInAnnotation("material.cas") +var AnnotationMaterialInlineCAS = builtInAnnotation("material.cas.inline") + +func builtInAnnotation(name string) string { + return fmt.Sprintf("%s%s", builtInAnnotationPrefix, name) +} func outputMaterials(att *v1.Attestation, onlyOutput bool) []*slsa_v1.ResourceDescriptor { // Sort material keys to stabilize output @@ -128,11 +134,20 @@ func outputMaterials(att *v1.Attestation, onlyOutput bool) []*slsa_v1.ResourceDe material.Content = nMaterial.Content } + // Required, built-in annotations material.Annotations = map[string]interface{}{ AnnotationMaterialType: artifactType.String(), AnnotationMaterialName: mdefName, } + // Custom annotations, it does not override the built-in ones + for k, v := range mdef.Annotations { + _, ok := material.Annotations[k] + if !ok { + material.Annotations[k] = v + } + } + if mdef.UploadedToCas { material.Annotations[AnnotationMaterialCAS] = true } else if mdef.InlineCas { @@ -164,6 +179,18 @@ func (p *ProvenancePredicateV02) GetMaterials() []*NormalizedMaterial { func normalizeMaterial(material *slsa_v1.ResourceDescriptor) (*NormalizedMaterial, error) { m := &NormalizedMaterial{} + // Set custom annotations + m.Annotations = make(map[string]string) + for k, v := range material.Annotations { + // if the annotation key doesn't start with chainloop. + // we set it as a custom annotation + if strings.HasPrefix(k, builtInAnnotationPrefix) { + continue + } + + m.Annotations[k] = v.(string) + } + mType, ok := material.Annotations[AnnotationMaterialType] if !ok { return nil, fmt.Errorf("material type not found") From 33c45528933e476abe656a3fa1ac89562cdb07b5 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 12:14:33 +0200 Subject: [PATCH 2/9] feat: improve output Signed-off-by: Miguel Martinez Trivino --- app/cli/cmd/workflow_workflow_run_describe.go | 4 + .../internal/action/workflow_run_describe.go | 5 +- .../controlplane/v1/response_messages.pb.go | 220 +++++++++--------- .../v1/response_messages.pb.validate.go | 2 + .../controlplane/v1/response_messages.proto | 2 + .../controlplane/v1/response_messages.ts | 17 +- .../internal/service/attestation.go | 27 ++- 7 files changed, 156 insertions(+), 121 deletions(-) diff --git a/app/cli/cmd/workflow_workflow_run_describe.go b/app/cli/cmd/workflow_workflow_run_describe.go index be704df06..b4e0c715c 100644 --- a/app/cli/cmd/workflow_workflow_run_describe.go +++ b/app/cli/cmd/workflow_workflow_run_describe.go @@ -139,6 +139,10 @@ func predicateV1Table(att *action.WorkflowRunAttestationItem) { mt.AppendRow(table.Row{"Name", m.Name}) mt.AppendRow(table.Row{"Type", m.Type}) mt.AppendRow(table.Row{"Value", wrap.String(m.Value, 100)}) + if m.Hash != "" { + mt.AppendRow(table.Row{"Digest", m.Hash}) + } + if len(m.Annotations) > 0 { mt.AppendRow(table.Row{"Annotations", "------"}) for _, a := range m.Annotations { diff --git a/app/cli/internal/action/workflow_run_describe.go b/app/cli/internal/action/workflow_run_describe.go index 6885d0c1a..b9a8c8322 100644 --- a/app/cli/internal/action/workflow_run_describe.go +++ b/app/cli/internal/action/workflow_run_describe.go @@ -52,8 +52,10 @@ type WorkflowRunAttestationItem struct { } type Material struct { - Name string `json:"name"` + Name string `json:"name"` + // filename, container image name, string value, ... Value string `json:"value"` + Hash string `json:"hash"` Type string `json:"type"` Annotations []*Annotation `json:"annotations,omitempty"` } @@ -146,6 +148,7 @@ func materialPBToAction(in *pb.AttestationItem_Material) *Material { Name: in.Name, Value: in.Value, Type: in.Type, + Hash: in.Hash, } // append annotations sorted diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.go b/app/controlplane/api/controlplane/v1/response_messages.pb.go index e837cb70f..74b82bc8c 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.go @@ -990,11 +990,13 @@ type AttestationItem_Material struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // This might be the raw value, the container image name, the filename and so on Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` // Material type, i.e ARTIFACT Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` Annotations map[string]string `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Hash string `protobuf:"bytes,5,opt,name=hash,proto3" json:"hash,omitempty"` } func (x *AttestationItem_Material) Reset() { @@ -1057,6 +1059,13 @@ func (x *AttestationItem_Material) GetAnnotations() map[string]string { return nil } +func (x *AttestationItem_Material) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + type CASBackendItem_Limits struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1164,7 +1173,7 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xac, 0x04, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xc0, 0x04, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, @@ -1184,7 +1193,7 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x6c, 0x73, 0x1a, 0x37, 0x0a, 0x0b, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xe6, 0x01, 0x0a, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xfa, 0x01, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, @@ -1195,112 +1204,113 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 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, 0xc1, 0x01, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x27, 0x0a, 0x0f, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x22, 0xc7, 0x01, 0x0a, 0x1b, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, - 0x35, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x04, 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, - 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, 0x0a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x22, 0x67, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, - 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, - 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xdb, 0x01, 0x0a, 0x11, - 0x4f, 0x72, 0x67, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x49, 0x74, 0x65, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0xc1, 0x01, 0x0a, 0x14, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x26, 0x0a, 0x03, 0x6f, 0x72, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4f, 0x72, 0x67, 0x52, 0x03, 0x6f, 0x72, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, - 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x64, 0x0a, 0x03, 0x4f, 0x72, 0x67, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x27, 0x0a, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6c, 0x61, 0x74, 0x65, 0x73, + 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x22, 0xc7, 0x01, 0x0a, + 0x1b, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, + 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x35, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x04, 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, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, 0x0a, 0x0a, 0x08, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x22, 0x67, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, + 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, - 0xe1, 0x04, 0x0a, 0x0e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, - 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, - 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5d, 0x0a, 0x11, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, - 0x3e, 0x0a, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, - 0x2e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, - 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x1a, 0x25, 0x0a, 0x06, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x22, 0x6e, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x41, 0x4c, 0x49, 0x44, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x41, - 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, - 0x44, 0x10, 0x02, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, - 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, - 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, - 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, - 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 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, 0x61, 0x70, 0x69, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, - 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0xdb, 0x01, 0x0a, 0x11, 0x4f, 0x72, 0x67, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x03, 0x6f, 0x72, 0x67, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x52, 0x03, 0x6f, 0x72, 0x67, 0x12, 0x18, 0x0a, + 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x64, 0x0a, + 0x03, 0x4f, 0x72, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x22, 0xe1, 0x04, 0x0a, 0x0e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, + 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, + 0x3d, 0x0a, 0x0c, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5d, + 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, + 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x10, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, + 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x12, 0x3e, 0x0a, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, + 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x1a, 0x25, 0x0a, 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, + 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, + 0x61, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x6e, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x56, + 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, + 0x0a, 0x14, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, + 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, + 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, + 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x1c, 0x41, + 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, + 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x1a, 0x04, 0xa8, + 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 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, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go b/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go index 7bbcec6a1..281b86bd3 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go @@ -1747,6 +1747,8 @@ func (m *AttestationItem_Material) validate(all bool) error { // no validation rules for Annotations + // no validation rules for Hash + if len(errors) > 0 { return AttestationItem_MaterialMultiError(errors) } diff --git a/app/controlplane/api/controlplane/v1/response_messages.proto b/app/controlplane/api/controlplane/v1/response_messages.proto index d9dec7df7..b3927b5b1 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.proto +++ b/app/controlplane/api/controlplane/v1/response_messages.proto @@ -65,10 +65,12 @@ message AttestationItem { message Material { string name = 1; + // This might be the raw value, the container image name, the filename and so on string value = 2; // Material type, i.e ARTIFACT string type = 3; map annotations = 4; + string hash = 5; } } diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts index c67cf969a..278bc3e5f 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts @@ -85,10 +85,12 @@ export interface AttestationItem_EnvVariable { export interface AttestationItem_Material { name: string; + /** This might be the raw value, the container image name, the filename and so on */ value: string; /** Material type, i.e ARTIFACT */ type: string; annotations: { [key: string]: string }; + hash: string; } export interface AttestationItem_Material_AnnotationsEntry { @@ -734,7 +736,7 @@ export const AttestationItem_EnvVariable = { }; function createBaseAttestationItem_Material(): AttestationItem_Material { - return { name: "", value: "", type: "", annotations: {} }; + return { name: "", value: "", type: "", annotations: {}, hash: "" }; } export const AttestationItem_Material = { @@ -751,6 +753,9 @@ export const AttestationItem_Material = { Object.entries(message.annotations).forEach(([key, value]) => { AttestationItem_Material_AnnotationsEntry.encode({ key: key as any, value }, writer.uint32(34).fork()).ldelim(); }); + if (message.hash !== "") { + writer.uint32(42).string(message.hash); + } return writer; }, @@ -792,6 +797,13 @@ export const AttestationItem_Material = { message.annotations[entry4.key] = entry4.value; } continue; + case 5: + if (tag !== 42) { + break; + } + + message.hash = reader.string(); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -812,6 +824,7 @@ export const AttestationItem_Material = { return acc; }, {}) : {}, + hash: isSet(object.hash) ? String(object.hash) : "", }; }, @@ -826,6 +839,7 @@ export const AttestationItem_Material = { obj.annotations[k] = v; }); } + message.hash !== undefined && (obj.hash = message.hash); return obj; }, @@ -847,6 +861,7 @@ export const AttestationItem_Material = { }, {}, ); + message.hash = object.hash ?? ""; return message; }, }; diff --git a/app/controlplane/internal/service/attestation.go b/app/controlplane/internal/service/attestation.go index 7875d99ac..cc8e47651 100644 --- a/app/controlplane/internal/service/attestation.go +++ b/app/controlplane/internal/service/attestation.go @@ -334,24 +334,23 @@ func extractEnvVariables(in map[string]string) []*cpAPI.AttestationItem_EnvVaria 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 + materialItem := &cpAPI.AttestationItem_Material{ + Name: m.Name, + Type: m.Type, + Annotations: m.Annotations, + Value: m.Value, + } + if m.Hash != nil { - name := m.Value - if m.EmbeddedInline || m.UploadedToCAS { - name = m.Filename - } + materialItem.Hash = m.Hash.String() + } - displayValue = fmt.Sprintf("%s@%s", name, m.Hash) + // Override the value for the filename of the item uploaded + if m.EmbeddedInline || m.UploadedToCAS { + materialItem.Value = m.Filename } - res = append(res, &cpAPI.AttestationItem_Material{ - Name: m.Name, - Value: displayValue, - Type: m.Type, - Annotations: m.Annotations, - }) + res = append(res, materialItem) } return res, nil From 6cd88a5ad01813062ac88e81f73659b8786cae04 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 13:07:39 +0200 Subject: [PATCH 3/9] feat: improve output Signed-off-by: Miguel Martinez Trivino --- .../internal/service/attestation_test.go | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/app/controlplane/internal/service/attestation_test.go b/app/controlplane/internal/service/attestation_test.go index c1d047f65..bae797333 100644 --- a/app/controlplane/internal/service/attestation_test.go +++ b/app/controlplane/internal/service/attestation_test.go @@ -38,6 +38,15 @@ func TestExtractMaterials(t *testing.T) { Type: "STRING", Value: "bar", }, + { + Name: "with_annotations", + Type: "STRING", + Value: "bar", + Annotations: map[string]string{ + "foo": "bar", + "bar": "baz", + }, + }, { Name: "foo", Type: "ARTIFACT", @@ -57,15 +66,26 @@ func TestExtractMaterials(t *testing.T) { Type: "STRING", Value: "bar", }, + { + Name: "with_annotations", + Type: "STRING", + Value: "bar", + Annotations: map[string]string{ + "foo": "bar", + "bar": "baz", + }, + }, { Name: "foo", Type: "ARTIFACT", - Value: "bar@sha256:deadbeef", + Value: "bar", + Hash: "sha256:deadbeef", }, { Name: "image", Type: "CONTAINER_IMAGE", - Value: "docker.io/nginx@sha256:deadbeef", + Value: "docker.io/nginx", + Hash: "sha256:deadbeef", }, }, }, From 97508cc2840599c9a11aa864dd8822466296b7d2 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 15:55:42 +0200 Subject: [PATCH 4/9] feat: improve output Signed-off-by: Miguel Martinez Trivino --- .../crafter/materials/artifact_test.go | 2 - .../crafter/materials/cyclonedxjson_test.go | 2 - .../crafter/materials/junit_xml_test.go | 2 - .../crafter/materials/materials_test.go | 56 +++++++++++++++++++ .../crafter/materials/spdxjson_test.go | 2 - .../crafter/materials/string_test.go | 2 - .../renderer/chainloop/chainloop_test.go | 11 +++- .../chainloop/testdata/valid.envelope.v2.json | 2 +- .../renderer/chainloop/v02_test.go | 35 +++++++++++- 9 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 internal/attestation/crafter/materials/materials_test.go diff --git a/internal/attestation/crafter/materials/artifact_test.go b/internal/attestation/crafter/materials/artifact_test.go index d3db175ec..bcd7a27e5 100644 --- a/internal/attestation/crafter/materials/artifact_test.go +++ b/internal/attestation/crafter/materials/artifact_test.go @@ -18,7 +18,6 @@ package materials_test import ( "context" "testing" - "time" "code.cloudfoundry.org/bytefmt" attestationApi "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" @@ -91,7 +90,6 @@ func TestArtifactCraft(t *testing.T) { assert.NoError(err) assert.Equal(contractAPI.CraftingSchema_Material_ARTIFACT.String(), got.MaterialType.String()) assert.True(got.UploadedToCas) - assert.WithinDuration(time.Now(), got.AddedAt.AsTime(), 5*time.Second) // The result includes the digest reference assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ diff --git a/internal/attestation/crafter/materials/cyclonedxjson_test.go b/internal/attestation/crafter/materials/cyclonedxjson_test.go index ce415f66e..496543c84 100644 --- a/internal/attestation/crafter/materials/cyclonedxjson_test.go +++ b/internal/attestation/crafter/materials/cyclonedxjson_test.go @@ -18,7 +18,6 @@ package materials_test import ( "context" "testing" - "time" attestationApi "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" contractAPI "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" @@ -121,7 +120,6 @@ func TestCyclonedxJSONCraft(t *testing.T) { require.NoError(t, err) assert.Equal(contractAPI.CraftingSchema_Material_SBOM_CYCLONEDX_JSON.String(), got.MaterialType.String()) - assert.WithinDuration(time.Now(), got.AddedAt.AsTime(), 5*time.Second) assert.True(got.UploadedToCas) // The result includes the digest reference diff --git a/internal/attestation/crafter/materials/junit_xml_test.go b/internal/attestation/crafter/materials/junit_xml_test.go index 4860c22cd..3d754125f 100644 --- a/internal/attestation/crafter/materials/junit_xml_test.go +++ b/internal/attestation/crafter/materials/junit_xml_test.go @@ -19,7 +19,6 @@ package materials_test import ( "context" "testing" - "time" attestationApi "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" contractAPI "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" @@ -124,7 +123,6 @@ func TestJUnitXMLCraft(t *testing.T) { require.NoError(t, err) assert.Equal(contractAPI.CraftingSchema_Material_JUNIT_XML.String(), got.MaterialType.String()) assert.True(got.UploadedToCas) - assert.WithinDuration(time.Now(), got.AddedAt.AsTime(), 5*time.Second) // The result includes the digest reference assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ diff --git a/internal/attestation/crafter/materials/materials_test.go b/internal/attestation/crafter/materials/materials_test.go new file mode 100644 index 000000000..82f5a3286 --- /dev/null +++ b/internal/attestation/crafter/materials/materials_test.go @@ -0,0 +1,56 @@ +// +// Copyright 2023 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package materials_test + +import ( + "context" + "testing" + "time" + + 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" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCraft(t *testing.T) { + assert := assert.New(t) + schema := &contractAPI.CraftingSchema_Material{ + Name: "test", + Type: contractAPI.CraftingSchema_Material_STRING, + Annotations: []*contractAPI.Annotation{ + { + Name: "test", + Value: "test", + }, + }, + } + + got, err := materials.Craft(context.TODO(), schema, "test-value", nil, nil) + require.NoError(t, err) + assert.Equal(contractAPI.CraftingSchema_Material_STRING, got.MaterialType) + assert.False(got.UploadedToCas) + assert.Equal(got.GetString_(), &attestationApi.Attestation_Material_KeyVal{ + Id: "test", Value: "test-value", + }) + + // Timestamp + assert.WithinDuration(time.Now(), got.AddedAt.AsTime(), 5*time.Second) + // Annotations + assert.Equal(map[string]string{"test": "test"}, got.Annotations) + +} diff --git a/internal/attestation/crafter/materials/spdxjson_test.go b/internal/attestation/crafter/materials/spdxjson_test.go index 4cd415bae..fc111004a 100644 --- a/internal/attestation/crafter/materials/spdxjson_test.go +++ b/internal/attestation/crafter/materials/spdxjson_test.go @@ -19,7 +19,6 @@ package materials_test import ( "context" "testing" - "time" attestationApi "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" contractAPI "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" @@ -123,7 +122,6 @@ func TestSPDXJSONCraft(t *testing.T) { assert.Equal(contractAPI.CraftingSchema_Material_SBOM_SPDX_JSON.String(), got.MaterialType.String()) assert.True(got.UploadedToCas) - assert.WithinDuration(time.Now(), got.AddedAt.AsTime(), 5*time.Second) // // The result includes the digest reference assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ diff --git a/internal/attestation/crafter/materials/string_test.go b/internal/attestation/crafter/materials/string_test.go index cc134e0c6..4633cbc35 100644 --- a/internal/attestation/crafter/materials/string_test.go +++ b/internal/attestation/crafter/materials/string_test.go @@ -18,7 +18,6 @@ package materials_test import ( "context" "testing" - "time" attestationApi "github.com/chainloop-dev/chainloop/app/cli/api/attestation/v1" contractAPI "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" @@ -77,7 +76,6 @@ func TestStringCraft(t *testing.T) { assert.NoError(err) assert.Equal(contractAPI.CraftingSchema_Material_STRING, got.MaterialType) assert.False(got.UploadedToCas) - assert.WithinDuration(time.Now(), got.AddedAt.AsTime(), 5*time.Second) assert.Equal(got.GetString_(), &attestationApi.Attestation_Material_KeyVal{ Id: "test", Value: "value", }) diff --git a/internal/attestation/renderer/chainloop/chainloop_test.go b/internal/attestation/renderer/chainloop/chainloop_test.go index 12668feb6..0e1bed910 100644 --- a/internal/attestation/renderer/chainloop/chainloop_test.go +++ b/internal/attestation/renderer/chainloop/chainloop_test.go @@ -66,17 +66,20 @@ func TestExtractPredicate(t *testing.T) { Filename: "main.go", Hash: &crv1.Hash{Algorithm: "sha256", Hex: "8fce0203a4efaac3b08ee3ad769233039faa762a3da0777c45b315f398f0c150"}, UploadedToCAS: true, + Annotations: map[string]string{"annotation": "baz"}, }, { Name: "image", Type: "CONTAINER_IMAGE", - Value: "index.docker.io/bitnami/nginx", - Hash: &crv1.Hash{Algorithm: "sha256", Hex: "747ef335ea27a2faf08aa292a5bc5491aff50c6a94ee4ebcbbcd43cdeccccaf1"}, + Value: "index.docker.io/bitnami/nginx", + Hash: &crv1.Hash{Algorithm: "sha256", Hex: "747ef335ea27a2faf08aa292a5bc5491aff50c6a94ee4ebcbbcd43cdeccccaf1"}, + Annotations: map[string]string{"another_annotation": "foo"}, }, { Name: "sbom", Type: "SBOM_CYCLONEDX_JSON", Filename: "sbom.cyclonedx.json", Hash: &crv1.Hash{Algorithm: "sha256", Hex: "16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c"}, UploadedToCAS: true, + Annotations: make(map[string]string), }, { Name: "sbom", Type: "SBOM_CYCLONEDX_JSON", @@ -84,10 +87,12 @@ func TestExtractPredicate(t *testing.T) { Hash: &crv1.Hash{Algorithm: "sha256", Hex: "16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c"}, EmbeddedInline: true, Value: "hello inline!", + Annotations: make(map[string]string), }, { Name: "stringvar", Type: "STRING", - Value: "helloworld", + Value: "helloworld", + Annotations: make(map[string]string), }, }, }, diff --git a/internal/attestation/renderer/chainloop/testdata/valid.envelope.v2.json b/internal/attestation/renderer/chainloop/testdata/valid.envelope.v2.json index dcac30516..5896f3b58 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": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImNoYWlubG9vcC5kZXYvYXR0ZXN0YXRpb24vdjAuMiIsCiAgInN1YmplY3QiOiBbCiAgICB7CiAgICAgICJuYW1lIjogImNoYWlubG9vcC5kZXYvd29ya2Zsb3cvb2xkIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhMjU2IjogIjA0MDdhMmIwMWZiZDg5OGJjYzExMDY1Zjc2MTA4ZDE2OTk4NjIwNjMwZmZjNDUzZDIxNjJjZjU3OWI0MmRlMDMiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJuYW1lIjogImluZGV4LmRvY2tlci5pby9iaXRuYW1pL25naW54IiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhMjU2IjogIjc0N2VmMzM1ZWEyN2EyZmFmMDhhYTI5MmE1YmM1NDkxYWZmNTBjNmE5NGVlNGViY2JiY2Q0M2NkZWNjY2NhZjEiCiAgICAgIH0KICAgIH0KICBdLAogICJwcmVkaWNhdGUiOiB7CiAgICAibWV0YWRhdGEiOiB7CiAgICAgICJuYW1lIjogIm9sZCIsCiAgICAgICJwcm9qZWN0IjogIm9sZCIsCiAgICAgICJ0ZWFtIjogIiIsCiAgICAgICJpbml0aWFsaXplZEF0IjogIjIwMjMtMDUtMDlUMTE6NTE6NDAuMjc3NTY3NDg0WiIsCiAgICAgICJmaW5pc2hlZEF0IjogIjIwMjMtMDUtMDlUMTM6NTI6MTQuMzM3NzY4MDg3KzAyOjAwIiwKICAgICAgIndvcmtmbG93UnVuSUQiOiAiMDAzYzZkNGYtMTkwNy00NWE3LWE1OTYtNTdjMzhlZjFmZGMzIiwKICAgICAgIndvcmtmbG93SUQiOiAiZjJmYjUzMzgtZjc5Yi00NGI4LTlhNjEtNjE2ZjUxMGMwMTliIgogICAgfSwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiY2hhaW5sb29wLmRldi9jbGkvZGV2QHNoYTI1Njo1ODkyZWUwYTNhZjJhMDU3NzAzZjM2YmM0ZDY4MjQxMGQzNzA5YTgzOTNjMGIwYjc5MTYyOTUxZTFjZDVlZWJiIgogICAgfSwKICAgICJidWlsZFR5cGUiOiAiY2hhaW5sb29wLmRldi93b3JrZmxvd3J1bi92MC4xIiwKICAgICJlbnYiOiB7ICJDVVNUT01fVkFSIjogImZvb2JhciIgfSwKICAgICJydW5uZXJUeXBlIjogIlJVTk5FUl9UWVBFX1VOU1BFQ0lGSUVEIiwKICAgICJtYXRlcmlhbHMiOiBbCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTI1NiI6ICI4ZmNlMDIwM2E0ZWZhYWMzYjA4ZWUzYWQ3NjkyMzMwMzlmYWE3NjJhM2RhMDc3N2M0NWIzMTVmMzk4ZjBjMTUwIgogICAgICAgIH0sCiAgICAgICAgIm5hbWUiOiAibWFpbi5nbyIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogImJpbmFyeSIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiAiQVJUSUZBQ1QiLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5jYXMiOiB0cnVlCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGEyNTYiOiAiNzQ3ZWYzMzVlYTI3YTJmYWYwOGFhMjkyYTViYzU0OTFhZmY1MGM2YTk0ZWU0ZWJjYmJjZDQzY2RlY2NjY2FmMSIKICAgICAgICB9LAogICAgICAgICJuYW1lIjogImluZGV4LmRvY2tlci5pby9iaXRuYW1pL25naW54IiwKICAgICAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLm5hbWUiOiAiaW1hZ2UiLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIkNPTlRBSU5FUl9JTUFHRSIKICAgICAgICB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTI1NiI6ICIxNjE1OWJiODgxZWI0YWI3ZWI1ZDhhZmM1MzUwYjBmZWVlZDFlMzFjMGEyNjhlMzU1ZTc0ZjljY2JlODg1ZTBjIgogICAgICAgIH0sCiAgICAgICAgIm5hbWUiOiAic2JvbS5jeWNsb25lZHguanNvbiIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogInNib20iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIlNCT01fQ1lDTE9ORURYX0pTT04iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5jYXMiOiB0cnVlCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGEyNTYiOiAiMTYxNTliYjg4MWViNGFiN2ViNWQ4YWZjNTM1MGIwZmVlZWQxZTMxYzBhMjY4ZTM1NWU3NGY5Y2NiZTg4NWUwYyIKICAgICAgICB9LAogICAgICAgICJuYW1lIjogImlubGluZS1zYm9tLmpzb24iLAogICAgICAgICJjb250ZW50IjogImFHVnNiRzhnYVc1c2FXNWxJUT09IiwKICAgICAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLm5hbWUiOiAic2JvbSIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiAiU0JPTV9DWUNMT05FRFhfSlNPTiIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLmNhcy5pbmxpbmUiOiB0cnVlCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImNvbnRlbnQiOiAiYUdWc2JHOTNiM0pzWkE9PSIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogInN0cmluZ3ZhciIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiAiU1RSSU5HIgogICAgICAgIH0KICAgICAgfQogICAgXQogIH0KfQo=", + "payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImNoYWlubG9vcC5kZXYvYXR0ZXN0YXRpb24vdjAuMiIsCiAgInN1YmplY3QiOiBbCiAgICB7CiAgICAgICJuYW1lIjogImNoYWlubG9vcC5kZXYvd29ya2Zsb3cvb2xkIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhMjU2IjogIjA0MDdhMmIwMWZiZDg5OGJjYzExMDY1Zjc2MTA4ZDE2OTk4NjIwNjMwZmZjNDUzZDIxNjJjZjU3OWI0MmRlMDMiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJuYW1lIjogImluZGV4LmRvY2tlci5pby9iaXRuYW1pL25naW54IiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhMjU2IjogIjc0N2VmMzM1ZWEyN2EyZmFmMDhhYTI5MmE1YmM1NDkxYWZmNTBjNmE5NGVlNGViY2JiY2Q0M2NkZWNjY2NhZjEiCiAgICAgIH0KICAgIH0KICBdLAogICJwcmVkaWNhdGUiOiB7CiAgICAibWV0YWRhdGEiOiB7CiAgICAgICJuYW1lIjogIm9sZCIsCiAgICAgICJwcm9qZWN0IjogIm9sZCIsCiAgICAgICJ0ZWFtIjogIiIsCiAgICAgICJpbml0aWFsaXplZEF0IjogIjIwMjMtMDUtMDlUMTE6NTE6NDAuMjc3NTY3NDg0WiIsCiAgICAgICJmaW5pc2hlZEF0IjogIjIwMjMtMDUtMDlUMTM6NTI6MTQuMzM3NzY4MDg3KzAyOjAwIiwKICAgICAgIndvcmtmbG93UnVuSUQiOiAiMDAzYzZkNGYtMTkwNy00NWE3LWE1OTYtNTdjMzhlZjFmZGMzIiwKICAgICAgIndvcmtmbG93SUQiOiAiZjJmYjUzMzgtZjc5Yi00NGI4LTlhNjEtNjE2ZjUxMGMwMTliIgogICAgfSwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiY2hhaW5sb29wLmRldi9jbGkvZGV2QHNoYTI1Njo1ODkyZWUwYTNhZjJhMDU3NzAzZjM2YmM0ZDY4MjQxMGQzNzA5YTgzOTNjMGIwYjc5MTYyOTUxZTFjZDVlZWJiIgogICAgfSwKICAgICJidWlsZFR5cGUiOiAiY2hhaW5sb29wLmRldi93b3JrZmxvd3J1bi92MC4xIiwKICAgICJlbnYiOiB7ICJDVVNUT01fVkFSIjogImZvb2JhciIgfSwKICAgICJydW5uZXJUeXBlIjogIlJVTk5FUl9UWVBFX1VOU1BFQ0lGSUVEIiwKICAgICJtYXRlcmlhbHMiOiBbCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTI1NiI6ICI4ZmNlMDIwM2E0ZWZhYWMzYjA4ZWUzYWQ3NjkyMzMwMzlmYWE3NjJhM2RhMDc3N2M0NWIzMTVmMzk4ZjBjMTUwIgogICAgICAgIH0sCiAgICAgICAgIm5hbWUiOiAibWFpbi5nbyIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogImJpbmFyeSIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiAiQVJUSUZBQ1QiLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5jYXMiOiB0cnVlLAogICAgICAgICAgImFubm90YXRpb24iOiAiYmF6IgogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgICAic2hhMjU2IjogIjc0N2VmMzM1ZWEyN2EyZmFmMDhhYTI5MmE1YmM1NDkxYWZmNTBjNmE5NGVlNGViY2JiY2Q0M2NkZWNjY2NhZjEiCiAgICAgICAgfSwKICAgICAgICAibmFtZSI6ICJpbmRleC5kb2NrZXIuaW8vYml0bmFtaS9uZ2lueCIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogImltYWdlIiwKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwudHlwZSI6ICJDT05UQUlORVJfSU1BR0UiLAogICAgICAgICAgImFub3RoZXJfYW5ub3RhdGlvbiI6ICJmb28iCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGEyNTYiOiAiMTYxNTliYjg4MWViNGFiN2ViNWQ4YWZjNTM1MGIwZmVlZWQxZTMxYzBhMjY4ZTM1NWU3NGY5Y2NiZTg4NWUwYyIKICAgICAgICB9LAogICAgICAgICJuYW1lIjogInNib20uY3ljbG9uZWR4Lmpzb24iLAogICAgICAgICJhbm5vdGF0aW9ucyI6IHsKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwubmFtZSI6ICJzYm9tIiwKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwudHlwZSI6ICJTQk9NX0NZQ0xPTkVEWF9KU09OIiwKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwuY2FzIjogdHJ1ZQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgICAic2hhMjU2IjogIjE2MTU5YmI4ODFlYjRhYjdlYjVkOGFmYzUzNTBiMGZlZWVkMWUzMWMwYTI2OGUzNTVlNzRmOWNjYmU4ODVlMGMiCiAgICAgICAgfSwKICAgICAgICAibmFtZSI6ICJpbmxpbmUtc2JvbS5qc29uIiwKICAgICAgICAiY29udGVudCI6ICJhR1ZzYkc4Z2FXNXNhVzVsSVE9PSIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogInNib20iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIlNCT01fQ1lDTE9ORURYX0pTT04iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5jYXMuaW5saW5lIjogdHJ1ZQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJjb250ZW50IjogImFHVnNiRzkzYjNKc1pBPT0iLAogICAgICAgICJhbm5vdGF0aW9ucyI6IHsKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwubmFtZSI6ICJzdHJpbmd2YXIiLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIlNUUklORyIKICAgICAgICB9CiAgICAgIH0KICAgIF0KICB9Cn0K", "signatures": [ { "keyid": "", diff --git a/internal/attestation/renderer/chainloop/v02_test.go b/internal/attestation/renderer/chainloop/v02_test.go index dc06c9ded..d82785f70 100644 --- a/internal/attestation/renderer/chainloop/v02_test.go +++ b/internal/attestation/renderer/chainloop/v02_test.go @@ -84,6 +84,8 @@ func TestRenderV02(t *testing.T) { } func TestNormalizeMaterial(t *testing.T) { + var emptyMap = make(map[string]string) + testCases := []struct { name string input *slsa_v1.ResourceDescriptor @@ -128,9 +130,10 @@ func TestNormalizeMaterial(t *testing.T) { Content: []byte("bar"), }, want: &NormalizedMaterial{ - Name: "foo", - Type: "STRING", - Value: "bar", + Name: "foo", + Type: "STRING", + Value: "bar", + Annotations: emptyMap, }, }, { @@ -162,6 +165,31 @@ func TestNormalizeMaterial(t *testing.T) { Filename: "artifact.tgz", Hash: &crv1.Hash{Algorithm: "sha256", Hex: "deadbeef"}, UploadedToCAS: true, + Annotations: emptyMap, + }, + }, + { + name: "valid artifact material with annotations", + input: &slsa_v1.ResourceDescriptor{ + Annotations: map[string]interface{}{ + "chainloop.material.name": "foo", + "chainloop.material.type": "ARTIFACT", + "chainloop.material.cas": true, + "foo": "bar", + "bar": "baz", + }, + Digest: map[string]string{ + "sha256": "deadbeef", + }, + Name: "artifact.tgz", + }, + want: &NormalizedMaterial{ + Name: "foo", + Type: "ARTIFACT", + Filename: "artifact.tgz", + Hash: &crv1.Hash{Algorithm: "sha256", Hex: "deadbeef"}, + UploadedToCAS: true, + Annotations: map[string]string{"foo": "bar", "bar": "baz"}, }, }, { @@ -185,6 +213,7 @@ func TestNormalizeMaterial(t *testing.T) { Value: "this is an inline material", Hash: &crv1.Hash{Algorithm: "sha256", Hex: "deadbeef"}, EmbeddedInline: true, + Annotations: emptyMap, }, }, { From d2981108cf27200e9be800a9bdabd2a88970a3b8 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 16:02:18 +0200 Subject: [PATCH 5/9] feat: improve output Signed-off-by: Miguel Martinez Trivino --- .../workflowcontract/v1/crafting_schema.ts | 2 ++ .../workflowcontract/v1/crafting_schema.pb.go | 20 ++++++++++--------- .../v1/crafting_schema.pb.validate.go | 11 +++++++++- .../workflowcontract/v1/crafting_schema.proto | 4 +++- .../crafter/materials/materials_test.go | 1 - 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts index 1b5c88953..80d55b2b9 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -140,6 +140,8 @@ export interface Annotation { /** Single word optionally separated with _ or - */ name: string; /** + * TODO: This value is required for now, but this behavior will chance once we allow + * The user to set the value during attestation * The value can be set in the contract or during the attestation process * that's why its value is optional */ diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index d7d6f3080..2bb7f3126 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -226,6 +226,8 @@ type Annotation struct { unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Single word optionally separated with _ or - + // TODO: This value is required for now, but this behavior will chance once we allow + // The user to set the value during attestation // The value can be set in the contract or during the attestation process // that's why its value is optional Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` @@ -467,17 +469,17 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 0x4d, 0x5f, 0x43, 0x59, 0x43, 0x4c, 0x4f, 0x4e, 0x45, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x53, 0x50, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x55, 0x4e, 0x49, 0x54, 0x5f, - 0x58, 0x4d, 0x4c, 0x10, 0x06, 0x22, 0x48, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x58, 0x4d, 0x4c, 0x10, 0x06, 0x22, 0x51, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x72, 0x0b, 0x32, 0x09, 0x5e, 0x5b, 0x5c, 0x77, 0x7c, 0x2d, - 0x5d, 0x2b, 0x24, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, - 0x4d, 0x5a, 0x4b, 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, 0x61, 0x70, 0x69, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x5d, 0x2b, 0x24, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x42, 0x4d, 0x5a, 0x4b, 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, + 0x61, 0x70, 0x69, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go index 2bba91baf..760dc000d 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go @@ -242,7 +242,16 @@ func (m *Annotation) validate(all bool) error { errors = append(errors, err) } - // no validation rules for Value + if utf8.RuneCountInString(m.GetValue()) < 1 { + err := AnnotationValidationError{ + field: "Value", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } if len(errors) > 0 { return AnnotationMultiError(errors) diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index c560008de..4242de91e 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -65,7 +65,9 @@ message CraftingSchema { message Annotation { string name = 1 [(validate.rules).string.pattern = "^[\\w|-]+$"]; // Single word optionally separated with _ or - + // TODO: This value is required for now, but this behavior will chance once we allow + // The user to set the value during attestation // The value can be set in the contract or during the attestation process // that's why its value is optional - string value = 2; + string value = 2 [(validate.rules).string.min_len = 1]; } \ No newline at end of file diff --git a/internal/attestation/crafter/materials/materials_test.go b/internal/attestation/crafter/materials/materials_test.go index 82f5a3286..d308fa84d 100644 --- a/internal/attestation/crafter/materials/materials_test.go +++ b/internal/attestation/crafter/materials/materials_test.go @@ -52,5 +52,4 @@ func TestCraft(t *testing.T) { assert.WithinDuration(time.Now(), got.AddedAt.AsTime(), 5*time.Second) // Annotations assert.Equal(map[string]string{"test": "test"}, got.Annotations) - } From b500304641286647636a6b90344066db97841950 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 16:24:19 +0200 Subject: [PATCH 6/9] feat: add tests Signed-off-by: Miguel Martinez Trivino --- .../workflowcontract/v1/crafting_schema.ts | 2 +- .../workflowcontract/v1/crafting_schema.pb.go | 24 ++--- .../v1/crafting_schema.pb.validate.go | 4 +- .../workflowcontract/v1/crafting_schema.proto | 2 +- .../v1/crafting_schema_test.go | 95 +++++++++++++++++++ 5 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 app/controlplane/api/workflowcontract/v1/crafting_schema_test.go diff --git a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts index 80d55b2b9..9966b66a0 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -137,7 +137,7 @@ export function craftingSchema_Material_MaterialTypeToJSON(object: CraftingSchem } export interface Annotation { - /** Single word optionally separated with _ or - */ + /** Single word optionally separated with _ */ name: string; /** * TODO: This value is required for now, but this behavior will chance once we allow diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index 2bb7f3126..09b5e3000 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -225,7 +225,7 @@ type Annotation struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Single word optionally separated with _ or - + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Single word optionally separated with _ // TODO: This value is required for now, but this behavior will chance once we allow // The user to set the value during attestation // The value can be set in the contract or during the attestation process @@ -469,17 +469,17 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 0x4d, 0x5f, 0x43, 0x59, 0x43, 0x4c, 0x4f, 0x4e, 0x45, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x53, 0x50, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x55, 0x4e, 0x49, 0x54, 0x5f, - 0x58, 0x4d, 0x4c, 0x10, 0x06, 0x22, 0x51, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x72, 0x0b, 0x32, 0x09, 0x5e, 0x5b, 0x5c, 0x77, 0x7c, 0x2d, - 0x5d, 0x2b, 0x24, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x42, 0x4d, 0x5a, 0x4b, 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, - 0x61, 0x70, 0x69, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x58, 0x4d, 0x4c, 0x10, 0x06, 0x22, 0x4f, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x0e, 0xfa, 0x42, 0x0b, 0x72, 0x09, 0x32, 0x07, 0x5e, 0x5b, 0x5c, 0x77, 0x5d, 0x2b, + 0x24, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x42, 0x4d, 0x5a, 0x4b, 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, 0x61, 0x70, + 0x69, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go index 760dc000d..3300fadf4 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.validate.go @@ -234,7 +234,7 @@ func (m *Annotation) validate(all bool) error { if !_Annotation_Name_Pattern.MatchString(m.GetName()) { err := AnnotationValidationError{ field: "Name", - reason: "value does not match regex pattern \"^[\\\\w|-]+$\"", + reason: "value does not match regex pattern \"^[\\\\w]+$\"", } if !all { return err @@ -330,7 +330,7 @@ var _ interface { ErrorName() string } = AnnotationValidationError{} -var _Annotation_Name_Pattern = regexp.MustCompile("^[\\w|-]+$") +var _Annotation_Name_Pattern = regexp.MustCompile("^[\\w]+$") // Validate checks the field values on CraftingSchema_Runner with the rules // defined in the proto definition for this message. If any rules are diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index 4242de91e..098d6cb61 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -64,7 +64,7 @@ message CraftingSchema { } message Annotation { - string name = 1 [(validate.rules).string.pattern = "^[\\w|-]+$"]; // Single word optionally separated with _ or - + string name = 1 [(validate.rules).string.pattern = "^[\\w]+$"]; // Single word optionally separated with _ // TODO: This value is required for now, but this behavior will chance once we allow // The user to set the value during attestation // The value can be set in the contract or during the attestation process diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go b/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go new file mode 100644 index 000000000..db57bc6dd --- /dev/null +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go @@ -0,0 +1,95 @@ +// +// Copyright 2023 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// limitations under the License. + +package v1_test + +import ( + "testing" + + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + "github.com/stretchr/testify/assert" +) + +func TestValidateAnnotations(t *testing.T) { + testCases := []struct { + desc string + name string + value string + wantErr bool + }{ + { + desc: "valid keys", + name: "hi", + value: "hi", + }, + { + desc: "missing key", + value: "hi", + wantErr: true, + }, + { + desc: "missing value", + name: "hi", + wantErr: true, + }, + { + desc: "valid key underscore", + name: "hello_world", + value: "hello_world", + }, + { + desc: "invalid key hyphen", + name: "hello-world", + value: "hello-world", + wantErr: true, + }, + { + desc: "invalid key space", + name: " hello", + value: "hello-world", + wantErr: true, + }, + { + desc: "valid key camel case", + name: "helloWorld", + value: "hello-world", + }, + { + desc: "valid content", + name: "hello", + value: "hello world this has spaces-and-hyphens", + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + annotation := &v1.Annotation{ + Name: tc.name, + Value: tc.value, + } + + err := annotation.ValidateAll() + if tc.wantErr { + assert.Error(t, err) + return + } + + assert.NoError(t, err) + }) + } + +} From ca9f5a31508a5b0ea0f4fbb87d17e8004b39d11b Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 16:27:15 +0200 Subject: [PATCH 7/9] feat: add tests Signed-off-by: Miguel Martinez Trivino --- .../api/workflowcontract/v1/crafting_schema.proto | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index 098d6cb61..372627f06 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -65,9 +65,7 @@ message CraftingSchema { message Annotation { string name = 1 [(validate.rules).string.pattern = "^[\\w]+$"]; // Single word optionally separated with _ - // TODO: This value is required for now, but this behavior will chance once we allow - // The user to set the value during attestation - // The value can be set in the contract or during the attestation process - // that's why its value is optional + // TODO: This value is required for now, but this behavior will change once we allow + // the user to set the value during attestation string value = 2 [(validate.rules).string.min_len = 1]; } \ No newline at end of file From 0e5eb986d80dd93c9bad250bad6f63f363b65f46 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 16:32:07 +0200 Subject: [PATCH 8/9] feat: add tests Signed-off-by: Miguel Martinez Trivino --- app/controlplane/api/workflowcontract/v1/crafting_schema_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go b/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go index db57bc6dd..75bcd0447 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go @@ -91,5 +91,4 @@ func TestValidateAnnotations(t *testing.T) { assert.NoError(t, err) }) } - } From ebddf48e1aa93cc451a0eeb03d80eb3e45606b38 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Fri, 28 Jul 2023 16:36:53 +0200 Subject: [PATCH 9/9] feat: add tests Signed-off-by: Miguel Martinez Trivino --- .../crafter/testdata/contracts/with_material_annotations.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/attestation/crafter/testdata/contracts/with_material_annotations.yaml b/internal/attestation/crafter/testdata/contracts/with_material_annotations.yaml index 6aa26d9c2..f56f9a84d 100644 --- a/internal/attestation/crafter/testdata/contracts/with_material_annotations.yaml +++ b/internal/attestation/crafter/testdata/contracts/with_material_annotations.yaml @@ -3,7 +3,5 @@ materials: - name: "string" type: "STRING" annotations: - - name: "with-default-val" + - name: "withDefaultVal" value: "val1" - - name: "without-default-val" - value: "boom"