Skip to content

Commit

Permalink
ratelimit: add route entry metadata to ratelimit actions (#13269)
Browse files Browse the repository at this point in the history
Modifies ratelimit filter to be able to use information
from the route's filter metadata as one of its actions

Signed-off-by: András Czigány <andras.czigany@strivacity.com>
  • Loading branch information
andrascz authored Oct 16, 2020
1 parent 0d15fee commit 06813b2
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 41 deletions.
48 changes: 44 additions & 4 deletions api/envoy/config/route/v3/route_components.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1510,7 +1510,7 @@ message VirtualCluster {
message RateLimit {
option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RateLimit";

// [#next-free-field: 8]
// [#next-free-field: 9]
message Action {
option (udpa.annotations.versioning).previous_message_type =
"envoy.api.v2.route.RateLimit.Action";
Expand Down Expand Up @@ -1627,11 +1627,15 @@ message RateLimit {
repeated HeaderMatcher headers = 3 [(validate.rules).repeated = {min_items: 1}];
}

// The following descriptor entry is appended when the dynamic metadata contains a key value:
// The following descriptor entry is appended when the
// :ref:`dynamic metadata <well_known_dynamic_metadata>` contains a key value:
//
// .. code-block:: cpp
//
// ("<descriptor_key>", "<value_queried_from_metadata>")
// ("<descriptor_key>", "<value_queried_from_dynamic_metadata>")
//
// .. attention::
// This action has been deprecated in favor of the :ref:`metadata <envoy_api_msg_config.route.v3.RateLimit.Action.MetaData>` action
message DynamicMetaData {
// The key to use in the descriptor entry.
string descriptor_key = 1 [(validate.rules).string = {min_len: 1}];
Expand All @@ -1645,6 +1649,35 @@ message RateLimit {
string default_value = 3;
}

// The following descriptor entry is appended when the metadata contains a key value:
//
// .. code-block:: cpp
//
// ("<descriptor_key>", "<value_queried_from_metadata>")
message MetaData {
enum Source {
// Query :ref:`dynamic metadata <well_known_dynamic_metadata>`
DYNAMIC = 0;

// Query :ref:`route entry metadata <envoy_api_field_config.route.v3.Route.metadata>`
ROUTE_ENTRY = 1;
}

// The key to use in the descriptor entry.
string descriptor_key = 1 [(validate.rules).string = {min_len: 1}];

// Metadata struct that defines the key and path to retrieve the string value. A match will
// only happen if the value in the metadata is of type string.
type.metadata.v3.MetadataKey metadata_key = 2 [(validate.rules).message = {required: true}];

// An optional value to use if *metadata_key* is empty. If not set and
// no value is present under the metadata_key then no descriptor is generated.
string default_value = 3;

// Source of metadata
Source source = 4 [(validate.rules).enum = {defined_only: true}];
}

oneof action_specifier {
option (validate.required) = true;

Expand All @@ -1667,7 +1700,14 @@ message RateLimit {
HeaderValueMatch header_value_match = 6;

// Rate limit on dynamic metadata.
DynamicMetaData dynamic_metadata = 7;
//
// .. attention::
// This field has been deprecated in favor of the :ref:`metadata <envoy_api_field_config.route.v3.RateLimit.Action.metadata>` field
DynamicMetaData dynamic_metadata = 7
[deprecated = true, (envoy.annotations.disallowed_by_default) = true];

// Rate limit on metadata.
MetaData metadata = 8;
}
}

Expand Down
50 changes: 45 additions & 5 deletions api/envoy/config/route/v4alpha/route_components.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ New Features
* hds: added support for delta updates in the :ref:`HealthCheckSpecifier <envoy_v3_api_msg_service.health.v3.HealthCheckSpecifier>`, making only the Endpoints and Health Checkers that changed be reconstructed on receiving a new message, rather than the entire HDS.
* health_check: added option to use :ref:`no_traffic_healthy_interval <envoy_v3_api_field_config.core.v3.HealthCheck.no_traffic_healthy_interval>` which allows a different no traffic interval when the host is healthy.
* mongo_proxy: the list of commands to produce metrics for is now :ref:`configurable <envoy_v3_api_field_extensions.filters.network.mongo_proxy.v3.MongoProxy.commands>`.
* ratelimit: added support for use of various :ref:`metadata <envoy_v3_api_field_config.route.v3.RateLimit.Action.metadata>` as a ratelimit action.
* ratelimit: added :ref:`disable_x_envoy_ratelimited_header <envoy_v3_api_msg_extensions.filters.http.ratelimit.v3.RateLimit>` option to disable `X-Envoy-RateLimited` header.
* tcp: added a new :ref:`envoy.overload_actions.reject_incoming_connections <config_overload_manager_overload_actions>` action to reject incoming TCP connections.

Deprecated
----------
* ratelimit: the :ref:`dynamic metadata <envoy_v3_api_field_config.route.v3.RateLimit.Action.dynamic_metadata>` action is deprecated in favor of the more generic :ref:`metadata <envoy_v3_api_field_config.route.v3.RateLimit.Action.metadata>` action.
48 changes: 44 additions & 4 deletions generated_api_shadow/envoy/config/route/v3/route_components.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 31 additions & 10 deletions source/common/router/router_ratelimit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,40 @@ bool GenericKeyAction::populateDescriptor(const Router::RouteEntry&,
return true;
}

DynamicMetaDataAction::DynamicMetaDataAction(
MetaDataAction::MetaDataAction(const envoy::config::route::v3::RateLimit::Action::MetaData& action)
: metadata_key_(action.metadata_key()), descriptor_key_(action.descriptor_key()),
default_value_(action.default_value()), source_(action.source()) {}

MetaDataAction::MetaDataAction(
const envoy::config::route::v3::RateLimit::Action::DynamicMetaData& action)
: metadata_key_(action.metadata_key()), descriptor_key_(action.descriptor_key()),
default_value_(action.default_value()) {}
default_value_(action.default_value()),
source_(envoy::config::route::v3::RateLimit::Action::MetaData::DYNAMIC) {}

bool DynamicMetaDataAction::populateDescriptor(
const Router::RouteEntry&, RateLimit::Descriptor& descriptor, const std::string&,
bool MetaDataAction::populateDescriptor(
const Router::RouteEntry& route, RateLimit::Descriptor& descriptor, const std::string&,
const Http::HeaderMap&, const Network::Address::Instance&,
const envoy::config::core::v3::Metadata* dynamic_metadata) const {
const ProtobufWkt::Value& metadata_value =
Envoy::Config::Metadata::metadataValue(dynamic_metadata, metadata_key_);
const envoy::config::core::v3::Metadata* metadata_source;

switch (source_) {
case envoy::config::route::v3::RateLimit::Action::MetaData::DYNAMIC:
metadata_source = dynamic_metadata;
break;
case envoy::config::route::v3::RateLimit::Action::MetaData::ROUTE_ENTRY:
metadata_source = &route.metadata();
break;
default:
NOT_REACHED_GCOVR_EXCL_LINE;
}

const std::string metadata_string_value =
Envoy::Config::Metadata::metadataValue(metadata_source, metadata_key_).string_value();

if (!metadata_value.string_value().empty()) {
descriptor.entries_.push_back({descriptor_key_, metadata_value.string_value()});
if (!metadata_string_value.empty()) {
descriptor.entries_.push_back({descriptor_key_, metadata_string_value});
return true;
} else if (metadata_value.string_value().empty() && !default_value_.empty()) {
} else if (metadata_string_value.empty() && !default_value_.empty()) {
descriptor.entries_.push_back({descriptor_key_, default_value_});
return true;
}
Expand Down Expand Up @@ -166,7 +184,10 @@ RateLimitPolicyEntryImpl::RateLimitPolicyEntryImpl(
actions_.emplace_back(new GenericKeyAction(action.generic_key()));
break;
case envoy::config::route::v3::RateLimit::Action::ActionSpecifierCase::kDynamicMetadata:
actions_.emplace_back(new DynamicMetaDataAction(action.dynamic_metadata()));
actions_.emplace_back(new MetaDataAction(action.dynamic_metadata()));
break;
case envoy::config::route::v3::RateLimit::Action::ActionSpecifierCase::kMetadata:
actions_.emplace_back(new MetaDataAction(action.metadata()));
break;
case envoy::config::route::v3::RateLimit::Action::ActionSpecifierCase::kHeaderValueMatch:
actions_.emplace_back(new HeaderValueMatchAction(action.header_value_match()));
Expand Down
Loading

0 comments on commit 06813b2

Please sign in to comment.