Skip to content

Commit

Permalink
Matchers: Add dynamic metadata to the http inputs (envoyproxy#34891)
Browse files Browse the repository at this point in the history
fixes: envoyproxy#34092

---------

Signed-off-by: Vikas Choudhary <[email protected]>
  • Loading branch information
vikaschoudhary16 authored Aug 5, 2024
1 parent 988a6d0 commit 520d88e
Show file tree
Hide file tree
Showing 24 changed files with 599 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,16 @@ extensions/filters/http/oauth2 @derekargueta @mattklein123
/*/extensions/matching/input_matchers/runtime_fraction @ravenblackx @sergkir85
# CEL input matcher
/*/extensions/matching/input_matchers/cel_matcher @tyxia @yanavlasov
# dynamic metadata input matcher
/*/extensions/matching/input_matchers/metadata @vikaschoudhary16 @kyessenov
# environment generic input
/*/extensions/matching/common_inputs/environment @donyu @mattklein123
# format string matching
/*/extensions/matching/actions/format_string @kyessenov @cpakulski
# CEL data input
/*/extensions/matching/http/cel_input @tyxia @yanavlasov
# dynamic metadata input
/*/extensions/matching/http/metadata_input @vikaschoudhary16 @kyessenov
# user space socket pair, event, connection and listener
/*/extensions/io_socket/user_space @kyessenov @lambdai @soulxu
/*/extensions/bootstrap/internal_listener @kyessenov @adisuissa
Expand Down
1 change: 1 addition & 0 deletions api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ proto_library(
"//envoy/extensions/matching/common_inputs/ssl/v3:pkg",
"//envoy/extensions/matching/input_matchers/consistent_hashing/v3:pkg",
"//envoy/extensions/matching/input_matchers/ip/v3:pkg",
"//envoy/extensions/matching/input_matchers/metadata/v3:pkg",
"//envoy/extensions/matching/input_matchers/runtime_fraction/v3:pkg",
"//envoy/extensions/network/dns_resolver/apple/v3:pkg",
"//envoy/extensions/network/dns_resolver/cares/v3:pkg",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,48 @@ message ApplicationProtocolInput {
message FilterStateInput {
string key = 1 [(validate.rules).string = {min_len: 1}];
}

// Input that matches dynamic metadata by key.
// DynamicMetadataInput provides a general interface using ``filter`` and ``path`` to retrieve value from
// :ref:`Metadata <envoy_v3_api_msg_config.core.v3.Metadata>`.
//
// For example, for the following Metadata:
//
// .. code-block:: yaml
//
// filter_metadata:
// envoy.xxx:
// prop:
// foo: bar
// xyz:
// hello: envoy
//
// The following DynamicMetadataInput will retrieve a string value "bar" from the Metadata.
//
// .. code-block:: yaml
//
// filter: envoy.xxx
// path:
// - key: prop
// - key: foo
//
// [#extension: envoy.matching.inputs.dynamic_metadata]
message DynamicMetadataInput {
// Specifies the segment in a path to retrieve value from Metadata.
// Note: Currently it's not supported to retrieve a value from a list in Metadata. This means that
// if the segment key refers to a list, it has to be the last segment in a path.
message PathSegment {
oneof segment {
option (validate.required) = true;

// If specified, use the key to retrieve the value in a Struct.
string key = 1 [(validate.rules).string = {min_len: 1}];
}
}

// The filter name to retrieve the Struct from the Metadata.
string filter = 1 [(validate.rules).string = {min_len: 1}];

// The path to retrieve the Value from the Struct.
repeated PathSegment path = 2 [(validate.rules).repeated = {min_items: 1}];
}
12 changes: 12 additions & 0 deletions api/envoy/extensions/matching/input_matchers/metadata/v3/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = [
"//envoy/type/matcher/v3:pkg",
"@com_github_cncf_xds//udpa/annotations:pkg",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
syntax = "proto3";

package envoy.extensions.matching.input_matchers.metadata.v3;

import "envoy/type/matcher/v3/value.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.matching.input_matchers.metadata.v3";
option java_outer_classname = "MetadataProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/metadata/v3;metadatav3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: metadata matcher]
// [#extension: envoy.matching.matchers.metadata_matcher]

// Metadata matcher for metadata from http matching input data.
message Metadata {
// The Metadata is matched if the value retrieved by metadata matching input is matched to this value.
type.matcher.v3.ValueMatcher value = 1 [(validate.rules).message = {required: true}];

// If true, the match result will be inverted.
bool invert = 4;
}
1 change: 1 addition & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ proto_library(
"//envoy/extensions/matching/common_inputs/ssl/v3:pkg",
"//envoy/extensions/matching/input_matchers/consistent_hashing/v3:pkg",
"//envoy/extensions/matching/input_matchers/ip/v3:pkg",
"//envoy/extensions/matching/input_matchers/metadata/v3:pkg",
"//envoy/extensions/matching/input_matchers/runtime_fraction/v3:pkg",
"//envoy/extensions/network/dns_resolver/apple/v3:pkg",
"//envoy/extensions/network/dns_resolver/cares/v3:pkg",
Expand Down
4 changes: 4 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ new_features:
<envoy_v3_api_field_extensions.transport_sockets.tls.v3.CommonTlsContext.custom_tls_certificate_selector>`
to allow overriding TLS certificate selection behavior.
An extension can select certificate base on the incoming SNI, in both sync and async mode.
- area: matching
change: |
Added dynamic metadata matcher support :ref:`Dynamic metadata input <extension_envoy.matching.inputs.dynamic_metadata>`
and :ref:`Dynamic metadata input matcher <extension_envoy.matching.matchers.metadata_matcher>`.
- area: ratelimit
change: |
Added the ability to modify :ref:`hits_addend <envoy_v3_api_field_service.ratelimit.v3.RateLimitRequest.hits_addend>`
Expand Down
1 change: 1 addition & 0 deletions docs/root/api-v3/common_messages/common_messages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Common messages
../extensions/early_data/v3/default_early_data_policy.proto
../config/core/v3/http_uri.proto
../extensions/matching/input_matchers/ip/v3/ip.proto
../extensions/matching/input_matchers/metadata/v3/metadata.proto
../extensions/matching/input_matchers/runtime_fraction/v3/runtime_fraction.proto
../config/core/v3/address.proto
../config/core/v3/protocol.proto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ These input functions are available for matching HTTP requests:
* :ref:`Response header value <extension_envoy.matching.inputs.response_headers>`.
* :ref:`Response trailer value <extension_envoy.matching.inputs.response_trailers>`.
* :ref:`Query parameters value <extension_envoy.matching.inputs.query_params>`.
* :ref:`Dynamic metadata <extension_envoy.matching.inputs.dynamic_metadata>`.

.. _extension_category_envoy.matching.network.input:

Expand Down
3 changes: 3 additions & 0 deletions envoy/http/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,9 @@ class HttpMatchingData {
virtual const Network::ConnectionInfoProvider& connectionInfoProvider() const PURE;

const StreamInfo::FilterState& filterState() const { return streamInfo().filterState(); }
const envoy::config::core::v3::Metadata& metadata() const {
return streamInfo().dynamicMetadata();
}

const Network::Address::Instance& localAddress() const {
return *connectionInfoProvider().localAddress();
Expand Down
6 changes: 6 additions & 0 deletions source/extensions/extensions_build_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ EXTENSIONS = {
"envoy.matching.matchers.ip": "//source/extensions/matching/input_matchers/ip:config",
"envoy.matching.matchers.runtime_fraction": "//source/extensions/matching/input_matchers/runtime_fraction:config",
"envoy.matching.matchers.cel_matcher": "//source/extensions/matching/input_matchers/cel_matcher:config",
"envoy.matching.matchers.metadata_matcher": "//source/extensions/matching/input_matchers/metadata:config",

#
# Network Matchers
Expand Down Expand Up @@ -109,6 +110,11 @@ EXTENSIONS = {
#
"envoy.matching.inputs.cel_data_input": "//source/extensions/matching/http/cel_input:cel_input_lib",

#
# Dynamic Metadata Matching Input
#
"envoy.matching.inputs.dynamic_metadata": "//source/extensions/matching/http/metadata_input:metadata_input_lib",

#
# Matching actions
#
Expand Down
14 changes: 14 additions & 0 deletions source/extensions/extensions_metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1565,6 +1565,13 @@ envoy.matching.inputs.filter_state:
status: stable
type_urls:
- envoy.extensions.matching.common_inputs.network.v3.FilterStateInput
envoy.matching.inputs.dynamic_metadata:
categories:
- envoy.matching.http.input
security_posture: unknown
status: stable
type_urls:
- envoy.extensions.matching.common_inputs.network.v3.DynamicMetadataInput
envoy.matching.inputs.uri_san:
categories:
- envoy.matching.http.input
Expand Down Expand Up @@ -1597,6 +1604,13 @@ envoy.matching.custom_matchers.trie_matcher:
status: stable
type_urls:
- xds.type.matcher.v3.IPMatcher
envoy.matching.matchers.metadata_matcher:
categories:
- envoy.matching.input_matchers
security_posture: unknown
status: alpha
type_urls:
- envoy.extensions.matching.input_matchers.metadata.v3.Metadata
envoy.load_balancing_policies.least_request:
categories:
- envoy.load_balancing_policies
Expand Down
3 changes: 3 additions & 0 deletions source/extensions/filters/http/rbac/rbac_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ absl::Status ActionValidationVisitor::performDataInputValidation(
{TypeUtil::descriptorFullNameToTypeUrl(
envoy::extensions::matching::common_inputs::ssl::v3::SubjectInput::descriptor()
->full_name())},
{TypeUtil::descriptorFullNameToTypeUrl(envoy::extensions::matching::common_inputs::network::
v3::DynamicMetadataInput::descriptor()
->full_name())},
{TypeUtil::descriptorFullNameToTypeUrl(
xds::type::matcher::v3::HttpAttributesCelMatchInput::descriptor()->full_name())}};
if (allowed_inputs_set.contains(type_url)) {
Expand Down
22 changes: 22 additions & 0 deletions source/extensions/matching/http/metadata_input/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_extension",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_extension(
name = "metadata_input_lib",
srcs = ["meta_input.cc"],
hdrs = ["meta_input.h"],
deps = [
"//envoy/http:filter_interface",
"//envoy/matcher:matcher_interface",
"//envoy/registry",
"//source/common/config:metadata_lib",
"@envoy_api//envoy/extensions/matching/common_inputs/network/v3:pkg_cc_proto",
],
)
20 changes: 20 additions & 0 deletions source/extensions/matching/http/metadata_input/meta_input.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "source/extensions/matching/http/metadata_input/meta_input.h"

#include "envoy/registry/registry.h"

namespace Envoy {
namespace Extensions {
namespace Matching {
namespace Http {
namespace MetadataInput {

class HttpDynamicMetadataInputFactory
: public DynamicMetadataInputBaseFactory<Envoy::Http::HttpMatchingData> {};
REGISTER_FACTORY(HttpDynamicMetadataInputFactory,
Matcher::DataInputFactory<Envoy::Http::HttpMatchingData>);

} // namespace MetadataInput
} // namespace Http
} // namespace Matching
} // namespace Extensions
} // namespace Envoy
82 changes: 82 additions & 0 deletions source/extensions/matching/http/metadata_input/meta_input.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#pragma once

#include "envoy/extensions/matching/common_inputs/network/v3/network_inputs.pb.h"
#include "envoy/extensions/matching/common_inputs/network/v3/network_inputs.pb.validate.h"
#include "envoy/http/filter.h"
#include "envoy/matcher/matcher.h"

#include "source/common/config/metadata.h"

namespace Envoy {
namespace Extensions {
namespace Matching {
namespace Http {
namespace MetadataInput {

class MetadataMatchData : public ::Envoy::Matcher::CustomMatchData {
public:
explicit MetadataMatchData(const ProtobufWkt::Value& value) : value_(value) {}
const ProtobufWkt::Value& value_;
};

template <class MatchingDataType>
class DynamicMetadataInput : public Matcher::DataInput<MatchingDataType> {
public:
DynamicMetadataInput(
const envoy::extensions::matching::common_inputs::network::v3::DynamicMetadataInput&
input_config)
: filter_(input_config.filter()), path_(initializePath(input_config.path())) {}

Matcher::DataInputGetResult get(const MatchingDataType& data) const override {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
std::make_unique<MetadataMatchData>(
Envoy::Config::Metadata::metadataValue(&data.metadata(), filter_, path_))};
}

private:
static std::vector<std::string> initializePath(
const Protobuf::RepeatedPtrField<envoy::extensions::matching::common_inputs::network::v3::
DynamicMetadataInput::PathSegment>& segments) {
std::vector<std::string> path;
for (const auto& seg : segments) {
path.push_back(seg.key());
}
return path;
}

const std::string filter_;
const std::vector<std::string> path_;
};

template <class MatchingDataType>
class DynamicMetadataInputBaseFactory : public Matcher::DataInputFactory<MatchingDataType> {
public:
std::string name() const override { return "envoy.matching.inputs.dynamic_metadata"; }

Matcher::DataInputFactoryCb<MatchingDataType>
createDataInputFactoryCb(const Protobuf::Message& message,
ProtobufMessage::ValidationVisitor& validation_visitor) override {
const auto& typed_config = MessageUtil::downcastAndValidate<
const envoy::extensions::matching::common_inputs::network::v3::DynamicMetadataInput&>(
message, validation_visitor);
auto config_ptr = std::make_shared<
envoy::extensions::matching::common_inputs::network::v3::DynamicMetadataInput>(
typed_config);
return [config_ptr] {
return std::make_unique<DynamicMetadataInput<MatchingDataType>>(*config_ptr);
};
};

ProtobufTypes::MessagePtr createEmptyConfigProto() override {
return std::make_unique<
envoy::extensions::matching::common_inputs::network::v3::DynamicMetadataInput>();
}
};

DECLARE_FACTORY(HttpDymanicMetadataInputFactory);

} // namespace MetadataInput
} // namespace Http
} // namespace Matching
} // namespace Extensions
} // namespace Envoy
36 changes: 36 additions & 0 deletions source/extensions/matching/input_matchers/metadata/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_extension",
"envoy_cc_library",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_library(
name = "metadata_lib",
srcs = ["matcher.cc"],
hdrs = ["matcher.h"],
deps = [
"//envoy/matcher:matcher_interface",
"//source/common/common:matchers_lib",
"//source/extensions/matching/http/metadata_input:metadata_input_lib",
"@envoy_api//envoy/extensions/matching/input_matchers/metadata/v3:pkg_cc_proto",
"@envoy_api//envoy/type/matcher/v3:pkg_cc_proto",
],
)

envoy_cc_extension(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
deps = [
":metadata_lib",
"//envoy/matcher:matcher_interface",
"//envoy/registry",
"//envoy/server:factory_context_interface",
"@envoy_api//envoy/extensions/matching/input_matchers/metadata/v3:pkg_cc_proto",
],
)
Loading

0 comments on commit 520d88e

Please sign in to comment.