Line data Source code
1 : #pragma once 2 : 3 : #include <string> 4 : #include <tuple> 5 : 6 : #include "envoy/http/header_map.h" 7 : #include "envoy/http/protocol.h" 8 : 9 : namespace Envoy { 10 : namespace Http { 11 : 12 : /** 13 : * Common interface for server and client header validators. 14 : */ 15 : class HeaderValidator { 16 : public: 17 0 : virtual ~HeaderValidator() = default; 18 : 19 : // A class that holds either success condition or an error condition with tuple of 20 : // action and error details. 21 : template <typename ActionType> class Result { 22 : public: 23 : using Action = ActionType; 24 : 25 : // Helper for constructing successful results 26 801 : static Result success() { return Result(ActionType::Accept, absl::string_view()); } 27 : 28 879 : Result(ActionType action, absl::string_view details) : result_(action, details) { 29 879 : ENVOY_BUG(action == ActionType::Accept || !details.empty(), 30 879 : "Error details must not be empty in case of an error"); 31 879 : } 32 : 33 527 : bool ok() const { return std::get<0>(result_) == ActionType::Accept; } 34 373 : operator bool() const { return ok(); } 35 0 : absl::string_view details() const { return std::get<1>(result_); } 36 784 : Action action() const { return std::get<0>(result_); } 37 : 38 : private: 39 : const std::tuple<ActionType, std::string> result_; 40 : }; 41 : 42 : enum class RejectAction { Accept, Reject }; 43 : enum class RejectOrRedirectAction { Accept, Reject, Redirect }; 44 : using RejectResult = Result<RejectAction>; 45 : using RejectOrRedirectResult = Result<RejectOrRedirectAction>; 46 : using TransformationResult = RejectResult; 47 : 48 : /** 49 : * Validate the entire request header map. 50 : * Returning the Reject value form this method causes the HTTP request to be rejected with 400 51 : * status, and the gRPC request with the INTERNAL (13) error code. 52 : */ 53 : using ValidationResult = RejectResult; 54 : virtual ValidationResult validateRequestHeaders(const RequestHeaderMap& header_map) PURE; 55 : 56 : /** 57 : * Validate the entire response header map. 58 : * Returning the Reject value causes the HTTP request to be rejected with the 502 status, 59 : * and the gRPC request with the UNAVAILABLE (14) error code. 60 : */ 61 : virtual ValidationResult validateResponseHeaders(const ResponseHeaderMap& header_map) PURE; 62 : 63 : /** 64 : * Validate the entire request trailer map. 65 : * Returning the Reject value causes the HTTP request to be rejected with the 502 status, 66 : * and the gRPC request with the UNAVAILABLE (14) error code. 67 : * If response headers have already been sent the request is reset. 68 : */ 69 : virtual ValidationResult validateRequestTrailers(const RequestTrailerMap& trailer_map) PURE; 70 : 71 : /** 72 : * Validate the entire response trailer map. 73 : * Returning the Reject value causes the HTTP request to be reset. 74 : */ 75 : virtual ValidationResult validateResponseTrailers(const ResponseTrailerMap& trailer_map) PURE; 76 : }; 77 : 78 : /** 79 : * Interface for server header validators. 80 : */ 81 : class ServerHeaderValidator : public HeaderValidator { 82 : public: 83 0 : ~ServerHeaderValidator() override = default; 84 : 85 : /** 86 : * Transform the entire request header map. 87 : * This method transforms the header map, for example by normalizing URI path, before processing 88 : * by the filter chain. 89 : * Returning the Reject value from this method causes the HTTP request to be rejected with 400 90 : * status, and the gRPC request with the INTERNAL (13) error code. Returning the Redirect 91 : * value causes the HTTP request to be redirected to the :path presudo header in the request map. 92 : * The gRPC request will still be rejected with the INTERNAL (13) error code. 93 : */ 94 : using RequestHeadersTransformationResult = RejectOrRedirectResult; 95 : virtual RequestHeadersTransformationResult 96 : transformRequestHeaders(RequestHeaderMap& header_map) PURE; 97 : 98 : /** 99 : * Transform the entire request trailer map. 100 : * Returning the Reject value causes the HTTP request to be rejected with the 502 status, 101 : * and the gRPC request with the UNAVAILABLE (14) error code. 102 : * If response headers have already been sent the request is reset. 103 : */ 104 : virtual TransformationResult transformRequestTrailers(RequestTrailerMap& header_map) PURE; 105 : 106 : /** 107 : * Transform the entire response header map. 108 : * HTTP/2 and HTTP/3 server header validator may transform the HTTP/1 upgrade response 109 : * to HTTP/2 extended CONNECT response, iff it transformed extended CONNECT to upgrade request 110 : * during request validation. 111 : * Returning the Reject value causes the HTTP request to be rejected with the 502 status, 112 : * and the gRPC request with the UNAVAILABLE (14) error code. 113 : */ 114 : struct ResponseHeadersTransformationResult { 115 0 : static ResponseHeadersTransformationResult success() { 116 0 : return ResponseHeadersTransformationResult{RejectResult::success(), nullptr}; 117 0 : } 118 : RejectResult status; 119 : ResponseHeaderMapPtr new_headers; 120 : }; 121 : virtual ResponseHeadersTransformationResult 122 : transformResponseHeaders(const ResponseHeaderMap& header_map) PURE; 123 : }; 124 : 125 : /** 126 : * Interface for server header validators. 127 : */ 128 : class ClientHeaderValidator : public HeaderValidator { 129 : public: 130 0 : ~ClientHeaderValidator() override = default; 131 : 132 : /** 133 : * Transform the entire request header map. 134 : * This method can not mutate the header map as it is immutable after the terminal decoder filter. 135 : * However HTTP/2 and HTTP/3 header validators may need to change the request from the HTTP/1 136 : * upgrade to to the extended CONNECT. In this case the new header map is returned in the 137 : * `new_headers` member of the returned structure. Returning the Reject value form this method 138 : * causes the HTTP request to be rejected with 400 status, and the gRPC request with the INTERNAL 139 : * (13) error code. 140 : */ 141 : struct RequestHeadersTransformationResult { 142 0 : static RequestHeadersTransformationResult success() { 143 0 : return RequestHeadersTransformationResult{RejectResult::success(), nullptr}; 144 0 : } 145 : RejectResult status; 146 : RequestHeaderMapPtr new_headers; 147 : }; 148 : virtual RequestHeadersTransformationResult 149 : transformRequestHeaders(const RequestHeaderMap& header_map) PURE; 150 : 151 : /** 152 : * Transform the entire response header map. 153 : * HTTP/2 and HTTP/3 client header validator may transform the extended CONNECT response 154 : * to HTTP/1 upgrade response, iff it transformed upgrade request to extended CONNECT 155 : * during request validation. 156 : * Returning the Reject value causes the HTTP request to be rejected with the 502 status, 157 : * and the gRPC request with the UNAVAILABLE (14) error code. 158 : */ 159 : virtual TransformationResult transformResponseHeaders(ResponseHeaderMap& header_map) PURE; 160 : }; 161 : 162 : using ServerHeaderValidatorPtr = std::unique_ptr<ServerHeaderValidator>; 163 : using ClientHeaderValidatorPtr = std::unique_ptr<ClientHeaderValidator>; 164 : 165 : /** 166 : * Interface for stats. 167 : */ 168 : class HeaderValidatorStats { 169 : public: 170 2607 : virtual ~HeaderValidatorStats() = default; 171 : 172 : virtual void incDroppedHeadersWithUnderscores() PURE; 173 : virtual void incRequestsRejectedWithUnderscoresInHeaders() PURE; 174 : virtual void incMessagingError() PURE; 175 : }; 176 : 177 : /** 178 : * Interface for creating header validators. 179 : * TODO(yanavlasov): split into factories dedicated to server and client header validators. 180 : */ 181 : class HeaderValidatorFactory { 182 : public: 183 0 : virtual ~HeaderValidatorFactory() = default; 184 : 185 : /** 186 : * Create a new header validator for the specified protocol. 187 : */ 188 : virtual ServerHeaderValidatorPtr createServerHeaderValidator(Protocol protocol, 189 : HeaderValidatorStats& stats) PURE; 190 : virtual ClientHeaderValidatorPtr createClientHeaderValidator(Protocol protocol, 191 : HeaderValidatorStats& stats) PURE; 192 : }; 193 : 194 : using HeaderValidatorFactoryPtr = std::unique_ptr<HeaderValidatorFactory>; 195 : 196 : } // namespace Http 197 : } // namespace Envoy