Cont. - Add Proto Message Extraction http filter (#35689)

The Proto Message Extraction Filter supports extracting gRPC
requests/responses (proto messages) as `google.protobuf.Struct` and
storing results in the dynamic metadata
`envoy.filters.http.proto_message_scrubbing` for later access.

---------

Signed-off-by: dchakarwarti@google.com <dchakarwarti@google.com>

Mirrored from https://github.com/envoyproxy/envoy @ 16759b97e02131cc9c8ca64d13cf663c75dae047
main
update-envoy[bot] 3 months ago
parent 536d5aae98
commit 396df43f17
  1. 2
      BUILD
  2. 0
      envoy/extensions/filters/http/proto_message_extraction/v3/BUILD
  3. 148
      envoy/extensions/filters/http/proto_message_extraction/v3/config.proto
  4. 2
      versioning/BUILD

@ -200,7 +200,7 @@ proto_library(
"//envoy/extensions/filters/http/oauth2/v3:pkg", "//envoy/extensions/filters/http/oauth2/v3:pkg",
"//envoy/extensions/filters/http/on_demand/v3:pkg", "//envoy/extensions/filters/http/on_demand/v3:pkg",
"//envoy/extensions/filters/http/original_src/v3:pkg", "//envoy/extensions/filters/http/original_src/v3:pkg",
"//envoy/extensions/filters/http/proto_message_logging/v3:pkg", "//envoy/extensions/filters/http/proto_message_extraction/v3:pkg",
"//envoy/extensions/filters/http/rate_limit_quota/v3:pkg", "//envoy/extensions/filters/http/rate_limit_quota/v3:pkg",
"//envoy/extensions/filters/http/ratelimit/v3:pkg", "//envoy/extensions/filters/http/ratelimit/v3:pkg",
"//envoy/extensions/filters/http/rbac/v3:pkg", "//envoy/extensions/filters/http/rbac/v3:pkg",

@ -1,6 +1,6 @@
syntax = "proto3"; syntax = "proto3";
package envoy.extensions.filters.http.proto_message_logging.v3; package envoy.extensions.filters.http.proto_message_extraction.v3;
import "envoy/config/core/v3/base.proto"; import "envoy/config/core/v3/base.proto";
@ -8,33 +8,39 @@ import "xds/annotations/v3/status.proto";
import "udpa/annotations/status.proto"; import "udpa/annotations/status.proto";
option java_package = "io.envoyproxy.envoy.extensions.filters.http.proto_message_logging.v3"; option java_package = "io.envoyproxy.envoy.extensions.filters.http.proto_message_extraction.v3";
option java_outer_classname = "ConfigProto"; option java_outer_classname = "ConfigProto";
option java_multiple_files = true; option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/proto_message_logging/v3;proto_message_loggingv3"; option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/proto_message_extraction/v3;proto_message_extractionv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE; option (udpa.annotations.file_status).package_version_status = ACTIVE;
option (xds.annotations.v3.file_status).work_in_progress = true; option (xds.annotations.v3.file_status).work_in_progress = true;
// [#not-implemented-hide:] // [#protodoc-title: Proto Message Extraction]
// [#protodoc-title: Proto Message Logging]
// Proto Message Logging :ref:`configuration overview
// <config_http_filters_proto_message_logging>`.
// [#extension: envoy.filters.http.proto_message_logging]
// //
// ProtoMessageLogging filter supports logging scrubbed gRPC requests/responses(proto messages) // [#extension: envoy.filters.http.proto_message_extraction]
// as google.protobuf.Struct and storing results //
// in the dynamic metadata `envoy.filters.http.proto_message_logging` for later access. // Overview
// --------
//
// ProtoMessageExtraction filter supports extracting gRPC
// requests/responses(proto messages) into google.protobuf.Struct and storing
// results in the dynamic metadata `envoy.filters.http.proto_message_extraction`
// for later access.
//
// Assumptions
// -----------
// //
// # Assumptions
// This filter assumes it is only applicable for gRPC with Protobuf as payload. // This filter assumes it is only applicable for gRPC with Protobuf as payload.
// //
// # Process Flow // Process Flow
// ------------
//
// On the request path, it will check // On the request path, it will check
// //
// 1. if the incoming gRPC request is configured, the filter tries to: // 1. if the incoming gRPC request is configured, the filter tries to:
// //
// a. buffer the incoming data to complete protobuf messages // a. buffer the incoming data to complete protobuf messages
// b. log individual protobuf messages according to directives // b. extract individual protobuf messages according to directives
// c. write the result into the dynamic metadata. // c. write the result into the dynamic metadata.
// d. pass through the request data // d. pass through the request data
// //
@ -45,50 +51,57 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
// 1. if the incoming gRPC request is configured, the filter tries to: // 1. if the incoming gRPC request is configured, the filter tries to:
// //
// a. buffer the incoming data to complete protobuf messages // a. buffer the incoming data to complete protobuf messages
// b. log individual protobuf messages according to directives // b. extract individual protobuf messages according to directives
// c. write the result into the dynamic metadata. // c. write the result into the dynamic metadata.
// d. pass through the response data // d. pass through the response data
// //
// 2. otherwise, pass through the response. // 2. otherwise, pass through the response.
// //
// # Config Requirements // Config Requirements
// -------------------
// Here are config requirements // Here are config requirements
//
// 1. the log target field should be among the following primitive types: `string`, `uint32`, `uint64`, `int32`, `int64`, `sint32`, `sint64`, `fixed32`, `fixed64`, `sfixed32`, `sfixed64`, `float`, `double`. // 1. the extracted target field should be among the following primitive types:
// // `string`, `uint32`, `uint64`, `int32`, `int64`, `sint32`, `sint64`,
// `fixed32`, `fixed64`, `sfixed32`, `sfixed64`, `float`, `double`.
// 2. the target field could be repeated. // 2. the target field could be repeated.
//
// 3. the intermediate type could also be repeated. // 3. the intermediate type could also be repeated.
//
// # Output Format // Output Format
// The logged requests and responses will be will be added in the dynamic ``metadata<google.protobuf.Struct>`` with the same layout of the message. // -------------
//
// The extracted requests and responses will be will be added in the dynamic
// ``metadata<google.protobuf.Struct>`` with the same layout of the message.
// For the default `FIRST_AND_LAST` mode, it will be like: // For the default `FIRST_AND_LAST` mode, it will be like:
// .. code-block:: json
// { // {
// "requests":{ // "requests":{
// "first":{ // "first":{
// "foo": "val_foo1", // "foo": "val_foo1",
// ...
// } // }
// "last":{ // "last":{
// "foo": "val_foo3", // "foo": "val_foo3",
// ...
// } // }
// }, // },
// "responses":{ // "responses":{
// "first":{ // "first":{
// "baz": "val_baz1", // "baz": "val_baz1",
// ...
// } // }
// "last":{ // "last":{
// "baz": "val_foo3", // "baz": "val_foo3",
// ...
// } // }
// } // }
// } // }
// Example for `FIRST_AND_LAST` mode
// ---------------------------------
// //
//
// # Example for `FIRST_AND_LAST` mode
// Let's say we have the following definition for the bi-streaming request // Let's say we have the following definition for the bi-streaming request
// `pkg.svc.Method`. // `pkg.svc.Method`.
// //
@ -111,7 +124,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
// //
// message Msg { // message Msg {
// string bar = 1; // string bar = 1;
// string not_logged = 2; // string not_extracted = 2;
// } // }
// //
// This is the filter config in JSON. // This is the filter config in JSON.
@ -121,15 +134,15 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
// { // {
// "descriptor_set":{}, // "descriptor_set":{},
// "mode": "FIRST_AND_LAST", // "mode": "FIRST_AND_LAST",
// "logging_by_method":{ // "extraction_by_method":{
// "pkg.svc.Method":{ // "pkg.svc.Method":{
// "request_logging_by_field":{ // "request_extraction_by_field":{
// "foo":"LOG", // "foo":"EXTRACT",
// "nested.doubled_nested.bar":"LOG", // "nested.doubled_nested.bar":"EXTRACT",
// "redacted":"LOG_REDACT" // "redacted":"EXTRACT_REDACT"
// }, // },
// "response_logging_by_field":{ // "response_extraction_by_field":{
// "bar":"LOG", // "bar":"EXTRACT",
// } // }
// } // }
// } // }
@ -142,18 +155,18 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
// //
// { // {
// "foo": "val_foo1", // "foo": "val_foo1",
// "nested": { "double_nested": {"bar": "val_bar1", "not_logged": "val_not_logged1"}, // "nested": { "double_nested": {"bar": "val_bar1", "not_extracted":
// "redacted": { "bar": "val_redacted_bar1"} // "val_not_extracted1"}, "redacted": { "bar": "val_redacted_bar1"}
// } // }
// { // {
// "foo": "val_foo2", // "foo": "val_foo2",
// "nested": { "double_nested": {"bar": "val_bar2", "not_logged": "val_not_logged2"}, // "nested": { "double_nested": {"bar": "val_bar2", "not_extracted":
// "redacted": { "bar": "val_redacted_bar2"} // "val_not_extracted2"}, "redacted": { "bar": "val_redacted_bar2"}
// } // }
// { // {
// "foo": "val_foo3", // "foo": "val_foo3",
// "nested": { "double_nested": {"bar": "val_bar3", "not_logged": "val_not_logged3"}, // "nested": { "double_nested": {"bar": "val_bar3", "not_extracted":
// "redacted": { "bar": "val_redacted_bar3"} // "val_not_extracted3"}, "redacted": { "bar": "val_redacted_bar3"}
// } // }
// //
// the filter receives the following `MethodResponse` message in // the filter receives the following `MethodResponse` message in
@ -172,7 +185,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
// } // }
// //
// The filter will write the following dynamic // The filter will write the following dynamic
// metadata(`envoy.filters.http.proto_message_logging`) in JSON. // metadata(`envoy.filters.http.proto_message_extraction`) in JSON.
// //
// .. code-block:: json // .. code-block:: json
// //
@ -199,11 +212,11 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
// } // }
// } // }
message ProtoMessageLoggingConfig { message ProtoMessageExtractionConfig {
enum LogMode { enum ExtractMode {
LogMode_UNSPECIFIED = 0; ExtractMode_UNSPECIFIED = 0;
// The filter will log the first and the last message for // The filter will extract the first and the last message for
// for streaming cases, containing // for streaming cases, containing
// client-side streaming, server-side streaming or bi-directional streaming. // client-side streaming, server-side streaming or bi-directional streaming.
FIRST_AND_LAST = 1; FIRST_AND_LAST = 1;
@ -216,40 +229,41 @@ message ProtoMessageLoggingConfig {
config.core.v3.DataSource data_source = 1; config.core.v3.DataSource data_source = 1;
// Unimplemented, the key of proto descriptor TypedMetadata. // Unimplemented, the key of proto descriptor TypedMetadata.
// Among filters depending on the proto descriptor, we can have a TypedMetadata // Among filters depending on the proto descriptor, we can have a
// for proto descriptors, so that these filters can share one copy of proto // TypedMetadata for proto descriptors, so that these filters can share one
// descriptor in memory. // copy of proto descriptor in memory.
string proto_descriptor_typed_metadata = 2; string proto_descriptor_typed_metadata = 2;
} }
LogMode mode = 3; ExtractMode mode = 3;
// Specify the message logging info. // Specify the message extraction info.
// The key is the fully qualified gRPC method name. // The key is the fully qualified gRPC method name.
// ``${package}.${Service}.${Method}``, like // ``${package}.${Service}.${Method}``, like
// ``endpoints.examples.bookstore.BookStore.GetShelf`` // ``endpoints.examples.bookstore.BookStore.GetShelf``
// //
// The value is the message logging information for individual gRPC methods. // The value is the message extraction information for individual gRPC
map<string, MethodLogging> logging_by_method = 4; // methods.
map<string, MethodExtraction> extraction_by_method = 4;
} }
// This message can be used to support per route config approach later even // This message can be used to support per route config approach later even
// though the Istio doesn't support that so far. // though the Istio doesn't support that so far.
message MethodLogging { message MethodExtraction {
enum LogDirective { enum ExtractDirective {
LogDirective_UNSPECIFIED = 0; ExtractDirective_UNSPECIFIED = 0;
// The value of this field will be logged. // The value of this field will be extracted.
LOG = 1; EXTRACT = 1;
// It should be only annotated on Message type fields so if the field isn't // It should be only annotated on Message type fields so if the field isn't
// empty, an empty Struct will be logged. // empty, an empty Struct will be extracted.
LOG_REDACT = 2; EXTRACT_REDACT = 2;
} }
// The mapping of field path to its LogDirective for request messages // The mapping of field path to its ExtractDirective for request messages
map<string, LogDirective> request_logging_by_field = 2; map<string, ExtractDirective> request_extraction_by_field = 2;
// The mapping of field path to its LogDirective for response messages // The mapping of field path to its ExtractDirective for response messages
map<string, LogDirective> response_logging_by_field = 3; map<string, ExtractDirective> response_extraction_by_field = 3;
} }

@ -138,7 +138,7 @@ proto_library(
"//envoy/extensions/filters/http/oauth2/v3:pkg", "//envoy/extensions/filters/http/oauth2/v3:pkg",
"//envoy/extensions/filters/http/on_demand/v3:pkg", "//envoy/extensions/filters/http/on_demand/v3:pkg",
"//envoy/extensions/filters/http/original_src/v3:pkg", "//envoy/extensions/filters/http/original_src/v3:pkg",
"//envoy/extensions/filters/http/proto_message_logging/v3:pkg", "//envoy/extensions/filters/http/proto_message_extraction/v3:pkg",
"//envoy/extensions/filters/http/rate_limit_quota/v3:pkg", "//envoy/extensions/filters/http/rate_limit_quota/v3:pkg",
"//envoy/extensions/filters/http/ratelimit/v3:pkg", "//envoy/extensions/filters/http/ratelimit/v3:pkg",
"//envoy/extensions/filters/http/rbac/v3:pkg", "//envoy/extensions/filters/http/rbac/v3:pkg",

Loading…
Cancel
Save