From 200bc083f68fb1ba5f94b7616a6095846ea86691 Mon Sep 17 00:00:00 2001 From: Jones Jefferson Date: Fri, 6 Sep 2024 08:11:01 +0530 Subject: [PATCH 1/6] Integrate Sentryflow With Summary Engine --- protobuf/go.mod | 12 +- protobuf/go.sum | 24 +- protobuf/sentryflow.pb.go | 802 ++++++++++++++++++----- protobuf/sentryflow.proto | 42 +- protobuf/sentryflow_grpc.pb.go | 195 +++--- protobuf/sentryflow_metrics.pb.go | 10 +- protobuf/sentryflow_metrics_grpc.pb.go | 88 +-- sentryflow/collector/collectorHandler.go | 19 +- sentryflow/collector/wasm.go | 51 ++ sentryflow/config/config.go | 19 +- sentryflow/core/sentryflow.go | 18 +- sentryflow/exporter/exportAPILogs.go | 73 ++- sentryflow/exporter/exporterHandler.go | 34 + sentryflow/go.mod | 27 +- sentryflow/go.sum | 85 +-- sentryflow/processor/logProcessor.go | 15 +- 16 files changed, 1077 insertions(+), 437 deletions(-) create mode 100644 sentryflow/collector/wasm.go diff --git a/protobuf/go.mod b/protobuf/go.mod index 2038b4d..d99f98a 100644 --- a/protobuf/go.mod +++ b/protobuf/go.mod @@ -3,13 +3,13 @@ module github.com/5GSEC/SentryFlow/protobuf go 1.21 require ( - google.golang.org/grpc v1.63.2 - google.golang.org/protobuf v1.34.1 + google.golang.org/grpc v1.66.0 + google.golang.org/protobuf v1.34.2 ) require ( - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect ) diff --git a/protobuf/go.sum b/protobuf/go.sum index c475bdd..a7a0b60 100644 --- a/protobuf/go.sum +++ b/protobuf/go.sum @@ -1,14 +1,14 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/protobuf/sentryflow.pb.go b/protobuf/sentryflow.pb.go index d664634..99015c5 100644 --- a/protobuf/sentryflow.pb.go +++ b/protobuf/sentryflow.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 -// protoc v5.26.0 +// protoc-gen-go v1.34.2 +// protoc v5.27.3 // source: sentryflow.proto package protobuf @@ -9,6 +9,7 @@ package protobuf import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -258,6 +259,369 @@ func (x *APILog) GetResponseCode() int32 { return 0 } +type APILogV2 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ContextId int32 `protobuf:"varint,1,opt,name=context_id,json=contextId,proto3" json:"context_id,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Source *Source `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` + Destination *Destination `protobuf:"bytes,4,opt,name=destination,proto3" json:"destination,omitempty"` + Request *Request `protobuf:"bytes,5,opt,name=request,proto3" json:"request,omitempty"` + Response *Response `protobuf:"bytes,6,opt,name=response,proto3" json:"response,omitempty"` + Protocol string `protobuf:"bytes,7,opt,name=Protocol,proto3" json:"Protocol,omitempty"` +} + +func (x *APILogV2) Reset() { + *x = APILogV2{} + if protoimpl.UnsafeEnabled { + mi := &file_sentryflow_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *APILogV2) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*APILogV2) ProtoMessage() {} + +func (x *APILogV2) ProtoReflect() protoreflect.Message { + mi := &file_sentryflow_proto_msgTypes[2] + 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 APILogV2.ProtoReflect.Descriptor instead. +func (*APILogV2) Descriptor() ([]byte, []int) { + return file_sentryflow_proto_rawDescGZIP(), []int{2} +} + +func (x *APILogV2) GetContextId() int32 { + if x != nil { + return x.ContextId + } + return 0 +} + +func (x *APILogV2) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +func (x *APILogV2) GetSource() *Source { + if x != nil { + return x.Source + } + return nil +} + +func (x *APILogV2) GetDestination() *Destination { + if x != nil { + return x.Destination + } + return nil +} + +func (x *APILogV2) GetRequest() *Request { + if x != nil { + return x.Request + } + return nil +} + +func (x *APILogV2) GetResponse() *Response { + if x != nil { + return x.Response + } + return nil +} + +func (x *APILogV2) GetProtocol() string { + if x != nil { + return x.Protocol + } + return "" +} + +type Source struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"` + Port int32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"` + Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type,omitempty"` +} + +func (x *Source) Reset() { + *x = Source{} + if protoimpl.UnsafeEnabled { + mi := &file_sentryflow_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Source) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Source) ProtoMessage() {} + +func (x *Source) ProtoReflect() protoreflect.Message { + mi := &file_sentryflow_proto_msgTypes[3] + 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 Source.ProtoReflect.Descriptor instead. +func (*Source) Descriptor() ([]byte, []int) { + return file_sentryflow_proto_rawDescGZIP(), []int{3} +} + +func (x *Source) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Source) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Source) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +func (x *Source) GetPort() int32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *Source) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +type Destination struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"` + Port int32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"` + Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type,omitempty"` +} + +func (x *Destination) Reset() { + *x = Destination{} + if protoimpl.UnsafeEnabled { + mi := &file_sentryflow_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Destination) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Destination) ProtoMessage() {} + +func (x *Destination) ProtoReflect() protoreflect.Message { + mi := &file_sentryflow_proto_msgTypes[4] + 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 Destination.ProtoReflect.Descriptor instead. +func (*Destination) Descriptor() ([]byte, []int) { + return file_sentryflow_proto_rawDescGZIP(), []int{4} +} + +func (x *Destination) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Destination) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Destination) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +func (x *Destination) GetPort() int32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *Destination) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +type Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Headers map[string]string `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Body string `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` +} + +func (x *Request) Reset() { + *x = Request{} + if protoimpl.UnsafeEnabled { + mi := &file_sentryflow_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Request) ProtoMessage() {} + +func (x *Request) ProtoReflect() protoreflect.Message { + mi := &file_sentryflow_proto_msgTypes[5] + 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 Request.ProtoReflect.Descriptor instead. +func (*Request) Descriptor() ([]byte, []int) { + return file_sentryflow_proto_rawDescGZIP(), []int{5} +} + +func (x *Request) GetHeaders() map[string]string { + if x != nil { + return x.Headers + } + return nil +} + +func (x *Request) GetBody() string { + if x != nil { + return x.Body + } + return "" +} + +type Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Headers map[string]string `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Body string `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` +} + +func (x *Response) Reset() { + *x = Response{} + if protoimpl.UnsafeEnabled { + mi := &file_sentryflow_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Response) ProtoMessage() {} + +func (x *Response) ProtoReflect() protoreflect.Message { + mi := &file_sentryflow_proto_msgTypes[6] + 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 Response.ProtoReflect.Descriptor instead. +func (*Response) Descriptor() ([]byte, []int) { + return file_sentryflow_proto_rawDescGZIP(), []int{6} +} + +func (x *Response) GetHeaders() map[string]string { + if x != nil { + return x.Headers + } + return nil +} + +func (x *Response) GetBody() string { + if x != nil { + return x.Body + } + return "" +} + type APIMetrics struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -269,7 +633,7 @@ type APIMetrics struct { func (x *APIMetrics) Reset() { *x = APIMetrics{} if protoimpl.UnsafeEnabled { - mi := &file_sentryflow_proto_msgTypes[2] + mi := &file_sentryflow_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -282,7 +646,7 @@ func (x *APIMetrics) String() string { func (*APIMetrics) ProtoMessage() {} func (x *APIMetrics) ProtoReflect() protoreflect.Message { - mi := &file_sentryflow_proto_msgTypes[2] + mi := &file_sentryflow_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -295,7 +659,7 @@ func (x *APIMetrics) ProtoReflect() protoreflect.Message { // Deprecated: Use APIMetrics.ProtoReflect.Descriptor instead. func (*APIMetrics) Descriptor() ([]byte, []int) { - return file_sentryflow_proto_rawDescGZIP(), []int{2} + return file_sentryflow_proto_rawDescGZIP(), []int{7} } func (x *APIMetrics) GetPerAPICounts() map[string]uint64 { @@ -316,7 +680,7 @@ type MetricValue struct { func (x *MetricValue) Reset() { *x = MetricValue{} if protoimpl.UnsafeEnabled { - mi := &file_sentryflow_proto_msgTypes[3] + mi := &file_sentryflow_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -329,7 +693,7 @@ func (x *MetricValue) String() string { func (*MetricValue) ProtoMessage() {} func (x *MetricValue) ProtoReflect() protoreflect.Message { - mi := &file_sentryflow_proto_msgTypes[3] + mi := &file_sentryflow_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -342,7 +706,7 @@ func (x *MetricValue) ProtoReflect() protoreflect.Message { // Deprecated: Use MetricValue.ProtoReflect.Descriptor instead. func (*MetricValue) Descriptor() ([]byte, []int) { - return file_sentryflow_proto_rawDescGZIP(), []int{3} + return file_sentryflow_proto_rawDescGZIP(), []int{8} } func (x *MetricValue) GetValue() map[string]string { @@ -368,7 +732,7 @@ type EnvoyMetrics struct { func (x *EnvoyMetrics) Reset() { *x = EnvoyMetrics{} if protoimpl.UnsafeEnabled { - mi := &file_sentryflow_proto_msgTypes[4] + mi := &file_sentryflow_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -381,7 +745,7 @@ func (x *EnvoyMetrics) String() string { func (*EnvoyMetrics) ProtoMessage() {} func (x *EnvoyMetrics) ProtoReflect() protoreflect.Message { - mi := &file_sentryflow_proto_msgTypes[4] + mi := &file_sentryflow_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -394,7 +758,7 @@ func (x *EnvoyMetrics) ProtoReflect() protoreflect.Message { // Deprecated: Use EnvoyMetrics.ProtoReflect.Descriptor instead. func (*EnvoyMetrics) Descriptor() ([]byte, []int) { - return file_sentryflow_proto_rawDescGZIP(), []int{4} + return file_sentryflow_proto_rawDescGZIP(), []int{9} } func (x *EnvoyMetrics) GetTimeStamp() string { @@ -443,111 +807,170 @@ var File_sentryflow_proto protoreflect.FileDescriptor var file_sentryflow_proto_rawDesc = []byte{ 0x0a, 0x10, 0x73, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x46, 0x0a, 0x0a, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, - 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, - 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x50, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, 0x50, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x22, 0xa4, 0x05, 0x0a, 0x06, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x22, 0x0a, - 0x0c, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x73, - 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x2e, - 0x53, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, - 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x54, 0x79, - 0x70, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x72, 0x63, 0x49, 0x50, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, - 0x72, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, 0x72, - 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x3a, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x21, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, - 0x4c, 0x6f, 0x67, 0x2e, 0x44, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x08, 0x64, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x64, - 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x29, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x73, 0x74, 0x49, 0x50, 0x18, 0x2a, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x64, - 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, - 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x18, 0x33, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x34, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x18, 0x35, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, - 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x36, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, - 0x65, 0x1a, 0x3b, 0x0a, 0x0d, 0x53, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0x3b, - 0x0a, 0x0d, 0x44, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 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, 0x46, 0x0a, + 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x68, + 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, + 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x50, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, 0x50, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xa4, 0x05, 0x0a, 0x06, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x22, + 0x0a, 0x0c, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x08, + 0x73, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, + 0x2e, 0x53, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, + 0x73, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x72, 0x63, 0x49, 0x50, 0x18, 0x16, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x50, + 0x6f, 0x72, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, + 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x3a, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x21, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, + 0x49, 0x4c, 0x6f, 0x67, 0x2e, 0x44, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x08, 0x64, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, + 0x64, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x29, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, + 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x73, 0x74, 0x49, 0x50, 0x18, + 0x2a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x50, 0x12, 0x18, 0x0a, 0x07, + 0x64, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, + 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x18, 0x33, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x34, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x35, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, + 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x36, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, + 0x64, 0x65, 0x1a, 0x3b, 0x0a, 0x0d, 0x53, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, + 0x3b, 0x0a, 0x0d, 0x44, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0xbf, 0x02, 0x0a, + 0x08, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x56, 0x32, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 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, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x72, + 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, + 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x22, 0x77, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x07, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 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, 0x95, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, + 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0x3a, 0x0a, + 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 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, 0x99, 0x01, 0x0a, 0x0a, 0x41, 0x50, + 0x49, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x4a, 0x0a, 0x0c, 0x70, 0x65, 0x72, 0x41, + 0x50, 0x49, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x70, 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x73, 0x1a, 0x3f, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 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, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7f, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x38, 0x0a, 0x0a, + 0x56, 0x61, 0x6c, 0x75, 0x65, 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, 0x85, 0x03, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x6f, 0x79, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x53, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x50, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, 0x50, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, + 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, + 0x73, 0x12, 0x3d, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x15, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, + 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, + 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0x99, 0x01, 0x0a, 0x0a, - 0x41, 0x50, 0x49, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x4a, 0x0a, 0x0c, 0x70, 0x65, - 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x70, 0x65, 0x72, 0x41, 0x50, 0x49, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x1a, 0x3f, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x41, 0x50, 0x49, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 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, 0x04, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7f, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x38, - 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x75, 0x65, 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, 0x85, 0x03, 0x0a, 0x0c, 0x45, 0x6e, 0x76, - 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x50, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, 0x50, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, - 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x12, 0x3d, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x15, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0x51, 0x0a, - 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 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, - 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x32, 0xc5, 0x01, 0x0a, 0x0a, 0x53, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x6c, 0x6f, 0x77, 0x12, - 0x35, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x12, 0x14, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, - 0x49, 0x4c, 0x6f, 0x67, 0x30, 0x01, 0x12, 0x3d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, - 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x14, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x73, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, - 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x16, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x30, 0x01, 0x42, 0x15, 0x5a, 0x13, 0x53, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x46, 0x6c, 0x6f, 0x77, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x51, 0x0a, 0x0c, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 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, 0x2b, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0x80, + 0x02, 0x0a, 0x0a, 0x53, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x35, 0x0a, + 0x09, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4c, + 0x6f, 0x67, 0x30, 0x01, 0x12, 0x39, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4c, 0x6f, + 0x67, 0x56, 0x32, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x56, 0x32, 0x30, 0x01, 0x12, + 0x3d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, + 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x30, 0x01, 0x12, 0x41, + 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x30, + 0x01, 0x42, 0x15, 0x5a, 0x13, 0x53, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x6c, 0x6f, 0x77, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -562,39 +985,56 @@ func file_sentryflow_proto_rawDescGZIP() []byte { return file_sentryflow_proto_rawDescData } -var file_sentryflow_proto_msgTypes = make([]protoimpl.MessageInfo, 11) -var file_sentryflow_proto_goTypes = []interface{}{ - (*ClientInfo)(nil), // 0: protobuf.ClientInfo - (*APILog)(nil), // 1: protobuf.APILog - (*APIMetrics)(nil), // 2: protobuf.APIMetrics - (*MetricValue)(nil), // 3: protobuf.MetricValue - (*EnvoyMetrics)(nil), // 4: protobuf.EnvoyMetrics - nil, // 5: protobuf.APILog.SrcLabelEntry - nil, // 6: protobuf.APILog.DstLabelEntry - nil, // 7: protobuf.APIMetrics.PerAPICountsEntry - nil, // 8: protobuf.MetricValue.ValueEntry - nil, // 9: protobuf.EnvoyMetrics.LabelsEntry - nil, // 10: protobuf.EnvoyMetrics.MetricsEntry +var file_sentryflow_proto_msgTypes = make([]protoimpl.MessageInfo, 18) +var file_sentryflow_proto_goTypes = []any{ + (*ClientInfo)(nil), // 0: protobuf.ClientInfo + (*APILog)(nil), // 1: protobuf.APILog + (*APILogV2)(nil), // 2: protobuf.APILogV2 + (*Source)(nil), // 3: protobuf.Source + (*Destination)(nil), // 4: protobuf.Destination + (*Request)(nil), // 5: protobuf.Request + (*Response)(nil), // 6: protobuf.Response + (*APIMetrics)(nil), // 7: protobuf.APIMetrics + (*MetricValue)(nil), // 8: protobuf.MetricValue + (*EnvoyMetrics)(nil), // 9: protobuf.EnvoyMetrics + nil, // 10: protobuf.APILog.SrcLabelEntry + nil, // 11: protobuf.APILog.DstLabelEntry + nil, // 12: protobuf.Request.HeadersEntry + nil, // 13: protobuf.Response.HeadersEntry + nil, // 14: protobuf.APIMetrics.PerAPICountsEntry + nil, // 15: protobuf.MetricValue.ValueEntry + nil, // 16: protobuf.EnvoyMetrics.LabelsEntry + nil, // 17: protobuf.EnvoyMetrics.MetricsEntry + (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp } var file_sentryflow_proto_depIdxs = []int32{ - 5, // 0: protobuf.APILog.srcLabel:type_name -> protobuf.APILog.SrcLabelEntry - 6, // 1: protobuf.APILog.dstLabel:type_name -> protobuf.APILog.DstLabelEntry - 7, // 2: protobuf.APIMetrics.perAPICounts:type_name -> protobuf.APIMetrics.PerAPICountsEntry - 8, // 3: protobuf.MetricValue.value:type_name -> protobuf.MetricValue.ValueEntry - 9, // 4: protobuf.EnvoyMetrics.labels:type_name -> protobuf.EnvoyMetrics.LabelsEntry - 10, // 5: protobuf.EnvoyMetrics.metrics:type_name -> protobuf.EnvoyMetrics.MetricsEntry - 3, // 6: protobuf.EnvoyMetrics.MetricsEntry.value:type_name -> protobuf.MetricValue - 0, // 7: protobuf.SentryFlow.GetAPILog:input_type -> protobuf.ClientInfo - 0, // 8: protobuf.SentryFlow.GetAPIMetrics:input_type -> protobuf.ClientInfo - 0, // 9: protobuf.SentryFlow.GetEnvoyMetrics:input_type -> protobuf.ClientInfo - 1, // 10: protobuf.SentryFlow.GetAPILog:output_type -> protobuf.APILog - 2, // 11: protobuf.SentryFlow.GetAPIMetrics:output_type -> protobuf.APIMetrics - 4, // 12: protobuf.SentryFlow.GetEnvoyMetrics:output_type -> protobuf.EnvoyMetrics - 10, // [10:13] is the sub-list for method output_type - 7, // [7:10] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 10, // 0: protobuf.APILog.srcLabel:type_name -> protobuf.APILog.SrcLabelEntry + 11, // 1: protobuf.APILog.dstLabel:type_name -> protobuf.APILog.DstLabelEntry + 18, // 2: protobuf.APILogV2.timestamp:type_name -> google.protobuf.Timestamp + 3, // 3: protobuf.APILogV2.source:type_name -> protobuf.Source + 4, // 4: protobuf.APILogV2.destination:type_name -> protobuf.Destination + 5, // 5: protobuf.APILogV2.request:type_name -> protobuf.Request + 6, // 6: protobuf.APILogV2.response:type_name -> protobuf.Response + 12, // 7: protobuf.Request.headers:type_name -> protobuf.Request.HeadersEntry + 13, // 8: protobuf.Response.headers:type_name -> protobuf.Response.HeadersEntry + 14, // 9: protobuf.APIMetrics.perAPICounts:type_name -> protobuf.APIMetrics.PerAPICountsEntry + 15, // 10: protobuf.MetricValue.value:type_name -> protobuf.MetricValue.ValueEntry + 16, // 11: protobuf.EnvoyMetrics.labels:type_name -> protobuf.EnvoyMetrics.LabelsEntry + 17, // 12: protobuf.EnvoyMetrics.metrics:type_name -> protobuf.EnvoyMetrics.MetricsEntry + 8, // 13: protobuf.EnvoyMetrics.MetricsEntry.value:type_name -> protobuf.MetricValue + 0, // 14: protobuf.SentryFlow.GetAPILog:input_type -> protobuf.ClientInfo + 0, // 15: protobuf.SentryFlow.GetAPILogV2:input_type -> protobuf.ClientInfo + 0, // 16: protobuf.SentryFlow.GetAPIMetrics:input_type -> protobuf.ClientInfo + 0, // 17: protobuf.SentryFlow.GetEnvoyMetrics:input_type -> protobuf.ClientInfo + 1, // 18: protobuf.SentryFlow.GetAPILog:output_type -> protobuf.APILog + 2, // 19: protobuf.SentryFlow.GetAPILogV2:output_type -> protobuf.APILogV2 + 7, // 20: protobuf.SentryFlow.GetAPIMetrics:output_type -> protobuf.APIMetrics + 9, // 21: protobuf.SentryFlow.GetEnvoyMetrics:output_type -> protobuf.EnvoyMetrics + 18, // [18:22] is the sub-list for method output_type + 14, // [14:18] 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 } func init() { file_sentryflow_proto_init() } @@ -603,7 +1043,7 @@ func file_sentryflow_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_sentryflow_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_sentryflow_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*ClientInfo); i { case 0: return &v.state @@ -615,7 +1055,7 @@ func file_sentryflow_proto_init() { return nil } } - file_sentryflow_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_sentryflow_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*APILog); i { case 0: return &v.state @@ -627,7 +1067,67 @@ func file_sentryflow_proto_init() { return nil } } - file_sentryflow_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_sentryflow_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*APILogV2); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sentryflow_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*Source); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sentryflow_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*Destination); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sentryflow_proto_msgTypes[5].Exporter = func(v any, i int) any { + switch v := v.(*Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sentryflow_proto_msgTypes[6].Exporter = func(v any, i int) any { + switch v := v.(*Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sentryflow_proto_msgTypes[7].Exporter = func(v any, i int) any { switch v := v.(*APIMetrics); i { case 0: return &v.state @@ -639,7 +1139,7 @@ func file_sentryflow_proto_init() { return nil } } - file_sentryflow_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_sentryflow_proto_msgTypes[8].Exporter = func(v any, i int) any { switch v := v.(*MetricValue); i { case 0: return &v.state @@ -651,7 +1151,7 @@ func file_sentryflow_proto_init() { return nil } } - file_sentryflow_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_sentryflow_proto_msgTypes[9].Exporter = func(v any, i int) any { switch v := v.(*EnvoyMetrics); i { case 0: return &v.state @@ -670,7 +1170,7 @@ func file_sentryflow_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_sentryflow_proto_rawDesc, NumEnums: 0, - NumMessages: 11, + NumMessages: 18, NumExtensions: 0, NumServices: 1, }, diff --git a/protobuf/sentryflow.proto b/protobuf/sentryflow.proto index eaed177..7bb7d1d 100644 --- a/protobuf/sentryflow.proto +++ b/protobuf/sentryflow.proto @@ -4,6 +4,9 @@ package protobuf; option go_package = "SentryFlow/protobuf"; +import "google/protobuf/timestamp.proto"; + + message ClientInfo { string hostName = 1; string IPAddress = 2; @@ -35,6 +38,42 @@ message APILog { int32 responseCode = 54; } +message APILogV2 { + int32 context_id = 1; + google.protobuf.Timestamp timestamp = 2; + Source source = 3; + Destination destination = 4; + Request request = 5; + Response response = 6; + string Protocol = 7; +} + +message Source { + string name = 1; + string namespace = 2; + string ip = 3; + int32 port = 4; + string type = 5; +} + +message Destination { + string name = 1; + string namespace = 2; + string ip = 3; + int32 port = 4; + string type = 5; +} + +message Request { + map headers = 1; + string body = 2; +} + +message Response { + map headers = 1; + string body = 2; +} + message APIMetrics { map perAPICounts = 1; // @todo: add some more metrics here @@ -56,7 +95,8 @@ message EnvoyMetrics { } service SentryFlow { - rpc GetAPILog(ClientInfo) returns (stream APILog); + rpc GetAPILog(ClientInfo) returns (stream APILog); // To be deprecated + rpc GetAPILogV2(ClientInfo) returns (stream APILogV2); rpc GetAPIMetrics(ClientInfo) returns (stream APIMetrics); rpc GetEnvoyMetrics(ClientInfo) returns (stream EnvoyMetrics); } diff --git a/protobuf/sentryflow_grpc.pb.go b/protobuf/sentryflow_grpc.pb.go index 11f431c..70e55bc 100644 --- a/protobuf/sentryflow_grpc.pb.go +++ b/protobuf/sentryflow_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v5.26.0 +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.27.3 // source: sentryflow.proto package protobuf @@ -15,11 +15,12 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( SentryFlow_GetAPILog_FullMethodName = "/protobuf.SentryFlow/GetAPILog" + SentryFlow_GetAPILogV2_FullMethodName = "/protobuf.SentryFlow/GetAPILogV2" SentryFlow_GetAPIMetrics_FullMethodName = "/protobuf.SentryFlow/GetAPIMetrics" SentryFlow_GetEnvoyMetrics_FullMethodName = "/protobuf.SentryFlow/GetEnvoyMetrics" ) @@ -28,9 +29,10 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type SentryFlowClient interface { - GetAPILog(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (SentryFlow_GetAPILogClient, error) - GetAPIMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (SentryFlow_GetAPIMetricsClient, error) - GetEnvoyMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (SentryFlow_GetEnvoyMetricsClient, error) + GetAPILog(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APILog], error) + GetAPILogV2(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APILogV2], error) + GetAPIMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APIMetrics], error) + GetEnvoyMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[EnvoyMetrics], error) } type sentryFlowClient struct { @@ -41,12 +43,13 @@ func NewSentryFlowClient(cc grpc.ClientConnInterface) SentryFlowClient { return &sentryFlowClient{cc} } -func (c *sentryFlowClient) GetAPILog(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (SentryFlow_GetAPILogClient, error) { - stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[0], SentryFlow_GetAPILog_FullMethodName, opts...) +func (c *sentryFlowClient) GetAPILog(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APILog], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[0], SentryFlow_GetAPILog_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &sentryFlowGetAPILogClient{stream} + x := &grpc.GenericClientStream[ClientInfo, APILog]{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -56,29 +59,16 @@ func (c *sentryFlowClient) GetAPILog(ctx context.Context, in *ClientInfo, opts . return x, nil } -type SentryFlow_GetAPILogClient interface { - Recv() (*APILog, error) - grpc.ClientStream -} - -type sentryFlowGetAPILogClient struct { - grpc.ClientStream -} - -func (x *sentryFlowGetAPILogClient) Recv() (*APILog, error) { - m := new(APILog) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type SentryFlow_GetAPILogClient = grpc.ServerStreamingClient[APILog] -func (c *sentryFlowClient) GetAPIMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (SentryFlow_GetAPIMetricsClient, error) { - stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[1], SentryFlow_GetAPIMetrics_FullMethodName, opts...) +func (c *sentryFlowClient) GetAPILogV2(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APILogV2], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[1], SentryFlow_GetAPILogV2_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &sentryFlowGetAPIMetricsClient{stream} + x := &grpc.GenericClientStream[ClientInfo, APILogV2]{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -88,29 +78,16 @@ func (c *sentryFlowClient) GetAPIMetrics(ctx context.Context, in *ClientInfo, op return x, nil } -type SentryFlow_GetAPIMetricsClient interface { - Recv() (*APIMetrics, error) - grpc.ClientStream -} - -type sentryFlowGetAPIMetricsClient struct { - grpc.ClientStream -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type SentryFlow_GetAPILogV2Client = grpc.ServerStreamingClient[APILogV2] -func (x *sentryFlowGetAPIMetricsClient) Recv() (*APIMetrics, error) { - m := new(APIMetrics) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *sentryFlowClient) GetEnvoyMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (SentryFlow_GetEnvoyMetricsClient, error) { - stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[2], SentryFlow_GetEnvoyMetrics_FullMethodName, opts...) +func (c *sentryFlowClient) GetAPIMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APIMetrics], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[2], SentryFlow_GetAPIMetrics_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &sentryFlowGetEnvoyMetricsClient{stream} + x := &grpc.GenericClientStream[ClientInfo, APIMetrics]{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -120,45 +97,58 @@ func (c *sentryFlowClient) GetEnvoyMetrics(ctx context.Context, in *ClientInfo, return x, nil } -type SentryFlow_GetEnvoyMetricsClient interface { - Recv() (*EnvoyMetrics, error) - grpc.ClientStream -} - -type sentryFlowGetEnvoyMetricsClient struct { - grpc.ClientStream -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type SentryFlow_GetAPIMetricsClient = grpc.ServerStreamingClient[APIMetrics] -func (x *sentryFlowGetEnvoyMetricsClient) Recv() (*EnvoyMetrics, error) { - m := new(EnvoyMetrics) - if err := x.ClientStream.RecvMsg(m); err != nil { +func (c *sentryFlowClient) GetEnvoyMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[EnvoyMetrics], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[3], SentryFlow_GetEnvoyMetrics_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[ClientInfo, EnvoyMetrics]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { return nil, err } - return m, nil + return x, nil } +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type SentryFlow_GetEnvoyMetricsClient = grpc.ServerStreamingClient[EnvoyMetrics] + // SentryFlowServer is the server API for SentryFlow service. // All implementations should embed UnimplementedSentryFlowServer -// for forward compatibility +// for forward compatibility. type SentryFlowServer interface { - GetAPILog(*ClientInfo, SentryFlow_GetAPILogServer) error - GetAPIMetrics(*ClientInfo, SentryFlow_GetAPIMetricsServer) error - GetEnvoyMetrics(*ClientInfo, SentryFlow_GetEnvoyMetricsServer) error + GetAPILog(*ClientInfo, grpc.ServerStreamingServer[APILog]) error + GetAPILogV2(*ClientInfo, grpc.ServerStreamingServer[APILogV2]) error + GetAPIMetrics(*ClientInfo, grpc.ServerStreamingServer[APIMetrics]) error + GetEnvoyMetrics(*ClientInfo, grpc.ServerStreamingServer[EnvoyMetrics]) error } -// UnimplementedSentryFlowServer should be embedded to have forward compatible implementations. -type UnimplementedSentryFlowServer struct { -} +// UnimplementedSentryFlowServer should be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedSentryFlowServer struct{} -func (UnimplementedSentryFlowServer) GetAPILog(*ClientInfo, SentryFlow_GetAPILogServer) error { +func (UnimplementedSentryFlowServer) GetAPILog(*ClientInfo, grpc.ServerStreamingServer[APILog]) error { return status.Errorf(codes.Unimplemented, "method GetAPILog not implemented") } -func (UnimplementedSentryFlowServer) GetAPIMetrics(*ClientInfo, SentryFlow_GetAPIMetricsServer) error { +func (UnimplementedSentryFlowServer) GetAPILogV2(*ClientInfo, grpc.ServerStreamingServer[APILogV2]) error { + return status.Errorf(codes.Unimplemented, "method GetAPILogV2 not implemented") +} +func (UnimplementedSentryFlowServer) GetAPIMetrics(*ClientInfo, grpc.ServerStreamingServer[APIMetrics]) error { return status.Errorf(codes.Unimplemented, "method GetAPIMetrics not implemented") } -func (UnimplementedSentryFlowServer) GetEnvoyMetrics(*ClientInfo, SentryFlow_GetEnvoyMetricsServer) error { +func (UnimplementedSentryFlowServer) GetEnvoyMetrics(*ClientInfo, grpc.ServerStreamingServer[EnvoyMetrics]) error { return status.Errorf(codes.Unimplemented, "method GetEnvoyMetrics not implemented") } +func (UnimplementedSentryFlowServer) testEmbeddedByValue() {} // UnsafeSentryFlowServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to SentryFlowServer will @@ -168,6 +158,13 @@ type UnsafeSentryFlowServer interface { } func RegisterSentryFlowServer(s grpc.ServiceRegistrar, srv SentryFlowServer) { + // If the following call pancis, it indicates UnimplementedSentryFlowServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&SentryFlow_ServiceDesc, srv) } @@ -176,63 +173,44 @@ func _SentryFlow_GetAPILog_Handler(srv interface{}, stream grpc.ServerStream) er if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SentryFlowServer).GetAPILog(m, &sentryFlowGetAPILogServer{stream}) + return srv.(SentryFlowServer).GetAPILog(m, &grpc.GenericServerStream[ClientInfo, APILog]{ServerStream: stream}) } -type SentryFlow_GetAPILogServer interface { - Send(*APILog) error - grpc.ServerStream -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type SentryFlow_GetAPILogServer = grpc.ServerStreamingServer[APILog] -type sentryFlowGetAPILogServer struct { - grpc.ServerStream +func _SentryFlow_GetAPILogV2_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ClientInfo) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(SentryFlowServer).GetAPILogV2(m, &grpc.GenericServerStream[ClientInfo, APILogV2]{ServerStream: stream}) } -func (x *sentryFlowGetAPILogServer) Send(m *APILog) error { - return x.ServerStream.SendMsg(m) -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type SentryFlow_GetAPILogV2Server = grpc.ServerStreamingServer[APILogV2] func _SentryFlow_GetAPIMetrics_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(ClientInfo) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SentryFlowServer).GetAPIMetrics(m, &sentryFlowGetAPIMetricsServer{stream}) -} - -type SentryFlow_GetAPIMetricsServer interface { - Send(*APIMetrics) error - grpc.ServerStream -} - -type sentryFlowGetAPIMetricsServer struct { - grpc.ServerStream + return srv.(SentryFlowServer).GetAPIMetrics(m, &grpc.GenericServerStream[ClientInfo, APIMetrics]{ServerStream: stream}) } -func (x *sentryFlowGetAPIMetricsServer) Send(m *APIMetrics) error { - return x.ServerStream.SendMsg(m) -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type SentryFlow_GetAPIMetricsServer = grpc.ServerStreamingServer[APIMetrics] func _SentryFlow_GetEnvoyMetrics_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(ClientInfo) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SentryFlowServer).GetEnvoyMetrics(m, &sentryFlowGetEnvoyMetricsServer{stream}) -} - -type SentryFlow_GetEnvoyMetricsServer interface { - Send(*EnvoyMetrics) error - grpc.ServerStream + return srv.(SentryFlowServer).GetEnvoyMetrics(m, &grpc.GenericServerStream[ClientInfo, EnvoyMetrics]{ServerStream: stream}) } -type sentryFlowGetEnvoyMetricsServer struct { - grpc.ServerStream -} - -func (x *sentryFlowGetEnvoyMetricsServer) Send(m *EnvoyMetrics) error { - return x.ServerStream.SendMsg(m) -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type SentryFlow_GetEnvoyMetricsServer = grpc.ServerStreamingServer[EnvoyMetrics] // SentryFlow_ServiceDesc is the grpc.ServiceDesc for SentryFlow service. // It's only intended for direct use with grpc.RegisterService, @@ -247,6 +225,11 @@ var SentryFlow_ServiceDesc = grpc.ServiceDesc{ Handler: _SentryFlow_GetAPILog_Handler, ServerStreams: true, }, + { + StreamName: "GetAPILogV2", + Handler: _SentryFlow_GetAPILogV2_Handler, + ServerStreams: true, + }, { StreamName: "GetAPIMetrics", Handler: _SentryFlow_GetAPIMetrics_Handler, diff --git a/protobuf/sentryflow_metrics.pb.go b/protobuf/sentryflow_metrics.pb.go index 1ed7b04..279cece 100644 --- a/protobuf/sentryflow_metrics.pb.go +++ b/protobuf/sentryflow_metrics.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 -// protoc v5.26.0 +// protoc-gen-go v1.34.2 +// protoc v5.27.3 // source: sentryflow_metrics.proto package protobuf @@ -155,7 +155,7 @@ func file_sentryflow_metrics_proto_rawDescGZIP() []byte { } var file_sentryflow_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_sentryflow_metrics_proto_goTypes = []interface{}{ +var file_sentryflow_metrics_proto_goTypes = []any{ (*APIClassifierRequest)(nil), // 0: protobuf.APIClassifierRequest (*APIClassifierResponse)(nil), // 1: protobuf.APIClassifierResponse nil, // 2: protobuf.APIClassifierResponse.APIsEntry @@ -177,7 +177,7 @@ func file_sentryflow_metrics_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_sentryflow_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_sentryflow_metrics_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*APIClassifierRequest); i { case 0: return &v.state @@ -189,7 +189,7 @@ func file_sentryflow_metrics_proto_init() { return nil } } - file_sentryflow_metrics_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_sentryflow_metrics_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*APIClassifierResponse); i { case 0: return &v.state diff --git a/protobuf/sentryflow_metrics_grpc.pb.go b/protobuf/sentryflow_metrics_grpc.pb.go index 0f3c100..696a0f0 100644 --- a/protobuf/sentryflow_metrics_grpc.pb.go +++ b/protobuf/sentryflow_metrics_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v5.26.0 +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.27.3 // source: sentryflow_metrics.proto package protobuf @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( APIClassifier_ClassifyAPIs_FullMethodName = "/protobuf.APIClassifier/ClassifyAPIs" @@ -26,7 +26,7 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type APIClassifierClient interface { - ClassifyAPIs(ctx context.Context, opts ...grpc.CallOption) (APIClassifier_ClassifyAPIsClient, error) + ClassifyAPIs(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[APIClassifierRequest, APIClassifierResponse], error) } type aPIClassifierClient struct { @@ -37,51 +37,37 @@ func NewAPIClassifierClient(cc grpc.ClientConnInterface) APIClassifierClient { return &aPIClassifierClient{cc} } -func (c *aPIClassifierClient) ClassifyAPIs(ctx context.Context, opts ...grpc.CallOption) (APIClassifier_ClassifyAPIsClient, error) { - stream, err := c.cc.NewStream(ctx, &APIClassifier_ServiceDesc.Streams[0], APIClassifier_ClassifyAPIs_FullMethodName, opts...) +func (c *aPIClassifierClient) ClassifyAPIs(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[APIClassifierRequest, APIClassifierResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &APIClassifier_ServiceDesc.Streams[0], APIClassifier_ClassifyAPIs_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &aPIClassifierClassifyAPIsClient{stream} + x := &grpc.GenericClientStream[APIClassifierRequest, APIClassifierResponse]{ClientStream: stream} return x, nil } -type APIClassifier_ClassifyAPIsClient interface { - Send(*APIClassifierRequest) error - Recv() (*APIClassifierResponse, error) - grpc.ClientStream -} - -type aPIClassifierClassifyAPIsClient struct { - grpc.ClientStream -} - -func (x *aPIClassifierClassifyAPIsClient) Send(m *APIClassifierRequest) error { - return x.ClientStream.SendMsg(m) -} - -func (x *aPIClassifierClassifyAPIsClient) Recv() (*APIClassifierResponse, error) { - m := new(APIClassifierResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type APIClassifier_ClassifyAPIsClient = grpc.BidiStreamingClient[APIClassifierRequest, APIClassifierResponse] // APIClassifierServer is the server API for APIClassifier service. // All implementations should embed UnimplementedAPIClassifierServer -// for forward compatibility +// for forward compatibility. type APIClassifierServer interface { - ClassifyAPIs(APIClassifier_ClassifyAPIsServer) error + ClassifyAPIs(grpc.BidiStreamingServer[APIClassifierRequest, APIClassifierResponse]) error } -// UnimplementedAPIClassifierServer should be embedded to have forward compatible implementations. -type UnimplementedAPIClassifierServer struct { -} +// UnimplementedAPIClassifierServer should be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAPIClassifierServer struct{} -func (UnimplementedAPIClassifierServer) ClassifyAPIs(APIClassifier_ClassifyAPIsServer) error { +func (UnimplementedAPIClassifierServer) ClassifyAPIs(grpc.BidiStreamingServer[APIClassifierRequest, APIClassifierResponse]) error { return status.Errorf(codes.Unimplemented, "method ClassifyAPIs not implemented") } +func (UnimplementedAPIClassifierServer) testEmbeddedByValue() {} // UnsafeAPIClassifierServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to APIClassifierServer will @@ -91,34 +77,22 @@ type UnsafeAPIClassifierServer interface { } func RegisterAPIClassifierServer(s grpc.ServiceRegistrar, srv APIClassifierServer) { + // If the following call pancis, it indicates UnimplementedAPIClassifierServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&APIClassifier_ServiceDesc, srv) } func _APIClassifier_ClassifyAPIs_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(APIClassifierServer).ClassifyAPIs(&aPIClassifierClassifyAPIsServer{stream}) -} - -type APIClassifier_ClassifyAPIsServer interface { - Send(*APIClassifierResponse) error - Recv() (*APIClassifierRequest, error) - grpc.ServerStream -} - -type aPIClassifierClassifyAPIsServer struct { - grpc.ServerStream + return srv.(APIClassifierServer).ClassifyAPIs(&grpc.GenericServerStream[APIClassifierRequest, APIClassifierResponse]{ServerStream: stream}) } -func (x *aPIClassifierClassifyAPIsServer) Send(m *APIClassifierResponse) error { - return x.ServerStream.SendMsg(m) -} - -func (x *aPIClassifierClassifyAPIsServer) Recv() (*APIClassifierRequest, error) { - m := new(APIClassifierRequest) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type APIClassifier_ClassifyAPIsServer = grpc.BidiStreamingServer[APIClassifierRequest, APIClassifierResponse] // APIClassifier_ServiceDesc is the grpc.ServiceDesc for APIClassifier service. // It's only intended for direct use with grpc.RegisterService, diff --git a/sentryflow/collector/collectorHandler.go b/sentryflow/collector/collectorHandler.go index 0c7a8b1..043c569 100644 --- a/sentryflow/collector/collectorHandler.go +++ b/sentryflow/collector/collectorHandler.go @@ -4,11 +4,11 @@ package collector import ( "fmt" - "log" - "net" - "github.com/5gsec/SentryFlow/config" "google.golang.org/grpc" + "log" + "net" + "net/http" ) // == // @@ -76,6 +76,19 @@ func StartCollector() bool { log.Print("[Collector] Serving Collector gRPC services") + // Start the http server + address := fmt.Sprintf("%s:%s", config.GlobalConfig.ApiLogCollectorAddr, config.GlobalConfig.ApiLogCollectorPort) + log.Print("[Collector] Serving Collector http service on ", address) + go func() { + // Create a new HTTP server + http.HandleFunc("/api/v1/events", DataHandler) + err = http.ListenAndServe(address, nil) + if err != nil { + log.Println("[Collector] Error serving Collector http service on ", err.Error()) + panic(err) + } + }() + return true } diff --git a/sentryflow/collector/wasm.go b/sentryflow/collector/wasm.go new file mode 100644 index 0000000..cd1379c --- /dev/null +++ b/sentryflow/collector/wasm.go @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 + +package collector + +import ( + "encoding/json" + "github.com/5gsec/SentryFlow/processor" + "github.com/5gsec/SentryFlow/protobuf" + "io/ioutil" + "log" + "net/http" +) + +// Handler for the HTTP endpoint to receive api events from WASM filter +func DataHandler(w http.ResponseWriter, r *http.Request) { + // Check if the request is POST + if r.Method != http.MethodPost { + http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed) + return + } + + // Read the request body + body, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, "Failed to read request body", http.StatusInternalServerError) + return + } + // Parse the JSON data into the TelemetryData struct + var apiLog *protobuf.APILogV2 + err = json.Unmarshal(body, &apiLog) + if err != nil { + log.Print("failed to parse json") + log.Print(err.Error()) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + // Check protocol version + if r.ProtoMajor == 2 { + apiLog.Protocol = "HTTP/2.0" + } else if r.ProtoMajor == 1 && r.ProtoMinor == 1 { + apiLog.Protocol = "HTTP/1.1" + } else if r.ProtoMajor == 1 && r.ProtoMinor == 0 { + apiLog.Protocol = "HTTP/1.0" + } else { + apiLog.Protocol = "Unknown" + } + processor.InsertAPILog(apiLog) + + // Log the received telemetry data + log.Printf("Received data: %+v\n", apiLog) +} diff --git a/sentryflow/config/config.go b/sentryflow/config/config.go index 03fa377..15e2c7e 100644 --- a/sentryflow/config/config.go +++ b/sentryflow/config/config.go @@ -13,8 +13,10 @@ import ( // SentryFlowConfig structure type SentryFlowConfig struct { - CollectorAddr string // Address for Collector gRPC - CollectorPort string // Port for Collector gRPC + CollectorAddr string // Address for Collector gRPC + CollectorPort string // Port for Collector gRPC + ApiLogCollectorAddr string // Address for API Log HTTP Collector + ApiLogCollectorPort string // Port for API Log HTTP Collector ExporterAddr string // IP address to use for exporter gRPC ExporterPort string // Port to use for exporter gRPC @@ -42,8 +44,10 @@ func init() { // Config const const ( - CollectorAddr string = "collectorAddr" - CollectorPort string = "collectorPort" + CollectorAddr string = "collectorAddr" + CollectorPort string = "collectorPort" + ApiLogCollectorAddr string = "apiLogCollectorAddr" + ApiLogCollectorPort string = "apiLogCollectorPort" ExporterAddr string = "exporterAddr" ExporterPort string = "exporterPort" @@ -64,6 +68,8 @@ const ( func readCmdLineParams() { collectorAddrStr := flag.String(CollectorAddr, "0.0.0.0", "Address for Collector gRPC") collectorPortStr := flag.String(CollectorPort, "4317", "Port for Collector gRPC") + apiLogCollectorAddrStr := flag.String(ApiLogCollectorAddr, "0.0.0.0", "Address for API log HTTP Colletor") + apiLogCollectorPortStr := flag.String(ApiLogCollectorPort, "8081", "Port for API log HTTP Colletor") exporterAddrStr := flag.String(ExporterAddr, "0.0.0.0", "Address for Exporter gRPC") exporterPortStr := flag.String(ExporterPort, "8080", "Port for Exporter gRPC") @@ -91,6 +97,8 @@ func readCmdLineParams() { viper.SetDefault(CollectorAddr, *collectorAddrStr) viper.SetDefault(CollectorPort, *collectorPortStr) + viper.SetDefault(ApiLogCollectorAddr, *apiLogCollectorAddrStr) + viper.SetDefault(ApiLogCollectorPort, *apiLogCollectorPortStr) viper.SetDefault(ExporterAddr, *exporterAddrStr) viper.SetDefault(ExporterPort, *exporterPortStr) @@ -118,7 +126,8 @@ func LoadConfig() error { GlobalConfig.CollectorAddr = viper.GetString(CollectorAddr) GlobalConfig.CollectorPort = viper.GetString(CollectorPort) - + GlobalConfig.ApiLogCollectorAddr = viper.GetString(ApiLogCollectorAddr) + GlobalConfig.ApiLogCollectorPort = viper.GetString(ApiLogCollectorPort) GlobalConfig.ExporterAddr = viper.GetString(ExporterAddr) GlobalConfig.ExporterPort = viper.GetString(ExporterPort) diff --git a/sentryflow/core/sentryflow.go b/sentryflow/core/sentryflow.go index a6a4825..886a2ae 100644 --- a/sentryflow/core/sentryflow.go +++ b/sentryflow/core/sentryflow.go @@ -71,11 +71,11 @@ func (sf *SentryFlowService) DestroySentryFlow() { } // Stop API classifier - if processor.StopAPIClassifier() { - log.Print("[SentryFlow] Stopped API Classifier") - } else { - log.Print("[SentryFlow] Failed to stop API Classifier") - } + // if processor.StopAPIClassifier() { + // log.Print("[SentryFlow] Stopped API Classifier") + // } else { + // log.Print("[SentryFlow] Failed to stop API Classifier") + // } // Stop exporter if exporter.StopExporter() { @@ -169,10 +169,10 @@ func SentryFlow() { } // Start API classifier - if !processor.StartAPIClassifier(sf.waitGroup) { - sf.DestroySentryFlow() - return - } + // if !processor.StartAPIClassifier(sf.waitGroup) { + // sf.DestroySentryFlow() + // return + // } // Start exporter if !exporter.StartExporter(sf.waitGroup) { diff --git a/sentryflow/exporter/exportAPILogs.go b/sentryflow/exporter/exportAPILogs.go index 5fe6351..5fe1f27 100644 --- a/sentryflow/exporter/exportAPILogs.go +++ b/sentryflow/exporter/exportAPILogs.go @@ -20,8 +20,16 @@ type apiLogStreamInform struct { IPAddress string stream protobuf.SentryFlow_GetAPILogServer + error chan error +} + +// apiLogStreamInformV2 structure +type apiLogStreamInformV2 struct { + Hostname string + IPAddress string - error chan error + stream protobuf.SentryFlow_GetAPILogV2Server + error chan error } // GetAPILog Function (for gRPC) @@ -41,12 +49,31 @@ func (exs *ExpService) GetAPILog(info *protobuf.ClientInfo, stream protobuf.Sent return <-currExporter.error } +// GetAPILogV2 Function (for gRPC) +func (exs *ExpService) GetAPILogV2(info *protobuf.ClientInfo, stream protobuf.SentryFlow_GetAPILogV2Server) error { + log.Printf("[Exporter] Client %s (%s) connected (GetAPILogV2)", info.HostName, info.IPAddress) + + currExporter := &apiLogStreamInformV2{ + Hostname: info.HostName, + IPAddress: info.IPAddress, + stream: stream, + } + + ExpH.exporterLock.Lock() + ExpH.apiLogExportersV2 = append(ExpH.apiLogExportersV2, currExporter) + ExpH.exporterLock.Unlock() + + return <-currExporter.error +} + // SendAPILogs Function func (exp *ExpHandler) SendAPILogs(apiLog *protobuf.APILog) error { failed := 0 total := len(exp.apiLogExporters) for _, exporter := range exp.apiLogExporters { + log.Print("Sending api log!!!!") + log.Printf("Sending api log right here!!!!! %+v\n", apiLog) if err := exporter.stream.Send(apiLog); err != nil { log.Printf("[Exporter] Failed to export an API log to %s (%s): %v", exporter.Hostname, exporter.IPAddress, err) failed++ @@ -61,21 +88,45 @@ func (exp *ExpHandler) SendAPILogs(apiLog *protobuf.APILog) error { return nil } +// SendAPILogsV2 Function +func (exp *ExpHandler) SendAPILogsV2(apiLog *protobuf.APILogV2) error { + failed := 0 + total := len(exp.apiLogExportersV2) + + for _, exporter := range exp.apiLogExportersV2 { + if err := exporter.stream.Send(apiLog); err != nil { + log.Printf("[Exporter] Failed to export an API log(V2) to %s (%s): %v", exporter.Hostname, exporter.IPAddress, err) + failed++ + } + } + + if failed != 0 { + msg := fmt.Sprintf("[Exporter] Failed to export API logs(V2) properly (%d/%d failed)", failed, total) + return errors.New(msg) + } + + return nil +} + // == // // InsertAPILog Function -func InsertAPILog(apiLog *protobuf.APILog) { - ExpH.exporterAPILogs <- apiLog +func InsertAPILog(apiLog interface{}) { + switch data := apiLog.(type) { + case *protobuf.APILog: + ExpH.exporterAPILogs <- data + // Make a string with labels + var labelString []string + for k, v := range data.SrcLabel { + labelString = append(labelString, fmt.Sprintf("%s:%s", k, v)) + } + sort.Strings(labelString) - // Make a string with labels - var labelString []string - for k, v := range apiLog.SrcLabel { - labelString = append(labelString, fmt.Sprintf("%s:%s", k, v)) + // Update Stats per namespace and per labels + UpdateStats(data.SrcNamespace, strings.Join(labelString, ","), data.GetPath()) + case *protobuf.APILogV2: + ExpH.exporterAPILogsV2 <- data } - sort.Strings(labelString) - - // Update Stats per namespace and per labels - UpdateStats(apiLog.SrcNamespace, strings.Join(labelString, ","), apiLog.GetPath()) } // == // diff --git a/sentryflow/exporter/exporterHandler.go b/sentryflow/exporter/exporterHandler.go index 6504984..05baed9 100644 --- a/sentryflow/exporter/exporterHandler.go +++ b/sentryflow/exporter/exporterHandler.go @@ -32,12 +32,14 @@ type ExpHandler struct { grpcService *ExpService apiLogExporters []*apiLogStreamInform + apiLogExportersV2 []*apiLogStreamInformV2 apiMetricsExporters []*apiMetricStreamInform envoyMetricsExporters []*envoyMetricsStreamInform exporterLock sync.Mutex exporterAPILogs chan *protobuf.APILog + exporterAPILogsV2 chan *protobuf.APILogV2 exporterAPIMetrics chan *protobuf.APIMetrics exporterMetrics chan *protobuf.EnvoyMetrics @@ -60,12 +62,14 @@ func NewExporterHandler() *ExpHandler { grpcService: new(ExpService), apiLogExporters: make([]*apiLogStreamInform, 0), + apiLogExportersV2: make([]*apiLogStreamInformV2, 0), apiMetricsExporters: make([]*apiMetricStreamInform, 0), envoyMetricsExporters: make([]*envoyMetricsStreamInform, 0), exporterLock: sync.Mutex{}, exporterAPILogs: make(chan *protobuf.APILog), + exporterAPILogsV2: make(chan *protobuf.APILogV2), exporterAPIMetrics: make(chan *protobuf.APIMetrics), exporterMetrics: make(chan *protobuf.EnvoyMetrics), @@ -111,6 +115,9 @@ func StartExporter(wg *sync.WaitGroup) bool { // Export APILogs go ExpH.exportAPILogs(wg) + // Export APILogsV2 + go ExpH.exportAPILogsV2(wg) + log.Printf("[Exporter] Exporting API logs through gRPC services") // Export APIMetrics @@ -135,6 +142,9 @@ func StopExporter() bool { // One for exportAPILogs ExpH.stopChan <- struct{}{} + // One for exportAPILogsV2 + ExpH.stopChan <- struct{}{} + // One for exportAPIMetrics ExpH.stopChan <- struct{}{} @@ -175,6 +185,30 @@ func (exp *ExpHandler) exportAPILogs(wg *sync.WaitGroup) { } } +// exportAPILogs Function +func (exp *ExpHandler) exportAPILogsV2(wg *sync.WaitGroup) { + wg.Add(1) + + for { + select { + case apiLog, ok := <-exp.exporterAPILogsV2: + if !ok { + log.Printf("[Exporter] Failed to fetch APILogs(V2) from APIs channel") + wg.Done() + return + } + + if err := exp.SendAPILogsV2(apiLog); err != nil { + log.Printf("[Exporter] Failed to export API Logs(V2): %v", err) + } + + case <-exp.stopChan: + wg.Done() + return + } + } +} + // exportAPIMetrics Function func (exp *ExpHandler) exportAPIMetrics(wg *sync.WaitGroup) { wg.Add(1) diff --git a/sentryflow/go.mod b/sentryflow/go.mod index 4a422de..3936109 100644 --- a/sentryflow/go.mod +++ b/sentryflow/go.mod @@ -6,10 +6,10 @@ replace github.com/5gsec/SentryFlow/protobuf => ../protobuf require ( github.com/5gsec/SentryFlow/protobuf v0.0.0-00010101000000-000000000000 - github.com/envoyproxy/go-control-plane v0.12.0 + github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 github.com/spf13/viper v1.18.2 go.opentelemetry.io/proto/otlp v1.0.0 - google.golang.org/grpc v1.63.2 + google.golang.org/grpc v1.66.0 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.29.0 k8s.io/apimachinery v0.29.0 @@ -17,7 +17,7 @@ require ( ) require ( - github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect + github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect @@ -43,7 +43,8 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/prometheus/client_model v0.6.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -54,17 +55,15 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/oauth2 v0.17.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.17.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/protobuf v1.34.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/sentryflow/go.sum b/sentryflow/go.sum index 0927d6d..c04d903 100644 --- a/sentryflow/go.sum +++ b/sentryflow/go.sum @@ -1,5 +1,5 @@ -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -7,8 +7,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= -github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -27,15 +27,12 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -82,11 +79,13 @@ github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -110,13 +109,13 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -126,72 +125,52 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= -golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/sentryflow/processor/logProcessor.go b/sentryflow/processor/logProcessor.go index f29aba7..f097b80 100644 --- a/sentryflow/processor/logProcessor.go +++ b/sentryflow/processor/logProcessor.go @@ -76,13 +76,20 @@ func ProcessAPILogs(wg *sync.WaitGroup) { for { select { - case logType, ok := <-LogH.apiLogChan: + case data, ok := <-LogH.apiLogChan: if !ok { log.Print("[LogProcessor] Failed to process an API log") } - - go AnalyzeAPI(logType.(*protobuf.APILog).Path) - go exporter.InsertAPILog(logType.(*protobuf.APILog)) + switch logType := data.(type) { + case *protobuf.APILog: + go AnalyzeAPI(logType.Path) + go exporter.InsertAPILog(logType) + case *protobuf.APILogV2: + go exporter.InsertAPILog(logType) + default: + log.Print("Unsupported API log Version") + continue + } case <-LogH.stopChan: wg.Done() From 5ff8548143787adfe2ed97406afc0b5d2d543fcf Mon Sep 17 00:00:00 2001 From: Anurag Rajawat Date: Tue, 17 Sep 2024 18:21:52 +0530 Subject: [PATCH 2/6] fix(proto): Update proto messages and Makefile Signed-off-by: Anurag Rajawat --- protobuf/Makefile | 44 +- protobuf/{ => golang}/go.mod | 4 +- protobuf/{ => golang}/go.sum | 4 +- protobuf/{ => golang}/sentryflow.pb.go | 534 +++++++++--------- protobuf/{ => golang}/sentryflow_grpc.pb.go | 82 ++- .../{ => golang}/sentryflow_metrics.pb.go | 9 +- .../sentryflow_metrics_grpc.pb.go | 10 +- .../{ => python}/sentryflow_metrics_pb2.py | 16 +- .../{ => python}/sentryflow_metrics_pb2.pyi | 0 protobuf/python/sentryflow_pb2.py | 93 +++ protobuf/python/sentryflow_pb2.pyi | 196 +++++++ protobuf/sentryflow.proto | 64 ++- protobuf/sentryflow_metrics.proto | 2 +- protobuf/sentryflow_metrics_pb2_grpc.py | 101 ---- 14 files changed, 714 insertions(+), 445 deletions(-) rename protobuf/{ => golang}/go.mod (88%) rename protobuf/{ => golang}/go.sum (88%) rename protobuf/{ => golang}/sentryflow.pb.go (56%) rename protobuf/{ => golang}/sentryflow_grpc.pb.go (75%) rename protobuf/{ => golang}/sentryflow_metrics.pb.go (95%) rename protobuf/{ => golang}/sentryflow_metrics_grpc.pb.go (92%) rename protobuf/{ => python}/sentryflow_metrics_pb2.py (81%) rename protobuf/{ => python}/sentryflow_metrics_pb2.pyi (100%) create mode 100644 protobuf/python/sentryflow_pb2.py create mode 100644 protobuf/python/sentryflow_pb2.pyi delete mode 100644 protobuf/sentryflow_metrics_pb2_grpc.py diff --git a/protobuf/Makefile b/protobuf/Makefile index fb48b51..9297546 100644 --- a/protobuf/Makefile +++ b/protobuf/Makefile @@ -1,25 +1,29 @@ -PROTO:=sentryflow.proto sentryflow_metrics.proto -PB_GO:=$(PROTO:.proto=.pb.go) +PROTOS:="sentryflow.proto sentryflow_metrics.proto" -.PHONY: build -build: $(PB_GO) go.sum +.PHONY: help +help: ## Display this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) -%.pb.go: %.proto -ifeq (, $(shell which protoc)) - sudo cp bin/protoc /usr/local/bin/protoc -endif -ifeq (, $(shell which protoc-gen-go)) - go install google.golang.org/protobuf/cmd/protoc-gen-go@latest -endif -ifeq (, $(shell which protoc-gen-go-grpc)) - go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest -endif - go mod tidy - protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative,require_unimplemented_servers=false $< +.DEFAULT_GOAL := help -go.sum: go.mod - go get . +.PHONY: all +all: golang python ## Generate code for Go and Python + +.PHONY: golang +golang: go-plugins ## Generate code for Go + @protoc --go_out=golang --go_opt=paths=source_relative --go-grpc_out=golang --go-grpc_opt=paths=source_relative "${PROTOS}" + @cd golang; go mod tidy + +.PHONY: python +python: ## Generate code for Python + @protoc -I=. --python_out=pyi_out:python "${PROTOS}" .PHONY: clean -clean: - rm -f go.sum *.pb.go +clean: ## Remove the generated code + @cd golang; rm -f *.pb.go; go mod tidy + @cd python; rm -f *.py* + +.PHONY: +go-plugins: ## Download Go plugins locally if necessary. + @test -s protoc-gen-go || go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + @test -s protoc-gen-go-grpc || go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest diff --git a/protobuf/go.mod b/protobuf/golang/go.mod similarity index 88% rename from protobuf/go.mod rename to protobuf/golang/go.mod index d99f98a..182e953 100644 --- a/protobuf/go.mod +++ b/protobuf/golang/go.mod @@ -1,9 +1,9 @@ module github.com/5GSEC/SentryFlow/protobuf -go 1.21 +go 1.22 require ( - google.golang.org/grpc v1.66.0 + google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.2 ) diff --git a/protobuf/go.sum b/protobuf/golang/go.sum similarity index 88% rename from protobuf/go.sum rename to protobuf/golang/go.sum index a7a0b60..fdf7709 100644 --- a/protobuf/go.sum +++ b/protobuf/golang/go.sum @@ -8,7 +8,7 @@ golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= -google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/protobuf/sentryflow.pb.go b/protobuf/golang/sentryflow.pb.go similarity index 56% rename from protobuf/sentryflow.pb.go rename to protobuf/golang/sentryflow.pb.go index 99015c5..6e41fab 100644 --- a/protobuf/sentryflow.pb.go +++ b/protobuf/golang/sentryflow.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.27.3 +// protoc v5.28.0 // source: sentryflow.proto package protobuf @@ -9,7 +9,6 @@ package protobuf import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -76,6 +75,7 @@ func (x *ClientInfo) GetIPAddress() string { return "" } +// Deprecated: Marked as deprecated in sentryflow.proto. type APILog struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -259,22 +259,23 @@ func (x *APILog) GetResponseCode() int32 { return 0 } -type APILogV2 struct { +// APIEvent represents an event related to an API call, including metadata, +// source and destination workloads, and network information. +type APIEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ContextId int32 `protobuf:"varint,1,opt,name=context_id,json=contextId,proto3" json:"context_id,omitempty"` - Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Source *Source `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` - Destination *Destination `protobuf:"bytes,4,opt,name=destination,proto3" json:"destination,omitempty"` - Request *Request `protobuf:"bytes,5,opt,name=request,proto3" json:"request,omitempty"` - Response *Response `protobuf:"bytes,6,opt,name=response,proto3" json:"response,omitempty"` - Protocol string `protobuf:"bytes,7,opt,name=Protocol,proto3" json:"Protocol,omitempty"` + Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + Source *Workload `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` + Destination *Workload `protobuf:"bytes,4,opt,name=destination,proto3" json:"destination,omitempty"` + Request *Request `protobuf:"bytes,5,opt,name=request,proto3" json:"request,omitempty"` + Response *Response `protobuf:"bytes,6,opt,name=response,proto3" json:"response,omitempty"` + Protocol string `protobuf:"bytes,7,opt,name=protocol,proto3" json:"protocol,omitempty"` } -func (x *APILogV2) Reset() { - *x = APILogV2{} +func (x *APIEvent) Reset() { + *x = APIEvent{} if protoimpl.UnsafeEnabled { mi := &file_sentryflow_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -282,13 +283,13 @@ func (x *APILogV2) Reset() { } } -func (x *APILogV2) String() string { +func (x *APIEvent) String() string { return protoimpl.X.MessageStringOf(x) } -func (*APILogV2) ProtoMessage() {} +func (*APIEvent) ProtoMessage() {} -func (x *APILogV2) ProtoReflect() protoreflect.Message { +func (x *APIEvent) ProtoReflect() protoreflect.Message { mi := &file_sentryflow_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -300,74 +301,69 @@ func (x *APILogV2) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use APILogV2.ProtoReflect.Descriptor instead. -func (*APILogV2) Descriptor() ([]byte, []int) { +// Deprecated: Use APIEvent.ProtoReflect.Descriptor instead. +func (*APIEvent) Descriptor() ([]byte, []int) { return file_sentryflow_proto_rawDescGZIP(), []int{2} } -func (x *APILogV2) GetContextId() int32 { +func (x *APIEvent) GetMetadata() *Metadata { if x != nil { - return x.ContextId - } - return 0 -} - -func (x *APILogV2) GetTimestamp() *timestamppb.Timestamp { - if x != nil { - return x.Timestamp + return x.Metadata } return nil } -func (x *APILogV2) GetSource() *Source { +func (x *APIEvent) GetSource() *Workload { if x != nil { return x.Source } return nil } -func (x *APILogV2) GetDestination() *Destination { +func (x *APIEvent) GetDestination() *Workload { if x != nil { return x.Destination } return nil } -func (x *APILogV2) GetRequest() *Request { +func (x *APIEvent) GetRequest() *Request { if x != nil { return x.Request } return nil } -func (x *APILogV2) GetResponse() *Response { +func (x *APIEvent) GetResponse() *Response { if x != nil { return x.Response } return nil } -func (x *APILogV2) GetProtocol() string { +func (x *APIEvent) GetProtocol() string { if x != nil { return x.Protocol } return "" } -type Source struct { +type Metadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"` - Port int32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"` - Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type,omitempty"` + ContextId uint32 `protobuf:"varint,1,opt,name=context_id,json=contextId,proto3" json:"context_id,omitempty"` + Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + IstioVersion string `protobuf:"bytes,3,opt,name=istio_version,json=istioVersion,proto3" json:"istio_version,omitempty"` + MeshId string `protobuf:"bytes,4,opt,name=mesh_id,json=meshId,proto3" json:"mesh_id,omitempty"` + // The name of the Kubernetes node where the workload is running. If the workload + // is not running in a Kubernetes environment, this field will be empty. + NodeName string `protobuf:"bytes,5,opt,name=node_name,json=nodeName,proto3" json:"node_name,omitempty"` } -func (x *Source) Reset() { - *x = Source{} +func (x *Metadata) Reset() { + *x = Metadata{} if protoimpl.UnsafeEnabled { mi := &file_sentryflow_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -375,13 +371,13 @@ func (x *Source) Reset() { } } -func (x *Source) String() string { +func (x *Metadata) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Source) ProtoMessage() {} +func (*Metadata) ProtoMessage() {} -func (x *Source) ProtoReflect() protoreflect.Message { +func (x *Metadata) ProtoReflect() protoreflect.Message { mi := &file_sentryflow_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -393,60 +389,67 @@ func (x *Source) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Source.ProtoReflect.Descriptor instead. -func (*Source) Descriptor() ([]byte, []int) { +// Deprecated: Use Metadata.ProtoReflect.Descriptor instead. +func (*Metadata) Descriptor() ([]byte, []int) { return file_sentryflow_proto_rawDescGZIP(), []int{3} } -func (x *Source) GetName() string { +func (x *Metadata) GetContextId() uint32 { if x != nil { - return x.Name + return x.ContextId } - return "" + return 0 } -func (x *Source) GetNamespace() string { +func (x *Metadata) GetTimestamp() uint64 { if x != nil { - return x.Namespace + return x.Timestamp } - return "" + return 0 } -func (x *Source) GetIp() string { +func (x *Metadata) GetIstioVersion() string { if x != nil { - return x.Ip + return x.IstioVersion } return "" } -func (x *Source) GetPort() int32 { +func (x *Metadata) GetMeshId() string { if x != nil { - return x.Port + return x.MeshId } - return 0 + return "" } -func (x *Source) GetType() string { +func (x *Metadata) GetNodeName() string { if x != nil { - return x.Type + return x.NodeName } return "" } -type Destination struct { +// Workload represents a generic entity that can be either a Kubernetes or +// non-Kubernetes resource. It serves as a source or destination for access +// within a system. +type Workload struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The name of the workload. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The namespace in which the workload is deployed. This field is only applicable + // for Kubernetes workloads. Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"` - Port int32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"` - Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type,omitempty"` + // The IP address of the workload. + Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"` + // The port number used by the workload. + Port int32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"` } -func (x *Destination) Reset() { - *x = Destination{} +func (x *Workload) Reset() { + *x = Workload{} if protoimpl.UnsafeEnabled { mi := &file_sentryflow_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -454,13 +457,13 @@ func (x *Destination) Reset() { } } -func (x *Destination) String() string { +func (x *Workload) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Destination) ProtoMessage() {} +func (*Workload) ProtoMessage() {} -func (x *Destination) ProtoReflect() protoreflect.Message { +func (x *Workload) ProtoReflect() protoreflect.Message { mi := &file_sentryflow_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -472,46 +475,40 @@ func (x *Destination) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Destination.ProtoReflect.Descriptor instead. -func (*Destination) Descriptor() ([]byte, []int) { +// Deprecated: Use Workload.ProtoReflect.Descriptor instead. +func (*Workload) Descriptor() ([]byte, []int) { return file_sentryflow_proto_rawDescGZIP(), []int{4} } -func (x *Destination) GetName() string { +func (x *Workload) GetName() string { if x != nil { return x.Name } return "" } -func (x *Destination) GetNamespace() string { +func (x *Workload) GetNamespace() string { if x != nil { return x.Namespace } return "" } -func (x *Destination) GetIp() string { +func (x *Workload) GetIp() string { if x != nil { return x.Ip } return "" } -func (x *Destination) GetPort() int32 { +func (x *Workload) GetPort() int32 { if x != nil { return x.Port } return 0 } -func (x *Destination) GetType() string { - if x != nil { - return x.Type - } - return "" -} - +// Request represents an incoming HTTP request. type Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -567,6 +564,7 @@ func (x *Request) GetBody() string { return "" } +// Response represents an outgoing HTTP response. type Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -807,160 +805,161 @@ var File_sentryflow_proto protoreflect.FileDescriptor var file_sentryflow_proto_rawDesc = []byte{ 0x0a, 0x10, 0x73, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 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, 0x46, 0x0a, - 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x68, - 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, - 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x50, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, 0x50, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xa4, 0x05, 0x0a, 0x06, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x22, - 0x0a, 0x0c, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x08, - 0x73, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, - 0x2e, 0x53, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, - 0x73, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x54, - 0x79, 0x70, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x72, 0x63, 0x49, 0x50, 0x18, 0x16, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x50, - 0x6f, 0x72, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x3a, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x21, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, - 0x49, 0x4c, 0x6f, 0x67, 0x2e, 0x44, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x08, 0x64, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, - 0x64, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x29, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, - 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x73, 0x74, 0x49, 0x50, 0x18, - 0x2a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x50, 0x12, 0x18, 0x0a, 0x07, - 0x64, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, - 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x18, 0x33, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x34, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x35, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, - 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x36, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, - 0x64, 0x65, 0x1a, 0x3b, 0x0a, 0x0d, 0x53, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, - 0x3b, 0x0a, 0x0d, 0x44, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0xbf, 0x02, 0x0a, - 0x08, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x56, 0x32, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 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, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x0b, - 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x72, - 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x46, 0x0a, 0x0a, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, + 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, + 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x50, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, 0x50, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x22, 0xa8, 0x05, 0x0a, 0x06, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x22, 0x0a, + 0x0c, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x73, + 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x2e, + 0x53, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, + 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x54, 0x79, + 0x70, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x72, 0x63, 0x49, 0x50, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, + 0x72, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, 0x72, + 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x3a, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x21, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, + 0x4c, 0x6f, 0x67, 0x2e, 0x44, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x08, 0x64, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x64, + 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x29, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x73, 0x74, 0x49, 0x50, 0x18, 0x2a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x64, + 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, + 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x18, 0x33, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x34, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x18, 0x35, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, + 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x36, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, + 0x65, 0x1a, 0x3b, 0x0a, 0x0d, 0x53, 0x72, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0x3b, + 0x0a, 0x0d, 0x44, 0x73, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0x3a, 0x02, 0x18, 0x01, 0x22, + 0x95, 0x02, 0x0a, 0x08, 0x41, 0x50, 0x49, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x08, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x06, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, + 0x64, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, + 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0xa2, 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x74, 0x69, 0x6f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x73, 0x74, 0x69, 0x6f, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x64, 0x12, + 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x60, 0x0a, 0x08, + 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, - 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x22, 0x77, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x07, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 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, 0x95, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, - 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0x3a, 0x0a, - 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x93, + 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, + 0x65, 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, 0x95, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x39, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 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, 0x99, 0x01, 0x0a, + 0x0a, 0x41, 0x50, 0x49, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x4a, 0x0a, 0x0c, 0x70, + 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x70, 0x65, 0x72, 0x41, 0x50, + 0x49, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x1a, 0x3f, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x41, 0x50, + 0x49, 0x43, 0x6f, 0x75, 0x6e, 0x74, 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, 0x04, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7f, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, + 0x38, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x75, 0x65, 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, 0x99, 0x01, 0x0a, 0x0a, 0x41, 0x50, - 0x49, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x4a, 0x0a, 0x0c, 0x70, 0x65, 0x72, 0x41, - 0x50, 0x49, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x70, 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x73, 0x1a, 0x3f, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x41, 0x50, 0x49, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 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, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7f, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x38, 0x0a, 0x0a, - 0x56, 0x61, 0x6c, 0x75, 0x65, 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, 0x85, 0x03, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x6f, 0x79, - 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x53, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x50, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, 0x50, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, - 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x12, 0x3d, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x15, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, - 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, - 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0x51, 0x0a, 0x0c, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 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, 0x2b, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0x80, - 0x02, 0x0a, 0x0a, 0x53, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x35, 0x0a, - 0x09, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4c, - 0x6f, 0x67, 0x30, 0x01, 0x12, 0x39, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4c, 0x6f, - 0x67, 0x56, 0x32, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x56, 0x32, 0x30, 0x01, 0x12, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x85, 0x03, 0x0a, 0x0c, 0x45, 0x6e, + 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x50, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, + 0x50, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, + 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x12, 0x3d, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, + 0x15, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 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, 0x51, + 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 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, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x32, 0xbd, 0x02, 0x0a, 0x0a, 0x53, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x6c, 0x6f, 0x77, + 0x12, 0x3a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x12, 0x14, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, + 0x50, 0x49, 0x4c, 0x6f, 0x67, 0x22, 0x03, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x39, 0x0a, 0x0b, + 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x41, + 0x50, 0x49, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0x12, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, @@ -969,8 +968,10 @@ var file_sentryflow_proto_rawDesc = []byte{ 0x73, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x30, - 0x01, 0x42, 0x15, 0x5a, 0x13, 0x53, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x6c, 0x6f, 0x77, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x01, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x35, 0x47, 0x53, 0x45, 0x43, 0x2f, 0x53, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x6c, 0x6f, 0x77, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -987,34 +988,33 @@ func file_sentryflow_proto_rawDescGZIP() []byte { var file_sentryflow_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_sentryflow_proto_goTypes = []any{ - (*ClientInfo)(nil), // 0: protobuf.ClientInfo - (*APILog)(nil), // 1: protobuf.APILog - (*APILogV2)(nil), // 2: protobuf.APILogV2 - (*Source)(nil), // 3: protobuf.Source - (*Destination)(nil), // 4: protobuf.Destination - (*Request)(nil), // 5: protobuf.Request - (*Response)(nil), // 6: protobuf.Response - (*APIMetrics)(nil), // 7: protobuf.APIMetrics - (*MetricValue)(nil), // 8: protobuf.MetricValue - (*EnvoyMetrics)(nil), // 9: protobuf.EnvoyMetrics - nil, // 10: protobuf.APILog.SrcLabelEntry - nil, // 11: protobuf.APILog.DstLabelEntry - nil, // 12: protobuf.Request.HeadersEntry - nil, // 13: protobuf.Response.HeadersEntry - nil, // 14: protobuf.APIMetrics.PerAPICountsEntry - nil, // 15: protobuf.MetricValue.ValueEntry - nil, // 16: protobuf.EnvoyMetrics.LabelsEntry - nil, // 17: protobuf.EnvoyMetrics.MetricsEntry - (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp + (*ClientInfo)(nil), // 0: protobuf.ClientInfo + (*APILog)(nil), // 1: protobuf.APILog + (*APIEvent)(nil), // 2: protobuf.APIEvent + (*Metadata)(nil), // 3: protobuf.Metadata + (*Workload)(nil), // 4: protobuf.Workload + (*Request)(nil), // 5: protobuf.Request + (*Response)(nil), // 6: protobuf.Response + (*APIMetrics)(nil), // 7: protobuf.APIMetrics + (*MetricValue)(nil), // 8: protobuf.MetricValue + (*EnvoyMetrics)(nil), // 9: protobuf.EnvoyMetrics + nil, // 10: protobuf.APILog.SrcLabelEntry + nil, // 11: protobuf.APILog.DstLabelEntry + nil, // 12: protobuf.Request.HeadersEntry + nil, // 13: protobuf.Response.HeadersEntry + nil, // 14: protobuf.APIMetrics.PerAPICountsEntry + nil, // 15: protobuf.MetricValue.ValueEntry + nil, // 16: protobuf.EnvoyMetrics.LabelsEntry + nil, // 17: protobuf.EnvoyMetrics.MetricsEntry } var file_sentryflow_proto_depIdxs = []int32{ 10, // 0: protobuf.APILog.srcLabel:type_name -> protobuf.APILog.SrcLabelEntry 11, // 1: protobuf.APILog.dstLabel:type_name -> protobuf.APILog.DstLabelEntry - 18, // 2: protobuf.APILogV2.timestamp:type_name -> google.protobuf.Timestamp - 3, // 3: protobuf.APILogV2.source:type_name -> protobuf.Source - 4, // 4: protobuf.APILogV2.destination:type_name -> protobuf.Destination - 5, // 5: protobuf.APILogV2.request:type_name -> protobuf.Request - 6, // 6: protobuf.APILogV2.response:type_name -> protobuf.Response + 3, // 2: protobuf.APIEvent.metadata:type_name -> protobuf.Metadata + 4, // 3: protobuf.APIEvent.source:type_name -> protobuf.Workload + 4, // 4: protobuf.APIEvent.destination:type_name -> protobuf.Workload + 5, // 5: protobuf.APIEvent.request:type_name -> protobuf.Request + 6, // 6: protobuf.APIEvent.response:type_name -> protobuf.Response 12, // 7: protobuf.Request.headers:type_name -> protobuf.Request.HeadersEntry 13, // 8: protobuf.Response.headers:type_name -> protobuf.Response.HeadersEntry 14, // 9: protobuf.APIMetrics.perAPICounts:type_name -> protobuf.APIMetrics.PerAPICountsEntry @@ -1023,15 +1023,17 @@ var file_sentryflow_proto_depIdxs = []int32{ 17, // 12: protobuf.EnvoyMetrics.metrics:type_name -> protobuf.EnvoyMetrics.MetricsEntry 8, // 13: protobuf.EnvoyMetrics.MetricsEntry.value:type_name -> protobuf.MetricValue 0, // 14: protobuf.SentryFlow.GetAPILog:input_type -> protobuf.ClientInfo - 0, // 15: protobuf.SentryFlow.GetAPILogV2:input_type -> protobuf.ClientInfo - 0, // 16: protobuf.SentryFlow.GetAPIMetrics:input_type -> protobuf.ClientInfo - 0, // 17: protobuf.SentryFlow.GetEnvoyMetrics:input_type -> protobuf.ClientInfo - 1, // 18: protobuf.SentryFlow.GetAPILog:output_type -> protobuf.APILog - 2, // 19: protobuf.SentryFlow.GetAPILogV2:output_type -> protobuf.APILogV2 - 7, // 20: protobuf.SentryFlow.GetAPIMetrics:output_type -> protobuf.APIMetrics - 9, // 21: protobuf.SentryFlow.GetEnvoyMetrics:output_type -> protobuf.EnvoyMetrics - 18, // [18:22] is the sub-list for method output_type - 14, // [14:18] is the sub-list for method input_type + 0, // 15: protobuf.SentryFlow.GetAPIEvent:input_type -> protobuf.ClientInfo + 2, // 16: protobuf.SentryFlow.SendAPIEvent:input_type -> protobuf.APIEvent + 0, // 17: protobuf.SentryFlow.GetAPIMetrics:input_type -> protobuf.ClientInfo + 0, // 18: protobuf.SentryFlow.GetEnvoyMetrics:input_type -> protobuf.ClientInfo + 1, // 19: protobuf.SentryFlow.GetAPILog:output_type -> protobuf.APILog + 2, // 20: protobuf.SentryFlow.GetAPIEvent:output_type -> protobuf.APIEvent + 2, // 21: protobuf.SentryFlow.SendAPIEvent:output_type -> protobuf.APIEvent + 7, // 22: protobuf.SentryFlow.GetAPIMetrics:output_type -> protobuf.APIMetrics + 9, // 23: protobuf.SentryFlow.GetEnvoyMetrics:output_type -> protobuf.EnvoyMetrics + 19, // [19:24] is the sub-list for method output_type + 14, // [14:19] 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 @@ -1068,7 +1070,7 @@ func file_sentryflow_proto_init() { } } file_sentryflow_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*APILogV2); i { + switch v := v.(*APIEvent); i { case 0: return &v.state case 1: @@ -1080,7 +1082,7 @@ func file_sentryflow_proto_init() { } } file_sentryflow_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*Source); i { + switch v := v.(*Metadata); i { case 0: return &v.state case 1: @@ -1092,7 +1094,7 @@ func file_sentryflow_proto_init() { } } file_sentryflow_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*Destination); i { + switch v := v.(*Workload); i { case 0: return &v.state case 1: diff --git a/protobuf/sentryflow_grpc.pb.go b/protobuf/golang/sentryflow_grpc.pb.go similarity index 75% rename from protobuf/sentryflow_grpc.pb.go rename to protobuf/golang/sentryflow_grpc.pb.go index 70e55bc..38538cd 100644 --- a/protobuf/sentryflow_grpc.pb.go +++ b/protobuf/golang/sentryflow_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v5.27.3 +// - protoc v5.28.0 // source: sentryflow.proto package protobuf @@ -20,7 +20,8 @@ const _ = grpc.SupportPackageIsVersion9 const ( SentryFlow_GetAPILog_FullMethodName = "/protobuf.SentryFlow/GetAPILog" - SentryFlow_GetAPILogV2_FullMethodName = "/protobuf.SentryFlow/GetAPILogV2" + SentryFlow_GetAPIEvent_FullMethodName = "/protobuf.SentryFlow/GetAPIEvent" + SentryFlow_SendAPIEvent_FullMethodName = "/protobuf.SentryFlow/SendAPIEvent" SentryFlow_GetAPIMetrics_FullMethodName = "/protobuf.SentryFlow/GetAPIMetrics" SentryFlow_GetEnvoyMetrics_FullMethodName = "/protobuf.SentryFlow/GetEnvoyMetrics" ) @@ -29,8 +30,10 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type SentryFlowClient interface { + // Deprecated: Do not use. GetAPILog(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APILog], error) - GetAPILogV2(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APILogV2], error) + GetAPIEvent(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APIEvent], error) + SendAPIEvent(ctx context.Context, in *APIEvent, opts ...grpc.CallOption) (*APIEvent, error) GetAPIMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APIMetrics], error) GetEnvoyMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[EnvoyMetrics], error) } @@ -43,6 +46,7 @@ func NewSentryFlowClient(cc grpc.ClientConnInterface) SentryFlowClient { return &sentryFlowClient{cc} } +// Deprecated: Do not use. func (c *sentryFlowClient) GetAPILog(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APILog], error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[0], SentryFlow_GetAPILog_FullMethodName, cOpts...) @@ -62,13 +66,13 @@ func (c *sentryFlowClient) GetAPILog(ctx context.Context, in *ClientInfo, opts . // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type SentryFlow_GetAPILogClient = grpc.ServerStreamingClient[APILog] -func (c *sentryFlowClient) GetAPILogV2(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APILogV2], error) { +func (c *sentryFlowClient) GetAPIEvent(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APIEvent], error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[1], SentryFlow_GetAPILogV2_FullMethodName, cOpts...) + stream, err := c.cc.NewStream(ctx, &SentryFlow_ServiceDesc.Streams[1], SentryFlow_GetAPIEvent_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &grpc.GenericClientStream[ClientInfo, APILogV2]{ClientStream: stream} + x := &grpc.GenericClientStream[ClientInfo, APIEvent]{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -79,7 +83,17 @@ func (c *sentryFlowClient) GetAPILogV2(ctx context.Context, in *ClientInfo, opts } // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type SentryFlow_GetAPILogV2Client = grpc.ServerStreamingClient[APILogV2] +type SentryFlow_GetAPIEventClient = grpc.ServerStreamingClient[APIEvent] + +func (c *sentryFlowClient) SendAPIEvent(ctx context.Context, in *APIEvent, opts ...grpc.CallOption) (*APIEvent, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(APIEvent) + err := c.cc.Invoke(ctx, SentryFlow_SendAPIEvent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} func (c *sentryFlowClient) GetAPIMetrics(ctx context.Context, in *ClientInfo, opts ...grpc.CallOption) (grpc.ServerStreamingClient[APIMetrics], error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -120,16 +134,19 @@ func (c *sentryFlowClient) GetEnvoyMetrics(ctx context.Context, in *ClientInfo, type SentryFlow_GetEnvoyMetricsClient = grpc.ServerStreamingClient[EnvoyMetrics] // SentryFlowServer is the server API for SentryFlow service. -// All implementations should embed UnimplementedSentryFlowServer +// All implementations must embed UnimplementedSentryFlowServer // for forward compatibility. type SentryFlowServer interface { + // Deprecated: Do not use. GetAPILog(*ClientInfo, grpc.ServerStreamingServer[APILog]) error - GetAPILogV2(*ClientInfo, grpc.ServerStreamingServer[APILogV2]) error + GetAPIEvent(*ClientInfo, grpc.ServerStreamingServer[APIEvent]) error + SendAPIEvent(context.Context, *APIEvent) (*APIEvent, error) GetAPIMetrics(*ClientInfo, grpc.ServerStreamingServer[APIMetrics]) error GetEnvoyMetrics(*ClientInfo, grpc.ServerStreamingServer[EnvoyMetrics]) error + mustEmbedUnimplementedSentryFlowServer() } -// UnimplementedSentryFlowServer should be embedded to have +// UnimplementedSentryFlowServer must be embedded to have // forward compatible implementations. // // NOTE: this should be embedded by value instead of pointer to avoid a nil @@ -139,8 +156,11 @@ type UnimplementedSentryFlowServer struct{} func (UnimplementedSentryFlowServer) GetAPILog(*ClientInfo, grpc.ServerStreamingServer[APILog]) error { return status.Errorf(codes.Unimplemented, "method GetAPILog not implemented") } -func (UnimplementedSentryFlowServer) GetAPILogV2(*ClientInfo, grpc.ServerStreamingServer[APILogV2]) error { - return status.Errorf(codes.Unimplemented, "method GetAPILogV2 not implemented") +func (UnimplementedSentryFlowServer) GetAPIEvent(*ClientInfo, grpc.ServerStreamingServer[APIEvent]) error { + return status.Errorf(codes.Unimplemented, "method GetAPIEvent not implemented") +} +func (UnimplementedSentryFlowServer) SendAPIEvent(context.Context, *APIEvent) (*APIEvent, error) { + return nil, status.Errorf(codes.Unimplemented, "method SendAPIEvent not implemented") } func (UnimplementedSentryFlowServer) GetAPIMetrics(*ClientInfo, grpc.ServerStreamingServer[APIMetrics]) error { return status.Errorf(codes.Unimplemented, "method GetAPIMetrics not implemented") @@ -148,7 +168,8 @@ func (UnimplementedSentryFlowServer) GetAPIMetrics(*ClientInfo, grpc.ServerStrea func (UnimplementedSentryFlowServer) GetEnvoyMetrics(*ClientInfo, grpc.ServerStreamingServer[EnvoyMetrics]) error { return status.Errorf(codes.Unimplemented, "method GetEnvoyMetrics not implemented") } -func (UnimplementedSentryFlowServer) testEmbeddedByValue() {} +func (UnimplementedSentryFlowServer) mustEmbedUnimplementedSentryFlowServer() {} +func (UnimplementedSentryFlowServer) testEmbeddedByValue() {} // UnsafeSentryFlowServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to SentryFlowServer will @@ -179,16 +200,34 @@ func _SentryFlow_GetAPILog_Handler(srv interface{}, stream grpc.ServerStream) er // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type SentryFlow_GetAPILogServer = grpc.ServerStreamingServer[APILog] -func _SentryFlow_GetAPILogV2_Handler(srv interface{}, stream grpc.ServerStream) error { +func _SentryFlow_GetAPIEvent_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(ClientInfo) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SentryFlowServer).GetAPILogV2(m, &grpc.GenericServerStream[ClientInfo, APILogV2]{ServerStream: stream}) + return srv.(SentryFlowServer).GetAPIEvent(m, &grpc.GenericServerStream[ClientInfo, APIEvent]{ServerStream: stream}) } // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type SentryFlow_GetAPILogV2Server = grpc.ServerStreamingServer[APILogV2] +type SentryFlow_GetAPIEventServer = grpc.ServerStreamingServer[APIEvent] + +func _SentryFlow_SendAPIEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(APIEvent) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SentryFlowServer).SendAPIEvent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SentryFlow_SendAPIEvent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SentryFlowServer).SendAPIEvent(ctx, req.(*APIEvent)) + } + return interceptor(ctx, in, info, handler) +} func _SentryFlow_GetAPIMetrics_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(ClientInfo) @@ -218,7 +257,12 @@ type SentryFlow_GetEnvoyMetricsServer = grpc.ServerStreamingServer[EnvoyMetrics] var SentryFlow_ServiceDesc = grpc.ServiceDesc{ ServiceName: "protobuf.SentryFlow", HandlerType: (*SentryFlowServer)(nil), - Methods: []grpc.MethodDesc{}, + Methods: []grpc.MethodDesc{ + { + MethodName: "SendAPIEvent", + Handler: _SentryFlow_SendAPIEvent_Handler, + }, + }, Streams: []grpc.StreamDesc{ { StreamName: "GetAPILog", @@ -226,8 +270,8 @@ var SentryFlow_ServiceDesc = grpc.ServiceDesc{ ServerStreams: true, }, { - StreamName: "GetAPILogV2", - Handler: _SentryFlow_GetAPILogV2_Handler, + StreamName: "GetAPIEvent", + Handler: _SentryFlow_GetAPIEvent_Handler, ServerStreams: true, }, { diff --git a/protobuf/sentryflow_metrics.pb.go b/protobuf/golang/sentryflow_metrics.pb.go similarity index 95% rename from protobuf/sentryflow_metrics.pb.go rename to protobuf/golang/sentryflow_metrics.pb.go index 279cece..45636b5 100644 --- a/protobuf/sentryflow_metrics.pb.go +++ b/protobuf/golang/sentryflow_metrics.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.27.3 +// protoc v5.28.0 // source: sentryflow_metrics.proto package protobuf @@ -137,9 +137,10 @@ var file_sentryflow_metrics_proto_rawDesc = []byte{ 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x50, 0x49, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x15, 0x5a, 0x13, 0x53, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x46, 0x6c, 0x6f, 0x77, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x35, 0x47, 0x53, 0x45, 0x43, 0x2f, 0x53, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x46, 0x6c, 0x6f, 0x77, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protobuf/sentryflow_metrics_grpc.pb.go b/protobuf/golang/sentryflow_metrics_grpc.pb.go similarity index 92% rename from protobuf/sentryflow_metrics_grpc.pb.go rename to protobuf/golang/sentryflow_metrics_grpc.pb.go index 696a0f0..dd072d6 100644 --- a/protobuf/sentryflow_metrics_grpc.pb.go +++ b/protobuf/golang/sentryflow_metrics_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v5.27.3 +// - protoc v5.28.0 // source: sentryflow_metrics.proto package protobuf @@ -51,13 +51,14 @@ func (c *aPIClassifierClient) ClassifyAPIs(ctx context.Context, opts ...grpc.Cal type APIClassifier_ClassifyAPIsClient = grpc.BidiStreamingClient[APIClassifierRequest, APIClassifierResponse] // APIClassifierServer is the server API for APIClassifier service. -// All implementations should embed UnimplementedAPIClassifierServer +// All implementations must embed UnimplementedAPIClassifierServer // for forward compatibility. type APIClassifierServer interface { ClassifyAPIs(grpc.BidiStreamingServer[APIClassifierRequest, APIClassifierResponse]) error + mustEmbedUnimplementedAPIClassifierServer() } -// UnimplementedAPIClassifierServer should be embedded to have +// UnimplementedAPIClassifierServer must be embedded to have // forward compatible implementations. // // NOTE: this should be embedded by value instead of pointer to avoid a nil @@ -67,7 +68,8 @@ type UnimplementedAPIClassifierServer struct{} func (UnimplementedAPIClassifierServer) ClassifyAPIs(grpc.BidiStreamingServer[APIClassifierRequest, APIClassifierResponse]) error { return status.Errorf(codes.Unimplemented, "method ClassifyAPIs not implemented") } -func (UnimplementedAPIClassifierServer) testEmbeddedByValue() {} +func (UnimplementedAPIClassifierServer) mustEmbedUnimplementedAPIClassifierServer() {} +func (UnimplementedAPIClassifierServer) testEmbeddedByValue() {} // UnsafeAPIClassifierServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to APIClassifierServer will diff --git a/protobuf/sentryflow_metrics_pb2.py b/protobuf/python/sentryflow_metrics_pb2.py similarity index 81% rename from protobuf/sentryflow_metrics_pb2.py rename to protobuf/python/sentryflow_metrics_pb2.py index e6cc29c..219cf91 100644 --- a/protobuf/sentryflow_metrics_pb2.py +++ b/protobuf/python/sentryflow_metrics_pb2.py @@ -1,12 +1,22 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE # source: sentryflow_metrics.proto -# Protobuf Python Version: 5.26.1 +# Protobuf Python Version: 5.28.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version from google.protobuf import symbol_database as _symbol_database from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 28, + 0, + '', + 'sentryflow_metrics.proto' +) # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -14,14 +24,14 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18sentryflow_metrics.proto\x12\x08protobuf\"#\n\x14\x41PIClassifierRequest\x12\x0b\n\x03\x41PI\x18\x01 \x03(\t\"}\n\x15\x41PIClassifierResponse\x12\x37\n\x04\x41PIs\x18\x01 \x03(\x0b\x32).protobuf.APIClassifierResponse.APIsEntry\x1a+\n\tAPIsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x32\x64\n\rAPIClassifier\x12S\n\x0c\x43lassifyAPIs\x12\x1e.protobuf.APIClassifierRequest\x1a\x1f.protobuf.APIClassifierResponse(\x01\x30\x01\x42\x15Z\x13SentryFlow/protobufb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18sentryflow_metrics.proto\x12\x08protobuf\"#\n\x14\x41PIClassifierRequest\x12\x0b\n\x03\x41PI\x18\x01 \x03(\t\"}\n\x15\x41PIClassifierResponse\x12\x37\n\x04\x41PIs\x18\x01 \x03(\x0b\x32).protobuf.APIClassifierResponse.APIsEntry\x1a+\n\tAPIsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x32\x64\n\rAPIClassifier\x12S\n\x0c\x43lassifyAPIs\x12\x1e.protobuf.APIClassifierRequest\x1a\x1f.protobuf.APIClassifierResponse(\x01\x30\x01\x42&Z$github.com/5GSEC/SentryFlow/protobufb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'sentryflow_metrics_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'Z\023SentryFlow/protobuf' + _globals['DESCRIPTOR']._serialized_options = b'Z$github.com/5GSEC/SentryFlow/protobuf' _globals['_APICLASSIFIERRESPONSE_APISENTRY']._loaded_options = None _globals['_APICLASSIFIERRESPONSE_APISENTRY']._serialized_options = b'8\001' _globals['_APICLASSIFIERREQUEST']._serialized_start=38 diff --git a/protobuf/sentryflow_metrics_pb2.pyi b/protobuf/python/sentryflow_metrics_pb2.pyi similarity index 100% rename from protobuf/sentryflow_metrics_pb2.pyi rename to protobuf/python/sentryflow_metrics_pb2.pyi diff --git a/protobuf/python/sentryflow_pb2.py b/protobuf/python/sentryflow_pb2.py new file mode 100644 index 0000000..1012138 --- /dev/null +++ b/protobuf/python/sentryflow_pb2.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: sentryflow.proto +# Protobuf Python Version: 5.28.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 28, + 0, + '', + 'sentryflow.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10sentryflow.proto\x12\x08protobuf\"1\n\nClientInfo\x12\x10\n\x08hostName\x18\x01 \x01(\t\x12\x11\n\tIPAddress\x18\x02 \x01(\t\"\xe7\x03\n\x06\x41PILog\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x11\n\ttimeStamp\x18\x02 \x01(\t\x12\x14\n\x0csrcNamespace\x18\x0b \x01(\t\x12\x0f\n\x07srcName\x18\x0c \x01(\t\x12\x30\n\x08srcLabel\x18\r \x03(\x0b\x32\x1e.protobuf.APILog.SrcLabelEntry\x12\x0f\n\x07srcType\x18\x15 \x01(\t\x12\r\n\x05srcIP\x18\x16 \x01(\t\x12\x0f\n\x07srcPort\x18\x17 \x01(\t\x12\x14\n\x0c\x64stNamespace\x18\x1f \x01(\t\x12\x0f\n\x07\x64stName\x18 \x01(\t\x12\x30\n\x08\x64stLabel\x18! \x03(\x0b\x32\x1e.protobuf.APILog.DstLabelEntry\x12\x0f\n\x07\x64stType\x18) \x01(\t\x12\r\n\x05\x64stIP\x18* \x01(\t\x12\x0f\n\x07\x64stPort\x18+ \x01(\t\x12\x10\n\x08protocol\x18\x33 \x01(\t\x12\x0e\n\x06method\x18\x34 \x01(\t\x12\x0c\n\x04path\x18\x35 \x01(\t\x12\x14\n\x0cresponseCode\x18\x36 \x01(\x05\x1a/\n\rSrcLabelEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a/\n\rDstLabelEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:\x02\x18\x01\"\xd9\x01\n\x08\x41PIEvent\x12$\n\x08metadata\x18\x01 \x01(\x0b\x32\x12.protobuf.Metadata\x12\"\n\x06source\x18\x03 \x01(\x0b\x32\x12.protobuf.Workload\x12\'\n\x0b\x64\x65stination\x18\x04 \x01(\x0b\x32\x12.protobuf.Workload\x12\"\n\x07request\x18\x05 \x01(\x0b\x32\x11.protobuf.Request\x12$\n\x08response\x18\x06 \x01(\x0b\x32\x12.protobuf.Response\x12\x10\n\x08protocol\x18\x07 \x01(\t\"l\n\x08Metadata\x12\x12\n\ncontext_id\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\x04\x12\x15\n\ristio_version\x18\x03 \x01(\t\x12\x0f\n\x07mesh_id\x18\x04 \x01(\t\x12\x11\n\tnode_name\x18\x05 \x01(\t\"E\n\x08Workload\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\n\n\x02ip\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\x05\"x\n\x07Request\x12/\n\x07headers\x18\x01 \x03(\x0b\x32\x1e.protobuf.Request.HeadersEntry\x12\x0c\n\x04\x62ody\x18\x02 \x01(\t\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"z\n\x08Response\x12\x30\n\x07headers\x18\x01 \x03(\x0b\x32\x1f.protobuf.Response.HeadersEntry\x12\x0c\n\x04\x62ody\x18\x02 \x01(\t\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x7f\n\nAPIMetrics\x12<\n\x0cperAPICounts\x18\x01 \x03(\x0b\x32&.protobuf.APIMetrics.PerAPICountsEntry\x1a\x33\n\x11PerAPICountsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\"l\n\x0bMetricValue\x12/\n\x05value\x18\x01 \x03(\x0b\x32 .protobuf.MetricValue.ValueEntry\x1a,\n\nValueEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xb5\x02\n\x0c\x45nvoyMetrics\x12\x11\n\ttimeStamp\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x0b \x01(\t\x12\x0c\n\x04name\x18\x0c \x01(\t\x12\x11\n\tIPAddress\x18\r \x01(\t\x12\x32\n\x06labels\x18\x0e \x03(\x0b\x32\".protobuf.EnvoyMetrics.LabelsEntry\x12\x34\n\x07metrics\x18\x15 \x03(\x0b\x32#.protobuf.EnvoyMetrics.MetricsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x45\n\x0cMetricsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.protobuf.MetricValue:\x02\x38\x01\x32\xbd\x02\n\nSentryFlow\x12:\n\tGetAPILog\x12\x14.protobuf.ClientInfo\x1a\x10.protobuf.APILog\"\x03\x88\x02\x01\x30\x01\x12\x39\n\x0bGetAPIEvent\x12\x14.protobuf.ClientInfo\x1a\x12.protobuf.APIEvent0\x01\x12\x36\n\x0cSendAPIEvent\x12\x12.protobuf.APIEvent\x1a\x12.protobuf.APIEvent\x12=\n\rGetAPIMetrics\x12\x14.protobuf.ClientInfo\x1a\x14.protobuf.APIMetrics0\x01\x12\x41\n\x0fGetEnvoyMetrics\x12\x14.protobuf.ClientInfo\x1a\x16.protobuf.EnvoyMetrics0\x01\x42&Z$github.com/5GSEC/SentryFlow/protobufb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'sentryflow_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'Z$github.com/5GSEC/SentryFlow/protobuf' + _globals['_APILOG_SRCLABELENTRY']._loaded_options = None + _globals['_APILOG_SRCLABELENTRY']._serialized_options = b'8\001' + _globals['_APILOG_DSTLABELENTRY']._loaded_options = None + _globals['_APILOG_DSTLABELENTRY']._serialized_options = b'8\001' + _globals['_APILOG']._loaded_options = None + _globals['_APILOG']._serialized_options = b'\030\001' + _globals['_REQUEST_HEADERSENTRY']._loaded_options = None + _globals['_REQUEST_HEADERSENTRY']._serialized_options = b'8\001' + _globals['_RESPONSE_HEADERSENTRY']._loaded_options = None + _globals['_RESPONSE_HEADERSENTRY']._serialized_options = b'8\001' + _globals['_APIMETRICS_PERAPICOUNTSENTRY']._loaded_options = None + _globals['_APIMETRICS_PERAPICOUNTSENTRY']._serialized_options = b'8\001' + _globals['_METRICVALUE_VALUEENTRY']._loaded_options = None + _globals['_METRICVALUE_VALUEENTRY']._serialized_options = b'8\001' + _globals['_ENVOYMETRICS_LABELSENTRY']._loaded_options = None + _globals['_ENVOYMETRICS_LABELSENTRY']._serialized_options = b'8\001' + _globals['_ENVOYMETRICS_METRICSENTRY']._loaded_options = None + _globals['_ENVOYMETRICS_METRICSENTRY']._serialized_options = b'8\001' + _globals['_SENTRYFLOW'].methods_by_name['GetAPILog']._loaded_options = None + _globals['_SENTRYFLOW'].methods_by_name['GetAPILog']._serialized_options = b'\210\002\001' + _globals['_CLIENTINFO']._serialized_start=30 + _globals['_CLIENTINFO']._serialized_end=79 + _globals['_APILOG']._serialized_start=82 + _globals['_APILOG']._serialized_end=569 + _globals['_APILOG_SRCLABELENTRY']._serialized_start=469 + _globals['_APILOG_SRCLABELENTRY']._serialized_end=516 + _globals['_APILOG_DSTLABELENTRY']._serialized_start=518 + _globals['_APILOG_DSTLABELENTRY']._serialized_end=565 + _globals['_APIEVENT']._serialized_start=572 + _globals['_APIEVENT']._serialized_end=789 + _globals['_METADATA']._serialized_start=791 + _globals['_METADATA']._serialized_end=899 + _globals['_WORKLOAD']._serialized_start=901 + _globals['_WORKLOAD']._serialized_end=970 + _globals['_REQUEST']._serialized_start=972 + _globals['_REQUEST']._serialized_end=1092 + _globals['_REQUEST_HEADERSENTRY']._serialized_start=1046 + _globals['_REQUEST_HEADERSENTRY']._serialized_end=1092 + _globals['_RESPONSE']._serialized_start=1094 + _globals['_RESPONSE']._serialized_end=1216 + _globals['_RESPONSE_HEADERSENTRY']._serialized_start=1046 + _globals['_RESPONSE_HEADERSENTRY']._serialized_end=1092 + _globals['_APIMETRICS']._serialized_start=1218 + _globals['_APIMETRICS']._serialized_end=1345 + _globals['_APIMETRICS_PERAPICOUNTSENTRY']._serialized_start=1294 + _globals['_APIMETRICS_PERAPICOUNTSENTRY']._serialized_end=1345 + _globals['_METRICVALUE']._serialized_start=1347 + _globals['_METRICVALUE']._serialized_end=1455 + _globals['_METRICVALUE_VALUEENTRY']._serialized_start=1411 + _globals['_METRICVALUE_VALUEENTRY']._serialized_end=1455 + _globals['_ENVOYMETRICS']._serialized_start=1458 + _globals['_ENVOYMETRICS']._serialized_end=1767 + _globals['_ENVOYMETRICS_LABELSENTRY']._serialized_start=1651 + _globals['_ENVOYMETRICS_LABELSENTRY']._serialized_end=1696 + _globals['_ENVOYMETRICS_METRICSENTRY']._serialized_start=1698 + _globals['_ENVOYMETRICS_METRICSENTRY']._serialized_end=1767 + _globals['_SENTRYFLOW']._serialized_start=1770 + _globals['_SENTRYFLOW']._serialized_end=2087 +# @@protoc_insertion_point(module_scope) diff --git a/protobuf/python/sentryflow_pb2.pyi b/protobuf/python/sentryflow_pb2.pyi new file mode 100644 index 0000000..da65788 --- /dev/null +++ b/protobuf/python/sentryflow_pb2.pyi @@ -0,0 +1,196 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ClientInfo(_message.Message): + __slots__ = ("hostName", "IPAddress") + HOSTNAME_FIELD_NUMBER: _ClassVar[int] + IPADDRESS_FIELD_NUMBER: _ClassVar[int] + hostName: str + IPAddress: str + def __init__(self, hostName: _Optional[str] = ..., IPAddress: _Optional[str] = ...) -> None: ... + +class APILog(_message.Message): + __slots__ = ("id", "timeStamp", "srcNamespace", "srcName", "srcLabel", "srcType", "srcIP", "srcPort", "dstNamespace", "dstName", "dstLabel", "dstType", "dstIP", "dstPort", "protocol", "method", "path", "responseCode") + class SrcLabelEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + class DstLabelEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + ID_FIELD_NUMBER: _ClassVar[int] + TIMESTAMP_FIELD_NUMBER: _ClassVar[int] + SRCNAMESPACE_FIELD_NUMBER: _ClassVar[int] + SRCNAME_FIELD_NUMBER: _ClassVar[int] + SRCLABEL_FIELD_NUMBER: _ClassVar[int] + SRCTYPE_FIELD_NUMBER: _ClassVar[int] + SRCIP_FIELD_NUMBER: _ClassVar[int] + SRCPORT_FIELD_NUMBER: _ClassVar[int] + DSTNAMESPACE_FIELD_NUMBER: _ClassVar[int] + DSTNAME_FIELD_NUMBER: _ClassVar[int] + DSTLABEL_FIELD_NUMBER: _ClassVar[int] + DSTTYPE_FIELD_NUMBER: _ClassVar[int] + DSTIP_FIELD_NUMBER: _ClassVar[int] + DSTPORT_FIELD_NUMBER: _ClassVar[int] + PROTOCOL_FIELD_NUMBER: _ClassVar[int] + METHOD_FIELD_NUMBER: _ClassVar[int] + PATH_FIELD_NUMBER: _ClassVar[int] + RESPONSECODE_FIELD_NUMBER: _ClassVar[int] + id: int + timeStamp: str + srcNamespace: str + srcName: str + srcLabel: _containers.ScalarMap[str, str] + srcType: str + srcIP: str + srcPort: str + dstNamespace: str + dstName: str + dstLabel: _containers.ScalarMap[str, str] + dstType: str + dstIP: str + dstPort: str + protocol: str + method: str + path: str + responseCode: int + def __init__(self, id: _Optional[int] = ..., timeStamp: _Optional[str] = ..., srcNamespace: _Optional[str] = ..., srcName: _Optional[str] = ..., srcLabel: _Optional[_Mapping[str, str]] = ..., srcType: _Optional[str] = ..., srcIP: _Optional[str] = ..., srcPort: _Optional[str] = ..., dstNamespace: _Optional[str] = ..., dstName: _Optional[str] = ..., dstLabel: _Optional[_Mapping[str, str]] = ..., dstType: _Optional[str] = ..., dstIP: _Optional[str] = ..., dstPort: _Optional[str] = ..., protocol: _Optional[str] = ..., method: _Optional[str] = ..., path: _Optional[str] = ..., responseCode: _Optional[int] = ...) -> None: ... + +class APIEvent(_message.Message): + __slots__ = ("metadata", "source", "destination", "request", "response", "protocol") + METADATA_FIELD_NUMBER: _ClassVar[int] + SOURCE_FIELD_NUMBER: _ClassVar[int] + DESTINATION_FIELD_NUMBER: _ClassVar[int] + REQUEST_FIELD_NUMBER: _ClassVar[int] + RESPONSE_FIELD_NUMBER: _ClassVar[int] + PROTOCOL_FIELD_NUMBER: _ClassVar[int] + metadata: Metadata + source: Workload + destination: Workload + request: Request + response: Response + protocol: str + def __init__(self, metadata: _Optional[_Union[Metadata, _Mapping]] = ..., source: _Optional[_Union[Workload, _Mapping]] = ..., destination: _Optional[_Union[Workload, _Mapping]] = ..., request: _Optional[_Union[Request, _Mapping]] = ..., response: _Optional[_Union[Response, _Mapping]] = ..., protocol: _Optional[str] = ...) -> None: ... + +class Metadata(_message.Message): + __slots__ = ("context_id", "timestamp", "istio_version", "mesh_id", "node_name") + CONTEXT_ID_FIELD_NUMBER: _ClassVar[int] + TIMESTAMP_FIELD_NUMBER: _ClassVar[int] + ISTIO_VERSION_FIELD_NUMBER: _ClassVar[int] + MESH_ID_FIELD_NUMBER: _ClassVar[int] + NODE_NAME_FIELD_NUMBER: _ClassVar[int] + context_id: int + timestamp: int + istio_version: str + mesh_id: str + node_name: str + def __init__(self, context_id: _Optional[int] = ..., timestamp: _Optional[int] = ..., istio_version: _Optional[str] = ..., mesh_id: _Optional[str] = ..., node_name: _Optional[str] = ...) -> None: ... + +class Workload(_message.Message): + __slots__ = ("name", "namespace", "ip", "port") + NAME_FIELD_NUMBER: _ClassVar[int] + NAMESPACE_FIELD_NUMBER: _ClassVar[int] + IP_FIELD_NUMBER: _ClassVar[int] + PORT_FIELD_NUMBER: _ClassVar[int] + name: str + namespace: str + ip: str + port: int + def __init__(self, name: _Optional[str] = ..., namespace: _Optional[str] = ..., ip: _Optional[str] = ..., port: _Optional[int] = ...) -> None: ... + +class Request(_message.Message): + __slots__ = ("headers", "body") + class HeadersEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + HEADERS_FIELD_NUMBER: _ClassVar[int] + BODY_FIELD_NUMBER: _ClassVar[int] + headers: _containers.ScalarMap[str, str] + body: str + def __init__(self, headers: _Optional[_Mapping[str, str]] = ..., body: _Optional[str] = ...) -> None: ... + +class Response(_message.Message): + __slots__ = ("headers", "body") + class HeadersEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + HEADERS_FIELD_NUMBER: _ClassVar[int] + BODY_FIELD_NUMBER: _ClassVar[int] + headers: _containers.ScalarMap[str, str] + body: str + def __init__(self, headers: _Optional[_Mapping[str, str]] = ..., body: _Optional[str] = ...) -> None: ... + +class APIMetrics(_message.Message): + __slots__ = ("perAPICounts",) + class PerAPICountsEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: int + def __init__(self, key: _Optional[str] = ..., value: _Optional[int] = ...) -> None: ... + PERAPICOUNTS_FIELD_NUMBER: _ClassVar[int] + perAPICounts: _containers.ScalarMap[str, int] + def __init__(self, perAPICounts: _Optional[_Mapping[str, int]] = ...) -> None: ... + +class MetricValue(_message.Message): + __slots__ = ("value",) + class ValueEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + VALUE_FIELD_NUMBER: _ClassVar[int] + value: _containers.ScalarMap[str, str] + def __init__(self, value: _Optional[_Mapping[str, str]] = ...) -> None: ... + +class EnvoyMetrics(_message.Message): + __slots__ = ("timeStamp", "namespace", "name", "IPAddress", "labels", "metrics") + class LabelsEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + class MetricsEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: MetricValue + def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[MetricValue, _Mapping]] = ...) -> None: ... + TIMESTAMP_FIELD_NUMBER: _ClassVar[int] + NAMESPACE_FIELD_NUMBER: _ClassVar[int] + NAME_FIELD_NUMBER: _ClassVar[int] + IPADDRESS_FIELD_NUMBER: _ClassVar[int] + LABELS_FIELD_NUMBER: _ClassVar[int] + METRICS_FIELD_NUMBER: _ClassVar[int] + timeStamp: str + namespace: str + name: str + IPAddress: str + labels: _containers.ScalarMap[str, str] + metrics: _containers.MessageMap[str, MetricValue] + def __init__(self, timeStamp: _Optional[str] = ..., namespace: _Optional[str] = ..., name: _Optional[str] = ..., IPAddress: _Optional[str] = ..., labels: _Optional[_Mapping[str, str]] = ..., metrics: _Optional[_Mapping[str, MetricValue]] = ...) -> None: ... diff --git a/protobuf/sentryflow.proto b/protobuf/sentryflow.proto index 7bb7d1d..762a47b 100644 --- a/protobuf/sentryflow.proto +++ b/protobuf/sentryflow.proto @@ -2,10 +2,7 @@ syntax = "proto3"; package protobuf; -option go_package = "SentryFlow/protobuf"; - -import "google/protobuf/timestamp.proto"; - +option go_package = "github.com/5GSEC/SentryFlow/protobuf"; message ClientInfo { string hostName = 1; @@ -13,6 +10,8 @@ message ClientInfo { } message APILog { + option deprecated = true; + uint64 id = 1; string timeStamp = 2; @@ -38,39 +37,55 @@ message APILog { int32 responseCode = 54; } -message APILogV2 { - int32 context_id = 1; - google.protobuf.Timestamp timestamp = 2; - Source source = 3; - Destination destination = 4; +// APIEvent represents an event related to an API call, including metadata, +// source and destination workloads, and network information. +message APIEvent { + Metadata metadata = 1; + Workload source = 3; + Workload destination = 4; Request request = 5; Response response = 6; - string Protocol = 7; + string protocol = 7; } -message Source { - string name = 1; - string namespace = 2; - string ip = 3; - int32 port = 4; - string type = 5; +message Metadata { + uint32 context_id = 1; + uint64 timestamp = 2; + string istio_version = 3; + string mesh_id = 4; + + // The name of the Kubernetes node where the workload is running. If the workload + // is not running in a Kubernetes environment, this field will be empty. + string node_name = 5; } -message Destination { +// Workload represents a generic entity that can be either a Kubernetes or +// non-Kubernetes resource. It serves as a source or destination for access +// within a system. +message Workload { + // The name of the workload. string name = 1; + + // The namespace in which the workload is deployed. This field is only applicable + // for Kubernetes workloads. string namespace = 2; + + // The IP address of the workload. string ip = 3; + + // The port number used by the workload. int32 port = 4; - string type = 5; } +// Request represents an incoming HTTP request. message Request { - map headers = 1; + map headers = 1; string body = 2; } +// Response represents an outgoing HTTP response. message Response { - map headers = 1; + map headers = 1; string body = 2; } @@ -85,7 +100,7 @@ message MetricValue { message EnvoyMetrics { string timeStamp = 1; - + string namespace = 11; string name = 12; string IPAddress = 13; @@ -95,8 +110,11 @@ message EnvoyMetrics { } service SentryFlow { - rpc GetAPILog(ClientInfo) returns (stream APILog); // To be deprecated - rpc GetAPILogV2(ClientInfo) returns (stream APILogV2); + rpc GetAPILog(ClientInfo) returns (stream APILog) { + option deprecated = true; + } + rpc GetAPIEvent(ClientInfo) returns (stream APIEvent); + rpc SendAPIEvent(APIEvent) returns(APIEvent); rpc GetAPIMetrics(ClientInfo) returns (stream APIMetrics); rpc GetEnvoyMetrics(ClientInfo) returns (stream EnvoyMetrics); } diff --git a/protobuf/sentryflow_metrics.proto b/protobuf/sentryflow_metrics.proto index 931c7b0..510e742 100644 --- a/protobuf/sentryflow_metrics.proto +++ b/protobuf/sentryflow_metrics.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package protobuf; -option go_package = "SentryFlow/protobuf"; +option go_package = "github.com/5GSEC/SentryFlow/protobuf"; message APIClassifierRequest { repeated string API = 1; diff --git a/protobuf/sentryflow_metrics_pb2_grpc.py b/protobuf/sentryflow_metrics_pb2_grpc.py deleted file mode 100644 index 87671ed..0000000 --- a/protobuf/sentryflow_metrics_pb2_grpc.py +++ /dev/null @@ -1,101 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" -import grpc -import warnings - -import sentryflow_metrics_pb2 as sentryflow__metrics__pb2 - -GRPC_GENERATED_VERSION = '1.63.0' -GRPC_VERSION = grpc.__version__ -EXPECTED_ERROR_RELEASE = '1.65.0' -SCHEDULED_RELEASE_DATE = 'June 25, 2024' -_version_not_supported = False - -try: - from grpc._utilities import first_version_is_lower - _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) -except ImportError: - _version_not_supported = True - -if _version_not_supported: - warnings.warn( - f'The grpc package installed is at version {GRPC_VERSION},' - + f' but the generated code in sentryflow_metrics_pb2_grpc.py depends on' - + f' grpcio>={GRPC_GENERATED_VERSION}.' - + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' - + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' - + f' This warning will become an error in {EXPECTED_ERROR_RELEASE},' - + f' scheduled for release on {SCHEDULED_RELEASE_DATE}.', - RuntimeWarning - ) - - -class APIClassifierStub(object): - """Missing associated documentation comment in .proto file.""" - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.ClassifyAPIs = channel.stream_stream( - '/protobuf.APIClassifier/ClassifyAPIs', - request_serializer=sentryflow__metrics__pb2.APIClassifierRequest.SerializeToString, - response_deserializer=sentryflow__metrics__pb2.APIClassifierResponse.FromString, - _registered_method=True) - - -class APIClassifierServicer(object): - """Missing associated documentation comment in .proto file.""" - - def ClassifyAPIs(self, request_iterator, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - -def add_APIClassifierServicer_to_server(servicer, server): - rpc_method_handlers = { - 'ClassifyAPIs': grpc.stream_stream_rpc_method_handler( - servicer.ClassifyAPIs, - request_deserializer=sentryflow__metrics__pb2.APIClassifierRequest.FromString, - response_serializer=sentryflow__metrics__pb2.APIClassifierResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - 'protobuf.APIClassifier', rpc_method_handlers) - server.add_generic_rpc_handlers((generic_handler,)) - - - # This class is part of an EXPERIMENTAL API. -class APIClassifier(object): - """Missing associated documentation comment in .proto file.""" - - @staticmethod - def ClassifyAPIs(request_iterator, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.stream_stream( - request_iterator, - target, - '/protobuf.APIClassifier/ClassifyAPIs', - sentryflow__metrics__pb2.APIClassifierRequest.SerializeToString, - sentryflow__metrics__pb2.APIClassifierResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) From 57041bab9497ba1ad974aeddb69edf7febab5003 Mon Sep 17 00:00:00 2001 From: Anurag Rajawat Date: Sat, 21 Sep 2024 18:34:17 +0530 Subject: [PATCH 3/6] refactor(*): Refactor for better maintainability Signed-off-by: Anurag Rajawat --- .gitignore | 2 + deployments/sentryflow.yaml | 122 +++-- sentryflow/.dockerignore | 1 + sentryflow/Dockerfile | 43 +- sentryflow/Makefile | 111 ++--- sentryflow/cmd/root.go | 57 +++ sentryflow/cmd/version.go | 20 + sentryflow/collector/collectorHandler.go | 104 ----- sentryflow/collector/envoy.go | 226 --------- sentryflow/collector/interface.go | 16 - sentryflow/collector/opentelemetry.go | 143 ------ sentryflow/collector/wasm.go | 51 -- sentryflow/config/config.go | 149 ------ sentryflow/config/default.yaml | 24 + sentryflow/core/sentryflow.go | 196 -------- sentryflow/exporter/exportAPILogs.go | 132 ------ sentryflow/exporter/exportAPIMetrics.go | 177 ------- sentryflow/exporter/exportEnvoyMetrics.go | 69 --- sentryflow/exporter/exporterHandler.go | 259 ----------- sentryflow/go.mod | 88 ++-- sentryflow/go.sum | 172 ++++--- sentryflow/k8s/istioPatcher.go | 246 ---------- sentryflow/k8s/k8sHandler.go | 437 ------------------ sentryflow/main.go | 10 +- sentryflow/pkg/config/config.go | 129 ++++++ sentryflow/pkg/core/sentryflow.go | 97 ++++ sentryflow/pkg/core/server.go | 91 ++++ sentryflow/pkg/exporter/exporter.go | 146 ++++++ sentryflow/pkg/k8s/client.go | 39 ++ sentryflow/pkg/receiver/receiver.go | 46 ++ .../receiver/svcmesh/istio/sidecar/sidecar.go | 270 +++++++++++ sentryflow/pkg/util/util.go | 23 + sentryflow/processor/apiAnalyzer.go | 95 ---- sentryflow/processor/apiClassifier.go | 215 --------- sentryflow/processor/logProcessor.go | 131 ------ sentryflow/types/types.go | 36 -- 36 files changed, 1270 insertions(+), 2903 deletions(-) create mode 100644 sentryflow/.dockerignore create mode 100644 sentryflow/cmd/root.go create mode 100644 sentryflow/cmd/version.go delete mode 100644 sentryflow/collector/collectorHandler.go delete mode 100644 sentryflow/collector/envoy.go delete mode 100644 sentryflow/collector/interface.go delete mode 100644 sentryflow/collector/opentelemetry.go delete mode 100644 sentryflow/collector/wasm.go delete mode 100644 sentryflow/config/config.go create mode 100644 sentryflow/config/default.yaml delete mode 100644 sentryflow/core/sentryflow.go delete mode 100644 sentryflow/exporter/exportAPILogs.go delete mode 100644 sentryflow/exporter/exportAPIMetrics.go delete mode 100644 sentryflow/exporter/exportEnvoyMetrics.go delete mode 100644 sentryflow/exporter/exporterHandler.go delete mode 100644 sentryflow/k8s/istioPatcher.go delete mode 100644 sentryflow/k8s/k8sHandler.go create mode 100644 sentryflow/pkg/config/config.go create mode 100644 sentryflow/pkg/core/sentryflow.go create mode 100644 sentryflow/pkg/core/server.go create mode 100644 sentryflow/pkg/exporter/exporter.go create mode 100644 sentryflow/pkg/k8s/client.go create mode 100644 sentryflow/pkg/receiver/receiver.go create mode 100644 sentryflow/pkg/receiver/svcmesh/istio/sidecar/sidecar.go create mode 100644 sentryflow/pkg/util/util.go delete mode 100644 sentryflow/processor/apiAnalyzer.go delete mode 100644 sentryflow/processor/apiClassifier.go delete mode 100644 sentryflow/processor/logProcessor.go delete mode 100644 sentryflow/types/types.go diff --git a/.gitignore b/.gitignore index 9a410bc..e52abff 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ go.work.sum *.swp *.swo *~ + +venv/ diff --git a/deployments/sentryflow.yaml b/deployments/sentryflow.yaml index d38da78..c29d217 100644 --- a/deployments/sentryflow.yaml +++ b/deployments/sentryflow.yaml @@ -2,45 +2,75 @@ apiVersion: v1 kind: Namespace metadata: name: sentryflow - labels: - istio-injection: disabled # avoid Istio sidecar-injection - pod-security.kubernetes.io/audit: privileged - pod-security.kubernetes.io/enforce: privileged - pod-security.kubernetes.io/warn: privileged --- apiVersion: v1 kind: ServiceAccount metadata: + name: sentryflow namespace: sentryflow - name: sentryflow-sa --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: sentryflow-cr + name: sentryflow rules: -- apiGroups: ["*"] - verbs: ["*"] - resources: ["*"] + - apiGroups: + - networking.istio.io + verbs: + - get + - create + - delete + resources: + - envoyfilters + - apiGroups: + - extensions.istio.io + verbs: + - get + - create + - delete + resources: + - wasmplugins --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: sentryflow-rb + name: sentryflow roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: sentryflow-cr + name: sentryflow subjects: -- kind: ServiceAccount + - kind: ServiceAccount + name: sentryflow + namespace: sentryflow +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config namespace: sentryflow - name: sentryflow-sa +data: + config.yaml: |2- + filters: + server: + port: 8081 + envoy: + uri: anuragrajawat/httpfilter:v0.1 + + receivers: + serviceMeshes: + - name: istio-sidecar + namespace: istio-system + + exporter: + grpc: + port: 8080 --- apiVersion: apps/v1 kind: Deployment metadata: - namespace: sentryflow name: sentryflow + namespace: sentryflow spec: replicas: 1 selector: @@ -51,17 +81,43 @@ spec: labels: app: sentryflow spec: - serviceAccountName: sentryflow-sa + serviceAccountName: sentryflow containers: - - name: sentryflow - image: 5gsec/sentryflow:v0.1 - ports: - - name: otel-grpc - protocol: TCP - containerPort: 4317 - - name: sentryflow-grpc - protocol: TCP - containerPort: 8080 + - name: sentryflow + image: docker.io/5gsec/sentryflow:v0.1 + imagePullPolicy: IfNotPresent + args: + - --config + - /var/lib/sentryflow/config.yaml + volumeMounts: + - mountPath: /var/lib/sentryflow/ + name: config + ports: + - containerPort: 8080 + name: exporter + protocol: TCP + securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1111 + allowPrivilegeEscalation: false + readinessProbe: + httpGet: + port: 8081 # Make sure to use the same port as `.filters.server.port` field in configMap + path: /healthz + httpHeaders: + - name: status + value: "200" + initialDelaySeconds: 5 + terminationGracePeriodSeconds: 30 + volumes: + - name: config + configMap: + name: config + defaultMode: 420 --- apiVersion: v1 kind: Service @@ -72,11 +128,11 @@ spec: selector: app: sentryflow ports: - - name: otel-grpc - protocol: TCP - port: 4317 - targetPort: 4317 - - name: sentryflow-grpc - protocol: TCP - port: 8080 - targetPort: 8080 + - name: exporter + port: 8080 + targetPort: 8080 + protocol: TCP + - name: filter-server + port: 8081 # Make sure to use the same port as `.filters.server.port` field in configMap + targetPort: 8081 # Make sure to use the same port as `.filters.server.port` field in configMap + protocol: TCP diff --git a/sentryflow/.dockerignore b/sentryflow/.dockerignore new file mode 100644 index 0000000..6dd29b7 --- /dev/null +++ b/sentryflow/.dockerignore @@ -0,0 +1 @@ +bin/ \ No newline at end of file diff --git a/sentryflow/Dockerfile b/sentryflow/Dockerfile index 4c1df63..a7cc1d5 100644 --- a/sentryflow/Dockerfile +++ b/sentryflow/Dockerfile @@ -1,36 +1,31 @@ -# SPDX-License-Identifier: Apache-2.0 +FROM golang:1.23 AS builder -### Builder +ARG TARGETOS +ARG TARGETARCH -FROM golang:1.21-alpine3.17 as builder +RUN mkdir -p /protobuf/golang -RUN apk --no-cache update -RUN apk add --no-cache git clang llvm make gcc protobuf musl-dev -RUN apk add --update alpine-sdk +COPY protobuf/golang /protobuf/golang -RUN go install github.com/golang/protobuf/protoc-gen-go@latest -RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest - -RUN mkdir /sentryflow -RUN mkdir /protobuf - -WORKDIR /protobuf -COPY /protobuf . +# Required to embed build info into binary. +COPY .git /.git WORKDIR /sentryflow -COPY /sentryflow . -RUN export CGO_ENABLED=1; export CC=gcc; -RUN go build -o sentryflow +COPY sentryflow/go.mod . +COPY sentryflow/go.sum . +RUN go mod download -### Make executable image +COPY sentryflow/cmd cmd/ +COPY sentryflow/pkg pkg/ +COPY sentryflow/main.go main.go +COPY sentryflow/Makefile Makefile -FROM alpine:3.17 as sentryflow +WORKDIR / -# RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories -# RUN apk --no-cache update -# RUN apk add bash +RUN GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} make -C sentryflow build -COPY --from=builder /sentryflow/sentryflow / +FROM scratch +COPY --from=builder /sentryflow/bin/sentryflow / -CMD ["/sentryflow"] +ENTRYPOINT ["/sentryflow"] diff --git a/sentryflow/Makefile b/sentryflow/Makefile index 91e228c..6dbda0f 100644 --- a/sentryflow/Makefile +++ b/sentryflow/Makefile @@ -1,60 +1,67 @@ -# SPDX-License-Identifier: Apache-2.0 +BINARY_NAME ?= sentryflow +REGISTRY ?= docker.io/5gsec +VERSION ?= $(shell git rev-parse HEAD) +BUILD_TS ?= $(shell date) +DOCKER_IMAGE ?= $(REGISTRY)/$(BINARY_NAME) +DOCKER_TAG ?= latest +CONTAINER_TOOL ?= docker -PROG_NAME = sentryflow -IMAGE_NAME = 5gsec/$(PROG_NAME) -TAG = v0.1 +.PHONY: help +help: ## Display this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) -.PHONY: build -build: gofmt golint gosec - go mod tidy - go build -o $(PROG_NAME) - -.PHONY: clean -clean: - rm -f $(PROG_NAME) - -.PHONY: gofmt -gofmt: - cd $(CURDIR); gofmt -w -s -d $(shell find . -type f -name '*.go' -print) - -.PHONY: golint -golint: -ifeq (, $(shell which golint)) - @{ \ - set -e ;\ - GOLINT_TEMP_DIR=$$(mktemp -d) ;\ - cd $$GOLINT_TEMP_DIR ;\ - go mod init tmp ;\ - go get golang.org/x/lint/golint ;\ - go install golang.org/x/lint/golint ;\ - rm -rf $$GOLINT_TEMP_DIR ;\ - } -endif - cd $(CURDIR); golint ./... +.DEFAULT_GOAL := help + +##@ Development +.PHONY: run +run: fmt vet build ## Run SentryFlow on your host + @./bin/"${BINARY_NAME}" --development true + +.PHONY: fmt +fmt: ## Run go fmt against code + @go fmt ./... + +.PHONY: vet +vet: ## Run go vet against code + @go vet ./... -.PHONY: gosec -gosec: -ifeq (, $(shell which gosec)) - @{ \ +GOLANGCI_LINT = $(shell pwd)/bin/golangci-lint +GOLANGCI_LINT_VERSION ?= v1.60.3 +golangci-lint: + @[ -f $(GOLANGCI_LINT) ] || { \ set -e ;\ - GOSEC_TEMP_DIR=$$(mktemp -d) ;\ - cd $$GOSEC_TEMP_DIR ;\ - go mod init tmp ;\ - go get github.com/securego/gosec/v2/cmd/gosec ;\ - go install github.com/securego/gosec/v2/cmd/gosec ;\ - rm -rf $$GOSEC_TEMP_DIR ;\ + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell dirname $(GOLANGCI_LINT)) $(GOLANGCI_LINT_VERSION) ;\ } -endif - cd $(CURDIR); gosec -exclude=G402 ./... -.PHONY: build-image -build-image: - docker build -t $(IMAGE_NAME):$(TAG) -f ./Dockerfile ../ +.PHONY: lint +lint: golangci-lint ## Run golangci-lint linter + @$(GOLANGCI_LINT) run + +.PHONY: license +license: ## Check and fix license header on all go files + @../scripts/add-license-header + +##@ Build + +.PHONY: build +build: fmt vet ## Build SentryFlow binary + @CGO_ENABLED=0 go build -ldflags="-s" -o bin/"${BINARY_NAME}" . + +.PHONY: image +image: ## Build SentryFlow's container image + $(CONTAINER_TOOL) build -t ${DOCKER_IMAGE}:${DOCKER_TAG} -f Dockerfile ../ -.PHONY: clean-image -clean-image: - docker rmi $(IMAGE_NAME):$(TAG) +.PHONY: push +push: ## Push SentryFlow's container image + $(CONTAINER_TOOL) push ${DOCKER_IMAGE}:${DOCKER_TAG} -.PHONY: run-image -run-image: - docker run -it --rm $(IMAGE_NAME):$(TAG) +PLATFORMS ?= linux/arm64,linux/amd64 +.PHONY: imagex +imagex: ## Build and push SentryFlow's container image for cross-platform support + # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile + sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross + - $(CONTAINER_TOOL) buildx create --name project-v3-builder + $(CONTAINER_TOOL) buildx use project-v3-builder + - $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${DOCKER_IMAGE}:${DOCKER_TAG} -f Dockerfile.cross ../ || { $(CONTAINER_TOOL) buildx rm project-v3-builder; rm Dockerfile.cross; exit 1; } + - $(CONTAINER_TOOL) buildx rm project-v3-builder + rm Dockerfile.cross diff --git a/sentryflow/cmd/root.go b/sentryflow/cmd/root.go new file mode 100644 index 0000000..273c9d4 --- /dev/null +++ b/sentryflow/cmd/root.go @@ -0,0 +1,57 @@ +package cmd + +import ( + "context" + + "github.com/spf13/cobra" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + ctrl "sigs.k8s.io/controller-runtime" + + "github.com/5GSEC/SentryFlow/pkg/core" + "github.com/5GSEC/SentryFlow/pkg/util" +) + +var ( + configFilePath string + kubeConfig string + development bool + logger *zap.SugaredLogger +) + +func init() { + RootCmd.PersistentFlags().StringVar(&configFilePath, "config", "", "config file path") + RootCmd.PersistentFlags().StringVar(&kubeConfig, "kubeconfig", "", "kubeconfig file path") + RootCmd.PersistentFlags().BoolVar(&development, "development", false, "run in development mode") +} + +var RootCmd = &cobra.Command{ + Use: "sentryflow", + Short: "API observability", + Long: ` +SentryFlow provides real-time monitoring of API calls made to and from your system. +`, + Run: func(cmd *cobra.Command, args []string) { + run() + }, +} + +func run() { + initLogger(development) + logBuildInfo() + ctx := context.WithValue(ctrl.SetupSignalHandler(), util.LoggerContextKey{}, logger) + core.Run(ctx, configFilePath, kubeConfig) +} + +func initLogger(development bool) { + cfg := zap.NewProductionConfig() + cfg.EncoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder + if development { + cfg = zap.NewDevelopmentConfig() + cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder + } + cfg.EncoderConfig.TimeKey = "timestamp" + cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + coreLogger, _ := cfg.Build() + logger = coreLogger.Sugar() +} diff --git a/sentryflow/cmd/version.go b/sentryflow/cmd/version.go new file mode 100644 index 0000000..77d5f89 --- /dev/null +++ b/sentryflow/cmd/version.go @@ -0,0 +1,20 @@ +package cmd + +import ( + "runtime" + "runtime/debug" +) + +func logBuildInfo() { + info, _ := debug.ReadBuildInfo() + vcsRev := "" + vcsTime := "" + for _, s := range info.Settings { + if s.Key == "vcs.revision" { + vcsRev = s.Value + } else if s.Key == "vcs.time" { + vcsTime = s.Value + } + } + logger.Infof("Git revision: %s, build time: %s, build version: %s, go os/arch: %s/%s", vcsRev, vcsTime, info.Main.Version, runtime.GOOS, runtime.GOARCH) +} diff --git a/sentryflow/collector/collectorHandler.go b/sentryflow/collector/collectorHandler.go deleted file mode 100644 index 043c569..0000000 --- a/sentryflow/collector/collectorHandler.go +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package collector - -import ( - "fmt" - "github.com/5gsec/SentryFlow/config" - "google.golang.org/grpc" - "log" - "net" - "net/http" -) - -// == // - -// ColH global reference for Collector Handler -var ColH *ColHandler - -// init Function -func init() { - ColH = NewCollectorHandler() -} - -// ColHandler Structure -type ColHandler struct { - colService net.Listener - grpcServer *grpc.Server - collectors []collectorInterface -} - -// NewCollectorHandler Function -func NewCollectorHandler() *ColHandler { - ch := &ColHandler{ - collectors: make([]collectorInterface, 0), - } - return ch -} - -// == // - -// StartCollector Function -func StartCollector() bool { - // Make a string with the given collector address and port - collectorService := fmt.Sprintf("%s:%s", config.GlobalConfig.CollectorAddr, config.GlobalConfig.CollectorPort) - - // Start listening gRPC port - colService, err := net.Listen("tcp", collectorService) - if err != nil { - log.Printf("[Collector] Failed to listen at %s: %v", collectorService, err) - return false - } - ColH.colService = colService - - log.Printf("[Collector] Listening Collector gRPC services (%s)", collectorService) - - // Create gRPC Service - gRPCServer := grpc.NewServer() - ColH.grpcServer = gRPCServer - - // initialize OpenTelemetry collector - ColH.collectors = append(ColH.collectors, newOpenTelemetryLogsServer()) - - // initialize Envoy collectors for AccessLogs and Metrics - ColH.collectors = append(ColH.collectors, newEnvoyAccessLogsServer()) - ColH.collectors = append(ColH.collectors, newEnvoyMetricsServer()) - - // register services - for _, col := range ColH.collectors { - col.registerService(ColH.grpcServer) - } - - log.Print("[Collector] Initialized Collector gRPC services") - - // Serve gRPC Service - go ColH.grpcServer.Serve(ColH.colService) - - log.Print("[Collector] Serving Collector gRPC services") - - // Start the http server - address := fmt.Sprintf("%s:%s", config.GlobalConfig.ApiLogCollectorAddr, config.GlobalConfig.ApiLogCollectorPort) - log.Print("[Collector] Serving Collector http service on ", address) - go func() { - // Create a new HTTP server - http.HandleFunc("/api/v1/events", DataHandler) - err = http.ListenAndServe(address, nil) - if err != nil { - log.Println("[Collector] Error serving Collector http service on ", err.Error()) - panic(err) - } - }() - - return true -} - -// StopCollector Function -func StopCollector() bool { - ColH.grpcServer.GracefulStop() - - log.Print("[Collector] Gracefully stopped Collector gRPC services") - - return true -} - -// == // diff --git a/sentryflow/collector/envoy.go b/sentryflow/collector/envoy.go deleted file mode 100644 index 7fbccee..0000000 --- a/sentryflow/collector/envoy.go +++ /dev/null @@ -1,226 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package collector - -import ( - "io" - "log" - "strconv" - - "github.com/5gsec/SentryFlow/k8s" - "github.com/5gsec/SentryFlow/processor" - "github.com/5gsec/SentryFlow/protobuf" - "github.com/5gsec/SentryFlow/types" - - envoyAccLogsData "github.com/envoyproxy/go-control-plane/envoy/data/accesslog/v3" - envoyAccLogs "github.com/envoyproxy/go-control-plane/envoy/service/accesslog/v3" - envoyMetrics "github.com/envoyproxy/go-control-plane/envoy/service/metrics/v3" - - "google.golang.org/grpc" -) - -// == // - -// EnvoyAccessLogsServer Structure -type EnvoyAccessLogsServer struct { - envoyAccLogs.UnimplementedAccessLogServiceServer - collectorInterface -} - -// newEnvoyAccessLogsServer Function -func newEnvoyAccessLogsServer() *EnvoyAccessLogsServer { - ret := &EnvoyAccessLogsServer{} - return ret -} - -// registerService Function -func (evyAccLogs *EnvoyAccessLogsServer) registerService(server *grpc.Server) { - envoyAccLogs.RegisterAccessLogServiceServer(server, evyAccLogs) -} - -// == // - -// EnvoyMetricsServer Structure -type EnvoyMetricsServer struct { - envoyMetrics.UnimplementedMetricsServiceServer - collectorInterface -} - -// newEnvoyMetricsServer Function -func newEnvoyMetricsServer() *EnvoyMetricsServer { - ret := &EnvoyMetricsServer{} - return ret -} - -// registerService Function -func (evyMetrics *EnvoyMetricsServer) registerService(server *grpc.Server) { - envoyMetrics.RegisterMetricsServiceServer(server, evyMetrics) -} - -// == // - -// generateAPILogsFromEnvoy Function -func generateAPILogsFromEnvoy(entry *envoyAccLogsData.HTTPAccessLogEntry) *protobuf.APILog { - comm := entry.GetCommonProperties() - timeStamp := comm.GetStartTime().Seconds - - srcInform := entry.GetCommonProperties().GetDownstreamRemoteAddress().GetSocketAddress() - srcIP := srcInform.GetAddress() - srcPort := strconv.Itoa(int(srcInform.GetPortValue())) - src := k8s.LookupK8sResource(srcIP) - - dstInform := entry.GetCommonProperties().GetUpstreamRemoteAddress().GetSocketAddress() - dstIP := dstInform.GetAddress() - dstPort := strconv.Itoa(int(dstInform.GetPortValue())) - dst := k8s.LookupK8sResource(dstIP) - - request := entry.GetRequest() - response := entry.GetResponse() - - protocol := entry.GetProtocolVersion().String() - method := request.GetRequestMethod().String() - path := request.GetPath() - resCode := response.GetResponseCode().GetValue() - - envoyAPILog := &protobuf.APILog{ - Id: 0, // @todo zero for now - TimeStamp: strconv.FormatInt(timeStamp, 10), - - SrcNamespace: src.Namespace, - SrcName: src.Name, - SrcLabel: src.Labels, - SrcIP: srcIP, - SrcPort: srcPort, - SrcType: types.K8sResourceTypeToString(src.Type), - - DstNamespace: dst.Namespace, - DstName: dst.Name, - DstLabel: dst.Labels, - DstIP: dstIP, - DstPort: dstPort, - DstType: types.K8sResourceTypeToString(dst.Type), - - Protocol: protocol, - Method: method, - Path: path, - ResponseCode: int32(resCode), - } - - return envoyAPILog -} - -// StreamAccessLogs Function -func (evyAccLogs *EnvoyAccessLogsServer) StreamAccessLogs(stream envoyAccLogs.AccessLogService_StreamAccessLogsServer) error { - for { - event, err := stream.Recv() - if err == io.EOF { - return nil - } else if err != nil { - log.Printf("[EnvoyAPILogs] Failed to receive an event: %v", err) - return err - } - - if event.GetHttpLogs() != nil { - for _, entry := range event.GetHttpLogs().LogEntry { - envoyAPILog := generateAPILogsFromEnvoy(entry) - processor.InsertAPILog(envoyAPILog) - } - } - } -} - -// == // - -// generateMetricsFromEnvoy Function -func generateMetricsFromEnvoy(event *envoyMetrics.StreamMetricsMessage, metaData map[string]interface{}) *protobuf.EnvoyMetrics { - envoyMetrics := &protobuf.EnvoyMetrics{ - TimeStamp: "", - - Namespace: metaData["NAMESPACE"].(string), - Name: metaData["NAME"].(string), - IPAddress: metaData["INSTANCE_IPS"].(string), - Labels: k8s.LookupK8sResource(metaData["INSTANCE_IPS"].(string)).Labels, - - Metrics: make(map[string]*protobuf.MetricValue), - } - - envoyMetrics.Metrics["GAUGE"] = &protobuf.MetricValue{ - Value: make(map[string]string), - } - - envoyMetrics.Metrics["COUNTER"] = &protobuf.MetricValue{ - Value: make(map[string]string), - } - - envoyMetrics.Metrics["HISTOGRAM"] = &protobuf.MetricValue{ - Value: make(map[string]string), - } - - envoyMetrics.Metrics["SUMMARY"] = &protobuf.MetricValue{ - Value: make(map[string]string), - } - - for _, metric := range event.GetEnvoyMetrics() { - metricType := metric.GetType().String() - metricName := metric.GetName() - - if envoyMetrics.Metrics[metricType].Value == nil { - continue - } - - for _, metricDetail := range metric.GetMetric() { - var metricValue string - - if envoyMetrics.TimeStamp == "" { - envoyMetrics.TimeStamp = strconv.FormatInt(metricDetail.GetTimestampMs(), 10) - } - - if metricType == "GAUGE" { - metricValue = strconv.FormatFloat(metricDetail.GetGauge().GetValue(), 'f', -1, 64) - } - - if metricType == "COUNTER" { - metricValue = strconv.FormatFloat(metricDetail.GetCounter().GetValue(), 'f', -1, 64) - } - - if metricType == "HISTOGRAM" { - metricValue = strconv.FormatUint(metricDetail.GetHistogram().GetSampleCount(), 10) - } - - if metricType == "SUMMARY" { - metricValue = strconv.FormatUint(metricDetail.GetHistogram().GetSampleCount(), 10) - } - - envoyMetrics.Metrics[metricType].Value[metricName] = metricValue - } - } - - return envoyMetrics -} - -// StreamMetrics Function -func (evyMetrics *EnvoyMetricsServer) StreamMetrics(stream envoyMetrics.MetricsService_StreamMetricsServer) error { - event, err := stream.Recv() - if err == io.EOF { - return nil - } else if err != nil { - log.Printf("[EnvoyMetrics] Failed to receive an event: %v", err) - return err - } - - err = event.ValidateAll() - if err != nil { - log.Printf("[EnvoyMetrics] Failed to validate an event: %v", err) - } - - identifier := event.GetIdentifier() - if identifier != nil { - metaData := identifier.GetNode().GetMetadata().AsMap() - envoyMetrics := generateMetricsFromEnvoy(event, metaData) - processor.InsertMetrics(envoyMetrics) - } - - return nil -} - -// == // diff --git a/sentryflow/collector/interface.go b/sentryflow/collector/interface.go deleted file mode 100644 index a610c4f..0000000 --- a/sentryflow/collector/interface.go +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package collector - -import ( - "google.golang.org/grpc" -) - -// == // - -// collectorInterface Interface -type collectorInterface interface { - registerService(server *grpc.Server) -} - -// == // diff --git a/sentryflow/collector/opentelemetry.go b/sentryflow/collector/opentelemetry.go deleted file mode 100644 index 05f9830..0000000 --- a/sentryflow/collector/opentelemetry.go +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package collector - -import ( - "context" - "strconv" - "strings" - - "github.com/5gsec/SentryFlow/k8s" - "github.com/5gsec/SentryFlow/processor" - "github.com/5gsec/SentryFlow/protobuf" - "github.com/5gsec/SentryFlow/types" - otelLogs "go.opentelemetry.io/proto/otlp/collector/logs/v1" - "google.golang.org/grpc" -) - -// == // - -// OpenTelemetryLogsServer structure -type OpenTelemetryLogsServer struct { - otelLogs.UnimplementedLogsServiceServer - collectorInterface -} - -// newOpenTelemetryLogsServer Function -func newOpenTelemetryLogsServer() *OpenTelemetryLogsServer { - ret := &OpenTelemetryLogsServer{} - return ret -} - -// registerService Function -func (otlLogs *OpenTelemetryLogsServer) registerService(server *grpc.Server) { - otelLogs.RegisterLogsServiceServer(server, otlLogs) -} - -// == // - -// generateAPILogsFromOtel Function -func generateAPILogsFromOtel(logText string) []*protobuf.APILog { - apiLogs := make([]*protobuf.APILog, 0) - - // Preprocess redundant chars - logText = strings.ReplaceAll(logText, `\"`, "") - logText = strings.ReplaceAll(logText, `}`, "") - - // Split logs by log_records, this is a single access log instance - parts := strings.Split(logText, "log_records") - if len(parts) == 0 { - return nil - } - - // Ignore the first entry (the metadata "resource_logs:{resource:{ scope_logs:{" part) - for _, accessLog := range parts[0:] { - var srcIP string - var srcPort string - var dstIP string - var dstPort string - - if len(accessLog) == 0 { - continue - } - - index := strings.Index(accessLog, "string_value:\"") - if index == -1 { - continue - } - - words := strings.Fields(accessLog[index+len("string_value:\""):]) - - timeStamp := words[0] - method := words[1] - path := words[2] - protocol := words[3] - resCode, _ := strconv.ParseInt(words[4], 10, 64) - - srcInform := words[21] - - // Extract the left and right words based on the colon delimiter (ADDR:PORT) - colonIndex := strings.LastIndex(srcInform, ":") - if colonIndex > 0 && colonIndex < len(srcInform)-1 { - srcIP = strings.TrimSpace(srcInform[:colonIndex]) - srcPort = strings.TrimSpace(srcInform[colonIndex+1:]) - } - src := k8s.LookupK8sResource(srcIP) - - dstInform := words[20] - - // Extract the left and right words based on the colon delimiter (ADDR:PORT) - colonIndex = strings.LastIndex(dstInform, ":") - if colonIndex > 0 && colonIndex < len(dstInform)-1 { - dstIP = strings.TrimSpace(dstInform[:colonIndex]) - dstPort = strings.TrimSpace(dstInform[colonIndex+1:]) - } - dst := k8s.LookupK8sResource(dstIP) - - // Create APILog - apiLog := protobuf.APILog{ - Id: 0, // @todo zero for now - TimeStamp: timeStamp, - - SrcNamespace: src.Namespace, - SrcName: src.Name, - SrcLabel: src.Labels, - SrcIP: srcIP, - SrcPort: srcPort, - SrcType: types.K8sResourceTypeToString(src.Type), - - DstNamespace: dst.Namespace, - DstName: dst.Name, - DstLabel: dst.Labels, - DstIP: dstIP, - DstPort: dstPort, - DstType: types.K8sResourceTypeToString(dst.Type), - - Protocol: protocol, - Method: method, - Path: path, - ResponseCode: int32(resCode), - } - - apiLogs = append(apiLogs, &apiLog) - } - - return apiLogs -} - -// Export Function for Log.Export in OpenTelemetry format -func (otlLogs *OpenTelemetryLogsServer) Export(_ context.Context, req *otelLogs.ExportLogsServiceRequest) (*otelLogs.ExportLogsServiceResponse, error) { - apiLogs := generateAPILogsFromOtel(req.String()) - for _, apiLog := range apiLogs { - processor.InsertAPILog(apiLog) - } - - // @todo not consider partial success - ret := otelLogs.ExportLogsServiceResponse{ - PartialSuccess: nil, - } - - return &ret, nil -} - -// == // diff --git a/sentryflow/collector/wasm.go b/sentryflow/collector/wasm.go deleted file mode 100644 index cd1379c..0000000 --- a/sentryflow/collector/wasm.go +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package collector - -import ( - "encoding/json" - "github.com/5gsec/SentryFlow/processor" - "github.com/5gsec/SentryFlow/protobuf" - "io/ioutil" - "log" - "net/http" -) - -// Handler for the HTTP endpoint to receive api events from WASM filter -func DataHandler(w http.ResponseWriter, r *http.Request) { - // Check if the request is POST - if r.Method != http.MethodPost { - http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed) - return - } - - // Read the request body - body, err := ioutil.ReadAll(r.Body) - if err != nil { - http.Error(w, "Failed to read request body", http.StatusInternalServerError) - return - } - // Parse the JSON data into the TelemetryData struct - var apiLog *protobuf.APILogV2 - err = json.Unmarshal(body, &apiLog) - if err != nil { - log.Print("failed to parse json") - log.Print(err.Error()) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - // Check protocol version - if r.ProtoMajor == 2 { - apiLog.Protocol = "HTTP/2.0" - } else if r.ProtoMajor == 1 && r.ProtoMinor == 1 { - apiLog.Protocol = "HTTP/1.1" - } else if r.ProtoMajor == 1 && r.ProtoMinor == 0 { - apiLog.Protocol = "HTTP/1.0" - } else { - apiLog.Protocol = "Unknown" - } - processor.InsertAPILog(apiLog) - - // Log the received telemetry data - log.Printf("Received data: %+v\n", apiLog) -} diff --git a/sentryflow/config/config.go b/sentryflow/config/config.go deleted file mode 100644 index 15e2c7e..0000000 --- a/sentryflow/config/config.go +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package config - -import ( - "flag" - "fmt" - "log" - "strings" - - "github.com/spf13/viper" -) - -// SentryFlowConfig structure -type SentryFlowConfig struct { - CollectorAddr string // Address for Collector gRPC - CollectorPort string // Port for Collector gRPC - ApiLogCollectorAddr string // Address for API Log HTTP Collector - ApiLogCollectorPort string // Port for API Log HTTP Collector - - ExporterAddr string // IP address to use for exporter gRPC - ExporterPort string // Port to use for exporter gRPC - - PatchingNamespaces bool // Enable/Disable patching namespaces with 'istio-injection' - RestartingPatchedDeployments bool // Enable/Disable restarting deployments after patching - - AggregationPeriod int // Period for aggregating metrics - CleanUpPeriod int // Period for cleaning up outdated metrics - - AIEngineService string // Address for AI Engine - AIEngineServicePort string // Port for AI Engine - AIEngineBatchSize int // Batch Size to send APIs to AI Engine - - Debug bool // Enable/Disable SentryFlow debug mode -} - -// GlobalConfig Global configuration for SentryFlow -var GlobalConfig SentryFlowConfig - -// init Function -func init() { - _ = LoadConfig() -} - -// Config const -const ( - CollectorAddr string = "collectorAddr" - CollectorPort string = "collectorPort" - ApiLogCollectorAddr string = "apiLogCollectorAddr" - ApiLogCollectorPort string = "apiLogCollectorPort" - - ExporterAddr string = "exporterAddr" - ExporterPort string = "exporterPort" - - PatchingNamespaces string = "patchingNamespaces" - RestartingPatchedDeployments string = "restartingPatchedDeployments" - - AggregationPeriod string = "aggregationPeriod" - CleanUpPeriod string = "cleanUpPeriod" - - AIEngineService string = "aiEngineService" - AIEngineServicePort string = "aiEngineServicePort" - AIEngineBatchSize string = "aiEngineBatchSize" - - Debug string = "debug" -) - -func readCmdLineParams() { - collectorAddrStr := flag.String(CollectorAddr, "0.0.0.0", "Address for Collector gRPC") - collectorPortStr := flag.String(CollectorPort, "4317", "Port for Collector gRPC") - apiLogCollectorAddrStr := flag.String(ApiLogCollectorAddr, "0.0.0.0", "Address for API log HTTP Colletor") - apiLogCollectorPortStr := flag.String(ApiLogCollectorPort, "8081", "Port for API log HTTP Colletor") - - exporterAddrStr := flag.String(ExporterAddr, "0.0.0.0", "Address for Exporter gRPC") - exporterPortStr := flag.String(ExporterPort, "8080", "Port for Exporter gRPC") - - patchingNamespacesB := flag.Bool(PatchingNamespaces, false, "Enable patching 'istio-injection' to all namespaces") - restartingPatchedDeploymentsB := flag.Bool(RestartingPatchedDeployments, false, "Enable restarting the deployments in all patched namespaces") - - aggregationPeriodInt := flag.Int(AggregationPeriod, 1, "Period for aggregating metrics") - cleanUpPeriodInt := flag.Int(CleanUpPeriod, 5, "Period for cleanning up outdated metrics") - - aiEngineServiceStr := flag.String(AIEngineService, "ai-engine.sentryflow.svc.cluster.local", "Address for SentryFlow AI Engine") - aiEngineServicePortStr := flag.String(AIEngineServicePort, "5000", "Port for SentryFlow AI Engine") - aiEngineBatchSizeInt := flag.Int(AIEngineBatchSize, 5, "Batch size to send APIs to SentryFlow AI Engine") - - configDebugB := flag.Bool(Debug, false, "Enable debugging mode") - - var flags []string - flag.VisitAll(func(f *flag.Flag) { - kv := fmt.Sprintf("%s:%v", f.Name, f.Value) - flags = append(flags, kv) - }) - log.Printf("Arguments [%s]", strings.Join(flags, " ")) - - flag.Parse() - - viper.SetDefault(CollectorAddr, *collectorAddrStr) - viper.SetDefault(CollectorPort, *collectorPortStr) - viper.SetDefault(ApiLogCollectorAddr, *apiLogCollectorAddrStr) - viper.SetDefault(ApiLogCollectorPort, *apiLogCollectorPortStr) - - viper.SetDefault(ExporterAddr, *exporterAddrStr) - viper.SetDefault(ExporterPort, *exporterPortStr) - - viper.SetDefault(PatchingNamespaces, *patchingNamespacesB) - viper.SetDefault(RestartingPatchedDeployments, *restartingPatchedDeploymentsB) - - viper.SetDefault(AggregationPeriod, *aggregationPeriodInt) - viper.SetDefault(CleanUpPeriod, *cleanUpPeriodInt) - - viper.SetDefault(AIEngineService, *aiEngineServiceStr) - viper.SetDefault(AIEngineServicePort, *aiEngineServicePortStr) - viper.SetDefault(AIEngineBatchSize, *aiEngineBatchSizeInt) - - viper.SetDefault(Debug, *configDebugB) -} - -// LoadConfig Load configuration -func LoadConfig() error { - // Read configuration from command line - readCmdLineParams() - - // Read environment variable, those are upper-cased - viper.AutomaticEnv() - - GlobalConfig.CollectorAddr = viper.GetString(CollectorAddr) - GlobalConfig.CollectorPort = viper.GetString(CollectorPort) - GlobalConfig.ApiLogCollectorAddr = viper.GetString(ApiLogCollectorAddr) - GlobalConfig.ApiLogCollectorPort = viper.GetString(ApiLogCollectorPort) - GlobalConfig.ExporterAddr = viper.GetString(ExporterAddr) - GlobalConfig.ExporterPort = viper.GetString(ExporterPort) - - GlobalConfig.PatchingNamespaces = viper.GetBool(PatchingNamespaces) - GlobalConfig.RestartingPatchedDeployments = viper.GetBool(RestartingPatchedDeployments) - - GlobalConfig.AggregationPeriod = viper.GetInt(AggregationPeriod) - GlobalConfig.CleanUpPeriod = viper.GetInt(CleanUpPeriod) - - GlobalConfig.AIEngineService = viper.GetString(AIEngineService) - GlobalConfig.AIEngineServicePort = viper.GetString(AIEngineServicePort) - GlobalConfig.AIEngineBatchSize = viper.GetInt(AIEngineBatchSize) - - GlobalConfig.Debug = viper.GetBool(Debug) - - log.Printf("Configuration [%+v]", GlobalConfig) - - return nil -} diff --git a/sentryflow/config/default.yaml b/sentryflow/config/default.yaml new file mode 100644 index 0000000..c440052 --- /dev/null +++ b/sentryflow/config/default.yaml @@ -0,0 +1,24 @@ +filters: + server: + port: 8081 + + envoy: + uri: anuragrajawat/httpfilter:v0.1 + +receivers: # aka sources + serviceMeshes: + - name: istio-sidecar + namespace: istio-system + others: # TBD + - name: "coroot" + # Either gRPC or HTTP not both + grpc: + url: localhost + port: 1234 + http: + url: localhost + port: 4321 + +exporter: + grpc: + port: 8080 diff --git a/sentryflow/core/sentryflow.go b/sentryflow/core/sentryflow.go deleted file mode 100644 index 886a2ae..0000000 --- a/sentryflow/core/sentryflow.go +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package core - -import ( - "log" - "os" - "os/signal" - "sync" - "syscall" - - "github.com/5gsec/SentryFlow/collector" - "github.com/5gsec/SentryFlow/config" - "github.com/5gsec/SentryFlow/exporter" - "github.com/5gsec/SentryFlow/k8s" - "github.com/5gsec/SentryFlow/processor" -) - -// == // - -// StopChan Channel -var StopChan chan struct{} - -// init Function -func init() { - StopChan = make(chan struct{}) -} - -// SentryFlowService Structure -type SentryFlowService struct { - waitGroup *sync.WaitGroup -} - -// NewSentryFlow Function -func NewSentryFlow() *SentryFlowService { - sf := new(SentryFlowService) - sf.waitGroup = new(sync.WaitGroup) - return sf -} - -// DestroySentryFlow Function -func (sf *SentryFlowService) DestroySentryFlow() { - close(StopChan) - - // Remove SentryFlow collector config from Kubernetes - if k8s.UnpatchIstioConfigMap() { - log.Print("[SentryFlow] Unpatched Istio ConfigMap") - } else { - log.Print("[SentryFlow] Failed to unpatch Istio ConfigMap") - } - - // Stop collector - if collector.StopCollector() { - log.Print("[SentryFlow] Stopped Collectors") - } else { - log.Print("[SentryFlow] Failed to stop Collectors") - } - - // Stop Log Processor - if processor.StopLogProcessor() { - log.Print("[SentryFlow] Stopped Log Processors") - } else { - log.Print("[SentryFlow] Failed to stop Log Processors") - } - - // Stop API Aanalyzer - if processor.StopAPIAnalyzer() { - log.Print("[SentryFlow] Stopped API Analyzer") - } else { - log.Print("[SentryFlow] Failed to stop API Analyzer") - } - - // Stop API classifier - // if processor.StopAPIClassifier() { - // log.Print("[SentryFlow] Stopped API Classifier") - // } else { - // log.Print("[SentryFlow] Failed to stop API Classifier") - // } - - // Stop exporter - if exporter.StopExporter() { - log.Print("[SentryFlow] Stopped Exporters") - } else { - log.Print("[SentryFlow] Failed to stop Exporters") - } - - log.Print("[SentryFlow] Waiting for routine terminations") - - sf.waitGroup.Wait() - - log.Print("[SentryFlow] Terminated SentryFlow") -} - -// == // - -// GetOSSigChannel Function -func GetOSSigChannel() chan os.Signal { - c := make(chan os.Signal, 1) - - signal.Notify(c, - syscall.SIGHUP, - syscall.SIGINT, - syscall.SIGTERM, - syscall.SIGQUIT, - os.Interrupt) - - return c -} - -// == // - -// SentryFlow Function -func SentryFlow() { - sf := NewSentryFlow() - - log.Print("[SentryFlow] Initializing SentryFlow") - - // == // - - // Initialize Kubernetes client - if !k8s.InitK8sClient() { - sf.DestroySentryFlow() - return - } - - // Start Kubernetes informers - k8s.RunInformers(StopChan, sf.waitGroup) - - // Patch Istio ConfigMap - if !k8s.PatchIstioConfigMap() { - sf.DestroySentryFlow() - return - } - - // Patch Namespaces - if config.GlobalConfig.PatchingNamespaces { - if !k8s.PatchNamespaces() { - sf.DestroySentryFlow() - return - } - } - - // Patch Deployments - if config.GlobalConfig.RestartingPatchedDeployments { - if !k8s.RestartDeployments() { - sf.DestroySentryFlow() - return - } - } - - // == // - - // Start collector - if !collector.StartCollector() { - sf.DestroySentryFlow() - return - } - - // Start log processor - if !processor.StartLogProcessor(sf.waitGroup) { - sf.DestroySentryFlow() - return - } - - // Start API analyzer - if !processor.StartAPIAnalyzer(sf.waitGroup) { - sf.DestroySentryFlow() - return - } - - // Start API classifier - // if !processor.StartAPIClassifier(sf.waitGroup) { - // sf.DestroySentryFlow() - // return - // } - - // Start exporter - if !exporter.StartExporter(sf.waitGroup) { - sf.DestroySentryFlow() - return - } - - log.Print("[SentryFlow] Initialization is completed") - - // == // - - // listen for interrupt signals - sigChan := GetOSSigChannel() - <-sigChan - log.Print("Got a signal to terminate SentryFlow") - - // == // - - // Destroy SentryFlow - sf.DestroySentryFlow() -} diff --git a/sentryflow/exporter/exportAPILogs.go b/sentryflow/exporter/exportAPILogs.go deleted file mode 100644 index 5fe1f27..0000000 --- a/sentryflow/exporter/exportAPILogs.go +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package exporter - -import ( - "errors" - "fmt" - "log" - "sort" - "strings" - - "github.com/5gsec/SentryFlow/protobuf" -) - -// == // - -// apiLogStreamInform structure -type apiLogStreamInform struct { - Hostname string - IPAddress string - - stream protobuf.SentryFlow_GetAPILogServer - error chan error -} - -// apiLogStreamInformV2 structure -type apiLogStreamInformV2 struct { - Hostname string - IPAddress string - - stream protobuf.SentryFlow_GetAPILogV2Server - error chan error -} - -// GetAPILog Function (for gRPC) -func (exs *ExpService) GetAPILog(info *protobuf.ClientInfo, stream protobuf.SentryFlow_GetAPILogServer) error { - log.Printf("[Exporter] Client %s (%s) connected (GetAPILog)", info.HostName, info.IPAddress) - - currExporter := &apiLogStreamInform{ - Hostname: info.HostName, - IPAddress: info.IPAddress, - stream: stream, - } - - ExpH.exporterLock.Lock() - ExpH.apiLogExporters = append(ExpH.apiLogExporters, currExporter) - ExpH.exporterLock.Unlock() - - return <-currExporter.error -} - -// GetAPILogV2 Function (for gRPC) -func (exs *ExpService) GetAPILogV2(info *protobuf.ClientInfo, stream protobuf.SentryFlow_GetAPILogV2Server) error { - log.Printf("[Exporter] Client %s (%s) connected (GetAPILogV2)", info.HostName, info.IPAddress) - - currExporter := &apiLogStreamInformV2{ - Hostname: info.HostName, - IPAddress: info.IPAddress, - stream: stream, - } - - ExpH.exporterLock.Lock() - ExpH.apiLogExportersV2 = append(ExpH.apiLogExportersV2, currExporter) - ExpH.exporterLock.Unlock() - - return <-currExporter.error -} - -// SendAPILogs Function -func (exp *ExpHandler) SendAPILogs(apiLog *protobuf.APILog) error { - failed := 0 - total := len(exp.apiLogExporters) - - for _, exporter := range exp.apiLogExporters { - log.Print("Sending api log!!!!") - log.Printf("Sending api log right here!!!!! %+v\n", apiLog) - if err := exporter.stream.Send(apiLog); err != nil { - log.Printf("[Exporter] Failed to export an API log to %s (%s): %v", exporter.Hostname, exporter.IPAddress, err) - failed++ - } - } - - if failed != 0 { - msg := fmt.Sprintf("[Exporter] Failed to export API logs properly (%d/%d failed)", failed, total) - return errors.New(msg) - } - - return nil -} - -// SendAPILogsV2 Function -func (exp *ExpHandler) SendAPILogsV2(apiLog *protobuf.APILogV2) error { - failed := 0 - total := len(exp.apiLogExportersV2) - - for _, exporter := range exp.apiLogExportersV2 { - if err := exporter.stream.Send(apiLog); err != nil { - log.Printf("[Exporter] Failed to export an API log(V2) to %s (%s): %v", exporter.Hostname, exporter.IPAddress, err) - failed++ - } - } - - if failed != 0 { - msg := fmt.Sprintf("[Exporter] Failed to export API logs(V2) properly (%d/%d failed)", failed, total) - return errors.New(msg) - } - - return nil -} - -// == // - -// InsertAPILog Function -func InsertAPILog(apiLog interface{}) { - switch data := apiLog.(type) { - case *protobuf.APILog: - ExpH.exporterAPILogs <- data - // Make a string with labels - var labelString []string - for k, v := range data.SrcLabel { - labelString = append(labelString, fmt.Sprintf("%s:%s", k, v)) - } - sort.Strings(labelString) - - // Update Stats per namespace and per labels - UpdateStats(data.SrcNamespace, strings.Join(labelString, ","), data.GetPath()) - case *protobuf.APILogV2: - ExpH.exporterAPILogsV2 <- data - } -} - -// == // diff --git a/sentryflow/exporter/exportAPIMetrics.go b/sentryflow/exporter/exportAPIMetrics.go deleted file mode 100644 index 65502fb..0000000 --- a/sentryflow/exporter/exportAPIMetrics.go +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package exporter - -import ( - "errors" - "fmt" - "log" - "time" - - "github.com/5gsec/SentryFlow/config" - "github.com/5gsec/SentryFlow/protobuf" -) - -// == // - -// Stats Structure -type Stats struct { - Count int -} - -// StatsPerLabel structure -type StatsPerLabel struct { - APIs map[string]Stats - LastUpdated uint64 -} - -// == // - -// apiMetricStreamInform structure -type apiMetricStreamInform struct { - Hostname string - IPAddress string - - apiMetricsStream protobuf.SentryFlow_GetAPIMetricsServer - - error chan error -} - -// GetAPIMetrics Function (for gRPC) -func (exs *ExpService) GetAPIMetrics(info *protobuf.ClientInfo, stream protobuf.SentryFlow_GetAPIMetricsServer) error { - log.Printf("[Exporter] Client %s (%s) connected (GetAPIMetrics)", info.HostName, info.IPAddress) - - currExporter := &apiMetricStreamInform{ - Hostname: info.HostName, - IPAddress: info.IPAddress, - apiMetricsStream: stream, - } - - ExpH.exporterLock.Lock() - ExpH.apiMetricsExporters = append(ExpH.apiMetricsExporters, currExporter) - ExpH.exporterLock.Unlock() - - return <-currExporter.error -} - -// SendAPIMetrics Function -func (exp *ExpHandler) SendAPIMetrics(apiMetrics *protobuf.APIMetrics) error { - failed := 0 - total := len(exp.apiMetricsExporters) - - for _, exporter := range exp.apiMetricsExporters { - if err := exporter.apiMetricsStream.Send(apiMetrics); err != nil { - log.Printf("[Exporter] Failed to export API metrics to %s (%s): %v", exporter.Hostname, exporter.IPAddress, err) - failed++ - } - } - - if failed != 0 { - msg := fmt.Sprintf("[Exporter] Failed to export API metrics properly (%d/%d failed)", failed, total) - return errors.New(msg) - } - - return nil -} - -// == // - -// UpdateStats Function -func UpdateStats(namespace string, label string, api string) { - ExpH.statsPerLabelLock.RLock() - defer ExpH.statsPerLabelLock.RUnlock() - - // Check if namespace+label exists - if _, ok := ExpH.statsPerLabel[namespace+label]; !ok { - ExpH.statsPerLabel[namespace+label] = StatsPerLabel{ - APIs: make(map[string]Stats), - LastUpdated: uint64(time.Now().Unix()), - } - } - - statsPerLabel := ExpH.statsPerLabel[namespace+label] - statsPerLabel.LastUpdated = uint64(time.Now().Unix()) - - // Check if API exists - if _, ok := statsPerLabel.APIs[api]; !ok { - init := Stats{ - Count: 1, - } - statsPerLabel.APIs[api] = init - } else { - stats := statsPerLabel.APIs[api] - stats.Count++ - statsPerLabel.APIs[api] = stats - } - - ExpH.statsPerLabel[namespace+label] = statsPerLabel -} - -// AggregateAPIMetrics Function -func AggregateAPIMetrics() { - ticker := time.NewTicker(time.Duration(config.GlobalConfig.AggregationPeriod) * time.Second) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - ExpH.statsPerLabelLock.RLock() - - APIMetrics := make(map[string]uint64) - - for _, statsPerLabel := range ExpH.statsPerLabel { - for api, stats := range statsPerLabel.APIs { - APIMetrics[api] = uint64(stats.Count) - } - } - - if len(APIMetrics) > 0 { - err := ExpH.SendAPIMetrics(&protobuf.APIMetrics{PerAPICounts: APIMetrics}) - if err != nil { - log.Printf("[Envoy] Failed to export API metrics: %v", err) - return - } - } - - ExpH.statsPerLabelLock.RUnlock() - case <-ExpH.stopChan: - return - } - } -} - -// CleanUpOutdatedStats Function -func CleanUpOutdatedStats() { - ticker := time.NewTicker(time.Duration(config.GlobalConfig.CleanUpPeriod) * time.Second) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - ExpH.statsPerLabelLock.Lock() - - cleanUpTime := uint64((time.Now().Add(-time.Duration(config.GlobalConfig.CleanUpPeriod) * time.Second)).Unix()) - labelToDelete := []string{} - - for label, statsPerLabel := range ExpH.statsPerLabel { - if statsPerLabel.LastUpdated < cleanUpTime { - labelToDelete = append(labelToDelete, label) - } - } - - for _, label := range labelToDelete { - delete(ExpH.statsPerLabel, label) - } - - ExpH.statsPerLabelLock.Unlock() - case <-ExpH.stopChan: - return - } - } -} - -// == // - -// Exporting API metrics is handled by API Classifier - -// == // diff --git a/sentryflow/exporter/exportEnvoyMetrics.go b/sentryflow/exporter/exportEnvoyMetrics.go deleted file mode 100644 index 7caf94a..0000000 --- a/sentryflow/exporter/exportEnvoyMetrics.go +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package exporter - -import ( - "errors" - "fmt" - "log" - - "github.com/5gsec/SentryFlow/protobuf" -) - -// == // - -// envoyMetricsStreamInform structure -type envoyMetricsStreamInform struct { - Hostname string - IPAddress string - - metricsStream protobuf.SentryFlow_GetEnvoyMetricsServer - - error chan error -} - -// GetEnvoyMetrics Function (for gRPC) -func (exs *ExpService) GetEnvoyMetrics(info *protobuf.ClientInfo, stream protobuf.SentryFlow_GetEnvoyMetricsServer) error { - log.Printf("[Exporter] Client %s (%s) connected (GetEnvoyMetrics)", info.HostName, info.IPAddress) - - currExporter := &envoyMetricsStreamInform{ - Hostname: info.HostName, - IPAddress: info.IPAddress, - metricsStream: stream, - } - - ExpH.exporterLock.Lock() - ExpH.envoyMetricsExporters = append(ExpH.envoyMetricsExporters, currExporter) - ExpH.exporterLock.Unlock() - - return <-currExporter.error -} - -// SendEnvoyMetrics Function -func (exp *ExpHandler) SendEnvoyMetrics(evyMetrics *protobuf.EnvoyMetrics) error { - failed := 0 - total := len(exp.envoyMetricsExporters) - - for _, exporter := range exp.envoyMetricsExporters { - if err := exporter.metricsStream.Send(evyMetrics); err != nil { - log.Printf("[Exporter] Failed to export Envoy metrics to %s(%s): %v", exporter.Hostname, exporter.IPAddress, err) - failed++ - } - } - - if failed != 0 { - msg := fmt.Sprintf("[Exporter] Failed to export Envoy metrics properly (%d/%d failed)", failed, total) - return errors.New(msg) - } - - return nil -} - -// == // - -// InsertEnvoyMetrics Function -func InsertEnvoyMetrics(evyMetrics *protobuf.EnvoyMetrics) { - ExpH.exporterMetrics <- evyMetrics -} - -// == // diff --git a/sentryflow/exporter/exporterHandler.go b/sentryflow/exporter/exporterHandler.go deleted file mode 100644 index 05baed9..0000000 --- a/sentryflow/exporter/exporterHandler.go +++ /dev/null @@ -1,259 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package exporter - -import ( - "fmt" - "net" - "sync" - - "github.com/5gsec/SentryFlow/config" - "github.com/5gsec/SentryFlow/protobuf" - - "log" - - "google.golang.org/grpc" -) - -// == // - -// ExpH global reference for Exporter Handler -var ExpH *ExpHandler - -// init Function -func init() { - ExpH = NewExporterHandler() -} - -// ExpHandler structure -type ExpHandler struct { - exporterService net.Listener - grpcServer *grpc.Server - grpcService *ExpService - - apiLogExporters []*apiLogStreamInform - apiLogExportersV2 []*apiLogStreamInformV2 - apiMetricsExporters []*apiMetricStreamInform - envoyMetricsExporters []*envoyMetricsStreamInform - - exporterLock sync.Mutex - - exporterAPILogs chan *protobuf.APILog - exporterAPILogsV2 chan *protobuf.APILogV2 - exporterAPIMetrics chan *protobuf.APIMetrics - exporterMetrics chan *protobuf.EnvoyMetrics - - statsPerLabel map[string]StatsPerLabel - statsPerLabelLock sync.RWMutex - - stopChan chan struct{} -} - -// ExpService Structure -type ExpService struct { - protobuf.UnimplementedSentryFlowServer -} - -// == // - -// NewExporterHandler Function -func NewExporterHandler() *ExpHandler { - exp := &ExpHandler{ - grpcService: new(ExpService), - - apiLogExporters: make([]*apiLogStreamInform, 0), - apiLogExportersV2: make([]*apiLogStreamInformV2, 0), - apiMetricsExporters: make([]*apiMetricStreamInform, 0), - envoyMetricsExporters: make([]*envoyMetricsStreamInform, 0), - - exporterLock: sync.Mutex{}, - - exporterAPILogs: make(chan *protobuf.APILog), - exporterAPILogsV2: make(chan *protobuf.APILogV2), - exporterAPIMetrics: make(chan *protobuf.APIMetrics), - exporterMetrics: make(chan *protobuf.EnvoyMetrics), - - statsPerLabel: make(map[string]StatsPerLabel), - statsPerLabelLock: sync.RWMutex{}, - - stopChan: make(chan struct{}), - } - - return exp -} - -// == // - -// StartExporter Function -func StartExporter(wg *sync.WaitGroup) bool { - // Make a string with the given exporter address and port - exporterService := fmt.Sprintf("%s:%s", config.GlobalConfig.ExporterAddr, config.GlobalConfig.ExporterPort) - - // Start listening gRPC port - expService, err := net.Listen("tcp", exporterService) - if err != nil { - log.Printf("[Exporter] Failed to listen at %s: %v", exporterService, err) - return false - } - ExpH.exporterService = expService - - log.Printf("[Exporter] Listening Exporter gRPC services (%s)", exporterService) - - // Create gRPC server - gRPCServer := grpc.NewServer() - ExpH.grpcServer = gRPCServer - - protobuf.RegisterSentryFlowServer(gRPCServer, ExpH.grpcService) - - log.Printf("[Exporter] Initialized Exporter gRPC services") - - // Serve gRPC Service - go ExpH.grpcServer.Serve(ExpH.exporterService) - - log.Printf("[Exporter] Serving Exporter gRPC services (%s)", exporterService) - - // Export APILogs - go ExpH.exportAPILogs(wg) - - // Export APILogsV2 - go ExpH.exportAPILogsV2(wg) - - log.Printf("[Exporter] Exporting API logs through gRPC services") - - // Export APIMetrics - go ExpH.exportAPIMetrics(wg) - - log.Printf("[Exporter] Exporting API metrics through gRPC services") - - // Export EnvoyMetrics - go ExpH.exportEnvoyMetrics(wg) - - log.Printf("[Exporter] Exporting Envoy metrics through gRPC services") - - // Start Export Time Ticker Routine - go AggregateAPIMetrics() - go CleanUpOutdatedStats() - - return true -} - -// StopExporter Function -func StopExporter() bool { - // One for exportAPILogs - ExpH.stopChan <- struct{}{} - - // One for exportAPILogsV2 - ExpH.stopChan <- struct{}{} - - // One for exportAPIMetrics - ExpH.stopChan <- struct{}{} - - // One for exportEnvoyMetrics - ExpH.stopChan <- struct{}{} - - // Stop gRPC server - ExpH.grpcServer.GracefulStop() - - log.Printf("[Exporter] Gracefully stopped Exporter gRPC services") - - return true -} - -// == // - -// exportAPILogs Function -func (exp *ExpHandler) exportAPILogs(wg *sync.WaitGroup) { - wg.Add(1) - - for { - select { - case apiLog, ok := <-exp.exporterAPILogs: - if !ok { - log.Printf("[Exporter] Failed to fetch APIs from APIs channel") - wg.Done() - return - } - - if err := exp.SendAPILogs(apiLog); err != nil { - log.Printf("[Exporter] Failed to export API Logs: %v", err) - } - - case <-exp.stopChan: - wg.Done() - return - } - } -} - -// exportAPILogs Function -func (exp *ExpHandler) exportAPILogsV2(wg *sync.WaitGroup) { - wg.Add(1) - - for { - select { - case apiLog, ok := <-exp.exporterAPILogsV2: - if !ok { - log.Printf("[Exporter] Failed to fetch APILogs(V2) from APIs channel") - wg.Done() - return - } - - if err := exp.SendAPILogsV2(apiLog); err != nil { - log.Printf("[Exporter] Failed to export API Logs(V2): %v", err) - } - - case <-exp.stopChan: - wg.Done() - return - } - } -} - -// exportAPIMetrics Function -func (exp *ExpHandler) exportAPIMetrics(wg *sync.WaitGroup) { - wg.Add(1) - - for { - select { - case apiMetrics, ok := <-exp.exporterAPIMetrics: - if !ok { - log.Printf("[Exporter] Failed to fetch metrics from API Metrics channel") - wg.Done() - return - } - if err := exp.SendAPIMetrics(apiMetrics); err != nil { - log.Printf("[Exporter] Failed to export API metrics: %v", err) - } - - case <-exp.stopChan: - wg.Done() - return - } - } -} - -// exportEnvoyMetrics Function -func (exp *ExpHandler) exportEnvoyMetrics(wg *sync.WaitGroup) { - wg.Add(1) - - for { - select { - case evyMetrics, ok := <-exp.exporterMetrics: - if !ok { - log.Printf("[Exporter] Failed to fetch metrics from Envoy Metrics channel") - wg.Done() - return - } - - if err := exp.SendEnvoyMetrics(evyMetrics); err != nil { - log.Printf("[Exporter] Failed to export Envoy metrics: %v", err) - } - - case <-exp.stopChan: - wg.Done() - return - } - } -} - -// == // diff --git a/sentryflow/go.mod b/sentryflow/go.mod index 3936109..acc2759 100644 --- a/sentryflow/go.mod +++ b/sentryflow/go.mod @@ -1,39 +1,45 @@ -module github.com/5gsec/SentryFlow +module github.com/5GSEC/SentryFlow -go 1.21 - -replace github.com/5gsec/SentryFlow/protobuf => ../protobuf +go 1.23 require ( - github.com/5gsec/SentryFlow/protobuf v0.0.0-00010101000000-000000000000 - github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 - github.com/spf13/viper v1.18.2 - go.opentelemetry.io/proto/otlp v1.0.0 - google.golang.org/grpc v1.66.0 - gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.29.0 - k8s.io/apimachinery v0.29.0 - k8s.io/client-go v0.29.0 + github.com/5GSEC/SentryFlow/protobuf v0.0.0-00010101000000-000000000000 + github.com/golang/protobuf v1.5.4 + github.com/google/uuid v1.6.0 + github.com/spf13/cobra v1.8.1 + github.com/spf13/viper v1.19.0 + go.opentelemetry.io/proto/otlp v1.3.1 + go.uber.org/zap v1.27.0 + google.golang.org/grpc v1.67.0 + google.golang.org/protobuf v1.34.2 + istio.io/api v1.23.2 + istio.io/client-go v1.23.2 + k8s.io/apimachinery v0.31.1 + k8s.io/client-go v0.31.1 + sigs.k8s.io/controller-runtime v0.19.0 ) require ( - github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/imdario/mergo v0.3.6 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -42,9 +48,12 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect - github.com/prometheus/client_model v0.6.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -52,25 +61,30 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.9.0 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/protobuf v1.34.2 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect - k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + k8s.io/api v0.31.1 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) + +replace github.com/5GSEC/SentryFlow/protobuf => ../protobuf/golang diff --git a/sentryflow/go.sum b/sentryflow/go.sum index c04d903..e28ba77 100644 --- a/sentryflow/go.sum +++ b/sentryflow/go.sum @@ -1,5 +1,8 @@ -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -7,28 +10,33 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -39,14 +47,18 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -73,21 +85,28 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= -github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -98,13 +117,16 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -114,14 +136,18 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -133,24 +159,24 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -163,17 +189,21 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= -google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= +google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= @@ -184,21 +214,29 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A= -k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA= -k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o= -k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis= -k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8= -k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +istio.io/api v1.23.2 h1:FvWi7GC+rWD60/ZFPuulX/h3k+f2Q9qot3dP8CIL8Ss= +istio.io/api v1.23.2/go.mod h1:QPSTGXuIQdnZFEm3myf9NZ5uBMwCdJWUvfj9ZZ+2oBM= +istio.io/client-go v1.23.2 h1:BIt6A+KaUOFin3SzXiDq2Fr/TMBev1+c836R0BfUfhU= +istio.io/client-go v1.23.2/go.mod h1:E08wpMtUulJk2tlWOCUVakjy1bKFxUNm22tM1R1QY0Y= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/sentryflow/k8s/istioPatcher.go b/sentryflow/k8s/istioPatcher.go deleted file mode 100644 index 6ec4d35..0000000 --- a/sentryflow/k8s/istioPatcher.go +++ /dev/null @@ -1,246 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package k8s - -import ( - "errors" - "log" - - "gopkg.in/yaml.v2" - "k8s.io/apimachinery/pkg/util/json" -) - -// meshConfig structure -type meshConfig struct { - DefaultConfig struct { - DiscoveryAddress string `yaml:"discoveryAddress"` - EnvoyAccessLogService struct { - Address string `yaml:"address"` - } `yaml:"envoyAccessLogService"` - EnvoyMetricsService struct { - Address string `yaml:"address"` - } `yaml:"envoyMetricsService"` - } `yaml:"defaultConfig"` - - DefaultProviders struct { - AccessLogs []string `yaml:"accessLogs"` - Metrics []string `yaml:"metrics"` - } `yaml:"defaultProviders"` - - EnableEnvoyAccessLogService bool `yaml:"enableEnvoyAccessLogService"` - - ExtensionProviders []struct { - EnvoyOtelAls struct { - Port string `yaml:"port"` - Service string `yaml:"service"` - } `yaml:"envoyOtelAls"` - Name string `yaml:"name"` - } `yaml:"extensionProviders"` - - ExtraFields map[string]interface{} `yaml:",inline"` // all extra fields that SentryFlow will not touch -} - -// PatchIstioConfigMap Function -func PatchIstioConfigMap() bool { - log.Print("[PatchIstioConfigMap] Patching Istio ConfigMap") - - meshCfg, err := parseIstioConfigMap() - if err != nil { - log.Printf("[PatchIstioConfigMap] Unable to parse Istio ConfigMap: %v", err) - return false - } - - if isIstioAlreadyPatched(meshCfg) { - log.Print("[PatchIstioConfigMap] Istio ConfigMap was already patched before, skipping...") - return true - } - - // set metrics and envoy access logging to Sentryflow - meshCfg.DefaultConfig.EnvoyAccessLogService.Address = "sentryflow.sentryflow.svc.cluster.local:4317" - meshCfg.DefaultConfig.EnvoyMetricsService.Address = "sentryflow.sentryflow.svc.cluster.local:4317" - - // add Sentryflow as Otel AL collector - if patched, _ := isEnvoyOtelAlPatched(meshCfg); !patched { - sfOtelAl := struct { - EnvoyOtelAls struct { - Port string `yaml:"port"` - Service string `yaml:"service"` - } `yaml:"envoyOtelAls"` - Name string `yaml:"name"` - }{ - EnvoyOtelAls: struct { - Port string `yaml:"port"` - Service string `yaml:"service"` - }{ - Port: "4317", - Service: "sentryflow.sentryflow.svc.cluster.local", - }, - Name: "sentryflow", - } - meshCfg.ExtensionProviders = append(meshCfg.ExtensionProviders, sfOtelAl) - } - - // add default access log provider - if patched, _ := isEnvoyALProviderPatched(meshCfg); !patched { - meshCfg.DefaultProviders.AccessLogs = append(meshCfg.DefaultProviders.AccessLogs, "sentryflow") - } - - meshCfg.EnableEnvoyAccessLogService = true - - yamlMeshCfg, err := yaml.Marshal(meshCfg) - if err != nil { - log.Printf("[PatchIstioConfigMap] Unable to unmarshall Istio ConfigMap: %v", err) - return false - } - - strMeshCfg := string(yamlMeshCfg[:]) - err = K8sH.updateConfigMap("istio-system", "istio", strMeshCfg) - if err != nil { - log.Printf("[PatchIstioConfigMap] Unable to update Istio ConfigMap: %v", err) - return false - } - - log.Print("[PatchIstioConfigMap] Successfully patched Istio ConfigMap") - - return true -} - -// UnpatchIstioConfigMap Function -func UnpatchIstioConfigMap() bool { - log.Print("[PatchIstioConfigMap] Unpatching Istio ConfigMap") - - meshCfg, err := parseIstioConfigMap() - if err != nil { - log.Printf("[PatchIstioConfigMap] Unable to parse Istio ConfigMap: %v", err) - return false - } - - // set metrics and envoy access logging back to empty value - meshCfg.DefaultConfig.EnvoyAccessLogService.Address = "" - meshCfg.DefaultConfig.EnvoyMetricsService.Address = "" - - // remove EnvoyOtelAl - if patched, targetIdx := isEnvoyOtelAlPatched(meshCfg); patched { - tmp := make([]struct { - EnvoyOtelAls struct { - Port string `yaml:"port"` - Service string `yaml:"service"` - } `yaml:"envoyOtelAls"` - Name string `yaml:"name"` - }, 0) - for idx, envoyOtelAl := range meshCfg.ExtensionProviders { - if idx != targetIdx { - tmp = append(tmp, envoyOtelAl) - } - } - meshCfg.ExtensionProviders = tmp - } - - // remove default access log provider - if patched, targetIdx := isEnvoyALProviderPatched(meshCfg); patched { - tmp := make([]string, 0) - for idx, provider := range meshCfg.DefaultProviders.AccessLogs { - if idx != targetIdx { - tmp = append(tmp, provider) - } - } - meshCfg.DefaultProviders.AccessLogs = tmp - } - - // @todo this might be incorrect, the user might have just set up envoy access log service manually before. - // @todo check if this shall actually be overwritten by SentryFlow - // meshCfg.EnableEnvoyAccessLogService = false - - yamlMeshCfg, err := yaml.Marshal(meshCfg) - if err != nil { - log.Printf("[PatchIstioConfigMap] Unable to unmarshall Istio ConfigMap: %v", err) - return false - } - - strMeshCfg := string(yamlMeshCfg[:]) - err = K8sH.updateConfigMap("istio-system", "istio", strMeshCfg) - if err != nil { - log.Printf("[PatchIstioConfigMap] Unable to update Istio ConfigMap: %v", err) - return false - } - - log.Print("[PatchIstioConfigMap] Successfully unpatched Istio ConfigMap") - - return true -} - -// parseIstioConfigMap Function -func parseIstioConfigMap() (meshConfig, error) { - var meshCfg meshConfig - - configMapData, err := K8sH.getConfigMap("istio-system", "istio") - if err != nil { - return meshCfg, err - } - - // unmarshall JSON format of Istio config - var rawIstioCfg map[string]interface{} - err = json.Unmarshal([]byte(configMapData), &rawIstioCfg) - if err != nil { - return meshCfg, err - } - - // extract mesh field from configmap - meshData, ok := rawIstioCfg["mesh"].(string) - if !ok { - return meshCfg, errors.New("[PatchIstioConfigMap] Unable to find field \"mesh\" from Istio config") - } - - // unmarshall YAML format of Istio config - err = yaml.Unmarshal([]byte(meshData), &meshCfg) - if err != nil { - return meshCfg, err - } - - return meshCfg, nil -} - -// isEnvoyOtelAlPatched Function -func isEnvoyOtelAlPatched(meshCfg meshConfig) (bool, int) { - for idx, envoyOtelAl := range meshCfg.ExtensionProviders { - if envoyOtelAl.Name == "sentryflow" && - envoyOtelAl.EnvoyOtelAls.Port == "4317" && - envoyOtelAl.EnvoyOtelAls.Service == "sentryflow.sentryflow.svc.cluster.local" { - return true, idx - } - } - - return false, -1 -} - -// isEnvoyALProviderPatched Function -func isEnvoyALProviderPatched(meshCfg meshConfig) (bool, int) { - for idx, accessLogProvider := range meshCfg.DefaultProviders.AccessLogs { - if accessLogProvider == "sentryflow" { - return true, idx - } - } - return false, -1 -} - -// isIstioAlreadyPatched Function -func isIstioAlreadyPatched(meshCfg meshConfig) bool { - if meshCfg.DefaultConfig.EnvoyAccessLogService.Address != "sentryflow.sentryflow.svc.cluster.local:4317" || - meshCfg.DefaultConfig.EnvoyMetricsService.Address != "sentryflow.sentryflow.svc.cluster.local:4317" { - return false - } - - if patched, _ := isEnvoyOtelAlPatched(meshCfg); !patched { - return false - } - - if patched, _ := isEnvoyALProviderPatched(meshCfg); !patched { - return false - } - - if !meshCfg.EnableEnvoyAccessLogService { - return false - } - - return true -} diff --git a/sentryflow/k8s/k8sHandler.go b/sentryflow/k8s/k8sHandler.go deleted file mode 100644 index a13a07f..0000000 --- a/sentryflow/k8s/k8sHandler.go +++ /dev/null @@ -1,437 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package k8s - -import ( - "context" - "errors" - "log" - "sync" - "time" - - "k8s.io/apimachinery/pkg/util/json" - - "github.com/5gsec/SentryFlow/types" - - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/cache" -) - -// == // - -// K8sH global reference for Kubernetes Handler -var K8sH *KubernetesHandler - -// init Function -func init() { - K8sH = NewK8sHandler() -} - -// KubernetesHandler Structure -type KubernetesHandler struct { - config *rest.Config - clientSet *kubernetes.Clientset - - watchers map[string]*cache.ListWatch - informers map[string]cache.Controller - - podMap map[string]*corev1.Pod // NOT thread safe - serviceMap map[string]*corev1.Service // NOT thread safe -} - -// NewK8sHandler Function -func NewK8sHandler() *KubernetesHandler { - kh := &KubernetesHandler{ - watchers: make(map[string]*cache.ListWatch), - informers: make(map[string]cache.Controller), - - podMap: make(map[string]*corev1.Pod), - serviceMap: make(map[string]*corev1.Service), - } - - return kh -} - -// == // - -// InitK8sClient Function -func InitK8sClient() bool { - var err error - - // Initialize in cluster config - K8sH.config, err = rest.InClusterConfig() - if err != nil { - log.Print("[InitK8sClient] Failed to initialize Kubernetes client") - return false - } - - // Initialize Kubernetes clientSet - K8sH.clientSet, err = kubernetes.NewForConfig(K8sH.config) - if err != nil { - log.Print("[InitK8sClient] Failed to initialize Kubernetes client") - return false - } - - // Create a mapping table for existing pods and services to IPs - K8sH.initExistingResources() - - watchTargets := []string{"pods", "services"} - - // Initialize watchers for pods and services - for _, target := range watchTargets { - watcher := cache.NewListWatchFromClient( - K8sH.clientSet.CoreV1().RESTClient(), - target, - corev1.NamespaceAll, - fields.Everything(), - ) - K8sH.watchers[target] = watcher - } - - // Initialize informers - K8sH.initInformers() - - log.Print("[InitK8sClient] Initialized Kubernetes client") - - return true -} - -// initExistingResources Function that creates a mapping table for existing pods and services to IPs -// This is required since informers are NOT going to see existing resources until they are updated, created or deleted -// @todo: Refactor this function, this is kind of messy -func (k8s *KubernetesHandler) initExistingResources() { - // List existing Pods - podList, err := k8s.clientSet.CoreV1().Pods(corev1.NamespaceAll).List(context.TODO(), v1.ListOptions{}) - if err != nil { - log.Printf("[K8s] Failed to get Pods: %v", err.Error()) - } - - // Add existing Pods to the podMap - for _, pod := range podList.Items { - currentPod := pod - k8s.podMap[pod.Status.PodIP] = ¤tPod - log.Printf("[K8s] Add existing pod %s: %s/%s", pod.Status.PodIP, pod.Namespace, pod.Name) - } - - // List existing Services - serviceList, err := k8s.clientSet.CoreV1().Services(corev1.NamespaceAll).List(context.TODO(), v1.ListOptions{}) - if err != nil { - log.Printf("[K8s] Failed to get Services: %v", err.Error()) - } - - // Add existing Services to the serviceMap - for _, service := range serviceList.Items { - currentService := service - - // Check if the service has a LoadBalancer type - if service.Spec.Type == "LoadBalancer" { - for _, lbIngress := range service.Status.LoadBalancer.Ingress { - lbIP := lbIngress.IP - if lbIP != "" { - k8s.serviceMap[lbIP] = ¤tService - log.Printf("[K8s] Add existing service (LoadBalancer) %s: %s/%s", lbIP, service.Namespace, service.Name) - } - } - } else { - k8s.serviceMap[service.Spec.ClusterIP] = ¤tService - if len(service.Spec.ExternalIPs) != 0 { - for _, eIP := range service.Spec.ExternalIPs { - k8s.serviceMap[eIP] = ¤tService - log.Printf("[K8s] Add existing service %s: %s/%s", eIP, service.Namespace, service.Name) - } - } - } - } -} - -// initInformers Function that initializes informers for services and pods in a cluster -func (k8s *KubernetesHandler) initInformers() { - // Create Pod controller informer - _, pc := cache.NewInformer( - k8s.watchers["pods"], - &corev1.Pod{}, - time.Second*0, - cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { // Add pod - pod := obj.(*corev1.Pod) - k8s.podMap[pod.Status.PodIP] = pod - }, - UpdateFunc: func(oldObj, newObj interface{}) { // Update pod - newPod := newObj.(*corev1.Pod) - k8s.podMap[newPod.Status.PodIP] = newPod - }, - DeleteFunc: func(obj interface{}) { // Remove deleted pod - pod := obj.(*corev1.Pod) - delete(k8s.podMap, pod.Status.PodIP) - }, - }, - ) - k8s.informers["pods"] = pc - - // Create Service controller informer - _, sc := cache.NewInformer( - k8s.watchers["services"], - &corev1.Service{}, - time.Second*0, - cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { // Add service - service := obj.(*corev1.Service) - - if service.Spec.Type == "LoadBalancer" { - for _, lbIngress := range service.Status.LoadBalancer.Ingress { - lbIP := lbIngress.IP - if lbIP != "" { - k8s.serviceMap[lbIP] = service - } - } - } else { - k8s.serviceMap[service.Spec.ClusterIP] = service - if len(service.Spec.ExternalIPs) != 0 { - for _, eIP := range service.Spec.ExternalIPs { - k8s.serviceMap[eIP] = service - } - } - } - }, - UpdateFunc: func(oldObj, newObj interface{}) { // Update service - newService := newObj.(*corev1.Service) - if newService.Spec.Type == "LoadBalancer" { - for _, lbIngress := range newService.Status.LoadBalancer.Ingress { - lbIP := lbIngress.IP - if lbIP != "" { - k8s.serviceMap[lbIP] = newService - } - } - } else { - k8s.serviceMap[newService.Spec.ClusterIP] = newService - if len(newService.Spec.ExternalIPs) != 0 { - for _, eIP := range newService.Spec.ExternalIPs { - k8s.serviceMap[eIP] = newService - } - } - } - }, - DeleteFunc: func(obj interface{}) { - service := obj.(*corev1.Service) - if service.Spec.Type == "LoadBalancer" { - for _, lbIngress := range service.Status.LoadBalancer.Ingress { - lbIP := lbIngress.IP - if lbIP != "" { - delete(k8s.serviceMap, lbIP) - } - } - } else { - delete(k8s.serviceMap, service.Spec.ClusterIP) // Remove deleted service - if len(service.Spec.ExternalIPs) != 0 { - for _, eIP := range service.Spec.ExternalIPs { - delete(k8s.serviceMap, eIP) - } - } - } - }, - }, - ) - k8s.informers["services"] = sc -} - -// == // - -// RunInformers Function that starts running informers -func RunInformers(stopChan chan struct{}, wg *sync.WaitGroup) { - wg.Add(1) - - for name, informer := range K8sH.informers { - name := name - informer := informer - go func() { - log.Printf("[RunInformers] Starting an informer for %s", name) - informer.Run(stopChan) - defer wg.Done() - }() - } - - log.Print("[RunInformers] Started all Kubernetes informers") -} - -// getConfigMap Function -func (k8s *KubernetesHandler) getConfigMap(namespace, name string) (string, error) { - cm, err := k8s.clientSet.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, v1.GetOptions{}) - if err != nil { - log.Printf("[K8s] Failed to get ConfigMaps: %v", err) - return "", err - } - - // convert data to string - data, err := json.Marshal(cm.Data) - if err != nil { - log.Printf("[K8s] Failed to marshal ConfigMap: %v", err) - return "", err - } - - return string(data), nil -} - -// updateConfigMap Function -func (k8s *KubernetesHandler) updateConfigMap(namespace, name, data string) error { - cm, err := k8s.clientSet.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, v1.GetOptions{}) - if err != nil { - log.Printf("[K8s] Failed to get ConfigMap: %v", err) - return err - } - - if _, ok := cm.Data["mesh"]; !ok { - return errors.New("[K8s] Unable to find field \"mesh\" from Istio config") - } - - cm.Data["mesh"] = data - if _, err := k8s.clientSet.CoreV1().ConfigMaps(namespace).Update(context.Background(), cm, v1.UpdateOptions{}); err != nil { - return err - } - - return nil -} - -// PatchNamespaces Function that patches namespaces for adding 'istio-injection' -func PatchNamespaces() bool { - namespaces, err := K8sH.clientSet.CoreV1().Namespaces().List(context.Background(), v1.ListOptions{}) - if err != nil { - log.Printf("[PatchNamespaces] Failed to get Namespaces: %v", err) - return false - } - - for _, ns := range namespaces.Items { - namespace := ns.DeepCopy() - - // Skip the following namespaces - if namespace.Name == "sentryflow" { - continue - } - - namespace.Labels["istio-injection"] = "enabled" - - // Patch the namespace - if _, err := K8sH.clientSet.CoreV1().Namespaces().Update(context.TODO(), namespace, v1.UpdateOptions{FieldManager: "patcher"}); err != nil { - log.Printf("[PatchNamespaces] Failed to update Namespace %s: %v", namespace.Name, err) - return false - } - - log.Printf("[PatchNamespaces] Updated Namespace %s", namespace.Name) - } - - log.Print("[PatchNamespaces] Updated all Namespaces") - - return true -} - -// restartDeployment Function that performs a rolling restart for a deployment in the specified namespace -// @todo: fix this, this DOES NOT restart deployments -func (k8s *KubernetesHandler) restartDeployment(namespace string, deploymentName string) error { - deploymentClient := k8s.clientSet.AppsV1().Deployments(namespace) - - // Get the deployment to retrieve the current spec - deployment, err := deploymentClient.Get(context.Background(), deploymentName, v1.GetOptions{}) - if err != nil { - return err - } - - // Trigger a rolling restart by updating the deployment's labels or annotations - deployment.Spec.Template.ObjectMeta.Labels["restartedAt"] = v1.Now().String() - - // Update the deployment to trigger the rolling restart - _, err = deploymentClient.Update(context.TODO(), deployment, v1.UpdateOptions{}) - if err != nil { - return err - } - - return nil -} - -// RestartDeployments Function that restarts the deployments in the namespaces with "istio-injection=enabled" -func RestartDeployments() bool { - deployments, err := K8sH.clientSet.AppsV1().Deployments("").List(context.Background(), v1.ListOptions{}) - if err != nil { - log.Printf("[PatchDeployments] Failed to get Deployments: %v", err) - return false - } - - for _, deployment := range deployments.Items { - // Skip the following namespaces - if deployment.Namespace == "sentryflow" { - continue - } - - // Restart the deployment - if err := K8sH.restartDeployment(deployment.Namespace, deployment.Name); err != nil { - log.Printf("[PatchDeployments] Failed to restart Deployment %s/%s: %v", deployment.Namespace, deployment.Name, err) - return false - } - - log.Printf("[PatchDeployments] Deployment %s/%s restarted", deployment.Namespace, deployment.Name) - } - - log.Print("[PatchDeployments] Restarted all patched deployments") - - return true -} - -// == // - -// lookupIPAddress Function -func lookupIPAddress(ipAddr string) interface{} { - // Look for pod map - pod, ok := K8sH.podMap[ipAddr] - if ok { - return pod - } - - // Look for service map - service, ok := K8sH.serviceMap[ipAddr] - if ok { - return service - } - - return nil -} - -// LookupK8sResource Function -func LookupK8sResource(srcIP string) types.K8sResource { - ret := types.K8sResource{ - Namespace: "Unknown", - Name: "Unknown", - Labels: make(map[string]string), - Type: types.K8sResourceTypeUnknown, - } - - // Find Kubernetes resource from source IP (service or a pod) - raw := lookupIPAddress(srcIP) - - // Currently supports Service or Pod - switch raw.(type) { - case *corev1.Pod: - pod, ok := raw.(*corev1.Pod) - if ok { - ret.Namespace = pod.Namespace - ret.Name = pod.Name - ret.Labels = pod.Labels - ret.Type = types.K8sResourceTypePod - } - case *corev1.Service: - svc, ok := raw.(*corev1.Service) - if ok { - ret.Namespace = svc.Namespace - ret.Name = svc.Name - ret.Labels = svc.Labels - ret.Type = types.K8sResourceTypeService - } - default: - ret.Type = types.K8sResourceTypeUnknown - } - - return ret -} - -// == // diff --git a/sentryflow/main.go b/sentryflow/main.go index d96e538..6163445 100644 --- a/sentryflow/main.go +++ b/sentryflow/main.go @@ -1,15 +1,9 @@ -// SPDX-License-Identifier: Apache-2.0 - package main import ( - "github.com/5gsec/SentryFlow/core" + "github.com/5GSEC/SentryFlow/cmd" ) -// ========== // -// == Main == // -// ========== // - func main() { - core.SentryFlow() + _ = cmd.RootCmd.Execute() } diff --git a/sentryflow/pkg/config/config.go b/sentryflow/pkg/config/config.go new file mode 100644 index 0000000..a202921 --- /dev/null +++ b/sentryflow/pkg/config/config.go @@ -0,0 +1,129 @@ +package config + +import ( + "encoding/json" + "fmt" + + "github.com/spf13/viper" + "go.uber.org/zap" +) + +const ( + DefaultConfigFilePath = "config/default.yaml" + SentryFlowDefaultFilterServerPort = 8081 +) + +type endpoint struct { + Url string `json:"url"` + Port uint16 `json:"port"` +} + +type base struct { + Name string `json:"name,omitempty"` + // Todo: Do we really need both gRPC and http variants? + Grpc *endpoint `json:"grpc,omitempty"` + Http *endpoint `json:"http,omitempty"` +} + +type serviceMesh struct { + Name string `json:"name"` + Namespace string `json:"namespace"` +} + +type receivers struct { + ServiceMeshes []*serviceMesh `json:"serviceMeshes,omitempty"` + Others []*base `json:"others,omitempty"` +} + +type envoyFilterConfig struct { + Uri string `json:"uri"` +} + +type server struct { + Port uint16 `json:"port"` +} + +type filters struct { + Envoy *envoyFilterConfig `json:"envoy,omitempty"` + Server *server `json:"server,omitempty"` +} + +type Config struct { + Filters *filters `json:"filters"` + Receivers *receivers `json:"receivers"` + Exporter *base `json:"exporter"` +} + +func (c *Config) validate() error { + if c.Filters == nil { + return fmt.Errorf("no filter configuration provided") + } + if c.Filters.Envoy != nil { + if c.Filters.Envoy.Uri == "" { + return fmt.Errorf("no envoy filter URI provided") + } + } + + if c.Exporter == nil { + return fmt.Errorf("no exporter configuration provided") + } + if c.Exporter.Grpc == nil { + return fmt.Errorf("no exporter's gRPC configuration provided") + } + if c.Exporter.Http != nil { + return fmt.Errorf("http exporter is not supported") + } + + if c.Receivers == nil { + return fmt.Errorf("no receiver configuration provided") + } + + for _, svcMesh := range c.Receivers.ServiceMeshes { + if svcMesh.Name == "" { + return fmt.Errorf("no service mesh name provided") + } + if svcMesh.Namespace == "" { + return fmt.Errorf("no service mesh namespace provided") + } + } + + return nil +} + +func New(configFilePath string, logger *zap.SugaredLogger) (*Config, error) { + if configFilePath == "" { + configFilePath = DefaultConfigFilePath + logger.Warnf("Using default configfile path: %s", configFilePath) + } + + viper.SetConfigFile(configFilePath) + if err := viper.ReadInConfig(); err != nil { + logger.Errorf("Failed to read config file: %v", err) + return nil, err + } + + config := &Config{} + if err := viper.Unmarshal(config); err != nil { + logger.Errorf("Failed to unmarshal config file: %v", err) + return nil, err + } + if config.Filters.Server == nil { + config.Filters.Server = &server{} + } + if config.Filters.Server.Port == 0 { + config.Filters.Server.Port = SentryFlowDefaultFilterServerPort + logger.Warnf("Using default SentryFlow filter server port %d", config.Filters.Server.Port) + } + + if err := config.validate(); err != nil { + return nil, err + } + + bytes, err := json.Marshal(config) + if err != nil { + logger.Errorf("Failed to marshal config file: %v", err) + } + logger.Debugf("Config: %s", string(bytes)) + + return config, nil +} diff --git a/sentryflow/pkg/core/sentryflow.go b/sentryflow/pkg/core/sentryflow.go new file mode 100644 index 0000000..42261a8 --- /dev/null +++ b/sentryflow/pkg/core/sentryflow.go @@ -0,0 +1,97 @@ +package core + +import ( + "context" + "net/http" + "sync" + + "go.uber.org/zap" + "google.golang.org/grpc" + "istio.io/client-go/pkg/apis/extensions/v1alpha1" + networkingv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/5GSEC/SentryFlow/pkg/config" + "github.com/5GSEC/SentryFlow/pkg/exporter" + "github.com/5GSEC/SentryFlow/pkg/k8s" + "github.com/5GSEC/SentryFlow/pkg/receiver" + "github.com/5GSEC/SentryFlow/pkg/util" + "github.com/5GSEC/SentryFlow/protobuf" +) + +type Manager struct { + Ctx context.Context + Logger *zap.SugaredLogger + GrpcServer *grpc.Server + HttpServer *http.Server + K8sClient client.Client + Wg *sync.WaitGroup + ApiEvents chan *protobuf.APIEvent +} + +func Run(ctx context.Context, configFilePath string, kubeConfig string) { + mgr := &Manager{ + Ctx: ctx, + Logger: util.LoggerFromCtx(ctx), + GrpcServer: grpc.NewServer(), + Wg: &sync.WaitGroup{}, + ApiEvents: make(chan *protobuf.APIEvent, 10240), + } + mgr.Logger.Info("Starting SentryFlow") + + cfg, err := config.New(configFilePath, mgr.Logger) + if err != nil { + mgr.Logger.Error(err) + return + } + + k8sClient, err := k8s.NewClient(registerAndGetScheme(), kubeConfig) + if err != nil { + mgr.Logger.Errorf("failed to create k8s client: %v", err) + return + } + mgr.K8sClient = k8sClient + + mgr.Wg.Add(1) + go func() { + defer mgr.Wg.Done() + mgr.startHttpServer(cfg.Filters.Server.Port) + }() + + if err := receiver.Init(mgr.Ctx, mgr.K8sClient, cfg, mgr.ApiEvents, mgr.GrpcServer, mgr.Wg); err != nil { + mgr.Logger.Errorf("failed to initialize receiver: %v", err) + return + } + + if err := exporter.Init(mgr.Ctx, mgr.GrpcServer, cfg, mgr.ApiEvents, mgr.Wg); err != nil { + mgr.Logger.Errorf("failed to initialize exporter: %v", err) + return + } + + mgr.Wg.Add(1) + go func() { + defer mgr.Wg.Done() + mgr.startGrpcServer(cfg.Exporter.Grpc.Port) + }() + + mgr.Logger.Info("Started SentryFlow") + + <-ctx.Done() + mgr.Logger.Info("Shutdown Signal Received. Waiting for all workers to finish.") + mgr.Logger.Info("Shutting down SentryFlow") + + mgr.stopServers() + mgr.Wg.Wait() + close(mgr.ApiEvents) + + mgr.Logger.Info("All workers finished. Stopped SentryFlow") +} + +func registerAndGetScheme() *runtime.Scheme { + scheme := runtime.NewScheme() + utilruntime.Must(networkingv1alpha3.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + return scheme +} diff --git a/sentryflow/pkg/core/server.go b/sentryflow/pkg/core/server.go new file mode 100644 index 0000000..9d2571c --- /dev/null +++ b/sentryflow/pkg/core/server.go @@ -0,0 +1,91 @@ +package core + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "net/http" + "time" + + "google.golang.org/protobuf/encoding/protojson" + + "github.com/5GSEC/SentryFlow/protobuf" +) + +func (m *Manager) startGrpcServer(port uint16) { + m.Logger.Info("Starting gRPC server") + listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + m.Logger.Fatalf("Failed to listen on %v port, error: %v", port, err) + } + + m.Logger.Infof("gRPC server listening on port %d", port) + if err := m.GrpcServer.Serve(listener); err != nil { + m.Logger.Fatalf("Failed to serve gRPC server on port %d, error: %v", port, err) + } +} + +func (m *Manager) startHttpServer(port uint16) { + m.Logger.Info("Starting HTTP server") + m.HttpServer = &http.Server{ + Addr: fmt.Sprintf(":%d", port), + ReadHeaderTimeout: 3 * time.Second, + } + m.registerRoutes() + + m.Logger.Infof("HTTP server listening on port %d", port) + if err := m.HttpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + m.Logger.Fatalf("Failed to serve http server, error: %v", err) + } +} + +func (m *Manager) stopServers() { + m.Logger.Info("Stopping servers") + if err := m.HttpServer.Shutdown(context.Background()); err != nil { + m.Logger.Errorf("Failed to shutdown http server, error: %v", err) + } + m.GrpcServer.GracefulStop() + m.Logger.Info("Stopped servers") +} + +func (m *Manager) registerRoutes() { + http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + w.WriteHeader(http.StatusOK) + }) + + // Register an endpoint to receive API events from EnvoyFilter + http.HandleFunc("/api/v1/events", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + if r.Body == nil { + m.Logger.Info("Body is nil") + w.WriteHeader(http.StatusBadRequest) + return + } + + body, err := io.ReadAll(r.Body) + if err != nil { + m.Logger.Errorf("failed to read request body, error: %v", err) + http.Error(w, "failed to read request body", http.StatusInternalServerError) + return + } + + apiEvent := &protobuf.APIEvent{} + if err := protojson.Unmarshal(body, apiEvent); err != nil { + m.Logger.Info("failed to unmarshal api event, error:", err) + http.Error(w, "failed to parse request body", http.StatusBadRequest) + return + } + + m.ApiEvents <- apiEvent + }) +} diff --git a/sentryflow/pkg/exporter/exporter.go b/sentryflow/pkg/exporter/exporter.go new file mode 100644 index 0000000..6cea493 --- /dev/null +++ b/sentryflow/pkg/exporter/exporter.go @@ -0,0 +1,146 @@ +package exporter + +import ( + "context" + "sync" + + "github.com/google/uuid" + "go.uber.org/zap" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + grpcstatus "google.golang.org/grpc/status" + + "github.com/5GSEC/SentryFlow/pkg/config" + "github.com/5GSEC/SentryFlow/pkg/util" + "github.com/5GSEC/SentryFlow/protobuf" +) + +// clientList represents a list of gRPC clients and their associated channels for +// sending API events. It uses a mutex to synchronize access to the client map. +type clientList struct { + *sync.Mutex + client map[string]chan *protobuf.APIEvent +} + +type exporter struct { + protobuf.UnimplementedSentryFlowServer + apiEvents chan *protobuf.APIEvent + logger *zap.SugaredLogger + clients *clientList +} + +// GetAPIEvent streams generated API events to connected clients. Each client is +// assigned a unique identifier (UID) and a dedicated channel to receive events. +// This ensures that all connected clients receive the same API events in +// real-time. +func (e *exporter) GetAPIEvent(clientInfo *protobuf.ClientInfo, stream grpc.ServerStreamingServer[protobuf.APIEvent]) error { + uid := uuid.Must(uuid.NewRandom()).String() + + connChan := e.addClientToList(uid) + defer e.deleteClientFromList(uid, connChan) + + e.logger.Infof("Client: %s %s (%s) connected", uid, clientInfo.HostName, clientInfo.IPAddress) + + for { + select { + case <-stream.Context().Done(): + e.logger.Infof("Client: %s %s (%s) disconnected", uid, clientInfo.HostName, clientInfo.IPAddress) + return stream.Context().Err() + case apiEvent, ok := <-connChan: + if !ok { + e.logger.Warn("Channel closed") + return nil + } + if status, ok := grpcstatus.FromError(stream.Send(apiEvent)); !ok { + if status.Code() == codes.Canceled { + e.logger.Infof("Client: %s %s (%s) cancelled the operation", uid, clientInfo.HostName, clientInfo.IPAddress) + return nil + } + e.logger.Errorf("Failed to send APIEvent: %v", status.Err()) + return status.Err() + } + } + } +} + +func (e *exporter) addClientToList(uid string) chan *protobuf.APIEvent { + e.clients.Lock() + connChan := make(chan *protobuf.APIEvent) + e.clients.client[uid] = connChan + e.clients.Unlock() + return connChan +} + +func (e *exporter) deleteClientFromList(uid string, connChan chan *protobuf.APIEvent) { + e.clients.Lock() + close(connChan) + delete(e.clients.client, uid) + e.clients.Unlock() +} + +// SendAPIEvent ingests an API event received from the source and publishes it to +// the `apiEvents` channel for subscribed clients to consume. +func (e *exporter) SendAPIEvent(ctx context.Context, apiEvent *protobuf.APIEvent) (*protobuf.APIEvent, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + e.apiEvents <- apiEvent + e.logger.Info("Received APIEvent") + return apiEvent, nil + } +} + +// putApiEventOnClientsChannel continuously listens to the `apiEvents` channel +// and forwards incoming API events to all connected clients. If the context is +// canceled, the function returns. +func (e *exporter) putApiEventOnClientsChannel(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + case apiEvent, ok := <-e.apiEvents: + if !ok { + e.logger.Warn("Channel closed") + continue + } + eventToSend := apiEvent + e.clients.Lock() + for _, clientChan := range e.clients.client { + select { + case clientChan <- eventToSend: + default: + e.logger.Warn("Event dropped") + } + } + e.clients.Unlock() + } + } +} + +// Init initializes and registers the gRPC-based exporter with the provided +// server. This allows clients to connect and consume the generated API events +// streamed through the server. +func Init(ctx context.Context, server *grpc.Server, cfg *config.Config, events chan *protobuf.APIEvent, wg *sync.WaitGroup) error { + logger := util.LoggerFromCtx(ctx).Named("exporter") + logger.Info("Starting exporter") + + e := &exporter{ + apiEvents: events, + logger: logger, + clients: &clientList{ + Mutex: &sync.Mutex{}, + client: make(map[string]chan *protobuf.APIEvent), + }, + } + + protobuf.RegisterSentryFlowServer(server, e) + + wg.Add(1) + go func(ctx context.Context) { + defer wg.Done() + e.putApiEventOnClientsChannel(ctx) + }(ctx) + + return nil +} diff --git a/sentryflow/pkg/k8s/client.go b/sentryflow/pkg/k8s/client.go new file mode 100644 index 0000000..b6b0e8d --- /dev/null +++ b/sentryflow/pkg/k8s/client.go @@ -0,0 +1,39 @@ +package k8s + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// NewClient returns a new Client using the provided scheme to map go structs to +// GroupVersionKinds. +func NewClient(scheme *runtime.Scheme, kubeConfig string) (client.Client, error) { + config, err := getConfig(kubeConfig) + if err != nil { + return nil, fmt.Errorf("failed to get config: %v", err) + } + return client.New(config, client.Options{ + Scheme: scheme, + }) +} + +func getConfig(kubeConfig string) (*rest.Config, error) { + config, err := rest.InClusterConfig() + if err != nil && errors.Is(err, rest.ErrNotInCluster) { + if kubeConfig == "" { + kubeConfig = filepath.Join(os.Getenv("HOME"), ".kube", "config") + } + config, err = clientcmd.BuildConfigFromFlags("", kubeConfig) + if err != nil { + return nil, err + } + } + return config, nil +} diff --git a/sentryflow/pkg/receiver/receiver.go b/sentryflow/pkg/receiver/receiver.go new file mode 100644 index 0000000..7c2312b --- /dev/null +++ b/sentryflow/pkg/receiver/receiver.go @@ -0,0 +1,46 @@ +package receiver + +import ( + "context" + "fmt" + "sync" + + "google.golang.org/grpc" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/5GSEC/SentryFlow/pkg/config" + istiosidecar "github.com/5GSEC/SentryFlow/pkg/receiver/svcmesh/istio/sidecar" + "github.com/5GSEC/SentryFlow/pkg/util" + "github.com/5GSEC/SentryFlow/protobuf" +) + +// Init initializes the API event sources based on the provided configuration. It +// starts monitoring from configured sources and supports adding other sources in +// the future. +func Init(ctx context.Context, k8sClient client.Client, cfg *config.Config, apiEvents chan *protobuf.APIEvent, server *grpc.Server, wg *sync.WaitGroup) error { + //logger := util.LoggerFromCtx(ctx).Named("receiver") + + for _, serviceMesh := range cfg.Receivers.ServiceMeshes { + if serviceMesh.Name != "" { + switch serviceMesh.Name { + case util.ServiceMeshIstioSidecar: + wg.Add(1) + go func() { + defer wg.Done() + istiosidecar.StartMonitoring(ctx, cfg, k8sClient) + }() + default: + return fmt.Errorf("unsupported Service Mesh, %v", serviceMesh.Name) + } + } + } + + // Placeholder for other sources (To be implemented based on requirements) + // TODO: Implement initialization for other telemetry sources based on the + // `cfg.Others` configuration. + // This would involve handling gRPC or HTTP configs + // for each supported source type and potentially adding new subdirectories in + // `pkg/receiver/other` for each source. + + return nil +} diff --git a/sentryflow/pkg/receiver/svcmesh/istio/sidecar/sidecar.go b/sentryflow/pkg/receiver/svcmesh/istio/sidecar/sidecar.go new file mode 100644 index 0000000..9b2e9a5 --- /dev/null +++ b/sentryflow/pkg/receiver/svcmesh/istio/sidecar/sidecar.go @@ -0,0 +1,270 @@ +package sidecar + +import ( + "bytes" + "context" + "fmt" + "text/template" + + _struct "github.com/golang/protobuf/ptypes/struct" + "go.uber.org/zap" + extensionsv1alpha1 "istio.io/api/extensions/v1alpha1" + "istio.io/api/type/v1beta1" + "istio.io/client-go/pkg/apis/extensions/v1alpha1" + networkingv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/yaml" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/5GSEC/SentryFlow/pkg/config" + "github.com/5GSEC/SentryFlow/pkg/util" +) + +const ( + FilterName = "http-filter" + UpstreamAndClusterName = "sentryflow" + ApiPath = "/api/v1/events" +) + +type envoyFilterData struct { + FilterName string + IstioRootNs string + UpstreamAndClusterName string + SentryFlowFilterServerPort uint16 +} + +// StartMonitoring begins monitoring API calls within the Istio (sidecar based) +// service mesh deployed in a Kubernetes cluster. It achieves this by creating a +// custom EnvoyFilter resource in Kubernetes. +func StartMonitoring(ctx context.Context, cfg *config.Config, k8sClient client.Client) { + logger := util.LoggerFromCtx(ctx).Named("istio-sidecar") + + logger.Info("Starting istio sidecar mesh monitoring") + + if err := setupWasmPlugin(ctx, cfg, k8sClient); err != nil { + logger.Error(err) + return + } + logger.Info("Started istio sidecar mesh monitoring") + + <-ctx.Done() + logger.Info("Shutting down istio sidecar mesh monitoring") + doCleanup(logger, k8sClient, getIstioRootNamespaceFromConfig(cfg)) + + logger.Info("Stopped istio sidecar mesh monitoring") +} + +func setupWasmPlugin(ctx context.Context, cfg *config.Config, k8sClient client.Client) error { + if err := createEnvoyFilter(ctx, cfg, k8sClient); err != nil { + return fmt.Errorf("failed to create EnvoyFilter. Stopping istio sidecar mesh monitoring, error: %v", err) + } + + if err := createWasmPlugin(ctx, cfg, k8sClient); err != nil { + return fmt.Errorf("failed to create WasmPlugin. Stopping istio sidecar monitoring, error: %v", err) + } + + return nil +} + +func doCleanup(logger *zap.SugaredLogger, k8sClient client.Client, istioRootNs string) { + if err := deleteEnvoyFilter(logger, k8sClient, istioRootNs); err != nil { + logger.Errorf("failed to delete EnvoyFilter, error: %v", err) + } + if err := deleteWasmPlugin(logger, k8sClient, istioRootNs); err != nil { + logger.Errorf("failed to delete WasmPlugin, error: %v", err) + } +} + +func createWasmPlugin(ctx context.Context, cfg *config.Config, k8sClient client.Client) error { + logger := util.LoggerFromCtx(ctx) + + wasmPlugin := &v1alpha1.WasmPlugin{ + TypeMeta: metav1.TypeMeta{ + Kind: "WasmPlugin", + APIVersion: "extensions.istio.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: FilterName, + Namespace: getIstioRootNamespaceFromConfig(cfg), + Labels: map[string]string{ + "app.kubernetes.io/managed-by": "sentryflow", + }, + }, + Spec: extensionsv1alpha1.WasmPlugin{ + Url: cfg.Filters.Envoy.Uri, + PluginConfig: &_struct.Struct{ + Fields: map[string]*_struct.Value{ + "upstream_name": { + Kind: &_struct.Value_StringValue{ + StringValue: UpstreamAndClusterName, + }, + }, + "authority": { + Kind: &_struct.Value_StringValue{ + StringValue: UpstreamAndClusterName, + }, + }, + "api_path": { + Kind: &_struct.Value_StringValue{ + StringValue: ApiPath, + }, + }, + }, + }, + PluginName: FilterName, + FailStrategy: extensionsv1alpha1.FailStrategy_FAIL_OPEN, + Match: []*extensionsv1alpha1.WasmPlugin_TrafficSelector{ + { + Mode: v1beta1.WorkloadMode_CLIENT, + }, + }, + Type: extensionsv1alpha1.PluginType_HTTP, + }, + } + + existingWasmPlugin := &v1alpha1.WasmPlugin{} + if err := k8sClient.Get(ctx, client.ObjectKeyFromObject(wasmPlugin), existingWasmPlugin); err != nil { + if errors.IsNotFound(err) { + if err := k8sClient.Create(ctx, wasmPlugin); err != nil { + return err + } + logger.Infow("Created WasmPlugin", "name", wasmPlugin.Name, "namespace", wasmPlugin.Namespace) + return nil + } + return err + } + logger.Infow("Found existing WasmPlugin", "name", wasmPlugin.Name, "namespace", wasmPlugin.Namespace) + return nil +} + +func deleteWasmPlugin(logger *zap.SugaredLogger, k8sClient client.Client, istioRootNs string) error { + existingWasmPlugin := &v1alpha1.WasmPlugin{} + if err := k8sClient.Get(context.Background(), types.NamespacedName{Name: FilterName, Namespace: istioRootNs}, existingWasmPlugin); err != nil { + return err + } + + if err := k8sClient.Delete(context.Background(), existingWasmPlugin); err != nil { + return err + } + logger.Infow("Deleted WasmPlugin", "name", FilterName, "namespace", istioRootNs) + return nil +} + +func createEnvoyFilter(ctx context.Context, cfg *config.Config, k8sClient client.Client) error { + logger := util.LoggerFromCtx(ctx) + + // Istio feature stages for reference to keep trace when they plan to move their + // alpha APIs to beta then stable. + // https://istio.io/latest/docs/releases/feature-stages/#extensibility + // https://istio.io/latest/docs/releases/feature-stages/#traffic-management [Enabling custom filters in Envoy] + const httpFilter = ` +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: {{ .FilterName }} + # Deploy the filter to whatever istio considers its "root" namespace so that we + # don't have to create the ConfigMap(s) containing the WASM filter binary, + # and the associated annotations/configuration for the Istio sidecar(s). + # https://istio.io/latest/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig:~:text=No-,rootNamespace,-string + namespace: {{ .IstioRootNs }} + labels: + app.kubernetes.io/managed-by: sentryflow +spec: + configPatches: + - applyTo: CLUSTER + match: + context: SIDECAR_OUTBOUND + patch: + operation: ADD + value: + name: {{ .UpstreamAndClusterName }} + type: LOGICAL_DNS + connect_timeout: 1s + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: {{ .UpstreamAndClusterName }} + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + protocol: TCP + address: {{ .UpstreamAndClusterName }}.{{ .UpstreamAndClusterName }} + port_value: {{ .SentryFlowFilterServerPort }} +` + + data := envoyFilterData{ + FilterName: FilterName, + IstioRootNs: getIstioRootNamespaceFromConfig(cfg), + UpstreamAndClusterName: UpstreamAndClusterName, + SentryFlowFilterServerPort: cfg.Filters.Server.Port, + } + + tmpl, err := template.New("envoyHttpFilter").Parse(httpFilter) + if err != nil { + logger.Errorf("Failed to parse EnvoyFilter template: %v", err) + return err + } + + envoyFilter := &bytes.Buffer{} + if err := tmpl.Execute(envoyFilter, data); err != nil { + logger.Errorf("Failed to execute EnvoyFilter template: %v", err) + return err + } + + filterToCreate := &networkingv1alpha3.EnvoyFilter{ + TypeMeta: metav1.TypeMeta{ + Kind: "EnvoyFilter", + APIVersion: "networking.istio.io/v1alpha3", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: FilterName, + Namespace: getIstioRootNamespaceFromConfig(cfg), + }, + } + if err := yaml.UnmarshalStrict(envoyFilter.Bytes(), filterToCreate); err != nil { + logger.Errorf("Failed to unmarshal EnvoyFilter: %v", err) + return err + } + + existingFilter := &networkingv1alpha3.EnvoyFilter{} + if err := k8sClient.Get(ctx, client.ObjectKeyFromObject(filterToCreate), existingFilter); err != nil { + if errors.IsNotFound(err) { + if err := k8sClient.Create(ctx, filterToCreate); err != nil { + return err + } + logger.Infow("Created EnvoyFilter", "name", filterToCreate.Name, "namespace", filterToCreate.Namespace) + return nil + } + return err + } + logger.Infow("Found existing EnvoyFilter", "name", filterToCreate.Name, "namespace", filterToCreate.Namespace) + + return nil +} + +func deleteEnvoyFilter(logger *zap.SugaredLogger, k8sClient client.Client, istioRootNs string) error { + existingFilter := &networkingv1alpha3.EnvoyFilter{} + if err := k8sClient.Get(context.Background(), types.NamespacedName{Name: FilterName, Namespace: istioRootNs}, existingFilter); err != nil { + return err + } + + if err := k8sClient.Delete(context.Background(), existingFilter); err != nil { + return err + } + logger.Infow("Deleted EnvoyFilter", "name", FilterName, "namespace", "istio-system") + + return nil +} + +func getIstioRootNamespaceFromConfig(cfg *config.Config) string { + for _, svcMesh := range cfg.Receivers.ServiceMeshes { + switch svcMesh.Name { + case util.ServiceMeshIstioSidecar: + return svcMesh.Namespace + } + } + return "" +} diff --git a/sentryflow/pkg/util/util.go b/sentryflow/pkg/util/util.go new file mode 100644 index 0000000..ee1bd7f --- /dev/null +++ b/sentryflow/pkg/util/util.go @@ -0,0 +1,23 @@ +package util + +import ( + "context" + + "go.uber.org/zap" +) + +type LoggerContextKey struct{} + +const ( + ServiceMeshIstioSidecar = "istio-sidecar" + ServiceMeshIstioAmbient = "istio-ambient" + ServiceMeshKong = "kong" + ServiceMeshConsul = "consul" + ServiceMeshLinkerd = "linkerd" + OpenTelemetry = "otel" +) + +func LoggerFromCtx(ctx context.Context) *zap.SugaredLogger { + logger, _ := ctx.Value(LoggerContextKey{}).(*zap.SugaredLogger) + return logger +} diff --git a/sentryflow/processor/apiAnalyzer.go b/sentryflow/processor/apiAnalyzer.go deleted file mode 100644 index b7d7474..0000000 --- a/sentryflow/processor/apiAnalyzer.go +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package processor - -import ( - "log" - "sync" - - "github.com/5gsec/SentryFlow/config" -) - -// == // - -// APIA Local reference for API Analyzer -var APIA *Analyzer - -// init function -func init() { - APIA = NewAPIAnalyzer() -} - -// Analyzer Structure -type Analyzer struct { - stopChan chan struct{} - - apiLog chan string - apiLogs []string - apiLogsLock sync.Mutex -} - -// NewAPIAnalyzer Function -func NewAPIAnalyzer() *Analyzer { - ret := &Analyzer{ - apiLog: make(chan string), - apiLogs: []string{}, - apiLogsLock: sync.Mutex{}, - } - return ret -} - -// StartAPIAnalyzer Function -func StartAPIAnalyzer(wg *sync.WaitGroup) bool { - // keep analyzing given APIs - go analyzeAPIs(wg) - - log.Print("[APIAnalyzer] Started API Analyzer") - - return true -} - -// AnalyzeAPI Function -func AnalyzeAPI(api string) { - APIA.apiLog <- api -} - -// StopAPIAnalyzer Function -func StopAPIAnalyzer() bool { - APIA.stopChan <- struct{}{} - - log.Print("[APIAnalyzer] Stopped API Analyzer") - - return true -} - -// == // - -// analyzeAPIs Function -func analyzeAPIs(wg *sync.WaitGroup) { - wg.Add(1) - - for { - select { - case api, ok := <-APIA.apiLog: - if !ok { - continue - } - - APIA.apiLogsLock.Lock() - - APIA.apiLogs = append(APIA.apiLogs, api) - - if len(APIA.apiLogs) > config.GlobalConfig.AIEngineBatchSize { - ClassifyAPIs(APIA.apiLogs) - APIA.apiLogs = []string{} - } - - APIA.apiLogsLock.Unlock() - case <-APIA.stopChan: - wg.Done() - return - } - } -} - -// == // diff --git a/sentryflow/processor/apiClassifier.go b/sentryflow/processor/apiClassifier.go deleted file mode 100644 index 79f86aa..0000000 --- a/sentryflow/processor/apiClassifier.go +++ /dev/null @@ -1,215 +0,0 @@ -// // SPDX-License-Identifier: Apache-2.0 - -package processor - -import ( - "context" - "fmt" - "io" - "log" - "sync" - "time" - - "github.com/5gsec/SentryFlow/config" - "github.com/5gsec/SentryFlow/exporter" - "github.com/5gsec/SentryFlow/protobuf" - "google.golang.org/grpc" -) - -// APIC Local reference for AI-driven API Classifier -var APIC *APIClassifier - -// APIClassifier Structure -type APIClassifier struct { - stopChan chan struct{} - - APIs chan []string - - connected bool - reConnTrial time.Duration - - AIStream *streamInform -} - -// streamInform Structure -type streamInform struct { - AIStream protobuf.APIClassifier_ClassifyAPIsClient -} - -// init Function -func init() { - APIC = NewAPIClassifier() -} - -// NewAPIClassifier Function -func NewAPIClassifier() *APIClassifier { - ah := &APIClassifier{ - stopChan: make(chan struct{}), - - APIs: make(chan []string), - - connected: false, - reConnTrial: (1 * time.Minute), - } - - return ah -} - -// initAPIClassifier Function -func initAPIClassifier() bool { - AIEngineService := fmt.Sprintf("%s:%s", config.GlobalConfig.AIEngineService, config.GlobalConfig.AIEngineServicePort) - - // Set up a connection to the server - conn, err := grpc.Dial(AIEngineService, grpc.WithInsecure()) - if err != nil { - log.Printf("[APIClassifier] Failed to connect to %s: %v", AIEngineService, err) - return false - } - - log.Printf("[APIClassifier] Connecting to %s", AIEngineService) - - client := protobuf.NewAPIClassifierClient(conn) - - // Start serving gRPC server - stream, err := client.ClassifyAPIs(context.Background()) - if err != nil { - log.Printf("[APIClassifier] Failed to make a stream: %v", err) - return false - } - - log.Printf("[APIClassifier] Successfully connected to %s", AIEngineService) - - APIC.AIStream = &streamInform{ - AIStream: stream, - } - - log.Print("[APIClassifier] Started API Classifier") - - return true -} - -// StartAPIClassifier Function -func StartAPIClassifier(wg *sync.WaitGroup) bool { - go connRoutine(wg) - go sendAPIRoutine(wg) - go recvAPIRoutine(wg) - - return true -} - -// ClassifyAPIs function -func ClassifyAPIs(APIs []string) { - if APIC.connected { - APIC.APIs <- APIs - } -} - -// StopAPIClassifier Function -func StopAPIClassifier() bool { - // one for connRoutine - APIC.stopChan <- struct{}{} - - // one for sendAPIRoutine - APIC.stopChan <- struct{}{} - - // one for recvAPIRoutine - APIC.stopChan <- struct{}{} - - log.Print("[APIClassifier] Stopped API Classifier") - - return true -} - -// connRoutine Function -func connRoutine(wg *sync.WaitGroup) { - wg.Add(1) - - for { - select { - case <-APIC.stopChan: - wg.Done() - return - default: - if !APIC.connected { - if initAPIClassifier() { - APIC.connected = true - } else { - time.Sleep(APIC.reConnTrial) - } - } - } - } -} - -// sendAPIRoutine Function -func sendAPIRoutine(wg *sync.WaitGroup) { - wg.Add(1) - - for { - if !APIC.connected { - time.Sleep(APIC.reConnTrial) - continue - } - - select { - case api, ok := <-APIC.APIs: - if !ok { - log.Print("[APIClassifier] Failed to fetch APIs from APIs channel") - continue - } - - curAPIRequest := &protobuf.APIClassifierRequest{ - API: api, - } - - err := APIC.AIStream.AIStream.Send(curAPIRequest) - if err != nil { - log.Printf("[APIClassifier] Failed to send an API to AI Engine: %v", err) - APIC.connected = false - continue - } - case <-APIC.stopChan: - wg.Done() - return - } - } -} - -// recvAPIRoutine Function -func recvAPIRoutine(wg *sync.WaitGroup) { - wg.Add(1) - - for { - if !APIC.connected { - time.Sleep(APIC.reConnTrial) - continue - } - - select { - default: - APIMetrics := make(map[string]uint64) - - event, err := APIC.AIStream.AIStream.Recv() - if err == io.EOF { - continue - } else if err != nil { - log.Printf("[APIClassifier] Failed to receive an event from AI Engine: %v", err) - APIC.connected = false - continue - } - - for api, count := range event.APIs { - APIMetrics[api] = count - } - - err = exporter.ExpH.SendAPIMetrics(&protobuf.APIMetrics{PerAPICounts: APIMetrics}) - if err != nil { - log.Printf("[APIClassifier] Failed to export API metrics: %v", err) - continue - } - case <-APIC.stopChan: - wg.Done() - return - } - } -} diff --git a/sentryflow/processor/logProcessor.go b/sentryflow/processor/logProcessor.go deleted file mode 100644 index f097b80..0000000 --- a/sentryflow/processor/logProcessor.go +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package processor - -import ( - "log" - "sync" - - "github.com/5gsec/SentryFlow/exporter" - "github.com/5gsec/SentryFlow/protobuf" -) - -// == // - -// LogH global reference for Log Handler -var LogH *LogHandler - -// init Function -func init() { - LogH = NewLogHandler() -} - -// LogHandler Structure -type LogHandler struct { - stopChan chan struct{} - - apiLogChan chan interface{} - metricsChan chan interface{} -} - -// NewLogHandler Structure -func NewLogHandler() *LogHandler { - lh := &LogHandler{ - stopChan: make(chan struct{}), - - apiLogChan: make(chan interface{}), - metricsChan: make(chan interface{}), - } - - return lh -} - -// == // - -// StartLogProcessor Function -func StartLogProcessor(wg *sync.WaitGroup) bool { - // handle API logs - go ProcessAPILogs(wg) - - // handle Envoy metrics - go ProcessEnvoyMetrics(wg) - - log.Print("[LogProcessor] Started Log Processors") - - return true -} - -// StopLogProcessor Function -func StopLogProcessor() bool { - // One for ProcessAPILogs - LogH.stopChan <- struct{}{} - - // One for ProcessMetrics - LogH.stopChan <- struct{}{} - - log.Print("[LogProcessor] Stopped Log Processors") - - return true -} - -// == // - -// ProcessAPILogs Function -func ProcessAPILogs(wg *sync.WaitGroup) { - wg.Add(1) - - for { - select { - case data, ok := <-LogH.apiLogChan: - if !ok { - log.Print("[LogProcessor] Failed to process an API log") - } - switch logType := data.(type) { - case *protobuf.APILog: - go AnalyzeAPI(logType.Path) - go exporter.InsertAPILog(logType) - case *protobuf.APILogV2: - go exporter.InsertAPILog(logType) - default: - log.Print("Unsupported API log Version") - continue - } - - case <-LogH.stopChan: - wg.Done() - return - } - } -} - -// InsertAPILog Function -func InsertAPILog(data interface{}) { - LogH.apiLogChan <- data -} - -// ProcessEnvoyMetrics Function -func ProcessEnvoyMetrics(wg *sync.WaitGroup) { - wg.Add(1) - - for { - select { - case logType, ok := <-LogH.metricsChan: - if !ok { - log.Print("[LogProcessor] Failed to process Envoy metrics") - } - - go exporter.InsertEnvoyMetrics(logType.(*protobuf.EnvoyMetrics)) - - case <-LogH.stopChan: - wg.Done() - return - } - } -} - -// InsertMetrics Function -func InsertMetrics(data interface{}) { - LogH.metricsChan <- data -} - -// == // diff --git a/sentryflow/types/types.go b/sentryflow/types/types.go deleted file mode 100644 index 4ce59ab..0000000 --- a/sentryflow/types/types.go +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package types - -// == // - -// K8sResourceTypes -const ( - K8sResourceTypeUnknown = 0 - K8sResourceTypePod = 1 - K8sResourceTypeService = 2 -) - -// K8sResource Structure -type K8sResource struct { - Type uint8 - Namespace string - Name string - Labels map[string]string - Containers []string -} - -// K8sResourceTypeToString Function -func K8sResourceTypeToString(resourceType uint8) string { - switch resourceType { - case K8sResourceTypePod: - return "Pod" - case K8sResourceTypeService: - return "Service" - case K8sResourceTypeUnknown: - return "Unknown" - } - return "Unknown" -} - -// == // From 5660ed796a19792adaeb32fd0aca512803358b7a Mon Sep 17 00:00:00 2001 From: Anurag Rajawat Date: Mon, 30 Sep 2024 15:51:04 +0530 Subject: [PATCH 4/6] chore: Add License Signed-off-by: Anurag Rajawat --- .licenserc.yaml | 2 ++ protobuf/Makefile | 3 +++ scripts/add-license-header | 20 +++++++++++++++++++ scripts/license.header | 2 ++ sentryflow/Dockerfile | 3 +++ sentryflow/Makefile | 3 +++ sentryflow/cmd/root.go | 3 +++ sentryflow/cmd/version.go | 3 +++ sentryflow/config/default.yaml | 3 +++ sentryflow/main.go | 3 +++ sentryflow/pkg/config/config.go | 3 +++ sentryflow/pkg/core/sentryflow.go | 3 +++ sentryflow/pkg/core/server.go | 3 +++ sentryflow/pkg/exporter/exporter.go | 3 +++ sentryflow/pkg/k8s/client.go | 3 +++ sentryflow/pkg/receiver/receiver.go | 3 +++ .../receiver/svcmesh/istio/sidecar/sidecar.go | 3 +++ sentryflow/pkg/util/util.go | 3 +++ 18 files changed, 69 insertions(+) create mode 100755 scripts/add-license-header create mode 100644 scripts/license.header diff --git a/.licenserc.yaml b/.licenserc.yaml index b683404..06090b9 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -12,6 +12,8 @@ header: paths-ignore: - "protobuf/*" + # Explicitly mention generated go files otherwise the check won't pass. + - "protobuf/**/*.go" comment: on-failure diff --git a/protobuf/Makefile b/protobuf/Makefile index 9297546..680c490 100644 --- a/protobuf/Makefile +++ b/protobuf/Makefile @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2024 Authors of SentryFlow + PROTOS:="sentryflow.proto sentryflow_metrics.proto" .PHONY: help diff --git a/scripts/add-license-header b/scripts/add-license-header new file mode 100755 index 0000000..a92bfb5 --- /dev/null +++ b/scripts/add-license-header @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2024 Authors of SentryFlow + +if ! command -v addlicense >/dev/null; then + echo "Installing addlicense..." + go install github.com/google/addlicense@latest +fi + +GIT_ROOT=$(git rev-parse --show-toplevel) +LICENSE_HEADER=${GIT_ROOT}/scripts/license.header + +if [ -z "$1" ]; then + echo "No Argument Supplied, Checking and Fixing all files from project root" + find "${GIT_ROOT}" -name "*.sh" -or -name "*.go" | xargs -I {} addlicense -f "${LICENSE_HEADER}" -v {} + echo "Done" +else + addlicense -f "${LICENSE_HEADER}" -v "$1" + echo "Done" +fi diff --git a/scripts/license.header b/scripts/license.header new file mode 100644 index 0000000..d7c0bd6 --- /dev/null +++ b/scripts/license.header @@ -0,0 +1,2 @@ +SPDX-License-Identifier: Apache-2.0 +Copyright 2024 Authors of SentryFlow diff --git a/sentryflow/Dockerfile b/sentryflow/Dockerfile index a7cc1d5..f66c4c5 100644 --- a/sentryflow/Dockerfile +++ b/sentryflow/Dockerfile @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2024 Authors of SentryFlow + FROM golang:1.23 AS builder ARG TARGETOS diff --git a/sentryflow/Makefile b/sentryflow/Makefile index 6dbda0f..17a8bce 100644 --- a/sentryflow/Makefile +++ b/sentryflow/Makefile @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2024 Authors of SentryFlow + BINARY_NAME ?= sentryflow REGISTRY ?= docker.io/5gsec VERSION ?= $(shell git rev-parse HEAD) diff --git a/sentryflow/cmd/root.go b/sentryflow/cmd/root.go index 273c9d4..743831b 100644 --- a/sentryflow/cmd/root.go +++ b/sentryflow/cmd/root.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package cmd import ( diff --git a/sentryflow/cmd/version.go b/sentryflow/cmd/version.go index 77d5f89..6fcfd4c 100644 --- a/sentryflow/cmd/version.go +++ b/sentryflow/cmd/version.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package cmd import ( diff --git a/sentryflow/config/default.yaml b/sentryflow/config/default.yaml index c440052..51c7907 100644 --- a/sentryflow/config/default.yaml +++ b/sentryflow/config/default.yaml @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2024 Authors of SentryFlow + filters: server: port: 8081 diff --git a/sentryflow/main.go b/sentryflow/main.go index 6163445..87ed3e2 100644 --- a/sentryflow/main.go +++ b/sentryflow/main.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package main import ( diff --git a/sentryflow/pkg/config/config.go b/sentryflow/pkg/config/config.go index a202921..27fe25d 100644 --- a/sentryflow/pkg/config/config.go +++ b/sentryflow/pkg/config/config.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package config import ( diff --git a/sentryflow/pkg/core/sentryflow.go b/sentryflow/pkg/core/sentryflow.go index 42261a8..1d6d194 100644 --- a/sentryflow/pkg/core/sentryflow.go +++ b/sentryflow/pkg/core/sentryflow.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package core import ( diff --git a/sentryflow/pkg/core/server.go b/sentryflow/pkg/core/server.go index 9d2571c..ec7a7d6 100644 --- a/sentryflow/pkg/core/server.go +++ b/sentryflow/pkg/core/server.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package core import ( diff --git a/sentryflow/pkg/exporter/exporter.go b/sentryflow/pkg/exporter/exporter.go index 6cea493..56a7717 100644 --- a/sentryflow/pkg/exporter/exporter.go +++ b/sentryflow/pkg/exporter/exporter.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package exporter import ( diff --git a/sentryflow/pkg/k8s/client.go b/sentryflow/pkg/k8s/client.go index b6b0e8d..9d74f60 100644 --- a/sentryflow/pkg/k8s/client.go +++ b/sentryflow/pkg/k8s/client.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package k8s import ( diff --git a/sentryflow/pkg/receiver/receiver.go b/sentryflow/pkg/receiver/receiver.go index 7c2312b..8ed148e 100644 --- a/sentryflow/pkg/receiver/receiver.go +++ b/sentryflow/pkg/receiver/receiver.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package receiver import ( diff --git a/sentryflow/pkg/receiver/svcmesh/istio/sidecar/sidecar.go b/sentryflow/pkg/receiver/svcmesh/istio/sidecar/sidecar.go index 9b2e9a5..4a576b9 100644 --- a/sentryflow/pkg/receiver/svcmesh/istio/sidecar/sidecar.go +++ b/sentryflow/pkg/receiver/svcmesh/istio/sidecar/sidecar.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package sidecar import ( diff --git a/sentryflow/pkg/util/util.go b/sentryflow/pkg/util/util.go index ee1bd7f..50e838b 100644 --- a/sentryflow/pkg/util/util.go +++ b/sentryflow/pkg/util/util.go @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of SentryFlow + package util import ( From bae8efcdcb704df1fd0953d3b9a478432ae8d729 Mon Sep 17 00:00:00 2001 From: Anurag Rajawat Date: Mon, 30 Sep 2024 15:51:23 +0530 Subject: [PATCH 5/6] feat(CI): Initial CI Signed-off-by: Anurag Rajawat --- .github/workflows/ci-test-go.yml | 56 ----------- .github/workflows/ci-test-py.yml | 156 +++++++++++++++---------------- .github/workflows/pr-checks.yaml | 75 +++++++++++++++ .github/workflows/pr-checks.yml | 35 ------- .github/workflows/release.yml | 49 ---------- 5 files changed, 153 insertions(+), 218 deletions(-) delete mode 100644 .github/workflows/ci-test-go.yml create mode 100644 .github/workflows/pr-checks.yaml delete mode 100644 .github/workflows/pr-checks.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/ci-test-go.yml b/.github/workflows/ci-test-go.yml deleted file mode 100644 index 2227246..0000000 --- a/.github/workflows/ci-test-go.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: ci-test-go -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - go-fmt-sentryflow: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-go@v3 - with: - go-version: "v1.21" - - - name: Check go-fmt - run: make gofmt - working-directory: sentryflow - - go-lint-sentryflow: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-go@v3 - with: - go-version: "v1.21" - - - name: Check Golint - run: make golint - working-directory: sentryflow - - go-sec-sentryflow: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-go@v3 - with: - go-version: "v1.21" - - - name: Run Gosec Security Scanner - run: make gosec - working-directory: sentryflow - - license: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Check License Header - uses: apache/skywalking-eyes@a790ab8dd23a7f861c18bd6aaa9b012e3a234bce - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci-test-py.yml b/.github/workflows/ci-test-py.yml index 4d6ba59..5ab4ed9 100644 --- a/.github/workflows/ci-test-py.yml +++ b/.github/workflows/ci-test-py.yml @@ -1,78 +1,78 @@ -name: ci-test-py -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - py-pip-ai-sentryflow: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.11' - cache: 'pip' - - - name: check Python pip3 requirements - run: | - pip install -r requirements.txt - working-directory: ai-engine - - py-ruff-ai-sentryflow: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.11' - cache: 'pip' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - working-directory: ai-engine - - - name: Create pyproject.toml - run: | - echo "[tool.ruff.lint.per-file-ignores]" > pyproject.toml - echo '"stringlifier/*" = ["E402", "F811", "F401"]' >> pyproject.toml - working-directory: ai-engine - - - name: Lint with Ruff - run: | - pip install ruff - ruff --output-format=github . - working-directory: ai-engine - - py-lint-ai-sentryflow: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.11' - cache: 'pip' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install pylint - working-directory: ai-engine - - - name: Lint with Pylint - run: | - pylint classifier.py - working-directory: ai-engine - - py-pep8-ai-sentryflow: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: 'Run PEP8' - uses: quentinguidee/pep8-action@v1 - with: - arguments: '--max-line-length=120 --exclude=*stringlifier/*,*protobuf/*' +#name: ci-test-py +#on: +# push: +# branches: [main] +# pull_request: +# branches: [main] +# +#jobs: +# py-pip-ai-sentryflow: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v3 +# - uses: actions/setup-python@v4 +# with: +# python-version: '3.11' +# cache: 'pip' +# +# - name: check Python pip3 requirements +# run: | +# pip install -r requirements.txt +# working-directory: ai-engine +# +# py-ruff-ai-sentryflow: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v3 +# - uses: actions/setup-python@v4 +# with: +# python-version: '3.11' +# cache: 'pip' +# +# - name: Install dependencies +# run: | +# python -m pip install --upgrade pip +# pip install -r requirements.txt +# working-directory: ai-engine +# +# - name: Create pyproject.toml +# run: | +# echo "[tool.ruff.lint.per-file-ignores]" > pyproject.toml +# echo '"stringlifier/*" = ["E402", "F811", "F401"]' >> pyproject.toml +# working-directory: ai-engine +# +# - name: Lint with Ruff +# run: | +# pip install ruff +# ruff --output-format=github . +# working-directory: ai-engine +# +# py-lint-ai-sentryflow: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v3 +# - uses: actions/setup-python@v4 +# with: +# python-version: '3.11' +# cache: 'pip' +# +# - name: Install dependencies +# run: | +# python -m pip install --upgrade pip +# pip install -r requirements.txt +# pip install pylint +# working-directory: ai-engine +# +# - name: Lint with Pylint +# run: | +# pylint classifier.py +# working-directory: ai-engine +# +# py-pep8-ai-sentryflow: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v3 +# - name: 'Run PEP8' +# uses: quentinguidee/pep8-action@v1 +# with: +# arguments: '--max-line-length=120 --exclude=*stringlifier/*,*protobuf/*' diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml new file mode 100644 index 0000000..2f340a2 --- /dev/null +++ b/.github/workflows/pr-checks.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2024 Authors of SentryFlow + +name: PR checks + +on: + pull_request: + types: [ opened, reopened, synchronize, ready_for_review ] + paths-ignore: + - '**.md' + - 'docs/**' + - 'LICENSE' + +permissions: read-all + +jobs: + license: + name: License + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./sentryflow + steps: + - uses: actions/checkout@v4 + + - name: Check License Header + uses: apache/skywalking-eyes@v0.6.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + static-checks: + name: Static checks + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./sentryflow + steps: + - uses: actions/checkout@v4 + + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version: '1.22' + + - name: go fmt + run: make fmt + + - name: Lint + uses: golangci/golangci-lint-action@v6 + with: + working-directory: ./sentryflow + version: v1.60.3 + args: --timeout=10m --out-format=line-number + skip-cache: true # https://github.com/golangci/golangci-lint-action/issues/244#issuecomment-1052197778 + + build-sentryflow-image: + name: Build SentryFlow container image + runs-on: ubuntu-latest + timeout-minutes: 20 + defaults: + run: + working-directory: ./sentryflow + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Build image + run: make image + + - name: Scan image + uses: anchore/scan-action@v4 + with: + image: "docker.io/5gsec/sentryflow:latest" + severity-cutoff: critical + output-format: sarif diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml deleted file mode 100644 index 99e3146..0000000 --- a/.github/workflows/pr-checks.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: pr-checks - -on: - pull_request: - branches: [main] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Setup Docker Build - uses: docker/setup-buildx-action@v1 - - - name: Get tag - id: tag - run: | - if [ ${{ github.ref }} == "refs/heads/main" ]; then - echo "tag=latest" >> $GITHUB_OUTPUT - else - echo "tag=tmp" >> $GITHUB_OUTPUT - fi - - - name: Build SentryFlow Image - working-directory: ./sentryflow - run: | - make TAG=${{ steps.tag.outputs.tag }} build-image - - - name: Build SentryFlow AI Engine Image - working-directory: ./ai-engine - run: | - make TAG=${{ steps.tag.outputs.tag }} build-image diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 904b408..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: release - -on: - push: - branches: [main] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Setup Docker Build - uses: docker/setup-buildx-action@v1 - - # - name: Login to DockerHub - # uses: docker/login-action@v1 - # with: - # username: ${{ secrets.DOCKERHUB_USERNAME }} - # password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Get tag - id: tag - run: | - if [ ${{ github.ref }} == "refs/heads/main" ]; then - echo "tag=latest" >> $GITHUB_OUTPUT - else - echo "tag=tmp" >> $GITHUB_OUTPUT - fi - - - name: Build SentryFlow Image - working-directory: ./sentryflow - run: | - make TAG=${{ steps.tag.outputs.tag }} build-image - - # - name: Push SentryFlow Image - # run: | - # docker push 5gsec/sentryflow:${{ steps.tag.outputs.tag }} - - - name: Build SentryFlow AI Engine Image - working-directory: ./ai-engine - run: | - make TAG=${{ steps.tag.outputs.tag }} build-image - - # - name: Push SentryFlow AI Engine Image - # run: | - # docker push 5gsec/sentryflow-ai-engine:${{ steps.tag.outputs.tag }} From d2d9ce4d3968e7ea6da9d0f3446072ea96b1b962 Mon Sep 17 00:00:00 2001 From: Anurag Rajawat Date: Thu, 3 Oct 2024 15:00:20 +0530 Subject: [PATCH 6/6] chore: Add label in SentryFlow objects Signed-off-by: Anurag Rajawat --- deployments/sentryflow.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/deployments/sentryflow.yaml b/deployments/sentryflow.yaml index c29d217..e3542f8 100644 --- a/deployments/sentryflow.yaml +++ b/deployments/sentryflow.yaml @@ -2,17 +2,23 @@ apiVersion: v1 kind: Namespace metadata: name: sentryflow + labels: + app.kubernetes.io/part-of: sentryflow --- apiVersion: v1 kind: ServiceAccount metadata: name: sentryflow namespace: sentryflow + labels: + app.kubernetes.io/part-of: sentryflow --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: sentryflow + labels: + app.kubernetes.io/part-of: sentryflow rules: - apiGroups: - networking.istio.io @@ -35,6 +41,8 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: sentryflow + labels: + app.kubernetes.io/part-of: sentryflow roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -49,6 +57,8 @@ kind: ConfigMap metadata: name: config namespace: sentryflow + labels: + app.kubernetes.io/part-of: sentryflow data: config.yaml: |2- filters: @@ -71,6 +81,8 @@ kind: Deployment metadata: name: sentryflow namespace: sentryflow + labels: + app.kubernetes.io/part-of: sentryflow spec: replicas: 1 selector: @@ -124,6 +136,8 @@ kind: Service metadata: namespace: sentryflow name: sentryflow + labels: + app.kubernetes.io/part-of: sentryflow spec: selector: app: sentryflow