Skip to content

Commit a857219

Browse files
ramaraochavaliggreenway
authored andcommitted
ratelimit: revert revert rate limit failure mode config and add tests (envoyproxy#4303)
Signed-off-by: Rama <[email protected]>
1 parent 1d34172 commit a857219

File tree

19 files changed

+255
-36
lines changed

19 files changed

+255
-36
lines changed

api/envoy/config/filter/accesslog/v2/accesslog.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,6 @@ message ResponseFlagFilter {
162162
// This field is optional. If it is not specified, then any response flag will pass
163163
// the filter check.
164164
repeated string flags = 1 [(validate.rules).repeated .items.string = {
165-
in: ["LH", "UH", "UT", "LR", "UR", "UF", "UC", "UO", "NR", "DI", "FI", "RL", "UAEX"]
165+
in: ["LH", "UH", "UT", "LR", "UR", "UF", "UC", "UO", "NR", "DI", "FI", "RL", "UAEX", "RLSE"]
166166
}];
167167
}

api/envoy/config/filter/http/rate_limit/v2/rate_limit.proto

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ message RateLimit {
3535
// set, this defaults to 20ms.
3636
google.protobuf.Duration timeout = 4 [(gogoproto.stdduration) = true];
3737

38-
// [#not-implemented-hide:] Hide from docs.
3938
// The filter's behaviour in case the rate limiting service does
4039
// not respond back. When it is set to true, Envoy will not allow traffic in case of
4140
// communication failure between rate limiting service and the proxy.

api/envoy/config/filter/network/rate_limit/v2/rate_limit.proto

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ message RateLimit {
2727
// set, this defaults to 20ms.
2828
google.protobuf.Duration timeout = 4 [(gogoproto.stdduration) = true];
2929

30-
// [#not-implemented-hide:] Hide from docs.
3130
// The filter's behaviour in case the rate limiting service does
3231
// not respond back. When it is set to true, Envoy will not allow traffic in case of
3332
// communication failure between rate limiting service and the proxy.

docs/root/configuration/http_filters/rate_limit_filter.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ apply to a request. Each configuration results in a descriptor being sent to the
1616
If the rate limit service is called, and the response for any of the descriptors is over limit, a
1717
429 response is returned.
1818

19+
If there is an error in calling rate limit service or rate limit service returns an error and :ref:`failure_mode_deny <envoy_api_msg_config.filter.http.rate_limit.v2.RateLimit>` is
20+
set to true, a 500 response is returned.
21+
1922
.. _config_http_filters_rate_limit_composing_actions:
2023

2124
Composing Actions
@@ -108,6 +111,8 @@ The buffer filter outputs statistics in the *cluster.<route target cluster>.rate
108111
ok, Counter, Total under limit responses from the rate limit service
109112
error, Counter, Total errors contacting the rate limit service
110113
over_limit, Counter, total over limit responses from the rate limit service
114+
failure_mode_allowed, Counter, "Total requests that were error(s) but were allowed through because
115+
of :ref:`failure_mode_deny <envoy_api_msg_config.filter.http.rate_limit.v2.RateLimit>` set to false."
111116

112117
Runtime
113118
-------

docs/root/configuration/network_filters/rate_limit_filter.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ following statistics:
2525
ok, Counter, Total under limit responses from the rate limit service
2626
cx_closed, Counter, Total connections closed due to an over limit response from the rate limit service
2727
active, Gauge, Total active requests to the rate limit service
28+
failure_mode_allowed, Counter, "Total requests that were error(s) but were allowed through because
29+
of :ref:`failure_mode_deny <envoy_api_msg_config.filter.http.rate_limit.v2.RateLimit>` set to false."
2830

2931
Runtime
3032
-------

include/envoy/request_info/request_info.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ enum ResponseFlag {
4848
RateLimited = 0x800,
4949
// Request was unauthorized by external authorization service.
5050
UnauthorizedExternalService = 0x1000,
51+
// Unable to call Ratelimit service.
52+
RateLimitServiceError = 0x2000,
5153
// ATTENTION: MAKE SURE THIS REMAINS EQUAL TO THE LAST FLAG.
52-
LastFlag = UnauthorizedExternalService
54+
LastFlag = RateLimitServiceError
5355
};
5456

5557
/**

source/common/request_info/utility.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const std::string ResponseFlagUtils::DELAY_INJECTED = "DI";
1919
const std::string ResponseFlagUtils::FAULT_INJECTED = "FI";
2020
const std::string ResponseFlagUtils::RATE_LIMITED = "RL";
2121
const std::string ResponseFlagUtils::UNAUTHORIZED_EXTERNAL_SERVICE = "UAEX";
22+
const std::string ResponseFlagUtils::RATELIMIT_SERVICE_ERROR = "RLSE";
2223

2324
void ResponseFlagUtils::appendString(std::string& result, const std::string& append) {
2425
if (result.empty()) {
@@ -31,7 +32,7 @@ void ResponseFlagUtils::appendString(std::string& result, const std::string& app
3132
const std::string ResponseFlagUtils::toShortString(const RequestInfo& request_info) {
3233
std::string result;
3334

34-
static_assert(ResponseFlag::LastFlag == 0x1000, "A flag has been added. Fix this code.");
35+
static_assert(ResponseFlag::LastFlag == 0x2000, "A flag has been added. Fix this code.");
3536

3637
if (request_info.hasResponseFlag(ResponseFlag::FailedLocalHealthCheck)) {
3738
appendString(result, FAILED_LOCAL_HEALTH_CHECK);
@@ -85,6 +86,10 @@ const std::string ResponseFlagUtils::toShortString(const RequestInfo& request_in
8586
appendString(result, UNAUTHORIZED_EXTERNAL_SERVICE);
8687
}
8788

89+
if (request_info.hasResponseFlag(ResponseFlag::RateLimitServiceError)) {
90+
appendString(result, RATELIMIT_SERVICE_ERROR);
91+
}
92+
8893
return result.empty() ? NONE : result;
8994
}
9095

@@ -104,6 +109,7 @@ absl::optional<ResponseFlag> ResponseFlagUtils::toResponseFlag(const std::string
104109
{ResponseFlagUtils::FAULT_INJECTED, ResponseFlag::FaultInjected},
105110
{ResponseFlagUtils::RATE_LIMITED, ResponseFlag::RateLimited},
106111
{ResponseFlagUtils::UNAUTHORIZED_EXTERNAL_SERVICE, ResponseFlag::UnauthorizedExternalService},
112+
{ResponseFlagUtils::RATELIMIT_SERVICE_ERROR, ResponseFlag::RateLimitServiceError},
107113
};
108114
const auto& it = map.find(flag);
109115
if (it != map.end()) {

source/common/request_info/utility.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class ResponseFlagUtils {
3434
const static std::string FAULT_INJECTED;
3535
const static std::string RATE_LIMITED;
3636
const static std::string UNAUTHORIZED_EXTERNAL_SERVICE;
37+
const static std::string RATELIMIT_SERVICE_ERROR;
3738
};
3839

3940
/**

source/extensions/access_loggers/http_grpc/grpc_access_log_impl.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void HttpGrpcAccessLog::responseFlagsToAccessLogResponseFlags(
8585
envoy::data::accesslog::v2::AccessLogCommon& common_access_log,
8686
const RequestInfo::RequestInfo& request_info) {
8787

88-
static_assert(RequestInfo::ResponseFlag::LastFlag == 0x1000,
88+
static_assert(RequestInfo::ResponseFlag::LastFlag == 0x2000,
8989
"A flag has been added. Fix this code.");
9090

9191
if (request_info.hasResponseFlag(RequestInfo::ResponseFlag::FailedLocalHealthCheck)) {
@@ -141,6 +141,10 @@ void HttpGrpcAccessLog::responseFlagsToAccessLogResponseFlags(
141141
envoy::data::accesslog::v2::ResponseFlags_Unauthorized_Reason::
142142
ResponseFlags_Unauthorized_Reason_EXTERNAL_SERVICE);
143143
}
144+
145+
if (request_info.hasResponseFlag(RequestInfo::ResponseFlag::RateLimitServiceError)) {
146+
common_access_log.mutable_response_flags()->set_rate_limit_service_error(true);
147+
}
144148
}
145149

146150
void HttpGrpcAccessLog::log(const Http::HeaderMap* request_headers,

source/extensions/filters/http/ratelimit/ratelimit.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,17 @@ void Filter::complete(RateLimit::LimitStatus status, Http::HeaderMapPtr&& header
147147
callbacks_->sendLocalReply(Http::Code::TooManyRequests, "",
148148
[this](Http::HeaderMap& headers) { addHeaders(headers); });
149149
callbacks_->requestInfo().setResponseFlag(RequestInfo::ResponseFlag::RateLimited);
150+
} else if (status == RateLimit::LimitStatus::Error) {
151+
if (config_->failureModeAllow()) {
152+
cluster_->statsScope().counter("ratelimit.failure_mode_allowed").inc();
153+
if (!initiating_call_) {
154+
callbacks_->continueDecoding();
155+
}
156+
} else {
157+
state_ = State::Responded;
158+
callbacks_->sendLocalReply(Http::Code::InternalServerError, "", nullptr);
159+
callbacks_->requestInfo().setResponseFlag(RequestInfo::ResponseFlag::RateLimitServiceError);
160+
}
150161
} else if (!initiating_call_) {
151162
callbacks_->continueDecoding();
152163
}

0 commit comments

Comments
 (0)