diff --git a/api/v1/README.md b/api/v1/README.md index ba525d45390..cb216d9ae76 100644 --- a/api/v1/README.md +++ b/api/v1/README.md @@ -68,6 +68,7 @@ - [GetEventsRequest](#tetragon-GetEventsRequest) - [GetEventsResponse](#tetragon-GetEventsResponse) - [RateLimitInfo](#tetragon-RateLimitInfo) + - [RedactionFilter](#tetragon-RedactionFilter) - [EventType](#tetragon-EventType) - [FieldFilterAction](#tetragon-FieldFilterAction) @@ -1289,6 +1290,22 @@ Capability set to filter over. NOTE: you may specify only ONE set here. + + + +### RedactionFilter + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| match | [Filter](#tetragon-Filter) | repeated | Match events that the redaction filter will apply to. | +| redact | [string](#string) | repeated | Regular expressions to use for redaction. Strings inside capture groups are redacted. | + + + + + diff --git a/api/v1/tetragon/events.pb.go b/api/v1/tetragon/events.pb.go index 64b259fbe4f..799d0a47dd5 100644 --- a/api/v1/tetragon/events.pb.go +++ b/api/v1/tetragon/events.pb.go @@ -432,6 +432,63 @@ func (x *CapFilterSet) GetNone() []CapabilitiesType { return nil } +type RedactionFilter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Match events that the redaction filter will apply to. + Match []*Filter `protobuf:"bytes,1,rep,name=match,proto3" json:"match,omitempty"` + // Regular expressions to use for redaction. Strings inside capture groups are redacted. + Redact []string `protobuf:"bytes,2,rep,name=redact,proto3" json:"redact,omitempty"` +} + +func (x *RedactionFilter) Reset() { + *x = RedactionFilter{} + if protoimpl.UnsafeEnabled { + mi := &file_tetragon_events_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RedactionFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RedactionFilter) ProtoMessage() {} + +func (x *RedactionFilter) ProtoReflect() protoreflect.Message { + mi := &file_tetragon_events_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 RedactionFilter.ProtoReflect.Descriptor instead. +func (*RedactionFilter) Descriptor() ([]byte, []int) { + return file_tetragon_events_proto_rawDescGZIP(), []int{3} +} + +func (x *RedactionFilter) GetMatch() []*Filter { + if x != nil { + return x.Match + } + return nil +} + +func (x *RedactionFilter) GetRedact() []string { + if x != nil { + return x.Redact + } + return nil +} + type FieldFilter struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -450,7 +507,7 @@ type FieldFilter struct { func (x *FieldFilter) Reset() { *x = FieldFilter{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[3] + mi := &file_tetragon_events_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -463,7 +520,7 @@ func (x *FieldFilter) String() string { func (*FieldFilter) ProtoMessage() {} func (x *FieldFilter) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[3] + mi := &file_tetragon_events_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -476,7 +533,7 @@ func (x *FieldFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use FieldFilter.ProtoReflect.Descriptor instead. func (*FieldFilter) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{3} + return file_tetragon_events_proto_rawDescGZIP(), []int{4} } func (x *FieldFilter) GetEventSet() []EventType { @@ -536,7 +593,7 @@ type GetEventsRequest struct { func (x *GetEventsRequest) Reset() { *x = GetEventsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[4] + mi := &file_tetragon_events_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -549,7 +606,7 @@ func (x *GetEventsRequest) String() string { func (*GetEventsRequest) ProtoMessage() {} func (x *GetEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[4] + mi := &file_tetragon_events_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -562,7 +619,7 @@ func (x *GetEventsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetEventsRequest.ProtoReflect.Descriptor instead. func (*GetEventsRequest) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{4} + return file_tetragon_events_proto_rawDescGZIP(), []int{5} } func (x *GetEventsRequest) GetAllowList() []*Filter { @@ -610,7 +667,7 @@ type AggregationOptions struct { func (x *AggregationOptions) Reset() { *x = AggregationOptions{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[5] + mi := &file_tetragon_events_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -623,7 +680,7 @@ func (x *AggregationOptions) String() string { func (*AggregationOptions) ProtoMessage() {} func (x *AggregationOptions) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[5] + mi := &file_tetragon_events_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -636,7 +693,7 @@ func (x *AggregationOptions) ProtoReflect() protoreflect.Message { // Deprecated: Use AggregationOptions.ProtoReflect.Descriptor instead. func (*AggregationOptions) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{5} + return file_tetragon_events_proto_rawDescGZIP(), []int{6} } func (x *AggregationOptions) GetWindowSize() *durationpb.Duration { @@ -666,7 +723,7 @@ type AggregationInfo struct { func (x *AggregationInfo) Reset() { *x = AggregationInfo{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[6] + mi := &file_tetragon_events_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -679,7 +736,7 @@ func (x *AggregationInfo) String() string { func (*AggregationInfo) ProtoMessage() {} func (x *AggregationInfo) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[6] + mi := &file_tetragon_events_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -692,7 +749,7 @@ func (x *AggregationInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use AggregationInfo.ProtoReflect.Descriptor instead. func (*AggregationInfo) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{6} + return file_tetragon_events_proto_rawDescGZIP(), []int{7} } func (x *AggregationInfo) GetCount() uint64 { @@ -713,7 +770,7 @@ type RateLimitInfo struct { func (x *RateLimitInfo) Reset() { *x = RateLimitInfo{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[7] + mi := &file_tetragon_events_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -726,7 +783,7 @@ func (x *RateLimitInfo) String() string { func (*RateLimitInfo) ProtoMessage() {} func (x *RateLimitInfo) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[7] + mi := &file_tetragon_events_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -739,7 +796,7 @@ func (x *RateLimitInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use RateLimitInfo.ProtoReflect.Descriptor instead. func (*RateLimitInfo) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{7} + return file_tetragon_events_proto_rawDescGZIP(), []int{8} } func (x *RateLimitInfo) GetNumberOfDroppedProcessEvents() uint64 { @@ -783,7 +840,7 @@ type GetEventsResponse struct { func (x *GetEventsResponse) Reset() { *x = GetEventsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[8] + mi := &file_tetragon_events_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -796,7 +853,7 @@ func (x *GetEventsResponse) String() string { func (*GetEventsResponse) ProtoMessage() {} func (x *GetEventsResponse) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[8] + mi := &file_tetragon_events_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -809,7 +866,7 @@ func (x *GetEventsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetEventsResponse.ProtoReflect.Descriptor instead. func (*GetEventsResponse) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{8} + return file_tetragon_events_proto_rawDescGZIP(), []int{9} } func (m *GetEventsResponse) GetEvent() isGetEventsResponse_Event { @@ -1022,112 +1079,117 @@ var file_tetragon_events_proto_rawDesc = []byte{ 0x74, 0x6c, 0x79, 0x12, 0x2e, 0x0a, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x6e, - 0x6f, 0x6e, 0x65, 0x22, 0xee, 0x01, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x74, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, - 0x6e, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x53, 0x65, 0x74, 0x12, 0x32, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 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, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, - 0x6b, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x06, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x74, 0x72, - 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, - 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x53, 0x65, 0x74, 0x22, 0xfd, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x09, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x09, 0x64, 0x65, - 0x6e, 0x79, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x08, 0x64, 0x65, 0x6e, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4d, 0x0a, 0x13, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, - 0x6e, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x22, 0x80, 0x01, 0x0a, 0x12, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x77, - 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x77, 0x69, 0x6e, - 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x27, 0x0a, 0x0f, 0x41, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x22, 0x57, 0x0a, 0x0d, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x46, 0x0a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x64, - 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1c, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x4f, 0x66, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xab, 0x05, 0x0a, 0x11, 0x47, 0x65, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3a, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, - 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x65, 0x63, 0x48, 0x00, 0x52, 0x0b, - 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x65, 0x63, 0x12, 0x3a, 0x0a, 0x0c, 0x70, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x69, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x45, 0x78, 0x69, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x6b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x4b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x4b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x4c, 0x0a, 0x12, 0x70, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, - 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x61, - 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x75, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x70, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x74, - 0x65, 0x73, 0x74, 0x18, 0xc0, 0xb8, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x65, - 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x74, - 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0xc1, 0xb8, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x61, 0x74, 0x65, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, - 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0xe9, - 0x07, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0xea, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x07, - 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2a, 0xb1, 0x01, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x10, 0x00, - 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x45, 0x43, - 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x45, 0x58, - 0x49, 0x54, 0x10, 0x05, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, - 0x4b, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x09, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x43, - 0x45, 0x53, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x0a, - 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, 0x4f, 0x41, 0x44, - 0x45, 0x52, 0x10, 0x0b, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, - 0x55, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x0c, 0x12, 0x0a, 0x0a, 0x04, 0x54, 0x45, 0x53, 0x54, - 0x10, 0xc0, 0xb8, 0x02, 0x12, 0x15, 0x0a, 0x0f, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x4c, 0x49, 0x4d, - 0x49, 0x54, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xc1, 0xb8, 0x02, 0x2a, 0x2d, 0x0a, 0x11, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, - 0x07, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6f, 0x6e, 0x65, 0x22, 0x51, 0x0a, 0x0f, 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, + 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x22, 0xee, 0x01, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x74, 0x72, + 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x12, 0x32, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x73, 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, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x06, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, + 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x44, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, + 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x22, 0xfd, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2d, 0x0a, + 0x09, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x08, 0x64, 0x65, 0x6e, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4d, 0x0a, 0x13, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x74, 0x72, + 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x0d, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0x80, 0x01, 0x0a, 0x12, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, + 0x0a, 0x0b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, + 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x27, 0x0a, 0x0f, 0x41, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, + 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x22, 0x57, 0x0a, 0x0d, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46, 0x0a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, + 0x66, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1c, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xab, 0x05, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x78, + 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, + 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x65, 0x63, 0x48, + 0x00, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x65, 0x63, 0x12, 0x3a, + 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x69, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x69, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x4c, 0x0a, 0x12, + 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, + 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x61, 0x63, 0x65, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0d, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0e, + 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x75, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x48, 0x00, 0x52, + 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x26, + 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x18, 0xc0, 0xb8, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x48, 0x00, + 0x52, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0xc1, 0xb8, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x61, + 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0xe9, 0x07, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0xea, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, + 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, + 0x6f, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2a, 0xb1, 0x01, 0x0a, 0x09, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, 0x44, 0x45, + 0x46, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x45, + 0x58, 0x45, 0x43, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, + 0x5f, 0x45, 0x58, 0x49, 0x54, 0x10, 0x05, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, + 0x53, 0x53, 0x5f, 0x4b, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x09, 0x12, 0x16, 0x0a, 0x12, 0x50, + 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x50, 0x4f, 0x49, 0x4e, + 0x54, 0x10, 0x0a, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, + 0x4f, 0x41, 0x44, 0x45, 0x52, 0x10, 0x0b, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, + 0x53, 0x53, 0x5f, 0x55, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x0c, 0x12, 0x0a, 0x0a, 0x04, 0x54, + 0x45, 0x53, 0x54, 0x10, 0xc0, 0xb8, 0x02, 0x12, 0x15, 0x0a, 0x0f, 0x52, 0x41, 0x54, 0x45, 0x5f, + 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xc1, 0xb8, 0x02, 0x2a, 0x2d, + 0x0a, 0x11, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x00, + 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x01, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1143,67 +1205,69 @@ func file_tetragon_events_proto_rawDescGZIP() []byte { } var file_tetragon_events_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_tetragon_events_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_tetragon_events_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_tetragon_events_proto_goTypes = []interface{}{ (EventType)(0), // 0: tetragon.EventType (FieldFilterAction)(0), // 1: tetragon.FieldFilterAction (*Filter)(nil), // 2: tetragon.Filter (*CapFilter)(nil), // 3: tetragon.CapFilter (*CapFilterSet)(nil), // 4: tetragon.CapFilterSet - (*FieldFilter)(nil), // 5: tetragon.FieldFilter - (*GetEventsRequest)(nil), // 6: tetragon.GetEventsRequest - (*AggregationOptions)(nil), // 7: tetragon.AggregationOptions - (*AggregationInfo)(nil), // 8: tetragon.AggregationInfo - (*RateLimitInfo)(nil), // 9: tetragon.RateLimitInfo - (*GetEventsResponse)(nil), // 10: tetragon.GetEventsResponse - (*wrapperspb.BoolValue)(nil), // 11: google.protobuf.BoolValue - (CapabilitiesType)(0), // 12: tetragon.CapabilitiesType - (*fieldmaskpb.FieldMask)(nil), // 13: google.protobuf.FieldMask - (*durationpb.Duration)(nil), // 14: google.protobuf.Duration - (*ProcessExec)(nil), // 15: tetragon.ProcessExec - (*ProcessExit)(nil), // 16: tetragon.ProcessExit - (*ProcessKprobe)(nil), // 17: tetragon.ProcessKprobe - (*ProcessTracepoint)(nil), // 18: tetragon.ProcessTracepoint - (*ProcessLoader)(nil), // 19: tetragon.ProcessLoader - (*ProcessUprobe)(nil), // 20: tetragon.ProcessUprobe - (*Test)(nil), // 21: tetragon.Test - (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp + (*RedactionFilter)(nil), // 5: tetragon.RedactionFilter + (*FieldFilter)(nil), // 6: tetragon.FieldFilter + (*GetEventsRequest)(nil), // 7: tetragon.GetEventsRequest + (*AggregationOptions)(nil), // 8: tetragon.AggregationOptions + (*AggregationInfo)(nil), // 9: tetragon.AggregationInfo + (*RateLimitInfo)(nil), // 10: tetragon.RateLimitInfo + (*GetEventsResponse)(nil), // 11: tetragon.GetEventsResponse + (*wrapperspb.BoolValue)(nil), // 12: google.protobuf.BoolValue + (CapabilitiesType)(0), // 13: tetragon.CapabilitiesType + (*fieldmaskpb.FieldMask)(nil), // 14: google.protobuf.FieldMask + (*durationpb.Duration)(nil), // 15: google.protobuf.Duration + (*ProcessExec)(nil), // 16: tetragon.ProcessExec + (*ProcessExit)(nil), // 17: tetragon.ProcessExit + (*ProcessKprobe)(nil), // 18: tetragon.ProcessKprobe + (*ProcessTracepoint)(nil), // 19: tetragon.ProcessTracepoint + (*ProcessLoader)(nil), // 20: tetragon.ProcessLoader + (*ProcessUprobe)(nil), // 21: tetragon.ProcessUprobe + (*Test)(nil), // 22: tetragon.Test + (*timestamppb.Timestamp)(nil), // 23: google.protobuf.Timestamp } var file_tetragon_events_proto_depIdxs = []int32{ - 11, // 0: tetragon.Filter.health_check:type_name -> google.protobuf.BoolValue + 12, // 0: tetragon.Filter.health_check:type_name -> google.protobuf.BoolValue 0, // 1: tetragon.Filter.event_set:type_name -> tetragon.EventType 3, // 2: tetragon.Filter.capabilities:type_name -> tetragon.CapFilter 4, // 3: tetragon.CapFilter.permitted:type_name -> tetragon.CapFilterSet 4, // 4: tetragon.CapFilter.effective:type_name -> tetragon.CapFilterSet 4, // 5: tetragon.CapFilter.inheritable:type_name -> tetragon.CapFilterSet - 12, // 6: tetragon.CapFilterSet.any:type_name -> tetragon.CapabilitiesType - 12, // 7: tetragon.CapFilterSet.all:type_name -> tetragon.CapabilitiesType - 12, // 8: tetragon.CapFilterSet.exactly:type_name -> tetragon.CapabilitiesType - 12, // 9: tetragon.CapFilterSet.none:type_name -> tetragon.CapabilitiesType - 0, // 10: tetragon.FieldFilter.event_set:type_name -> tetragon.EventType - 13, // 11: tetragon.FieldFilter.fields:type_name -> google.protobuf.FieldMask - 1, // 12: tetragon.FieldFilter.action:type_name -> tetragon.FieldFilterAction - 11, // 13: tetragon.FieldFilter.invert_event_set:type_name -> google.protobuf.BoolValue - 2, // 14: tetragon.GetEventsRequest.allow_list:type_name -> tetragon.Filter - 2, // 15: tetragon.GetEventsRequest.deny_list:type_name -> tetragon.Filter - 7, // 16: tetragon.GetEventsRequest.aggregation_options:type_name -> tetragon.AggregationOptions - 5, // 17: tetragon.GetEventsRequest.field_filters:type_name -> tetragon.FieldFilter - 14, // 18: tetragon.AggregationOptions.window_size:type_name -> google.protobuf.Duration - 15, // 19: tetragon.GetEventsResponse.process_exec:type_name -> tetragon.ProcessExec - 16, // 20: tetragon.GetEventsResponse.process_exit:type_name -> tetragon.ProcessExit - 17, // 21: tetragon.GetEventsResponse.process_kprobe:type_name -> tetragon.ProcessKprobe - 18, // 22: tetragon.GetEventsResponse.process_tracepoint:type_name -> tetragon.ProcessTracepoint - 19, // 23: tetragon.GetEventsResponse.process_loader:type_name -> tetragon.ProcessLoader - 20, // 24: tetragon.GetEventsResponse.process_uprobe:type_name -> tetragon.ProcessUprobe - 21, // 25: tetragon.GetEventsResponse.test:type_name -> tetragon.Test - 9, // 26: tetragon.GetEventsResponse.rate_limit_info:type_name -> tetragon.RateLimitInfo - 22, // 27: tetragon.GetEventsResponse.time:type_name -> google.protobuf.Timestamp - 8, // 28: tetragon.GetEventsResponse.aggregation_info:type_name -> tetragon.AggregationInfo - 29, // [29:29] is the sub-list for method output_type - 29, // [29:29] is the sub-list for method input_type - 29, // [29:29] is the sub-list for extension type_name - 29, // [29:29] is the sub-list for extension extendee - 0, // [0:29] is the sub-list for field type_name + 13, // 6: tetragon.CapFilterSet.any:type_name -> tetragon.CapabilitiesType + 13, // 7: tetragon.CapFilterSet.all:type_name -> tetragon.CapabilitiesType + 13, // 8: tetragon.CapFilterSet.exactly:type_name -> tetragon.CapabilitiesType + 13, // 9: tetragon.CapFilterSet.none:type_name -> tetragon.CapabilitiesType + 2, // 10: tetragon.RedactionFilter.match:type_name -> tetragon.Filter + 0, // 11: tetragon.FieldFilter.event_set:type_name -> tetragon.EventType + 14, // 12: tetragon.FieldFilter.fields:type_name -> google.protobuf.FieldMask + 1, // 13: tetragon.FieldFilter.action:type_name -> tetragon.FieldFilterAction + 12, // 14: tetragon.FieldFilter.invert_event_set:type_name -> google.protobuf.BoolValue + 2, // 15: tetragon.GetEventsRequest.allow_list:type_name -> tetragon.Filter + 2, // 16: tetragon.GetEventsRequest.deny_list:type_name -> tetragon.Filter + 8, // 17: tetragon.GetEventsRequest.aggregation_options:type_name -> tetragon.AggregationOptions + 6, // 18: tetragon.GetEventsRequest.field_filters:type_name -> tetragon.FieldFilter + 15, // 19: tetragon.AggregationOptions.window_size:type_name -> google.protobuf.Duration + 16, // 20: tetragon.GetEventsResponse.process_exec:type_name -> tetragon.ProcessExec + 17, // 21: tetragon.GetEventsResponse.process_exit:type_name -> tetragon.ProcessExit + 18, // 22: tetragon.GetEventsResponse.process_kprobe:type_name -> tetragon.ProcessKprobe + 19, // 23: tetragon.GetEventsResponse.process_tracepoint:type_name -> tetragon.ProcessTracepoint + 20, // 24: tetragon.GetEventsResponse.process_loader:type_name -> tetragon.ProcessLoader + 21, // 25: tetragon.GetEventsResponse.process_uprobe:type_name -> tetragon.ProcessUprobe + 22, // 26: tetragon.GetEventsResponse.test:type_name -> tetragon.Test + 10, // 27: tetragon.GetEventsResponse.rate_limit_info:type_name -> tetragon.RateLimitInfo + 23, // 28: tetragon.GetEventsResponse.time:type_name -> google.protobuf.Timestamp + 9, // 29: tetragon.GetEventsResponse.aggregation_info:type_name -> tetragon.AggregationInfo + 30, // [30:30] is the sub-list for method output_type + 30, // [30:30] is the sub-list for method input_type + 30, // [30:30] is the sub-list for extension type_name + 30, // [30:30] is the sub-list for extension extendee + 0, // [0:30] is the sub-list for field type_name } func init() { file_tetragon_events_proto_init() } @@ -1251,7 +1315,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FieldFilter); i { + switch v := v.(*RedactionFilter); i { case 0: return &v.state case 1: @@ -1263,7 +1327,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetEventsRequest); i { + switch v := v.(*FieldFilter); i { case 0: return &v.state case 1: @@ -1275,7 +1339,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AggregationOptions); i { + switch v := v.(*GetEventsRequest); i { case 0: return &v.state case 1: @@ -1287,7 +1351,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AggregationInfo); i { + switch v := v.(*AggregationOptions); i { case 0: return &v.state case 1: @@ -1299,7 +1363,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RateLimitInfo); i { + switch v := v.(*AggregationInfo); i { case 0: return &v.state case 1: @@ -1311,6 +1375,18 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimitInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tetragon_events_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetEventsResponse); i { case 0: return &v.state @@ -1323,7 +1399,7 @@ func file_tetragon_events_proto_init() { } } } - file_tetragon_events_proto_msgTypes[8].OneofWrappers = []interface{}{ + file_tetragon_events_proto_msgTypes[9].OneofWrappers = []interface{}{ (*GetEventsResponse_ProcessExec)(nil), (*GetEventsResponse_ProcessExit)(nil), (*GetEventsResponse_ProcessKprobe)(nil), @@ -1339,7 +1415,7 @@ func file_tetragon_events_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tetragon_events_proto_rawDesc, NumEnums: 2, - NumMessages: 9, + NumMessages: 10, NumExtensions: 0, NumServices: 0, }, diff --git a/api/v1/tetragon/events.pb.json.go b/api/v1/tetragon/events.pb.json.go index 161fd1783e8..44af480b37a 100644 --- a/api/v1/tetragon/events.pb.json.go +++ b/api/v1/tetragon/events.pb.json.go @@ -55,6 +55,22 @@ func (msg *CapFilterSet) UnmarshalJSON(b []byte) error { }.Unmarshal(b, msg) } +// MarshalJSON implements json.Marshaler +func (msg *RedactionFilter) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{ + UseEnumNumbers: false, + EmitUnpopulated: false, + UseProtoNames: true, + }.Marshal(msg) +} + +// UnmarshalJSON implements json.Unmarshaler +func (msg *RedactionFilter) UnmarshalJSON(b []byte) error { + return protojson.UnmarshalOptions{ + DiscardUnknown: false, + }.Unmarshal(b, msg) +} + // MarshalJSON implements json.Marshaler func (msg *FieldFilter) MarshalJSON() ([]byte, error) { return protojson.MarshalOptions{ diff --git a/api/v1/tetragon/events.proto b/api/v1/tetragon/events.proto index 2ecebe6e9be..5fd1322e99a 100644 --- a/api/v1/tetragon/events.proto +++ b/api/v1/tetragon/events.proto @@ -83,6 +83,13 @@ message CapFilterSet { repeated CapabilitiesType none = 4; } +message RedactionFilter { + // Match events that the redaction filter will apply to. + repeated Filter match = 1; + // Regular expressions to use for redaction. Strings inside capture groups are redacted. + repeated string redact = 2; +} + // Determines the behavior of a field filter enum FieldFilterAction { INCLUDE = 0; diff --git a/cmd/tetragon/main.go b/cmd/tetragon/main.go index 56cf463a676..be0b38986ae 100644 --- a/cmd/tetragon/main.go +++ b/cmd/tetragon/main.go @@ -108,6 +108,11 @@ func getFieldFilters() ([]*tetragon.FieldFilter, error) { return filters, nil } +func getRedactionFilters() (fieldfilters.RedactionFilterList, error) { + redactionFilters := viper.GetString(option.KeyRedactionFilters) + return fieldfilters.ParseRedactionFilterList(redactionFilters) +} + // Save daemon information so it is used by client cli but // also by bugtool func saveInitInfo() error { @@ -401,11 +406,18 @@ func tetragonExecute() error { hookRunner := rthooks.GlobalRunner().WithWatcher(k8sWatcher) + redactionFilters, err := getRedactionFilters() + if err != nil { + return err + } + log.WithFields(logrus.Fields{"redactionFilters": redactionFilters}).Info("Configured redaction filters") + pm, err := tetragonGrpc.NewProcessManager( ctx, &cleanupWg, observer.GetSensorManager(), - hookRunner) + hookRunner, + redactionFilters) if err != nil { return err } @@ -705,7 +717,7 @@ func startExporter(ctx context.Context, server *server.Server) error { } } req := tetragon.GetEventsRequest{AllowList: allowList, DenyList: denyList, AggregationOptions: aggregationOptions, FieldFilters: fieldFilters} - log.WithFields(logrus.Fields{"fieldFilters": fieldFilters}).Debug("Configured field filters") + log.WithFields(logrus.Fields{"fieldFilters": fieldFilters}).Info("Configured field filters") log.WithFields(logrus.Fields{"logger": writer, "request": &req}).Info("Starting JSON exporter") exporter := exporter.NewExporter(ctx, &req, server, encoder, writer, rateLimiter) return exporter.Start() diff --git a/docs/content/en/docs/concepts/events.md b/docs/content/en/docs/concepts/events.md index 09ae04785d6..9e2e7e1c62f 100644 --- a/docs/content/en/docs/concepts/events.md +++ b/docs/content/en/docs/concepts/events.md @@ -197,6 +197,49 @@ only `exec_id` and `parent_exec_id` in all event types except for {"fields":"process.exec_id,process.parent_exec_id", "event_set": ["PROCESS_EXEC"], "invert_event_set": true, "action": "INCLUDE"} ``` +#### Redacting Sensitive Information + +Since Tetragon traces the entire system, event exports might sometimes contain +sensitive information (for example, a secret passed via a command line argument +to a process). To prevent this information from being exfiltrated via Tetragon +JSON export, Tetragon provides a mechanism called Redaction Filters which can be +used to select events and string patterns to redact. These filters are written +in JSON and passed to the Tetragon agent via the `--redaction-filters` command +line flag or the `redactionFilters` Helm value. + +To perform redactions, redaction filters define regular expressions in the +`redact` field. Any capture groups in these regular expressions are redacted and +replaced with `"*****"`. + +{{< warning >}} +When writing regular expressions in JSON, it is important to escape backslash +characters. For instance `\Wpasswd\W?` would be written as `{"redact": "\\Wpasswd\\W?"}`. +{{< /warning >}} + +Redaction filters select events using the `match` field, which contains one or +more filters (these filters are defined the same way as export filters). If no +match filter is defined, all events are selected. + +As a concrete example, the following will redact all passwords passed to +processes with the `"--password"` argument: + +```json +{"redact": ["--password(?:\\s+|=)(\\S*)"]} +``` + +Now, an event that contains the string `"--password=foo"` would have that string +replaced with `"--password=*****"`. + +Suppose we also see some passwords passed via the -p shorthand for a specific binary, foo. +We can also redact these as follows: + +```json +{"match": [{"binary_regex": "(?:^|/)foo$"}], "redact": ["-p(?:\\s+|=)(\\S*)"]} +``` + +With both of the above redaction filters in place, we are now redacting all +password arguments. + ### `tetra` CLI A second way is to use the [`tetra`](https://github.com/cilium/tetragon/tree/main/cmd/tetra) CLI. This @@ -245,4 +288,4 @@ An example gRPC endpoint is the Tetra CLI when its not piped JSON output directl ```shell kubectl exec -ti -n kube-system ds/tetragon -c tetragon -- tetra getevents -o compact -``` +``` \ No newline at end of file diff --git a/docs/content/en/docs/reference/grpc-api.md b/docs/content/en/docs/reference/grpc-api.md index baeca000273..2b166979a9d 100644 --- a/docs/content/en/docs/reference/grpc-api.md +++ b/docs/content/en/docs/reference/grpc-api.md @@ -790,6 +790,15 @@ Capability set to filter over. NOTE: you may specify only ONE set here. | ----- | ---- | ----- | ----------- | | number_of_dropped_process_events | [uint64](#uint64) | | | + + +### RedactionFilter + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| match | [Filter](#tetragon-Filter) | repeated | Match events that the redaction filter will apply to. | +| redact | [string](#string) | repeated | Regular expressions to use for redaction. Strings inside capture groups are redacted. | + ### EventType diff --git a/docs/content/en/docs/reference/helm-chart.md b/docs/content/en/docs/reference/helm-chart.md index 27743f389ef..dafe071f5f4 100644 --- a/docs/content/en/docs/reference/helm-chart.md +++ b/docs/content/en/docs/reference/helm-chart.md @@ -72,7 +72,7 @@ To use [the values available](#values), with `helm install` or `helm upgrade`, u | tetragon.extraArgs | object | `{}` | | | tetragon.extraEnv | list | `[]` | | | tetragon.extraVolumeMounts | list | `[]` | | -| tetragon.fieldFilters | string | `"{}"` | | +| tetragon.fieldFilters | string | `""` | | | tetragon.gops.address | string | `"localhost"` | The address at which to expose gops. | | tetragon.gops.port | int | `8118` | The port at which to expose gops. | | tetragon.grpc.address | string | `"localhost:54321"` | The address at which to expose gRPC. Examples: localhost:54321, unix:///var/run/tetragon/tetragon.sock | @@ -95,6 +95,7 @@ To use [the values available](#values), with `helm install` or `helm upgrade`, u | tetragon.prometheus.serviceMonitor.enabled | bool | `false` | Whether to create a 'ServiceMonitor' resource targeting the tetragon pods. | | tetragon.prometheus.serviceMonitor.labelsOverride | object | `{}` | The set of labels to place on the 'ServiceMonitor' resource. | | tetragon.prometheus.serviceMonitor.scrapeInterval | string | `"10s"` | Interval at which metrics should be scraped. If not specified, Prometheus' global scrape interval is used. | +| tetragon.redactionFilters | string | `""` | | | tetragon.resources | object | `{}` | | | tetragon.securityContext.privileged | bool | `true` | | | tetragonOperator | object | `{"affinity":{},"annotations":{},"enabled":true,"extraLabels":{},"extraPodLabels":{},"extraVolumeMounts":[],"extraVolumes":[],"forceUpdateCRDs":false,"image":{"override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/tetragon-operator","tag":"v1.0.2"},"nodeSelector":{},"podAnnotations":{},"podInfo":{"enabled":false},"podSecurityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}},"priorityClassName":"","prometheus":{"address":"","enabled":true,"port":2113,"serviceMonitor":{"enabled":false,"labelsOverride":{},"scrapeInterval":"10s"}},"resources":{"limits":{"cpu":"500m","memory":"128Mi"},"requests":{"cpu":"10m","memory":"64Mi"}},"securityContext":{},"serviceAccount":{"annotations":{},"create":true,"name":""},"skipCRDCreation":false,"strategy":{},"tolerations":[{"operator":"Exists"}],"tracingPolicy":{"enabled":true}}` | Tetragon Operator settings | diff --git a/docs/data/tetragon_flags.yaml b/docs/data/tetragon_flags.yaml index 42a5e5ddcee..22fb29a9873 100644 --- a/docs/data/tetragon_flags.yaml +++ b/docs/data/tetragon_flags.yaml @@ -160,6 +160,8 @@ options: default_value: "0" usage: | Set perf ring buffer size in total for all cpus (default 65k per cpu, allows K/M/G suffix) + - name: redaction-filters + usage: Redaction filters for events - name: release-pinned-bpf default_value: "true" usage: | diff --git a/install/kubernetes/tetragon/README.md b/install/kubernetes/tetragon/README.md index 198a88caa06..862863d559c 100644 --- a/install/kubernetes/tetragon/README.md +++ b/install/kubernetes/tetragon/README.md @@ -54,7 +54,7 @@ Helm chart for Tetragon | tetragon.extraArgs | object | `{}` | | | tetragon.extraEnv | list | `[]` | | | tetragon.extraVolumeMounts | list | `[]` | | -| tetragon.fieldFilters | string | `"{}"` | | +| tetragon.fieldFilters | string | `""` | | | tetragon.gops.address | string | `"localhost"` | The address at which to expose gops. | | tetragon.gops.port | int | `8118` | The port at which to expose gops. | | tetragon.grpc.address | string | `"localhost:54321"` | The address at which to expose gRPC. Examples: localhost:54321, unix:///var/run/tetragon/tetragon.sock | @@ -77,6 +77,7 @@ Helm chart for Tetragon | tetragon.prometheus.serviceMonitor.enabled | bool | `false` | Whether to create a 'ServiceMonitor' resource targeting the tetragon pods. | | tetragon.prometheus.serviceMonitor.labelsOverride | object | `{}` | The set of labels to place on the 'ServiceMonitor' resource. | | tetragon.prometheus.serviceMonitor.scrapeInterval | string | `"10s"` | Interval at which metrics should be scraped. If not specified, Prometheus' global scrape interval is used. | +| tetragon.redactionFilters | string | `""` | | | tetragon.resources | object | `{}` | | | tetragon.securityContext.privileged | bool | `true` | | | tetragonOperator | object | `{"affinity":{},"annotations":{},"enabled":true,"extraLabels":{},"extraPodLabels":{},"extraVolumeMounts":[],"extraVolumes":[],"forceUpdateCRDs":false,"image":{"override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/tetragon-operator","tag":"v1.0.2"},"nodeSelector":{},"podAnnotations":{},"podInfo":{"enabled":false},"podSecurityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}},"priorityClassName":"","prometheus":{"address":"","enabled":true,"port":2113,"serviceMonitor":{"enabled":false,"labelsOverride":{},"scrapeInterval":"10s"}},"resources":{"limits":{"cpu":"500m","memory":"128Mi"},"requests":{"cpu":"10m","memory":"64Mi"}},"securityContext":{},"serviceAccount":{"annotations":{},"create":true,"name":""},"skipCRDCreation":false,"strategy":{},"tolerations":[{"operator":"Exists"}],"tracingPolicy":{"enabled":true}}` | Tetragon Operator settings | diff --git a/install/kubernetes/tetragon/templates/tetragon_configmap.yaml b/install/kubernetes/tetragon/templates/tetragon_configmap.yaml index b0dbecf0e69..c3e36cfc095 100644 --- a/install/kubernetes/tetragon/templates/tetragon_configmap.yaml +++ b/install/kubernetes/tetragon/templates/tetragon_configmap.yaml @@ -25,6 +25,8 @@ data: {{- .Values.tetragon.exportDenyList | trim | nindent 4 }} field-filters: |- {{- .Values.tetragon.fieldFilters | trim | nindent 4 }} + redaction-filters: |- +{{- .Values.tetragon.redactionFilters | trim | nindent 4 }} export-rate-limit: {{ .Values.tetragon.exportRateLimit | quote }} {{- end }} {{- if .Values.tetragon.enableK8sAPI }} diff --git a/install/kubernetes/tetragon/values.yaml b/install/kubernetes/tetragon/values.yaml index 312e87d544a..c788d66f9a6 100644 --- a/install/kubernetes/tetragon/values.yaml +++ b/install/kubernetes/tetragon/values.yaml @@ -111,7 +111,33 @@ tetragon: # {"event_set": ["PROCESS_KPROBE"], "fields": "process", "action": "INCLUDE"} # fieldFilters: |- - {} + + # Filters to redact secrets from string fields in Tetragon events. To perform + # redactions, redaction filters define regular expressions in the `redact` + # field. Any capture groups in these regular expressions are redacted and + # replaced with "*****". + # + # Redaction filters select events using the `match` field, which contains one + # or more filters (these filters are defined the same way as export filters). + # If no match filter is defined, all events are selected. + # + # As a concrete example, the following will redact all passwords passed to + # processes with the "--password" argument: + # + # {"redact": ["--password(?:\s+|=)(\S*)"]} + # + # Now, an event which contains the string "--password=foo" would have that + # string replaced with "--password=*****". + # + # Suppose we also see some passwords passed via the -p shorthand for a specific binary, foo. + # We can also redact these as follows: + # + # {"match": [{"binary_regex": "(?:^|/)foo$"}], "redact": ["-p(?:\s+|=)(\S*)"]} + # + # With both of the above redaction filters in place, we are now redacting all + # password arguments. + redactionFilters: |- + # Access Kubernetes API to associate Tetragon events with Kubernetes pods. enableK8sAPI: true # enableProcessCred enables Capabilities visibility in exec and kprobe events. diff --git a/pkg/bench/bench.go b/pkg/bench/bench.go index 4c9adc8239a..0a4d27efac2 100644 --- a/pkg/bench/bench.go +++ b/pkg/bench/bench.go @@ -24,6 +24,7 @@ import ( "github.com/cilium/tetragon/pkg/cilium" "github.com/cilium/tetragon/pkg/defaults" "github.com/cilium/tetragon/pkg/exporter" + "github.com/cilium/tetragon/pkg/fieldfilters" "github.com/cilium/tetragon/pkg/grpc" "github.com/cilium/tetragon/pkg/logger" "github.com/cilium/tetragon/pkg/observer" @@ -227,7 +228,8 @@ func startBenchmarkExporter(ctx context.Context, obs *observer.Observer, summary ctx, &wg, observer.GetSensorManager(), - hookRunner) + hookRunner, + fieldfilters.RedactionFilterList{}) if err != nil { return err } diff --git a/pkg/exporter/exporter_test.go b/pkg/exporter/exporter_test.go index a9518d5672b..82c8bb9dc5f 100644 --- a/pkg/exporter/exporter_test.go +++ b/pkg/exporter/exporter_test.go @@ -15,6 +15,7 @@ import ( "github.com/cilium/tetragon/api/v1/tetragon" "github.com/cilium/tetragon/pkg/encoder" + "github.com/cilium/tetragon/pkg/fieldfilters" "github.com/cilium/tetragon/pkg/ratelimit" "github.com/cilium/tetragon/pkg/rthooks" "github.com/cilium/tetragon/pkg/server" @@ -85,7 +86,7 @@ func TestExporter_Send(t *testing.T) { eventNotifier := newFakeNotifier() ctx, cancel := context.WithCancel(context.Background()) dr := rthooks.DummyHookRunner{} - grpcServer := server.NewServer(ctx, &wg, eventNotifier, &server.FakeObserver{}, dr) + grpcServer := server.NewServer(ctx, &wg, eventNotifier, &server.FakeObserver{}, dr, fieldfilters.RedactionFilterList{}) numRecords := 2 results := newArrayWriter(numRecords) encoder := encoder.NewProtojsonEncoder(results) @@ -190,7 +191,7 @@ func Test_rateLimitExport(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) eventNotifier := newFakeNotifier() dr := rthooks.DummyHookRunner{} - grpcServer := server.NewServer(ctx, &wg, eventNotifier, &server.FakeObserver{}, dr) + grpcServer := server.NewServer(ctx, &wg, eventNotifier, &server.FakeObserver{}, dr, fieldfilters.RedactionFilterList{}) results := newArrayWriter(tt.totalEvents) encoder := encoder.NewProtojsonEncoder(results) request := &tetragon.GetEventsRequest{} diff --git a/pkg/fieldfilters/redaction.go b/pkg/fieldfilters/redaction.go new file mode 100644 index 00000000000..88931dc6bf6 --- /dev/null +++ b/pkg/fieldfilters/redaction.go @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Tetragon + +package fieldfilters + +import ( + "context" + "encoding/json" + "fmt" + "io" + "regexp" + "strings" + + "github.com/cilium/tetragon/api/v1/tetragon" + "github.com/cilium/tetragon/pkg/filters" + v1 "github.com/cilium/tetragon/pkg/oldhubble/api/v1" + hubbleFilters "github.com/cilium/tetragon/pkg/oldhubble/filters" + "google.golang.org/protobuf/reflect/protopath" + "google.golang.org/protobuf/reflect/protorange" + "google.golang.org/protobuf/reflect/protoreflect" +) + +const REDACTION_STR = "*****" + +type RedactionFilter struct { + match hubbleFilters.FilterFuncs + redact []*regexp.Regexp +} + +type RedactionFilterList []*RedactionFilter + +func ParseRedactionFilterList(filters string) (RedactionFilterList, error) { + if filters == "" { + return nil, nil + } + dec := json.NewDecoder(strings.NewReader(filters)) + var results []*tetragon.RedactionFilter + for { + var result tetragon.RedactionFilter + if err := dec.Decode(&result); err != nil { + if err == io.EOF { + break + } + return nil, fmt.Errorf("failed to parse redaction filter list: %w", err) + } + results = append(results, &result) + } + compiled, err := RedactionFilterListFromProto(results) + if err != nil { + return nil, err + } + return compiled, nil +} + +func RedactionFilterListFromProto(protoFilters []*tetragon.RedactionFilter) ([]*RedactionFilter, error) { + var filters []*RedactionFilter + for _, f := range protoFilters { + filter, err := redactionFilterFromProto(f) + if err != nil { + return nil, err + } + filters = append(filters, filter) + } + + return filters, nil +} + +// redactionFilterFromProto constructs a new RedactionFilter from a Tetragon API redaction filter. +func redactionFilterFromProto(protoFilter *tetragon.RedactionFilter) (*RedactionFilter, error) { + var err error + filter := &RedactionFilter{} + + // Construct match funcs + filter.match, err = filters.BuildFilterList(context.TODO(), protoFilter.Match, filters.Filters) + if err != nil { + return nil, fmt.Errorf("failed to construct match for redaction filter: %w", err) + } + + if len(protoFilter.Redact) == 0 { + return nil, fmt.Errorf("refusing to construct redaction filter with no redactions") + } + + // Compile regex + for _, re := range protoFilter.Redact { + compiled, err := regexp.Compile(re) + if err != nil { + return nil, fmt.Errorf("failed to compile redaction regex `%s`: %w", re, err) + } + filter.redact = append(filter.redact, compiled) + } + + return filter, nil +} + +// Redact resursively checks any string fields in the event for matches to +// redaction regexes and replaces any capture groups with `*****`. +func (f RedactionFilterList) Redact(event *tetragon.GetEventsResponse) { + // We need to do this in two batch stages: match and redact. + // This is necessary to handle the case where we have a redaction filter + // earlier in the list that would redact a field used in a match statement + // of another redaction filter later in the list. If we don't do the + // matching first, the second redaction filter would never match. + doesMatch := []bool{} + ev := &v1.Event{Event: event} + for _, filter := range f { + doesMatch = append(doesMatch, filter.match.MatchOne(ev)) + } + + for i := range f { + if !doesMatch[i] { + continue + } + f[i].doRedact(event.ProtoReflect()) + } +} + +// Redact resursively checks any string fields in the event for matches to +// redaction regexes and replaces any capture groups with `*****`. +// +// NOTE: If you're using multiple redaction filters, reach for RedactionFilterList.Redact() instead. +func (f RedactionFilter) Redact(event *tetragon.GetEventsResponse) { + ev := &v1.Event{Event: event} + if !f.match.MatchOne(ev) { + return + } + f.doRedact(event.ProtoReflect()) +} + +func (f *RedactionFilter) doRedact(msg protoreflect.Message) { + protorange.Range(msg, func(p protopath.Values) error { + last := p.Index(-1) + s, ok := last.Value.Interface().(string) + if !ok { + return nil + } + + for _, re := range f.redact { + s = redactString(re, s) + } + + beforeLast := p.Index(-2) + switch last.Step.Kind() { + case protopath.FieldAccessStep: + m := beforeLast.Value.Message() + fd := last.Step.FieldDescriptor() + m.Set(fd, protoreflect.ValueOfString(s)) + case protopath.ListIndexStep: + ls := beforeLast.Value.List() + i := last.Step.ListIndex() + ls.Set(i, protoreflect.ValueOfString(s)) + case protopath.MapIndexStep: + ms := beforeLast.Value.Map() + k := last.Step.MapIndex() + ms.Set(k, protoreflect.ValueOfString(s)) + } + + return nil + }) +} + +func redactString(re *regexp.Regexp, s string) string { + s = re.ReplaceAllStringFunc(s, func(s string) string { + var redacted strings.Builder + + idx := re.FindStringSubmatchIndex(s) + if len(idx) < 2 { + return s + } + + // Skip first idx pair which is entire string + lastOffset := 0 + for i := 2; i < len(idx); i += 2 { + // Handle nested capture groups that have already been redacted + if idx[i] < lastOffset { + continue + } + redacted.WriteString(s[lastOffset:idx[i]]) + redacted.WriteString(REDACTION_STR) + lastOffset = idx[i+1] + } + // Write the rest of the string + redacted.WriteString(s[lastOffset:]) + + return redacted.String() + }) + return s +} diff --git a/pkg/fieldfilters/redaction_test.go b/pkg/fieldfilters/redaction_test.go new file mode 100644 index 00000000000..8c7ccb41abc --- /dev/null +++ b/pkg/fieldfilters/redaction_test.go @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Tetragon + +package fieldfilters + +import ( + "regexp" + "testing" + + "github.com/cilium/tetragon/api/v1/tetragon" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRedactString_Simple(t *testing.T) { + re := regexp.MustCompile(`(ab)cd`) + + s := "abcd" + assert.Equal(t, REDACTION_STR+"cd", redactString(re, s)) + + s = "cdef" + assert.Equal(t, "cdef", redactString(re, s)) + + s = "abef" + assert.Equal(t, "abef", redactString(re, s)) + + s = "innocent" + assert.Equal(t, "innocent", redactString(re, s)) +} + +func TestRedactString_NonCapturing(t *testing.T) { + re := regexp.MustCompile(`(?:--password|-p)\s+(\S+)`) + + s := "--password fooBarQuxBaz!" + assert.Equal(t, "--password "+REDACTION_STR, redactString(re, s)) + + s = "-p fooBarQuxBaz!" + assert.Equal(t, "-p "+REDACTION_STR, redactString(re, s)) + + s = "innocent" + assert.Equal(t, "innocent", redactString(re, s)) +} + +func TestRedactString_Nested(t *testing.T) { + re := regexp.MustCompile(`(foo(bar))qux`) + + s := "foobarqux" + assert.Equal(t, REDACTION_STR+"qux", redactString(re, s)) + + s = "innocent" + assert.Equal(t, "innocent", redactString(re, s)) +} + +func TestRedact_ExecFilter(t *testing.T) { + event := &tetragon.GetEventsResponse{ + Event: &tetragon.GetEventsResponse_ProcessExec{ + ProcessExec: &tetragon.ProcessExec{ + Process: &tetragon.Process{ + Arguments: "--verbsose=true --password ybx511!ackt544 --username foobar", + }, + }, + }, + } + + filterList := `{"redact": ["(?:--password|-p)[\\s=]+(\\S+)"]}` + filters, err := ParseRedactionFilterList(filterList) + require.NoError(t, err) + + filters.Redact(event) + assert.Equal(t, "--verbsose=true --password "+REDACTION_STR+" --username foobar", event.GetProcessExec().Process.Arguments) +} + +func TestRedact_NoFilter(t *testing.T) { + event := &tetragon.GetEventsResponse{ + Event: &tetragon.GetEventsResponse_ProcessExec{ + ProcessExec: &tetragon.ProcessExec{ + Process: &tetragon.Process{ + Arguments: "--verbsose=true --password ybx511!ackt544 --username foobar", + }, + }, + }, + } + + filterList := `{"match": [{"event_set": ["PROCESS_EXEC"]}], "redact": ["(?:--password|-p)[\\s=]+(\\S+)"]}` + filters, err := ParseRedactionFilterList(filterList) + require.NoError(t, err) + + filters.Redact(event) + assert.Equal(t, "--verbsose=true --password "+REDACTION_STR+" --username foobar", event.GetProcessExec().Process.Arguments) +} + +func TestRedact_Multi(t *testing.T) { + event := &tetragon.GetEventsResponse{ + Event: &tetragon.GetEventsResponse_ProcessExec{ + ProcessExec: &tetragon.ProcessExec{ + Process: &tetragon.Process{ + Arguments: "--verbsose=true --password ybx511!ackt544 --username foobar", + }, + Parent: &tetragon.Process{ + Arguments: "cheesecake TOPSECRET innocent", + }, + }, + }, + } + + filterList := `{"match": [{"event_set": ["PROCESS_EXEC"]}], "redact": ["(?:--password|-p)[\\s=]+(\\S+)", "\\W(TOPSECRET)\\W", "(cheese)cake"]}` + filters, err := ParseRedactionFilterList(filterList) + require.NoError(t, err) + + filters.Redact(event) + assert.Equal(t, "--verbsose=true --password "+REDACTION_STR+" --username foobar", event.GetProcessExec().Process.Arguments) + assert.Equal(t, REDACTION_STR+"cake "+REDACTION_STR+" innocent", event.GetProcessExec().Parent.Arguments) +} + +func TestRedact_ParsedMultiStep(t *testing.T) { + filterList := `{"match": [{"event_set": ["PROCESS_EXEC"]}], "redact": ["\\W(passwd)\\W?"]} + {"match": [{"binary_regex": ["passwd"]}], "redact": ["(?:-p|--password)(?:\\s+|=)(\\S*)"]}` + filters, err := ParseRedactionFilterList(filterList) + require.NoError(t, err) + + event := &tetragon.GetEventsResponse{ + Event: &tetragon.GetEventsResponse_ProcessExec{ + ProcessExec: &tetragon.ProcessExec{ + Process: &tetragon.Process{ + Binary: "/bin/passwd", + Arguments: "-p foobarQux1337", + }, + }, + }, + } + + filters.Redact(event) + + assert.Equal(t, "/bin/"+REDACTION_STR, event.GetProcessExec().Process.Binary) + assert.Equal(t, "-p "+REDACTION_STR, event.GetProcessExec().Process.Arguments) +} diff --git a/pkg/grpc/exec/exec_test_helper.go b/pkg/grpc/exec/exec_test_helper.go index d0a0376288e..ca17e9d33ea 100644 --- a/pkg/grpc/exec/exec_test_helper.go +++ b/pkg/grpc/exec/exec_test_helper.go @@ -14,6 +14,7 @@ import ( tetragonAPI "github.com/cilium/tetragon/pkg/api/processapi" "github.com/cilium/tetragon/pkg/cilium" "github.com/cilium/tetragon/pkg/eventcache" + "github.com/cilium/tetragon/pkg/fieldfilters" "github.com/cilium/tetragon/pkg/option" "github.com/cilium/tetragon/pkg/process" "github.com/cilium/tetragon/pkg/reader/notify" @@ -292,7 +293,7 @@ func InitEnv[EXEC notify.Message, EXIT notify.Message](t *testing.T, cancelWg *s dn := DummyNotifier[EXEC, EXIT]{t} dr := rthooks.DummyHookRunner{} - lServer := server.NewServer(ctx, cancelWg, dn, &server.FakeObserver{}, dr) + lServer := server.NewServer(ctx, cancelWg, dn, &server.FakeObserver{}, dr, fieldfilters.RedactionFilterList{}) // Exec cache is always needed to ensure events have an associated Process{} eventcache.NewWithTimer(lServer, time.Millisecond*CacheTimerMs) diff --git a/pkg/grpc/process_manager.go b/pkg/grpc/process_manager.go index 39013cbab10..83a5948ba6e 100644 --- a/pkg/grpc/process_manager.go +++ b/pkg/grpc/process_manager.go @@ -9,6 +9,7 @@ import ( "github.com/cilium/tetragon/api/v1/tetragon" "github.com/cilium/tetragon/pkg/eventcache" + "github.com/cilium/tetragon/pkg/fieldfilters" "github.com/cilium/tetragon/pkg/logger" "github.com/cilium/tetragon/pkg/metrics/eventmetrics" "github.com/cilium/tetragon/pkg/option" @@ -35,13 +36,14 @@ func NewProcessManager( wg *sync.WaitGroup, manager *sensors.Manager, hookRunner *rthooks.Runner, + redactionFilters fieldfilters.RedactionFilterList, ) (*ProcessManager, error) { pm := &ProcessManager{ nodeName: node.GetNodeNameForExport(), listeners: make(map[server.Listener]struct{}), } - pm.Server = server.NewServer(ctx, wg, pm, manager, hookRunner) + pm.Server = server.NewServer(ctx, wg, pm, manager, hookRunner, redactionFilters) // Exec cache is always needed to ensure events have an associated Process{} eventcache.New(pm.Server) diff --git a/pkg/grpc/process_manager_test.go b/pkg/grpc/process_manager_test.go index 4c9e3e3bbf9..2ca53e02c47 100644 --- a/pkg/grpc/process_manager_test.go +++ b/pkg/grpc/process_manager_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/cilium/tetragon/pkg/fieldfilters" "github.com/cilium/tetragon/pkg/grpc/exec" "github.com/cilium/tetragon/pkg/option" @@ -165,7 +166,8 @@ func TestProcessManager_GetProcessExec(t *testing.T) { context.Background(), &wg, nil, - &rthooks.Runner{}) + &rthooks.Runner{}, + fieldfilters.RedactionFilterList{}) assert.NoError(t, err) pi := &exec.MsgExecveEventUnix{ Unix: &processapi.MsgExecveEventUnix{ diff --git a/pkg/observer/observertesthelper/observer_test_helper.go b/pkg/observer/observertesthelper/observer_test_helper.go index 4fae6678e16..8a1e5a60092 100644 --- a/pkg/observer/observertesthelper/observer_test_helper.go +++ b/pkg/observer/observertesthelper/observer_test_helper.go @@ -20,6 +20,7 @@ import ( "time" "github.com/cilium/tetragon/pkg/encoder" + "github.com/cilium/tetragon/pkg/fieldfilters" "github.com/cilium/tetragon/pkg/metrics" "github.com/cilium/tetragon/pkg/metrics/metricsconfig" "github.com/cilium/tetragon/pkg/observer" @@ -69,6 +70,7 @@ type testExporterOptions struct { ciliumState *hubbleCilium.State allowList []*tetragon.Filter denyList []*tetragon.Filter + redactions []*tetragon.RedactionFilter } type TestOptions struct { @@ -99,6 +101,12 @@ func WithDenyList(denyList *tetragon.Filter) TestOption { } } +func WithRedactions(redactions *tetragon.RedactionFilter) TestOption { + return func(o *TestOptions) { + o.exporter.redactions = append(o.exporter.redactions, redactions) + } +} + func WithConfig(config string) TestOption { return func(o *TestOptions) { o.observer.config = config @@ -402,6 +410,11 @@ func loadExporter(tb testing.TB, ctx context.Context, obs *observer.Observer, op // use an empty hooks runner hookRunner := (&rthooks.Runner{}).WithWatcher(watcher) + redactions, err := fieldfilters.RedactionFilterListFromProto(opts.redactions) + if err != nil { + return err + } + // For testing we disable the eventcache and cilium cache by default. If we // enable these then every tests would need to wait for the 1.5 mimutes needed // to bounce events through the cache waiting for Cilium to reply with endpoints @@ -410,7 +423,7 @@ func loadExporter(tb testing.TB, ctx context.Context, obs *observer.Observer, op option.Config.EnableProcessNs = true option.Config.EnableProcessCred = true option.Config.EnableCilium = false - processManager, err := tetragonGrpc.NewProcessManager(ctx, &cancelWg, sensorManager, hookRunner) + processManager, err := tetragonGrpc.NewProcessManager(ctx, &cancelWg, sensorManager, hookRunner, redactions) if err != nil { return err } diff --git a/pkg/option/flags.go b/pkg/option/flags.go index 56b2d4a9fcb..d933194a113 100644 --- a/pkg/option/flags.go +++ b/pkg/option/flags.go @@ -63,7 +63,8 @@ const ( KeyExportAllowlist = "export-allowlist" KeyExportDenylist = "export-denylist" - KeyFieldFilters = "field-filters" + KeyFieldFilters = "field-filters" + KeyRedactionFilters = "redaction-filters" KeyNetnsDir = "netns-dir" @@ -243,6 +244,9 @@ func AddFlags(flags *pflag.FlagSet) { // Field filters options for export flags.String(KeyFieldFilters, "", "Field filters for event exports") + // Redaction filters + flags.String(KeyRedactionFilters, "", "Redaction filters for events") + // Network namespace options flags.String(KeyNetnsDir, "/var/run/docker/netns/", "Network namespace dir") diff --git a/pkg/server/server.go b/pkg/server/server.go index 958b4dece28..bcee926487d 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -59,24 +59,26 @@ type hookRunner interface { } type Server struct { - ctx context.Context - ctxCleanupWG *sync.WaitGroup - notifier notifier - observer observer - hookRunner hookRunner + ctx context.Context + ctxCleanupWG *sync.WaitGroup + notifier notifier + observer observer + hookRunner hookRunner + redactionFilters fieldfilters.RedactionFilterList } type getEventsListener struct { events chan *tetragon.GetEventsResponse } -func NewServer(ctx context.Context, cleanupWg *sync.WaitGroup, notifier notifier, observer observer, hookRunner hookRunner) *Server { +func NewServer(ctx context.Context, cleanupWg *sync.WaitGroup, notifier notifier, observer observer, hookRunner hookRunner, redactionFilters fieldfilters.RedactionFilterList) *Server { return &Server{ - ctx: ctx, - ctxCleanupWG: cleanupWg, - notifier: notifier, - observer: observer, - hookRunner: hookRunner, + ctx: ctx, + ctxCleanupWG: cleanupWg, + notifier: notifier, + observer: observer, + hookRunner: hookRunner, + redactionFilters: redactionFilters, } } @@ -172,12 +174,13 @@ func (s *Server) GetEventsWG(request *tetragon.GetEventsRequest, server tetragon continue } - // Filter the GetEventsResponse fields + // Get field filters filters, err := fieldfilters.FieldFiltersFromGetEventsRequest(request) if err != nil { return fmt.Errorf("failed to create field filters: %w", err) } + // Apply field filters for _, filter := range filters { ev, err := filter.Filter(event) if err != nil { @@ -187,6 +190,9 @@ func (s *Server) GetEventsWG(request *tetragon.GetEventsRequest, server tetragon event = ev } + // Apply redaction filters + s.redactionFilters.Redact(event) + if aggregator != nil { // Send event to aggregator. select { diff --git a/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.pb.go b/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.pb.go index 64b259fbe4f..799d0a47dd5 100644 --- a/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.pb.go +++ b/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.pb.go @@ -432,6 +432,63 @@ func (x *CapFilterSet) GetNone() []CapabilitiesType { return nil } +type RedactionFilter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Match events that the redaction filter will apply to. + Match []*Filter `protobuf:"bytes,1,rep,name=match,proto3" json:"match,omitempty"` + // Regular expressions to use for redaction. Strings inside capture groups are redacted. + Redact []string `protobuf:"bytes,2,rep,name=redact,proto3" json:"redact,omitempty"` +} + +func (x *RedactionFilter) Reset() { + *x = RedactionFilter{} + if protoimpl.UnsafeEnabled { + mi := &file_tetragon_events_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RedactionFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RedactionFilter) ProtoMessage() {} + +func (x *RedactionFilter) ProtoReflect() protoreflect.Message { + mi := &file_tetragon_events_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 RedactionFilter.ProtoReflect.Descriptor instead. +func (*RedactionFilter) Descriptor() ([]byte, []int) { + return file_tetragon_events_proto_rawDescGZIP(), []int{3} +} + +func (x *RedactionFilter) GetMatch() []*Filter { + if x != nil { + return x.Match + } + return nil +} + +func (x *RedactionFilter) GetRedact() []string { + if x != nil { + return x.Redact + } + return nil +} + type FieldFilter struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -450,7 +507,7 @@ type FieldFilter struct { func (x *FieldFilter) Reset() { *x = FieldFilter{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[3] + mi := &file_tetragon_events_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -463,7 +520,7 @@ func (x *FieldFilter) String() string { func (*FieldFilter) ProtoMessage() {} func (x *FieldFilter) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[3] + mi := &file_tetragon_events_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -476,7 +533,7 @@ func (x *FieldFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use FieldFilter.ProtoReflect.Descriptor instead. func (*FieldFilter) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{3} + return file_tetragon_events_proto_rawDescGZIP(), []int{4} } func (x *FieldFilter) GetEventSet() []EventType { @@ -536,7 +593,7 @@ type GetEventsRequest struct { func (x *GetEventsRequest) Reset() { *x = GetEventsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[4] + mi := &file_tetragon_events_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -549,7 +606,7 @@ func (x *GetEventsRequest) String() string { func (*GetEventsRequest) ProtoMessage() {} func (x *GetEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[4] + mi := &file_tetragon_events_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -562,7 +619,7 @@ func (x *GetEventsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetEventsRequest.ProtoReflect.Descriptor instead. func (*GetEventsRequest) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{4} + return file_tetragon_events_proto_rawDescGZIP(), []int{5} } func (x *GetEventsRequest) GetAllowList() []*Filter { @@ -610,7 +667,7 @@ type AggregationOptions struct { func (x *AggregationOptions) Reset() { *x = AggregationOptions{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[5] + mi := &file_tetragon_events_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -623,7 +680,7 @@ func (x *AggregationOptions) String() string { func (*AggregationOptions) ProtoMessage() {} func (x *AggregationOptions) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[5] + mi := &file_tetragon_events_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -636,7 +693,7 @@ func (x *AggregationOptions) ProtoReflect() protoreflect.Message { // Deprecated: Use AggregationOptions.ProtoReflect.Descriptor instead. func (*AggregationOptions) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{5} + return file_tetragon_events_proto_rawDescGZIP(), []int{6} } func (x *AggregationOptions) GetWindowSize() *durationpb.Duration { @@ -666,7 +723,7 @@ type AggregationInfo struct { func (x *AggregationInfo) Reset() { *x = AggregationInfo{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[6] + mi := &file_tetragon_events_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -679,7 +736,7 @@ func (x *AggregationInfo) String() string { func (*AggregationInfo) ProtoMessage() {} func (x *AggregationInfo) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[6] + mi := &file_tetragon_events_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -692,7 +749,7 @@ func (x *AggregationInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use AggregationInfo.ProtoReflect.Descriptor instead. func (*AggregationInfo) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{6} + return file_tetragon_events_proto_rawDescGZIP(), []int{7} } func (x *AggregationInfo) GetCount() uint64 { @@ -713,7 +770,7 @@ type RateLimitInfo struct { func (x *RateLimitInfo) Reset() { *x = RateLimitInfo{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[7] + mi := &file_tetragon_events_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -726,7 +783,7 @@ func (x *RateLimitInfo) String() string { func (*RateLimitInfo) ProtoMessage() {} func (x *RateLimitInfo) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[7] + mi := &file_tetragon_events_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -739,7 +796,7 @@ func (x *RateLimitInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use RateLimitInfo.ProtoReflect.Descriptor instead. func (*RateLimitInfo) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{7} + return file_tetragon_events_proto_rawDescGZIP(), []int{8} } func (x *RateLimitInfo) GetNumberOfDroppedProcessEvents() uint64 { @@ -783,7 +840,7 @@ type GetEventsResponse struct { func (x *GetEventsResponse) Reset() { *x = GetEventsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_tetragon_events_proto_msgTypes[8] + mi := &file_tetragon_events_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -796,7 +853,7 @@ func (x *GetEventsResponse) String() string { func (*GetEventsResponse) ProtoMessage() {} func (x *GetEventsResponse) ProtoReflect() protoreflect.Message { - mi := &file_tetragon_events_proto_msgTypes[8] + mi := &file_tetragon_events_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -809,7 +866,7 @@ func (x *GetEventsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetEventsResponse.ProtoReflect.Descriptor instead. func (*GetEventsResponse) Descriptor() ([]byte, []int) { - return file_tetragon_events_proto_rawDescGZIP(), []int{8} + return file_tetragon_events_proto_rawDescGZIP(), []int{9} } func (m *GetEventsResponse) GetEvent() isGetEventsResponse_Event { @@ -1022,112 +1079,117 @@ var file_tetragon_events_proto_rawDesc = []byte{ 0x74, 0x6c, 0x79, 0x12, 0x2e, 0x0a, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x6e, - 0x6f, 0x6e, 0x65, 0x22, 0xee, 0x01, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x74, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, - 0x6e, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x53, 0x65, 0x74, 0x12, 0x32, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 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, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, - 0x6b, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x06, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x74, 0x72, - 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, - 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x53, 0x65, 0x74, 0x22, 0xfd, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x09, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x09, 0x64, 0x65, - 0x6e, 0x79, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x08, 0x64, 0x65, 0x6e, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4d, 0x0a, 0x13, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, - 0x6e, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x22, 0x80, 0x01, 0x0a, 0x12, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x77, - 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x77, 0x69, 0x6e, - 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x27, 0x0a, 0x0f, 0x41, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x22, 0x57, 0x0a, 0x0d, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x46, 0x0a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x64, - 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1c, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x4f, 0x66, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xab, 0x05, 0x0a, 0x11, 0x47, 0x65, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3a, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, - 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x65, 0x63, 0x48, 0x00, 0x52, 0x0b, - 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x65, 0x63, 0x12, 0x3a, 0x0a, 0x0c, 0x70, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x69, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x45, 0x78, 0x69, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x6b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x4b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x4b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x4c, 0x0a, 0x12, 0x70, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, - 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x61, - 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x75, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x70, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x74, - 0x65, 0x73, 0x74, 0x18, 0xc0, 0xb8, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x65, - 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x74, - 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0xc1, 0xb8, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x61, 0x74, 0x65, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, - 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0xe9, - 0x07, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0xea, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x07, - 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2a, 0xb1, 0x01, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x10, 0x00, - 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x45, 0x43, - 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x45, 0x58, - 0x49, 0x54, 0x10, 0x05, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, - 0x4b, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x09, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x43, - 0x45, 0x53, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x0a, - 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, 0x4f, 0x41, 0x44, - 0x45, 0x52, 0x10, 0x0b, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, - 0x55, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x0c, 0x12, 0x0a, 0x0a, 0x04, 0x54, 0x45, 0x53, 0x54, - 0x10, 0xc0, 0xb8, 0x02, 0x12, 0x15, 0x0a, 0x0f, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x4c, 0x49, 0x4d, - 0x49, 0x54, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xc1, 0xb8, 0x02, 0x2a, 0x2d, 0x0a, 0x11, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, - 0x07, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6f, 0x6e, 0x65, 0x22, 0x51, 0x0a, 0x0f, 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, + 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x22, 0xee, 0x01, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x74, 0x72, + 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x12, 0x32, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x73, 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, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x06, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, + 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x44, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, + 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x22, 0xfd, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2d, 0x0a, + 0x09, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x08, 0x64, 0x65, 0x6e, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4d, 0x0a, 0x13, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x74, 0x72, + 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x0d, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0x80, 0x01, 0x0a, 0x12, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, + 0x0a, 0x0b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, + 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x27, 0x0a, 0x0f, 0x41, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, + 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x22, 0x57, 0x0a, 0x0d, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46, 0x0a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, + 0x66, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1c, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xab, 0x05, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x78, + 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, + 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x65, 0x63, 0x48, + 0x00, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x65, 0x63, 0x12, 0x3a, + 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x69, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x78, 0x69, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x4c, 0x0a, 0x12, + 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, + 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x61, 0x63, 0x65, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0d, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0e, + 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x75, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x48, 0x00, 0x52, + 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x26, + 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x18, 0xc0, 0xb8, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x48, 0x00, + 0x52, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0xc1, 0xb8, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x61, + 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0xe9, 0x07, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0xea, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x6e, + 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, + 0x6f, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2a, 0xb1, 0x01, 0x0a, 0x09, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, 0x44, 0x45, + 0x46, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x45, + 0x58, 0x45, 0x43, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, + 0x5f, 0x45, 0x58, 0x49, 0x54, 0x10, 0x05, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, + 0x53, 0x53, 0x5f, 0x4b, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x09, 0x12, 0x16, 0x0a, 0x12, 0x50, + 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x50, 0x4f, 0x49, 0x4e, + 0x54, 0x10, 0x0a, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, + 0x4f, 0x41, 0x44, 0x45, 0x52, 0x10, 0x0b, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x43, 0x45, + 0x53, 0x53, 0x5f, 0x55, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x0c, 0x12, 0x0a, 0x0a, 0x04, 0x54, + 0x45, 0x53, 0x54, 0x10, 0xc0, 0xb8, 0x02, 0x12, 0x15, 0x0a, 0x0f, 0x52, 0x41, 0x54, 0x45, 0x5f, + 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xc1, 0xb8, 0x02, 0x2a, 0x2d, + 0x0a, 0x11, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x00, + 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x01, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1143,67 +1205,69 @@ func file_tetragon_events_proto_rawDescGZIP() []byte { } var file_tetragon_events_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_tetragon_events_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_tetragon_events_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_tetragon_events_proto_goTypes = []interface{}{ (EventType)(0), // 0: tetragon.EventType (FieldFilterAction)(0), // 1: tetragon.FieldFilterAction (*Filter)(nil), // 2: tetragon.Filter (*CapFilter)(nil), // 3: tetragon.CapFilter (*CapFilterSet)(nil), // 4: tetragon.CapFilterSet - (*FieldFilter)(nil), // 5: tetragon.FieldFilter - (*GetEventsRequest)(nil), // 6: tetragon.GetEventsRequest - (*AggregationOptions)(nil), // 7: tetragon.AggregationOptions - (*AggregationInfo)(nil), // 8: tetragon.AggregationInfo - (*RateLimitInfo)(nil), // 9: tetragon.RateLimitInfo - (*GetEventsResponse)(nil), // 10: tetragon.GetEventsResponse - (*wrapperspb.BoolValue)(nil), // 11: google.protobuf.BoolValue - (CapabilitiesType)(0), // 12: tetragon.CapabilitiesType - (*fieldmaskpb.FieldMask)(nil), // 13: google.protobuf.FieldMask - (*durationpb.Duration)(nil), // 14: google.protobuf.Duration - (*ProcessExec)(nil), // 15: tetragon.ProcessExec - (*ProcessExit)(nil), // 16: tetragon.ProcessExit - (*ProcessKprobe)(nil), // 17: tetragon.ProcessKprobe - (*ProcessTracepoint)(nil), // 18: tetragon.ProcessTracepoint - (*ProcessLoader)(nil), // 19: tetragon.ProcessLoader - (*ProcessUprobe)(nil), // 20: tetragon.ProcessUprobe - (*Test)(nil), // 21: tetragon.Test - (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp + (*RedactionFilter)(nil), // 5: tetragon.RedactionFilter + (*FieldFilter)(nil), // 6: tetragon.FieldFilter + (*GetEventsRequest)(nil), // 7: tetragon.GetEventsRequest + (*AggregationOptions)(nil), // 8: tetragon.AggregationOptions + (*AggregationInfo)(nil), // 9: tetragon.AggregationInfo + (*RateLimitInfo)(nil), // 10: tetragon.RateLimitInfo + (*GetEventsResponse)(nil), // 11: tetragon.GetEventsResponse + (*wrapperspb.BoolValue)(nil), // 12: google.protobuf.BoolValue + (CapabilitiesType)(0), // 13: tetragon.CapabilitiesType + (*fieldmaskpb.FieldMask)(nil), // 14: google.protobuf.FieldMask + (*durationpb.Duration)(nil), // 15: google.protobuf.Duration + (*ProcessExec)(nil), // 16: tetragon.ProcessExec + (*ProcessExit)(nil), // 17: tetragon.ProcessExit + (*ProcessKprobe)(nil), // 18: tetragon.ProcessKprobe + (*ProcessTracepoint)(nil), // 19: tetragon.ProcessTracepoint + (*ProcessLoader)(nil), // 20: tetragon.ProcessLoader + (*ProcessUprobe)(nil), // 21: tetragon.ProcessUprobe + (*Test)(nil), // 22: tetragon.Test + (*timestamppb.Timestamp)(nil), // 23: google.protobuf.Timestamp } var file_tetragon_events_proto_depIdxs = []int32{ - 11, // 0: tetragon.Filter.health_check:type_name -> google.protobuf.BoolValue + 12, // 0: tetragon.Filter.health_check:type_name -> google.protobuf.BoolValue 0, // 1: tetragon.Filter.event_set:type_name -> tetragon.EventType 3, // 2: tetragon.Filter.capabilities:type_name -> tetragon.CapFilter 4, // 3: tetragon.CapFilter.permitted:type_name -> tetragon.CapFilterSet 4, // 4: tetragon.CapFilter.effective:type_name -> tetragon.CapFilterSet 4, // 5: tetragon.CapFilter.inheritable:type_name -> tetragon.CapFilterSet - 12, // 6: tetragon.CapFilterSet.any:type_name -> tetragon.CapabilitiesType - 12, // 7: tetragon.CapFilterSet.all:type_name -> tetragon.CapabilitiesType - 12, // 8: tetragon.CapFilterSet.exactly:type_name -> tetragon.CapabilitiesType - 12, // 9: tetragon.CapFilterSet.none:type_name -> tetragon.CapabilitiesType - 0, // 10: tetragon.FieldFilter.event_set:type_name -> tetragon.EventType - 13, // 11: tetragon.FieldFilter.fields:type_name -> google.protobuf.FieldMask - 1, // 12: tetragon.FieldFilter.action:type_name -> tetragon.FieldFilterAction - 11, // 13: tetragon.FieldFilter.invert_event_set:type_name -> google.protobuf.BoolValue - 2, // 14: tetragon.GetEventsRequest.allow_list:type_name -> tetragon.Filter - 2, // 15: tetragon.GetEventsRequest.deny_list:type_name -> tetragon.Filter - 7, // 16: tetragon.GetEventsRequest.aggregation_options:type_name -> tetragon.AggregationOptions - 5, // 17: tetragon.GetEventsRequest.field_filters:type_name -> tetragon.FieldFilter - 14, // 18: tetragon.AggregationOptions.window_size:type_name -> google.protobuf.Duration - 15, // 19: tetragon.GetEventsResponse.process_exec:type_name -> tetragon.ProcessExec - 16, // 20: tetragon.GetEventsResponse.process_exit:type_name -> tetragon.ProcessExit - 17, // 21: tetragon.GetEventsResponse.process_kprobe:type_name -> tetragon.ProcessKprobe - 18, // 22: tetragon.GetEventsResponse.process_tracepoint:type_name -> tetragon.ProcessTracepoint - 19, // 23: tetragon.GetEventsResponse.process_loader:type_name -> tetragon.ProcessLoader - 20, // 24: tetragon.GetEventsResponse.process_uprobe:type_name -> tetragon.ProcessUprobe - 21, // 25: tetragon.GetEventsResponse.test:type_name -> tetragon.Test - 9, // 26: tetragon.GetEventsResponse.rate_limit_info:type_name -> tetragon.RateLimitInfo - 22, // 27: tetragon.GetEventsResponse.time:type_name -> google.protobuf.Timestamp - 8, // 28: tetragon.GetEventsResponse.aggregation_info:type_name -> tetragon.AggregationInfo - 29, // [29:29] is the sub-list for method output_type - 29, // [29:29] is the sub-list for method input_type - 29, // [29:29] is the sub-list for extension type_name - 29, // [29:29] is the sub-list for extension extendee - 0, // [0:29] is the sub-list for field type_name + 13, // 6: tetragon.CapFilterSet.any:type_name -> tetragon.CapabilitiesType + 13, // 7: tetragon.CapFilterSet.all:type_name -> tetragon.CapabilitiesType + 13, // 8: tetragon.CapFilterSet.exactly:type_name -> tetragon.CapabilitiesType + 13, // 9: tetragon.CapFilterSet.none:type_name -> tetragon.CapabilitiesType + 2, // 10: tetragon.RedactionFilter.match:type_name -> tetragon.Filter + 0, // 11: tetragon.FieldFilter.event_set:type_name -> tetragon.EventType + 14, // 12: tetragon.FieldFilter.fields:type_name -> google.protobuf.FieldMask + 1, // 13: tetragon.FieldFilter.action:type_name -> tetragon.FieldFilterAction + 12, // 14: tetragon.FieldFilter.invert_event_set:type_name -> google.protobuf.BoolValue + 2, // 15: tetragon.GetEventsRequest.allow_list:type_name -> tetragon.Filter + 2, // 16: tetragon.GetEventsRequest.deny_list:type_name -> tetragon.Filter + 8, // 17: tetragon.GetEventsRequest.aggregation_options:type_name -> tetragon.AggregationOptions + 6, // 18: tetragon.GetEventsRequest.field_filters:type_name -> tetragon.FieldFilter + 15, // 19: tetragon.AggregationOptions.window_size:type_name -> google.protobuf.Duration + 16, // 20: tetragon.GetEventsResponse.process_exec:type_name -> tetragon.ProcessExec + 17, // 21: tetragon.GetEventsResponse.process_exit:type_name -> tetragon.ProcessExit + 18, // 22: tetragon.GetEventsResponse.process_kprobe:type_name -> tetragon.ProcessKprobe + 19, // 23: tetragon.GetEventsResponse.process_tracepoint:type_name -> tetragon.ProcessTracepoint + 20, // 24: tetragon.GetEventsResponse.process_loader:type_name -> tetragon.ProcessLoader + 21, // 25: tetragon.GetEventsResponse.process_uprobe:type_name -> tetragon.ProcessUprobe + 22, // 26: tetragon.GetEventsResponse.test:type_name -> tetragon.Test + 10, // 27: tetragon.GetEventsResponse.rate_limit_info:type_name -> tetragon.RateLimitInfo + 23, // 28: tetragon.GetEventsResponse.time:type_name -> google.protobuf.Timestamp + 9, // 29: tetragon.GetEventsResponse.aggregation_info:type_name -> tetragon.AggregationInfo + 30, // [30:30] is the sub-list for method output_type + 30, // [30:30] is the sub-list for method input_type + 30, // [30:30] is the sub-list for extension type_name + 30, // [30:30] is the sub-list for extension extendee + 0, // [0:30] is the sub-list for field type_name } func init() { file_tetragon_events_proto_init() } @@ -1251,7 +1315,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FieldFilter); i { + switch v := v.(*RedactionFilter); i { case 0: return &v.state case 1: @@ -1263,7 +1327,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetEventsRequest); i { + switch v := v.(*FieldFilter); i { case 0: return &v.state case 1: @@ -1275,7 +1339,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AggregationOptions); i { + switch v := v.(*GetEventsRequest); i { case 0: return &v.state case 1: @@ -1287,7 +1351,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AggregationInfo); i { + switch v := v.(*AggregationOptions); i { case 0: return &v.state case 1: @@ -1299,7 +1363,7 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RateLimitInfo); i { + switch v := v.(*AggregationInfo); i { case 0: return &v.state case 1: @@ -1311,6 +1375,18 @@ func file_tetragon_events_proto_init() { } } file_tetragon_events_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RateLimitInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tetragon_events_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetEventsResponse); i { case 0: return &v.state @@ -1323,7 +1399,7 @@ func file_tetragon_events_proto_init() { } } } - file_tetragon_events_proto_msgTypes[8].OneofWrappers = []interface{}{ + file_tetragon_events_proto_msgTypes[9].OneofWrappers = []interface{}{ (*GetEventsResponse_ProcessExec)(nil), (*GetEventsResponse_ProcessExit)(nil), (*GetEventsResponse_ProcessKprobe)(nil), @@ -1339,7 +1415,7 @@ func file_tetragon_events_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tetragon_events_proto_rawDesc, NumEnums: 2, - NumMessages: 9, + NumMessages: 10, NumExtensions: 0, NumServices: 0, }, diff --git a/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.pb.json.go b/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.pb.json.go index 161fd1783e8..44af480b37a 100644 --- a/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.pb.json.go +++ b/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.pb.json.go @@ -55,6 +55,22 @@ func (msg *CapFilterSet) UnmarshalJSON(b []byte) error { }.Unmarshal(b, msg) } +// MarshalJSON implements json.Marshaler +func (msg *RedactionFilter) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{ + UseEnumNumbers: false, + EmitUnpopulated: false, + UseProtoNames: true, + }.Marshal(msg) +} + +// UnmarshalJSON implements json.Unmarshaler +func (msg *RedactionFilter) UnmarshalJSON(b []byte) error { + return protojson.UnmarshalOptions{ + DiscardUnknown: false, + }.Unmarshal(b, msg) +} + // MarshalJSON implements json.Marshaler func (msg *FieldFilter) MarshalJSON() ([]byte, error) { return protojson.MarshalOptions{ diff --git a/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.proto b/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.proto index 2ecebe6e9be..5fd1322e99a 100644 --- a/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.proto +++ b/vendor/github.com/cilium/tetragon/api/v1/tetragon/events.proto @@ -83,6 +83,13 @@ message CapFilterSet { repeated CapabilitiesType none = 4; } +message RedactionFilter { + // Match events that the redaction filter will apply to. + repeated Filter match = 1; + // Regular expressions to use for redaction. Strings inside capture groups are redacted. + repeated string redact = 2; +} + // Determines the behavior of a field filter enum FieldFilterAction { INCLUDE = 0; diff --git a/vendor/google.golang.org/protobuf/internal/msgfmt/format.go b/vendor/google.golang.org/protobuf/internal/msgfmt/format.go new file mode 100644 index 00000000000..a319550f69e --- /dev/null +++ b/vendor/google.golang.org/protobuf/internal/msgfmt/format.go @@ -0,0 +1,261 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package msgfmt implements a text marshaler combining the desirable features +// of both the JSON and proto text formats. +// It is optimized for human readability and has no associated deserializer. +package msgfmt + +import ( + "bytes" + "fmt" + "reflect" + "sort" + "strconv" + "strings" + "time" + + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/internal/detrand" + "google.golang.org/protobuf/internal/genid" + "google.golang.org/protobuf/internal/order" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" +) + +// Format returns a formatted string for the message. +func Format(m proto.Message) string { + return string(appendMessage(nil, m.ProtoReflect())) +} + +// FormatValue returns a formatted string for an arbitrary value. +func FormatValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) string { + return string(appendValue(nil, v, fd)) +} + +func appendValue(b []byte, v protoreflect.Value, fd protoreflect.FieldDescriptor) []byte { + switch v := v.Interface().(type) { + case nil: + return append(b, ""...) + case bool, int32, int64, uint32, uint64, float32, float64: + return append(b, fmt.Sprint(v)...) + case string: + return append(b, strconv.Quote(string(v))...) + case []byte: + return append(b, strconv.Quote(string(v))...) + case protoreflect.EnumNumber: + return appendEnum(b, v, fd) + case protoreflect.Message: + return appendMessage(b, v) + case protoreflect.List: + return appendList(b, v, fd) + case protoreflect.Map: + return appendMap(b, v, fd) + default: + panic(fmt.Sprintf("invalid type: %T", v)) + } +} + +func appendEnum(b []byte, v protoreflect.EnumNumber, fd protoreflect.FieldDescriptor) []byte { + if fd != nil { + if ev := fd.Enum().Values().ByNumber(v); ev != nil { + return append(b, ev.Name()...) + } + } + return strconv.AppendInt(b, int64(v), 10) +} + +func appendMessage(b []byte, m protoreflect.Message) []byte { + if b2 := appendKnownMessage(b, m); b2 != nil { + return b2 + } + + b = append(b, '{') + order.RangeFields(m, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { + b = append(b, fd.TextName()...) + b = append(b, ':') + b = appendValue(b, v, fd) + b = append(b, delim()...) + return true + }) + b = appendUnknown(b, m.GetUnknown()) + b = bytes.TrimRight(b, delim()) + b = append(b, '}') + return b +} + +var protocmpMessageType = reflect.TypeOf(map[string]interface{}(nil)) + +func appendKnownMessage(b []byte, m protoreflect.Message) []byte { + md := m.Descriptor() + fds := md.Fields() + switch md.FullName() { + case genid.Any_message_fullname: + var msgVal protoreflect.Message + url := m.Get(fds.ByNumber(genid.Any_TypeUrl_field_number)).String() + if v := reflect.ValueOf(m); v.Type().ConvertibleTo(protocmpMessageType) { + // For protocmp.Message, directly obtain the sub-message value + // which is stored in structured form, rather than as raw bytes. + m2 := v.Convert(protocmpMessageType).Interface().(map[string]interface{}) + v, ok := m2[string(genid.Any_Value_field_name)].(proto.Message) + if !ok { + return nil + } + msgVal = v.ProtoReflect() + } else { + val := m.Get(fds.ByNumber(genid.Any_Value_field_number)).Bytes() + mt, err := protoregistry.GlobalTypes.FindMessageByURL(url) + if err != nil { + return nil + } + msgVal = mt.New() + err = proto.UnmarshalOptions{AllowPartial: true}.Unmarshal(val, msgVal.Interface()) + if err != nil { + return nil + } + } + + b = append(b, '{') + b = append(b, "["+url+"]"...) + b = append(b, ':') + b = appendMessage(b, msgVal) + b = append(b, '}') + return b + + case genid.Timestamp_message_fullname: + secs := m.Get(fds.ByNumber(genid.Timestamp_Seconds_field_number)).Int() + nanos := m.Get(fds.ByNumber(genid.Timestamp_Nanos_field_number)).Int() + if nanos < 0 || nanos >= 1e9 { + return nil + } + t := time.Unix(secs, nanos).UTC() + x := t.Format("2006-01-02T15:04:05.000000000") // RFC 3339 + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, ".000") + return append(b, x+"Z"...) + + case genid.Duration_message_fullname: + sign := "" + secs := m.Get(fds.ByNumber(genid.Duration_Seconds_field_number)).Int() + nanos := m.Get(fds.ByNumber(genid.Duration_Nanos_field_number)).Int() + if nanos <= -1e9 || nanos >= 1e9 || (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0) { + return nil + } + if secs < 0 || nanos < 0 { + sign, secs, nanos = "-", -1*secs, -1*nanos + } + x := fmt.Sprintf("%s%d.%09d", sign, secs, nanos) + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, ".000") + return append(b, x+"s"...) + + case genid.BoolValue_message_fullname, + genid.Int32Value_message_fullname, + genid.Int64Value_message_fullname, + genid.UInt32Value_message_fullname, + genid.UInt64Value_message_fullname, + genid.FloatValue_message_fullname, + genid.DoubleValue_message_fullname, + genid.StringValue_message_fullname, + genid.BytesValue_message_fullname: + fd := fds.ByNumber(genid.WrapperValue_Value_field_number) + return appendValue(b, m.Get(fd), fd) + } + + return nil +} + +func appendUnknown(b []byte, raw protoreflect.RawFields) []byte { + rs := make(map[protoreflect.FieldNumber][]protoreflect.RawFields) + for len(raw) > 0 { + num, _, n := protowire.ConsumeField(raw) + rs[num] = append(rs[num], raw[:n]) + raw = raw[n:] + } + + var ns []protoreflect.FieldNumber + for n := range rs { + ns = append(ns, n) + } + sort.Slice(ns, func(i, j int) bool { return ns[i] < ns[j] }) + + for _, n := range ns { + var leftBracket, rightBracket string + if len(rs[n]) > 1 { + leftBracket, rightBracket = "[", "]" + } + + b = strconv.AppendInt(b, int64(n), 10) + b = append(b, ':') + b = append(b, leftBracket...) + for _, r := range rs[n] { + num, typ, n := protowire.ConsumeTag(r) + r = r[n:] + switch typ { + case protowire.VarintType: + v, _ := protowire.ConsumeVarint(r) + b = strconv.AppendInt(b, int64(v), 10) + case protowire.Fixed32Type: + v, _ := protowire.ConsumeFixed32(r) + b = append(b, fmt.Sprintf("0x%08x", v)...) + case protowire.Fixed64Type: + v, _ := protowire.ConsumeFixed64(r) + b = append(b, fmt.Sprintf("0x%016x", v)...) + case protowire.BytesType: + v, _ := protowire.ConsumeBytes(r) + b = strconv.AppendQuote(b, string(v)) + case protowire.StartGroupType: + v, _ := protowire.ConsumeGroup(num, r) + b = append(b, '{') + b = appendUnknown(b, v) + b = bytes.TrimRight(b, delim()) + b = append(b, '}') + default: + panic(fmt.Sprintf("invalid type: %v", typ)) + } + b = append(b, delim()...) + } + b = bytes.TrimRight(b, delim()) + b = append(b, rightBracket...) + b = append(b, delim()...) + } + return b +} + +func appendList(b []byte, v protoreflect.List, fd protoreflect.FieldDescriptor) []byte { + b = append(b, '[') + for i := 0; i < v.Len(); i++ { + b = appendValue(b, v.Get(i), fd) + b = append(b, delim()...) + } + b = bytes.TrimRight(b, delim()) + b = append(b, ']') + return b +} + +func appendMap(b []byte, v protoreflect.Map, fd protoreflect.FieldDescriptor) []byte { + b = append(b, '{') + order.RangeEntries(v, order.GenericKeyOrder, func(k protoreflect.MapKey, v protoreflect.Value) bool { + b = appendValue(b, k.Value(), fd.MapKey()) + b = append(b, ':') + b = appendValue(b, v, fd.MapValue()) + b = append(b, delim()...) + return true + }) + b = bytes.TrimRight(b, delim()) + b = append(b, '}') + return b +} + +func delim() string { + // Deliberately introduce instability into the message string to + // discourage users from depending on it. + if detrand.Bool() { + return " " + } + return ", " +} diff --git a/vendor/google.golang.org/protobuf/reflect/protopath/path.go b/vendor/google.golang.org/protobuf/reflect/protopath/path.go new file mode 100644 index 00000000000..fffac00ebce --- /dev/null +++ b/vendor/google.golang.org/protobuf/reflect/protopath/path.go @@ -0,0 +1,122 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package protopath provides functionality for +// representing a sequence of protobuf reflection operations on a message. +package protopath + +import ( + "fmt" + + "google.golang.org/protobuf/internal/msgfmt" + "google.golang.org/protobuf/reflect/protoreflect" +) + +// NOTE: The Path and Values are separate types here since there are use cases +// where you would like to "address" some value in a message with just the path +// and don't have the value information available. +// +// This is different from how github.com/google/go-cmp/cmp.Path operates, +// which combines both path and value information together. +// Since the cmp package itself is the only one ever constructing a cmp.Path, +// it will always have the value available. + +// Path is a sequence of protobuf reflection steps applied to some root +// protobuf message value to arrive at the current value. +// The first step must be a [Root] step. +type Path []Step + +// TODO: Provide a Parse function that parses something similar to or +// perhaps identical to the output of Path.String. + +// Index returns the ith step in the path and supports negative indexing. +// A negative index starts counting from the tail of the Path such that -1 +// refers to the last step, -2 refers to the second-to-last step, and so on. +// It returns a zero Step value if the index is out-of-bounds. +func (p Path) Index(i int) Step { + if i < 0 { + i = len(p) + i + } + if i < 0 || i >= len(p) { + return Step{} + } + return p[i] +} + +// String returns a structured representation of the path +// by concatenating the string representation of every path step. +func (p Path) String() string { + var b []byte + for _, s := range p { + b = s.appendString(b) + } + return string(b) +} + +// Values is a Path paired with a sequence of values at each step. +// The lengths of [Values.Path] and [Values.Values] must be identical. +// The first step must be a [Root] step and +// the first value must be a concrete message value. +type Values struct { + Path Path + Values []protoreflect.Value +} + +// Len reports the length of the path and values. +// If the path and values have differing length, it returns the minimum length. +func (p Values) Len() int { + n := len(p.Path) + if n > len(p.Values) { + n = len(p.Values) + } + return n +} + +// Index returns the ith step and value and supports negative indexing. +// A negative index starts counting from the tail of the Values such that -1 +// refers to the last pair, -2 refers to the second-to-last pair, and so on. +func (p Values) Index(i int) (out struct { + Step Step + Value protoreflect.Value +}) { + // NOTE: This returns a single struct instead of two return values so that + // callers can make use of the the value in an expression: + // vs.Index(i).Value.Interface() + n := p.Len() + if i < 0 { + i = n + i + } + if i < 0 || i >= n { + return out + } + out.Step = p.Path[i] + out.Value = p.Values[i] + return out +} + +// String returns a humanly readable representation of the path and last value. +// Do not depend on the output being stable. +// +// For example: +// +// (path.to.MyMessage).list_field[5].map_field["hello"] = {hello: "world"} +func (p Values) String() string { + n := p.Len() + if n == 0 { + return "" + } + + // Determine the field descriptor associated with the last step. + var fd protoreflect.FieldDescriptor + last := p.Index(-1) + switch last.Step.kind { + case FieldAccessStep: + fd = last.Step.FieldDescriptor() + case MapIndexStep, ListIndexStep: + fd = p.Index(-2).Step.FieldDescriptor() + } + + // Format the full path with the last value. + return fmt.Sprintf("%v = %v", p.Path[:n], msgfmt.FormatValue(last.Value, fd)) +} diff --git a/vendor/google.golang.org/protobuf/reflect/protopath/step.go b/vendor/google.golang.org/protobuf/reflect/protopath/step.go new file mode 100644 index 00000000000..95ae85c5b1d --- /dev/null +++ b/vendor/google.golang.org/protobuf/reflect/protopath/step.go @@ -0,0 +1,241 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package protopath + +import ( + "fmt" + "strconv" + "strings" + + "google.golang.org/protobuf/internal/encoding/text" + "google.golang.org/protobuf/reflect/protoreflect" +) + +// StepKind identifies the kind of step operation. +// Each kind of step corresponds with some protobuf reflection operation. +type StepKind int + +const ( + invalidStep StepKind = iota + // RootStep identifies a step as the Root step operation. + RootStep + // FieldAccessStep identifies a step as the FieldAccess step operation. + FieldAccessStep + // UnknownAccessStep identifies a step as the UnknownAccess step operation. + UnknownAccessStep + // ListIndexStep identifies a step as the ListIndex step operation. + ListIndexStep + // MapIndexStep identifies a step as the MapIndex step operation. + MapIndexStep + // AnyExpandStep identifies a step as the AnyExpand step operation. + AnyExpandStep +) + +func (k StepKind) String() string { + switch k { + case invalidStep: + return "" + case RootStep: + return "Root" + case FieldAccessStep: + return "FieldAccess" + case UnknownAccessStep: + return "UnknownAccess" + case ListIndexStep: + return "ListIndex" + case MapIndexStep: + return "MapIndex" + case AnyExpandStep: + return "AnyExpand" + default: + return fmt.Sprintf("", k) + } +} + +// Step is a union where only one step operation may be specified at a time. +// The different kinds of steps are specified by the constants defined for +// the StepKind type. +type Step struct { + kind StepKind + desc protoreflect.Descriptor + key protoreflect.Value +} + +// Root indicates the root message that a path is relative to. +// It should always (and only ever) be the first step in a path. +func Root(md protoreflect.MessageDescriptor) Step { + if md == nil { + panic("nil message descriptor") + } + return Step{kind: RootStep, desc: md} +} + +// FieldAccess describes access of a field within a message. +// Extension field accesses are also represented using a FieldAccess and +// must be provided with a protoreflect.FieldDescriptor +// +// Within the context of Values, +// the type of the previous step value is always a message, and +// the type of the current step value is determined by the field descriptor. +func FieldAccess(fd protoreflect.FieldDescriptor) Step { + if fd == nil { + panic("nil field descriptor") + } else if _, ok := fd.(protoreflect.ExtensionTypeDescriptor); !ok && fd.IsExtension() { + panic(fmt.Sprintf("extension field %q must implement protoreflect.ExtensionTypeDescriptor", fd.FullName())) + } + return Step{kind: FieldAccessStep, desc: fd} +} + +// UnknownAccess describes access to the unknown fields within a message. +// +// Within the context of Values, +// the type of the previous step value is always a message, and +// the type of the current step value is always a bytes type. +func UnknownAccess() Step { + return Step{kind: UnknownAccessStep} +} + +// ListIndex describes index of an element within a list. +// +// Within the context of Values, +// the type of the previous, previous step value is always a message, +// the type of the previous step value is always a list, and +// the type of the current step value is determined by the field descriptor. +func ListIndex(i int) Step { + if i < 0 { + panic(fmt.Sprintf("invalid list index: %v", i)) + } + return Step{kind: ListIndexStep, key: protoreflect.ValueOfInt64(int64(i))} +} + +// MapIndex describes index of an entry within a map. +// The key type is determined by field descriptor that the map belongs to. +// +// Within the context of Values, +// the type of the previous previous step value is always a message, +// the type of the previous step value is always a map, and +// the type of the current step value is determined by the field descriptor. +func MapIndex(k protoreflect.MapKey) Step { + if !k.IsValid() { + panic("invalid map index") + } + return Step{kind: MapIndexStep, key: k.Value()} +} + +// AnyExpand describes expansion of a google.protobuf.Any message into +// a structured representation of the underlying message. +// +// Within the context of Values, +// the type of the previous step value is always a google.protobuf.Any message, and +// the type of the current step value is always a message. +func AnyExpand(md protoreflect.MessageDescriptor) Step { + if md == nil { + panic("nil message descriptor") + } + return Step{kind: AnyExpandStep, desc: md} +} + +// MessageDescriptor returns the message descriptor for Root or AnyExpand steps, +// otherwise it returns nil. +func (s Step) MessageDescriptor() protoreflect.MessageDescriptor { + switch s.kind { + case RootStep, AnyExpandStep: + return s.desc.(protoreflect.MessageDescriptor) + default: + return nil + } +} + +// FieldDescriptor returns the field descriptor for FieldAccess steps, +// otherwise it returns nil. +func (s Step) FieldDescriptor() protoreflect.FieldDescriptor { + switch s.kind { + case FieldAccessStep: + return s.desc.(protoreflect.FieldDescriptor) + default: + return nil + } +} + +// ListIndex returns the list index for ListIndex steps, +// otherwise it returns 0. +func (s Step) ListIndex() int { + switch s.kind { + case ListIndexStep: + return int(s.key.Int()) + default: + return 0 + } +} + +// MapIndex returns the map key for MapIndex steps, +// otherwise it returns an invalid map key. +func (s Step) MapIndex() protoreflect.MapKey { + switch s.kind { + case MapIndexStep: + return s.key.MapKey() + default: + return protoreflect.MapKey{} + } +} + +// Kind reports which kind of step this is. +func (s Step) Kind() StepKind { + return s.kind +} + +func (s Step) String() string { + return string(s.appendString(nil)) +} + +func (s Step) appendString(b []byte) []byte { + switch s.kind { + case RootStep: + b = append(b, '(') + b = append(b, s.desc.FullName()...) + b = append(b, ')') + case FieldAccessStep: + b = append(b, '.') + if fd := s.desc.(protoreflect.FieldDescriptor); fd.IsExtension() { + b = append(b, '(') + b = append(b, strings.Trim(fd.TextName(), "[]")...) + b = append(b, ')') + } else { + b = append(b, fd.TextName()...) + } + case UnknownAccessStep: + b = append(b, '.') + b = append(b, '?') + case ListIndexStep: + b = append(b, '[') + b = strconv.AppendInt(b, s.key.Int(), 10) + b = append(b, ']') + case MapIndexStep: + b = append(b, '[') + switch k := s.key.Interface().(type) { + case bool: + b = strconv.AppendBool(b, bool(k)) // e.g., "true" or "false" + case int32: + b = strconv.AppendInt(b, int64(k), 10) // e.g., "-32" + case int64: + b = strconv.AppendInt(b, int64(k), 10) // e.g., "-64" + case uint32: + b = strconv.AppendUint(b, uint64(k), 10) // e.g., "32" + case uint64: + b = strconv.AppendUint(b, uint64(k), 10) // e.g., "64" + case string: + b = text.AppendString(b, k) // e.g., `"hello, world"` + } + b = append(b, ']') + case AnyExpandStep: + b = append(b, '.') + b = append(b, '(') + b = append(b, s.desc.FullName()...) + b = append(b, ')') + default: + b = append(b, ""...) + } + return b +} diff --git a/vendor/google.golang.org/protobuf/reflect/protorange/range.go b/vendor/google.golang.org/protobuf/reflect/protorange/range.go new file mode 100644 index 00000000000..7a032758b51 --- /dev/null +++ b/vendor/google.golang.org/protobuf/reflect/protorange/range.go @@ -0,0 +1,316 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package protorange provides functionality to traverse a message value. +package protorange + +import ( + "bytes" + "errors" + + "google.golang.org/protobuf/internal/genid" + "google.golang.org/protobuf/internal/order" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protopath" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" +) + +var ( + // Break breaks traversal of children in the current value. + // It has no effect when traversing values that are not composite types + // (e.g., messages, lists, and maps). + Break = errors.New("break traversal of children in current value") + + // Terminate terminates the entire range operation. + // All necessary Pop operations continue to be called. + Terminate = errors.New("terminate range operation") +) + +// Range performs a depth-first traversal over reachable values in a message. +// +// See [Options.Range] for details. +func Range(m protoreflect.Message, f func(protopath.Values) error) error { + return Options{}.Range(m, f, nil) +} + +// Options configures traversal of a message value tree. +type Options struct { + // Stable specifies whether to visit message fields and map entries + // in a stable ordering. If false, then the ordering is undefined and + // may be non-deterministic. + // + // Message fields are visited in ascending order by field number. + // Map entries are visited in ascending order, where + // boolean keys are ordered such that false sorts before true, + // numeric keys are ordered based on the numeric value, and + // string keys are lexicographically ordered by Unicode codepoints. + Stable bool + + // Resolver is used for looking up types when expanding google.protobuf.Any + // messages. If nil, this defaults to using protoregistry.GlobalTypes. + // To prevent expansion of Any messages, pass an empty protoregistry.Types: + // + // Options{Resolver: (*protoregistry.Types)(nil)} + // + Resolver interface { + protoregistry.ExtensionTypeResolver + protoregistry.MessageTypeResolver + } +} + +// Range performs a depth-first traversal over reachable values in a message. +// The first push and the last pop are to push/pop a [protopath.Root] step. +// If push or pop return any non-nil error (other than [Break] or [Terminate]), +// it terminates the traversal and is returned by Range. +// +// The rules for traversing a message is as follows: +// +// - For messages, iterate over every populated known and extension field. +// Each field is preceded by a push of a [protopath.FieldAccess] step, +// followed by recursive application of the rules on the field value, +// and succeeded by a pop of that step. +// If the message has unknown fields, then push an [protopath.UnknownAccess] step +// followed immediately by pop of that step. +// +// - As an exception to the above rule, if the current message is a +// google.protobuf.Any message, expand the underlying message (if resolvable). +// The expanded message is preceded by a push of a [protopath.AnyExpand] step, +// followed by recursive application of the rules on the underlying message, +// and succeeded by a pop of that step. Mutations to the expanded message +// are written back to the Any message when popping back out. +// +// - For lists, iterate over every element. Each element is preceded by a push +// of a [protopath.ListIndex] step, followed by recursive application of the rules +// on the list element, and succeeded by a pop of that step. +// +// - For maps, iterate over every entry. Each entry is preceded by a push +// of a [protopath.MapIndex] step, followed by recursive application of the rules +// on the map entry value, and succeeded by a pop of that step. +// +// Mutations should only be made to the last value, otherwise the effects on +// traversal will be undefined. If the mutation is made to the last value +// during to a push, then the effects of the mutation will affect traversal. +// For example, if the last value is currently a message, and the push function +// populates a few fields in that message, then the newly modified fields +// will be traversed. +// +// The [protopath.Values] provided to push functions is only valid until the +// corresponding pop call and the values provided to a pop call is only valid +// for the duration of the pop call itself. +func (o Options) Range(m protoreflect.Message, push, pop func(protopath.Values) error) error { + var err error + p := new(protopath.Values) + if o.Resolver == nil { + o.Resolver = protoregistry.GlobalTypes + } + + pushStep(p, protopath.Root(m.Descriptor()), protoreflect.ValueOfMessage(m)) + if push != nil { + err = amendError(err, push(*p)) + } + if err == nil { + err = o.rangeMessage(p, m, push, pop) + } + if pop != nil { + err = amendError(err, pop(*p)) + } + popStep(p) + + if err == Break || err == Terminate { + err = nil + } + return err +} + +func (o Options) rangeMessage(p *protopath.Values, m protoreflect.Message, push, pop func(protopath.Values) error) (err error) { + if ok, err := o.rangeAnyMessage(p, m, push, pop); ok { + return err + } + + fieldOrder := order.AnyFieldOrder + if o.Stable { + fieldOrder = order.NumberFieldOrder + } + order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { + pushStep(p, protopath.FieldAccess(fd), v) + if push != nil { + err = amendError(err, push(*p)) + } + if err == nil { + switch { + case fd.IsMap(): + err = o.rangeMap(p, fd, v.Map(), push, pop) + case fd.IsList(): + err = o.rangeList(p, fd, v.List(), push, pop) + case fd.Message() != nil: + err = o.rangeMessage(p, v.Message(), push, pop) + } + } + if pop != nil { + err = amendError(err, pop(*p)) + } + popStep(p) + return err == nil + }) + + if b := m.GetUnknown(); len(b) > 0 && err == nil { + pushStep(p, protopath.UnknownAccess(), protoreflect.ValueOfBytes(b)) + if push != nil { + err = amendError(err, push(*p)) + } + if pop != nil { + err = amendError(err, pop(*p)) + } + popStep(p) + } + + if err == Break { + err = nil + } + return err +} + +func (o Options) rangeAnyMessage(p *protopath.Values, m protoreflect.Message, push, pop func(protopath.Values) error) (ok bool, err error) { + md := m.Descriptor() + if md.FullName() != "google.protobuf.Any" { + return false, nil + } + + fds := md.Fields() + url := m.Get(fds.ByNumber(genid.Any_TypeUrl_field_number)).String() + val := m.Get(fds.ByNumber(genid.Any_Value_field_number)).Bytes() + mt, errFind := o.Resolver.FindMessageByURL(url) + if errFind != nil { + return false, nil + } + + // Unmarshal the raw encoded message value into a structured message value. + m2 := mt.New() + errUnmarshal := proto.UnmarshalOptions{ + Merge: true, + AllowPartial: true, + Resolver: o.Resolver, + }.Unmarshal(val, m2.Interface()) + if errUnmarshal != nil { + // If the the underlying message cannot be unmarshaled, + // then just treat this as an normal message type. + return false, nil + } + + // Marshal Any before ranging to detect possible mutations. + b1, errMarshal := proto.MarshalOptions{ + AllowPartial: true, + Deterministic: true, + }.Marshal(m2.Interface()) + if errMarshal != nil { + return true, errMarshal + } + + pushStep(p, protopath.AnyExpand(m2.Descriptor()), protoreflect.ValueOfMessage(m2)) + if push != nil { + err = amendError(err, push(*p)) + } + if err == nil { + err = o.rangeMessage(p, m2, push, pop) + } + if pop != nil { + err = amendError(err, pop(*p)) + } + popStep(p) + + // Marshal Any after ranging to detect possible mutations. + b2, errMarshal := proto.MarshalOptions{ + AllowPartial: true, + Deterministic: true, + }.Marshal(m2.Interface()) + if errMarshal != nil { + return true, errMarshal + } + + // Mutations detected, write the new sequence of bytes to the Any message. + if !bytes.Equal(b1, b2) { + m.Set(fds.ByNumber(genid.Any_Value_field_number), protoreflect.ValueOfBytes(b2)) + } + + if err == Break { + err = nil + } + return true, err +} + +func (o Options) rangeList(p *protopath.Values, fd protoreflect.FieldDescriptor, ls protoreflect.List, push, pop func(protopath.Values) error) (err error) { + for i := 0; i < ls.Len() && err == nil; i++ { + v := ls.Get(i) + pushStep(p, protopath.ListIndex(i), v) + if push != nil { + err = amendError(err, push(*p)) + } + if err == nil && fd.Message() != nil { + err = o.rangeMessage(p, v.Message(), push, pop) + } + if pop != nil { + err = amendError(err, pop(*p)) + } + popStep(p) + } + + if err == Break { + err = nil + } + return err +} + +func (o Options) rangeMap(p *protopath.Values, fd protoreflect.FieldDescriptor, ms protoreflect.Map, push, pop func(protopath.Values) error) (err error) { + keyOrder := order.AnyKeyOrder + if o.Stable { + keyOrder = order.GenericKeyOrder + } + order.RangeEntries(ms, keyOrder, func(k protoreflect.MapKey, v protoreflect.Value) bool { + pushStep(p, protopath.MapIndex(k), v) + if push != nil { + err = amendError(err, push(*p)) + } + if err == nil && fd.MapValue().Message() != nil { + err = o.rangeMessage(p, v.Message(), push, pop) + } + if pop != nil { + err = amendError(err, pop(*p)) + } + popStep(p) + return err == nil + }) + + if err == Break { + err = nil + } + return err +} + +func pushStep(p *protopath.Values, s protopath.Step, v protoreflect.Value) { + p.Path = append(p.Path, s) + p.Values = append(p.Values, v) +} + +func popStep(p *protopath.Values) { + p.Path = p.Path[:len(p.Path)-1] + p.Values = p.Values[:len(p.Values)-1] +} + +// amendError amends the previous error with the current error if it is +// considered more serious. The precedence order for errors is: +// +// nil < Break < Terminate < previous non-nil < current non-nil +func amendError(prev, curr error) error { + switch { + case curr == nil: + return prev + case curr == Break && prev != nil: + return prev + case curr == Terminate && prev != nil && prev != Break: + return prev + default: + return curr + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 52a1a96c1e4..59407e24171 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1093,6 +1093,7 @@ google.golang.org/protobuf/internal/filetype google.golang.org/protobuf/internal/flags google.golang.org/protobuf/internal/genid google.golang.org/protobuf/internal/impl +google.golang.org/protobuf/internal/msgfmt google.golang.org/protobuf/internal/order google.golang.org/protobuf/internal/pragma google.golang.org/protobuf/internal/set @@ -1101,6 +1102,8 @@ google.golang.org/protobuf/internal/version google.golang.org/protobuf/proto google.golang.org/protobuf/protoadapt google.golang.org/protobuf/reflect/protodesc +google.golang.org/protobuf/reflect/protopath +google.golang.org/protobuf/reflect/protorange google.golang.org/protobuf/reflect/protoreflect google.golang.org/protobuf/reflect/protoregistry google.golang.org/protobuf/runtime/protoiface