From c30f58d4ab37102f84b7a5a0f4119f13aa857321 Mon Sep 17 00:00:00 2001 From: William Findlay Date: Wed, 20 Mar 2024 14:34:50 -0400 Subject: [PATCH] implement redaction filters Implement a new field filter type, the refaction filter. Redaction filters use regular expressions to suppress sensitive information in string fields in Tetragon events. When a regular expression in a redcation filter matches a string, everything inside of its capture groups is replaced with `*****`, effectively censoring the output. For example, the regular expression `(?:--password|-p)(?:\s+|=)(\S*)` will convert the string "--password=foo" into "--password=*****". In some cases, it is not desirable to apply a redaction filter to all events. For this use case, redaction filters also include an event filter which can be used to select events to redact. This event filter is configured with the same syntax as an export filter. As a more concrete example: {"match": {"binary_regex": ["^foo$"]}, "redact": ["\W(qux)\W"]} The above filter would redact any occurrences of the word "qux" in events with the binary name "foo". Due to the sensitive nature of redaction, these filters are applied as configured in the agent, regardless of whether an event is exported via gRPC or the JSON exporter. In other words, redaction filter configuration always happens at the agent config level, not in the gRPC client CLI. Signed-off-by: William Findlay --- api/v1/README.md | 17 + api/v1/tetragon/events.pb.go | 434 ++++++++++-------- api/v1/tetragon/events.pb.json.go | 16 + api/v1/tetragon/events.proto | 7 + cmd/tetragon/main.go | 14 +- docs/content/en/docs/concepts/events.md | 45 +- docs/content/en/docs/reference/grpc-api.md | 9 + docs/content/en/docs/reference/helm-chart.md | 3 +- docs/data/tetragon_flags.yaml | 2 + install/kubernetes/tetragon/README.md | 3 +- .../templates/tetragon_configmap.yaml | 2 + install/kubernetes/tetragon/values.yaml | 28 +- pkg/bench/bench.go | 4 +- pkg/exporter/exporter_test.go | 5 +- pkg/fieldfilters/redaction.go | 187 ++++++++ pkg/fieldfilters/redaction_test.go | 136 ++++++ pkg/filters/filters_test.go | 2 + pkg/grpc/exec/exec_test_helper.go | 3 +- pkg/grpc/process_manager.go | 4 +- pkg/grpc/process_manager_test.go | 4 +- .../observer_test_helper.go | 15 +- pkg/option/flags.go | 6 +- pkg/server/server.go | 30 +- .../tetragon/api/v1/tetragon/events.pb.go | 434 ++++++++++-------- .../api/v1/tetragon/events.pb.json.go | 16 + .../tetragon/api/v1/tetragon/events.proto | 7 + .../protobuf/internal/msgfmt/format.go | 261 +++++++++++ .../protobuf/reflect/protopath/path.go | 122 +++++ .../protobuf/reflect/protopath/step.go | 241 ++++++++++ .../protobuf/reflect/protorange/range.go | 316 +++++++++++++ vendor/modules.txt | 3 + 31 files changed, 1993 insertions(+), 383 deletions(-) create mode 100644 pkg/fieldfilters/redaction.go create mode 100644 pkg/fieldfilters/redaction_test.go create mode 100644 vendor/google.golang.org/protobuf/internal/msgfmt/format.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protopath/path.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protopath/step.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protorange/range.go 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..6eafc3dd014 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,17 @@ func tetragonExecute() error { hookRunner := rthooks.GlobalRunner().WithWatcher(k8sWatcher) + redactionFilters, err := getRedactionFilters() + if err != nil { + return err + } + pm, err := tetragonGrpc.NewProcessManager( ctx, &cleanupWg, observer.GetSensorManager(), - hookRunner) + hookRunner, + redactionFilters) if err != nil { return err } @@ -706,6 +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{"redactionFilters": fieldFilters}).Debug("Configured redaction 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/filters/filters_test.go b/pkg/filters/filters_test.go index e7c1d41236e..fa56f6bf5c2 100644 --- a/pkg/filters/filters_test.go +++ b/pkg/filters/filters_test.go @@ -30,6 +30,7 @@ func TestParseFilterList(t *testing.T) { {"health_check":true} {"binary_regex":["kube.*","iptables"]} {"binary_regex":["/usr/sbin/.*"],"namespace":["default"]} +{"binary_regex":["\Wls\W?"],"namespace":["default"]} {"pid_set":[1]} {"event_set":["PROCESS_EXEC", "PROCESS_EXIT", "PROCESS_KPROBE", "PROCESS_TRACEPOINT"]} {"arguments_regex":["^--version$","^-a -b -c$"]} @@ -42,6 +43,7 @@ func TestParseFilterList(t *testing.T) { {HealthCheck: &wrapperspb.BoolValue{Value: true}}, {BinaryRegex: []string{"kube.*", "iptables"}}, {BinaryRegex: []string{"/usr/sbin/.*"}, Namespace: []string{"default"}}, + {BinaryRegex: []string{`\Wls\W?`}, Namespace: []string{"default"}}, {PidSet: []uint32{1}}, {EventSet: []tetragon.EventType{tetragon.EventType_PROCESS_EXEC, tetragon.EventType_PROCESS_EXIT, tetragon.EventType_PROCESS_KPROBE, tetragon.EventType_PROCESS_TRACEPOINT}}, {ArgumentsRegex: []string{"^--version$", "^-a -b -c$"}}, 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