Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose fault.http.abort.http_status setting via HTTP header #10294

Merged
merged 43 commits into from
Mar 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ec89763
Start implementation of HTTP abort header
Augustyniak Mar 6, 2020
d9caef6
Fix proto field number
Augustyniak Mar 6, 2020
9b28c7d
Apply patch proposed by tool
Augustyniak Mar 6, 2020
31126b4
Apply patch proposed by the tool
Augustyniak Mar 6, 2020
e1cf997
Add missing switch case and method
Augustyniak Mar 6, 2020
c534968
lint fixes
Augustyniak Mar 6, 2020
386cf81
Start using abort provider in fault_filter
Augustyniak Mar 7, 2020
ec19b1a
Fix formatting
Augustyniak Mar 7, 2020
e8657fe
Rename statusCode to status_code
Augustyniak Mar 7, 2020
49042c3
Rename abort_code to abort
Augustyniak Mar 7, 2020
239c406
Add unit test
Augustyniak Mar 7, 2020
a63b408
Rename AbortCodeRequest to AbortRequest
Augustyniak Mar 7, 2020
d20a624
Add doc string
Augustyniak Mar 7, 2020
bd32f55
Update existing fault_filter_test tests
Augustyniak Mar 8, 2020
e3c7ca6
Add unit test
Augustyniak Mar 8, 2020
3cd511b
Fix format
Augustyniak Mar 8, 2020
a43c6ef
Update header faults integration test
Augustyniak Mar 8, 2020
17ed854
Update existing unit tests
Augustyniak Mar 8, 2020
559465e
Use a different HTTP header name
Augustyniak Mar 8, 2020
93a6332
Update documentation
Augustyniak Mar 8, 2020
3483611
Fix test
Augustyniak Mar 8, 2020
28e4cf8
Fix header name
Augustyniak Mar 8, 2020
ac46ced
Use strongly typed Http::Code instead of int
Augustyniak Mar 9, 2020
58e21f7
Update unit test
Augustyniak Mar 9, 2020
97ab5b3
Update tests
Augustyniak Mar 9, 2020
18f9152
format fix
Augustyniak Mar 9, 2020
f337341
Fix docs
Augustyniak Mar 9, 2020
224fa21
http -> HTTP doc strings update
Augustyniak Mar 9, 2020
109531e
Update autogenerated files
Augustyniak Mar 9, 2020
4ba49b7
status_code -> statusCode rename
Augustyniak Mar 10, 2020
08ecf36
Performance optimalizations
Augustyniak Mar 10, 2020
2228f5f
Update docs
Augustyniak Mar 10, 2020
60abf18
add unit tests and use &&
Augustyniak Mar 10, 2020
87c61e8
Reorder
Augustyniak Mar 10, 2020
7db79dc
Better doc strings
Augustyniak Mar 10, 2020
0c21567
:hammer:
Augustyniak Mar 10, 2020
deec559
Add integration test
Augustyniak Mar 10, 2020
5d62ece
Add const
Augustyniak Mar 10, 2020
1c1420f
Update docs
Augustyniak Mar 10, 2020
e647685
Fix docs
Augustyniak Mar 10, 2020
95941c0
fix focs
Augustyniak Mar 11, 2020
26651ab
Fix docs
Augustyniak Mar 11, 2020
651ba63
:hammer:
Augustyniak Mar 11, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/envoy/config/filter/fault/v2/fault.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ message FaultDelay {
}

// Fault delays are controlled via an HTTP header (if applicable). See the
// :ref:`http fault filter <config_http_filters_fault_injection_http_header>` documentation for
// :ref:`HTTP fault filter <config_http_filters_fault_injection_http_header>` documentation for
// more information.
message HeaderDelay {
}
Expand Down Expand Up @@ -65,7 +65,7 @@ message FaultRateLimit {
}

// Rate limits are controlled via an HTTP header (if applicable). See the
// :ref:`http fault filter <config_http_filters_fault_injection_http_header>` documentation for
// :ref:`HTTP fault filter <config_http_filters_fault_injection_http_header>` documentation for
// more information.
message HeaderLimit {
}
Expand Down
9 changes: 9 additions & 0 deletions api/envoy/config/filter/http/fault/v2/fault.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,22 @@ option (udpa.annotations.file_migrate).move_to_package = "envoy.extensions.filte
// [#extension: envoy.filters.http.fault]

message FaultAbort {
// Fault aborts are controlled via an HTTP header (if applicable). See the
// :ref:`HTTP fault filter <config_http_filters_fault_injection_http_header>` documentation for
// more information.
message HeaderAbort {
}

reserved 1;

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

// HTTP status code to use to abort the HTTP request.
uint32 http_status = 2 [(validate.rules).uint32 = {lt: 600 gte: 200}];

// Fault aborts are controlled via an HTTP header (if applicable).
HeaderAbort header_abort = 4;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call this header_error. The abort is still controlled by the normal mechanisms, it's just the nature of the error is expressed in the header.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can change it but I think that header_abort is a better name because:

  1. header_error can be in theory used to inject status codes such as 200 or 204 that are not errors.
  2. header_abort follows a naming scheme used by header_limit and header_delay fields. header_error would've been a better choice if header_limit was header_kbs and header_delay was header_duration.

Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would be inclined to stick with header_abort for the reasons that @Augustyniak outlines. @htuch WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough.

}

// The percentage of requests/operations/connections that will be aborted with the error code
Expand Down
4 changes: 2 additions & 2 deletions api/envoy/extensions/filters/common/fault/v3/fault.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ message FaultDelay {
}

// Fault delays are controlled via an HTTP header (if applicable). See the
// :ref:`http fault filter <config_http_filters_fault_injection_http_header>` documentation for
// :ref:`HTTP fault filter <config_http_filters_fault_injection_http_header>` documentation for
// more information.
message HeaderDelay {
option (udpa.annotations.versioning).previous_message_type =
Expand Down Expand Up @@ -75,7 +75,7 @@ message FaultRateLimit {
}

// Rate limits are controlled via an HTTP header (if applicable). See the
// :ref:`http fault filter <config_http_filters_fault_injection_http_header>` documentation for
// :ref:`HTTP fault filter <config_http_filters_fault_injection_http_header>` documentation for
// more information.
message HeaderLimit {
option (udpa.annotations.versioning).previous_message_type =
Expand Down
11 changes: 11 additions & 0 deletions api/envoy/extensions/filters/http/fault/v3/fault.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,24 @@ message FaultAbort {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.fault.v2.FaultAbort";

// Fault aborts are controlled via an HTTP header (if applicable). See the
// :ref:`HTTP fault filter <config_http_filters_fault_injection_http_header>` documentation for
// more information.
message HeaderAbort {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.fault.v2.FaultAbort.HeaderAbort";
}

reserved 1;

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

// HTTP status code to use to abort the HTTP request.
uint32 http_status = 2 [(validate.rules).uint32 = {lt: 600 gte: 200}];

// Fault aborts are controlled via an HTTP header (if applicable).
HeaderAbort header_abort = 4;
}

// The percentage of requests/operations/connections that will be aborted with the error code
Expand Down
14 changes: 13 additions & 1 deletion docs/root/configuration/http/http_filters/fault_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,18 @@ The fault filter has the capability to allow fault configuration to be specified
This is useful in certain scenarios in which it is desired to allow the client to specify its own
fault configuration. The currently supported header controls are:

* Request abort configuration via the *x-envoy-fault-abort-request* header. The header value
should be an integer that specifies the HTTP status code to return in response to a request
and must be in the range [200, 600). In order for the header to work, :ref:`header_abort
<envoy_api_field_config.filter.http.fault.v2.FaultAbort.header_abort>` needs to be set.
* Request delay configuration via the *x-envoy-fault-delay-request* header. The header value
should be an integer that specifies the number of milliseconds to throttle the latency for.
In order for the header to work, :ref:`header_delay
<envoy_api_field_config.filter.fault.v2.FaultDelay.header_delay>` needs to be set.
* Response rate limit configuration via the *x-envoy-fault-throughput-response* header. The
header value should be an integer that specified the limit in KiB/s and must be > 0.
header value should be an integer that specified the limit in KiB/s and must be > 0. In order
for the header to work, :ref:`header_limit
<envoy_api_field_config.filter.fault.v2.FaultRateLimit.header_limit>` needs to be set.

.. attention::

Expand All @@ -57,6 +65,10 @@ options:
typed_config:
"@type": type.googleapis.com/envoy.config.filter.http.fault.v2.HTTPFault
max_active_faults: 100
abort:
header_abort: {}
percentage:
numerator: 100
delay:
header_delay: {}
percentage:
Expand Down
1 change: 1 addition & 0 deletions docs/root/intro/version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Version history
of extension names is available in the :ref:`deprecated <deprecated>` documentation.
* ext_authz: disabled the use of lowercase string matcher for headers matching in HTTP-based `ext_authz`.
Can be reverted temporarily by setting runtime feature `envoy.reloadable_features.ext_authz_http_service_enable_case_sensitive_string_matcher` to false.
* fault: added support for controlling abort faults with :ref:`HTTP header fault configuration <config_http_filters_fault_injection_http_header>` to the HTTP fault filter.
* http: added HTTP/1.1 flood protection. Can be temporarily disabled using the runtime feature `envoy.reloadable_features.http1_flood_protection`
* http: fixing a bug in HTTP/1.0 responses where Connection: keep-alive was not appended for connections which were kept alive.
* http: fixed a bug that could send extra METADATA frames and underflow memory when encoding METADATA frames on a connection that was dispatching data.
Expand Down
4 changes: 2 additions & 2 deletions generated_api_shadow/envoy/config/filter/fault/v2/fault.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.

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.

2 changes: 2 additions & 0 deletions source/extensions/filters/common/fault/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ envoy_cc_library(
hdrs = ["fault_config.h"],
deps = [
"//include/envoy/http:header_map_interface",
"//source/common/http:codes_lib",
"//source/common/http:headers_lib",
"//source/common/protobuf:utility_lib",
"@envoy_api//envoy/extensions/filters/common/fault/v3:pkg_cc_proto",
"@envoy_api//envoy/extensions/filters/http/fault/v3:pkg_cc_proto",
"@envoy_api//envoy/type/v3:pkg_cc_proto",
],
)
35 changes: 35 additions & 0 deletions source/extensions/filters/common/fault/fault_config.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "extensions/filters/common/fault/fault_config.h"

#include "envoy/extensions/filters/common/fault/v3/fault.pb.h"
#include "envoy/extensions/filters/http/fault/v3/fault.pb.h"

#include "common/protobuf/utility.h"

Expand All @@ -10,6 +11,40 @@ namespace Filters {
namespace Common {
namespace Fault {

FaultAbortConfig::FaultAbortConfig(
const envoy::extensions::filters::http::fault::v3::FaultAbort& abort_config)
: percentage_(abort_config.percentage()) {
switch (abort_config.error_type_case()) {
case envoy::extensions::filters::http::fault::v3::FaultAbort::ErrorTypeCase::kHttpStatus:
provider_ = std::make_unique<FixedAbortProvider>(abort_config.http_status());
break;
case envoy::extensions::filters::http::fault::v3::FaultAbort::ErrorTypeCase::kHeaderAbort:
provider_ = std::make_unique<HeaderAbortProvider>();
break;
case envoy::extensions::filters::http::fault::v3::FaultAbort::ErrorTypeCase::ERROR_TYPE_NOT_SET:
NOT_REACHED_GCOVR_EXCL_LINE;
}
}

absl::optional<Http::Code>
FaultAbortConfig::HeaderAbortProvider::statusCode(const Http::HeaderEntry* header) const {
absl::optional<Http::Code> ret;
if (header == nullptr) {
return ret;
}

uint64_t code;
if (!absl::SimpleAtoi(header->value().getStringView(), &code)) {
return ret;
}

if (code >= 200 && code < 600) {
ret = static_cast<Http::Code>(code);
}

return ret;
}

FaultDelayConfig::FaultDelayConfig(
const envoy::extensions::filters::common::fault::v3::FaultDelay& delay_config)
: percentage_(delay_config.percentage()) {
Expand Down
52 changes: 52 additions & 0 deletions source/extensions/filters/common/fault/fault_config.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#pragma once

#include "envoy/extensions/filters/common/fault/v3/fault.pb.h"
#include "envoy/extensions/filters/http/fault/v3/fault.pb.h"
#include "envoy/http/header_map.h"
#include "envoy/type/v3/percent.pb.h"

#include "common/http/codes.h"
#include "common/http/headers.h"
#include "common/singleton/const_singleton.h"

Expand All @@ -20,10 +22,60 @@ class HeaderNameValues {
const Http::LowerCaseString DelayRequest{absl::StrCat(prefix(), "-fault-delay-request")};
const Http::LowerCaseString ThroughputResponse{
absl::StrCat(prefix(), "-fault-throughput-response")};
const Http::LowerCaseString AbortRequest{absl::StrCat(prefix(), "-fault-abort-request")};
};

using HeaderNames = ConstSingleton<HeaderNameValues>;

class FaultAbortConfig {
public:
FaultAbortConfig(const envoy::extensions::filters::http::fault::v3::FaultAbort& abort_config);

const envoy::type::v3::FractionalPercent& percentage() const { return percentage_; }
absl::optional<Http::Code> statusCode(const Http::HeaderEntry* header) const {
return provider_->statusCode(header);
}

private:
// Abstract abort provider.
class AbortProvider {
public:
virtual ~AbortProvider() = default;

// Return the HTTP status code to use. Optionally passed an HTTP header that may contain the
// HTTP status code depending on the provider implementation.
virtual absl::optional<Http::Code> statusCode(const Http::HeaderEntry* header) const PURE;
};

// Delay provider that uses a fixed abort status code.
class FixedAbortProvider : public AbortProvider {
public:
FixedAbortProvider(uint64_t status_code) : status_code_(status_code) {}

// AbortProvider
absl::optional<Http::Code> statusCode(const Http::HeaderEntry*) const override {
return static_cast<Http::Code>(status_code_);
}

private:
const uint64_t status_code_;
};

// Abort provider the reads a status code from an HTTP header.
class HeaderAbortProvider : public AbortProvider {
public:
// AbortProvider
absl::optional<Http::Code> statusCode(const Http::HeaderEntry* header) const override;
};

using AbortProviderPtr = std::unique_ptr<AbortProvider>;

AbortProviderPtr provider_;
const envoy::type::v3::FractionalPercent percentage_;
};

using FaultAbortConfigPtr = std::unique_ptr<FaultAbortConfig>;

/**
* Generic configuration for a delay fault.
*/
Expand Down
Loading