Skip to content

Commit c43da05

Browse files
committed
feat: Add comprehensive downstream validation for Envoy
Signed-off-by: Yash Nandwana yashneelam975@gmail.com adding downstream validation for envoy (streamErrorOnInvalidHttpMessage) added to OnChange() for getting loaded during DAG build
1 parent a26ea44 commit c43da05

File tree

11 files changed

+102
-5
lines changed

11 files changed

+102
-5
lines changed

apis/projectcontour/v1alpha1/contourconfig.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,15 @@ type EnvoyListenerConfig struct {
430430
// +kubebuilder:validation:Minimum=1
431431
// +optional
432432
MaxConnectionsPerListener *uint32 `json:"maxConnectionsPerListener,omitempty"`
433+
434+
// StreamErrorOnInvalidHTTP
435+
// If this option is false (default), Envoy will err on the conservative side handling HTTP errors, terminating both
436+
// HTTP/1.1 and HTTP/2 connections when receiving an invalid request. If this option is set to true,
437+
// Envoy will be more permissive, only resetting the invalid stream in the case of HTTP/2 and leaving the
438+
// connection open where possible (if the entire request is read for HTTP/1.1)
439+
//
440+
// +optional
441+
StreamErrorOnInvalidHTTP *bool `json:"streamErrorOnInvalidHTTP,omitempty"`
433442
}
434443

435444
// SocketOptions defines configurable socket options for Envoy listeners.

cmd/contour/serve.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ func (s *Server) doServe() error {
466466
HTTP2MaxConcurrentStreams: contourConfiguration.Envoy.Listener.HTTP2MaxConcurrentStreams,
467467
PerConnectionBufferLimitBytes: contourConfiguration.Envoy.Listener.PerConnectionBufferLimitBytes,
468468
SocketOptions: contourConfiguration.Envoy.Listener.SocketOptions,
469+
StreamErrorOnInvalidHTTP: contourConfiguration.Envoy.Listener.StreamErrorOnInvalidHTTP,
469470
}
470471

471472
if listenerConfig.TracingConfig, err = s.setupTracingService(contourConfiguration.Tracing); err != nil {

cmd/contour/servecontext.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_v1alpha1.Co
557557
MaxRequestsPerIOCycle: ctx.Config.Listener.MaxRequestsPerIOCycle,
558558
HTTP2MaxConcurrentStreams: ctx.Config.Listener.HTTP2MaxConcurrentStreams,
559559
MaxConnectionsPerListener: ctx.Config.Listener.MaxConnectionsPerListener,
560+
StreamErrorOnInvalidHTTP: ctx.Config.Listener.StreamErrorOnInvalidHTTP,
560561
TLS: &contour_v1alpha1.EnvoyTLS{
561562
MinimumProtocolVersion: ctx.Config.TLS.MinimumProtocolVersion,
562563
MaximumProtocolVersion: ctx.Config.TLS.MaximumProtocolVersion,

examples/contour/01-crds.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,12 @@ spec:
339339
format: int32
340340
minimum: 1
341341
type: integer
342+
streamErrorOnInvalidHTTP:
343+
description: |-
344+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
345+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
346+
for more information.
347+
type: boolean
342348
maxRequestsPerConnection:
343349
description: |-
344350
Defines the maximum requests for downstream connections. If not specified, there is no limit.
@@ -4202,6 +4208,12 @@ spec:
42024208
format: int32
42034209
minimum: 1
42044210
type: integer
4211+
streamErrorOnInvalidHTTP:
4212+
description: |-
4213+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
4214+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
4215+
for more information.
4216+
type: boolean
42054217
maxRequestsPerConnection:
42064218
description: |-
42074219
Defines the maximum requests for downstream connections. If not specified, there is no limit.

examples/render/contour-deployment.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,12 @@ spec:
558558
format: int32
559559
minimum: 1
560560
type: integer
561+
streamErrorOnInvalidHTTP:
562+
description: |-
563+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
564+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
565+
for more information.
566+
type: boolean
561567
maxRequestsPerConnection:
562568
description: |-
563569
Defines the maximum requests for downstream connections. If not specified, there is no limit.
@@ -4421,6 +4427,12 @@ spec:
44214427
format: int32
44224428
minimum: 1
44234429
type: integer
4430+
streamErrorOnInvalidHTTP:
4431+
description: |-
4432+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
4433+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
4434+
for more information.
4435+
type: boolean
44244436
maxRequestsPerConnection:
44254437
description: |-
44264438
Defines the maximum requests for downstream connections. If not specified, there is no limit.

examples/render/contour-gateway-provisioner.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,12 @@ spec:
350350
format: int32
351351
minimum: 1
352352
type: integer
353+
streamErrorOnInvalidHTTP:
354+
description: |-
355+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
356+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
357+
for more information.
358+
type: boolean
353359
maxRequestsPerConnection:
354360
description: |-
355361
Defines the maximum requests for downstream connections. If not specified, there is no limit.
@@ -4213,6 +4219,12 @@ spec:
42134219
format: int32
42144220
minimum: 1
42154221
type: integer
4222+
streamErrorOnInvalidHTTP:
4223+
description: |-
4224+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
4225+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
4226+
for more information.
4227+
type: boolean
42164228
maxRequestsPerConnection:
42174229
description: |-
42184230
Defines the maximum requests for downstream connections. If not specified, there is no limit.

examples/render/contour-gateway.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,12 @@ spec:
375375
format: int32
376376
minimum: 1
377377
type: integer
378+
streamErrorOnInvalidHTTP:
379+
description: |-
380+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
381+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
382+
for more information.
383+
type: boolean
378384
maxRequestsPerConnection:
379385
description: |-
380386
Defines the maximum requests for downstream connections. If not specified, there is no limit.
@@ -4238,6 +4244,12 @@ spec:
42384244
format: int32
42394245
minimum: 1
42404246
type: integer
4247+
streamErrorOnInvalidHTTP:
4248+
description: |-
4249+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
4250+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
4251+
for more information.
4252+
type: boolean
42414253
maxRequestsPerConnection:
42424254
description: |-
42434255
Defines the maximum requests for downstream connections. If not specified, there is no limit.

examples/render/contour.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,12 @@ spec:
558558
format: int32
559559
minimum: 1
560560
type: integer
561+
streamErrorOnInvalidHTTP:
562+
description: |-
563+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
564+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
565+
for more information.
566+
type: boolean
561567
maxRequestsPerConnection:
562568
description: |-
563569
Defines the maximum requests for downstream connections. If not specified, there is no limit.
@@ -4421,6 +4427,12 @@ spec:
44214427
format: int32
44224428
minimum: 1
44234429
type: integer
4430+
streamErrorOnInvalidHTTP:
4431+
description: |-
4432+
Defines envoy's behaviour for invalid HTTP response from downstream. Default value is false.
4433+
see https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-error-on-invalid-http-message
4434+
for more information.
4435+
type: boolean
44244436
maxRequestsPerConnection:
44254437
description: |-
44264438
Defines the maximum requests for downstream connections. If not specified, there is no limit.

internal/envoy/v3/listener.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ package v3
1616
import (
1717
"errors"
1818
"fmt"
19-
v1 "github.com/projectcontour/contour/apis/projectcontour/v1"
2019
"sort"
2120
"strings"
2221
"time"
@@ -195,7 +194,7 @@ type httpConnectionManagerBuilder struct {
195194
http2MaxConcurrentStreams *uint32
196195
enableWebsockets bool
197196
compression *contour_v1alpha1.EnvoyCompression
198-
streamErrorForInvalidHttp bool
197+
streamErrorOnInvalidHttp bool
199198
}
200199

201200
func (b *httpConnectionManagerBuilder) EnableWebsockets(enable bool) *httpConnectionManagerBuilder {
@@ -329,6 +328,11 @@ func (b *httpConnectionManagerBuilder) HTTP2MaxConcurrentStreams(http2MaxConcurr
329328
return b
330329
}
331330

331+
func (b *httpConnectionManagerBuilder) StreamErrorOnInvalidHTTP(streamErrorOnInvalidHttp bool) *httpConnectionManagerBuilder {
332+
b.streamErrorOnInvalidHttp = streamErrorOnInvalidHttp
333+
return b
334+
}
335+
332336
func (b *httpConnectionManagerBuilder) DefaultFilters() *httpConnectionManagerBuilder {
333337
// Add a default set of ordered http filters.
334338
// The names are not required to match anything and are
@@ -543,9 +547,11 @@ func (b *httpConnectionManagerBuilder) Get() *envoy_config_listener_v3.Filter {
543547
Tracing: b.tracingConfig,
544548
HttpFilters: b.filters,
545549
CommonHttpProtocolOptions: &envoy_config_core_v3.HttpProtocolOptions{
546-
IdleTimeout: envoy.Timeout(b.connectionIdleTimeout),
547-
DownstreamValidation: wrapperspb.Bool(b.streamErrorForInvalidHttp),
550+
IdleTimeout: envoy.Timeout(b.connectionIdleTimeout),
548551
},
552+
553+
StreamErrorOnInvalidHttpMessage: wrapperspb.Bool(b.streamErrorOnInvalidHttp),
554+
549555
HttpProtocolOptions: &envoy_config_core_v3.Http1ProtocolOptions{
550556
// Enable support for HTTP/1.0 requests that carry
551557
// a Host: header. See #537.

internal/xdscache/v3/listener.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ type ListenerConfig struct {
156156

157157
// SocketOptions configures socket options HTTP and HTTPS listeners.
158158
SocketOptions *contour_v1alpha1.SocketOptions
159+
160+
// StreamErrorOnInvalidHTTP
161+
// If this option is false (default), Envoy will err on the conservative side handling HTTP errors, terminating both
162+
// HTTP/1.1 and HTTP/2 connections when receiving an invalid request. If this option is set to true,
163+
// Envoy will be more permissive, only resetting the invalid stream in the case of HTTP/2 and leaving the
164+
// connection open where possible (if the entire request is read for HTTP/1.1)
165+
StreamErrorOnInvalidHTTP bool
159166
}
160167

161168
type ExtensionServiceConfig struct {
@@ -395,6 +402,7 @@ func (c *ListenerCache) OnChange(root *dag.DAG) {
395402
StripTrailingHostDot(cfg.StripTrailingHostDot).
396403
MaxRequestsPerConnection(cfg.MaxRequestsPerConnection).
397404
HTTP2MaxConcurrentStreams(cfg.HTTP2MaxConcurrentStreams).
405+
StreamErrorOnInvalidHTTP(cfg.StreamErrorOnInvalidHTTP).
398406
AddFilter(httpGlobalExternalAuthConfig(cfg.GlobalExternalAuthConfig)).
399407
Tracing(envoy_v3.TracingConfig(envoyTracingConfig(cfg.TracingConfig))).
400408
AddFilter(envoy_v3.GlobalRateLimitFilter(envoyGlobalRateLimitConfig(cfg.RateLimitConfig))).
@@ -475,6 +483,7 @@ func (c *ListenerCache) OnChange(root *dag.DAG) {
475483
ForwardClientCertificate(forwardClientCertificate).
476484
MaxRequestsPerConnection(cfg.MaxRequestsPerConnection).
477485
HTTP2MaxConcurrentStreams(cfg.HTTP2MaxConcurrentStreams).
486+
StreamErrorOnInvalidHTTP(cfg.StreamErrorOnInvalidHTTP).
478487
EnableWebsockets(listener.EnableWebsockets).
479488
Get()
480489

@@ -558,6 +567,7 @@ func (c *ListenerCache) OnChange(root *dag.DAG) {
558567
ForwardClientCertificate(forwardClientCertificate).
559568
MaxRequestsPerConnection(cfg.MaxRequestsPerConnection).
560569
HTTP2MaxConcurrentStreams(cfg.HTTP2MaxConcurrentStreams).
570+
StreamErrorOnInvalidHTTP(cfg.StreamErrorOnInvalidHTTP).
561571
EnableWebsockets(listener.EnableWebsockets).
562572
Get()
563573

0 commit comments

Comments
 (0)