diff --git a/apis/projectcontour/v1/httpproxy.go b/apis/projectcontour/v1/httpproxy.go index 498be837a8b..7159a17a82b 100644 --- a/apis/projectcontour/v1/httpproxy.go +++ b/apis/projectcontour/v1/httpproxy.go @@ -18,6 +18,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// HTTPVersion is an alias to enforce validation +// +kubebuilder:validation:Enum=h2;http/1.1 +type HTTPVersion string + // HTTPProxySpec defines the spec of the CRD. type HTTPProxySpec struct { // Virtualhost appears at most once. If it is present, the object is considered @@ -338,6 +342,11 @@ type VirtualHost struct { // Only one of IPAllowFilterPolicy and IPDenyFilterPolicy can be defined. // The rules defined here may be overridden in a Route. IPDenyFilterPolicy []IPFilterPolicy `json:"ipDenyPolicy,omitempty"` + + // HTTPVersions specify the http versions to offer for this HTTPProxy. + // If empty, the DefaultHTTPVersions from v1alpha1.EnvoyConfig will be used. + // It is ignored when TCPProxy is set. + HTTPVersions []HTTPVersion `json:"httpVersions,omitempty"` } // JWTProvider defines how to verify JWTs on requests. diff --git a/apis/projectcontour/v1/zz_generated.deepcopy.go b/apis/projectcontour/v1/zz_generated.deepcopy.go index 3c3537ef24e..3601556e259 100644 --- a/apis/projectcontour/v1/zz_generated.deepcopy.go +++ b/apis/projectcontour/v1/zz_generated.deepcopy.go @@ -1486,6 +1486,11 @@ func (in *VirtualHost) DeepCopyInto(out *VirtualHost) { *out = make([]IPFilterPolicy, len(*in)) copy(*out, *in) } + if in.HTTPVersions != nil { + in, out := &in.HTTPVersions, &out.HTTPVersions + *out = make([]HTTPVersion, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualHost. diff --git a/changelogs/unreleased/5802-therealak12-small.md b/changelogs/unreleased/5802-therealak12-small.md new file mode 100644 index 00000000000..43fadbe9fbe --- /dev/null +++ b/changelogs/unreleased/5802-therealak12-small.md @@ -0,0 +1 @@ +Adds HTTPVersions field to HTTPProxy spec. The field is used to specify ALPNProtocols on the corresponding tls context. diff --git a/examples/contour/01-crds.yaml b/examples/contour/01-crds.yaml index 98b9fe9cebd..6bfb18bfe34 100644 --- a/examples/contour/01-crds.yaml +++ b/examples/contour/01-crds.yaml @@ -6933,6 +6933,17 @@ spec: to the fqdn. pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + httpVersions: + description: HTTPVersions specify the http versions to offer for + this HTTPProxy. If empty, the DefaultHTTPVersions from v1alpha1.EnvoyConfig + will be used. It is ignored when TCPProxy is set. + items: + description: HTTPVersion is an alias to enforce validation + enum: + - h2 + - http/1.1 + type: string + type: array ipAllowPolicy: description: IPAllowFilterPolicy is a list of ipv4/6 filter rules for which matching requests should be allowed. All other requests diff --git a/examples/render/contour-deployment.yaml b/examples/render/contour-deployment.yaml index 4caa7156abd..b9dc517ec10 100644 --- a/examples/render/contour-deployment.yaml +++ b/examples/render/contour-deployment.yaml @@ -7152,6 +7152,17 @@ spec: to the fqdn. pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + httpVersions: + description: HTTPVersions specify the http versions to offer for + this HTTPProxy. If empty, the DefaultHTTPVersions from v1alpha1.EnvoyConfig + will be used. It is ignored when TCPProxy is set. + items: + description: HTTPVersion is an alias to enforce validation + enum: + - h2 + - http/1.1 + type: string + type: array ipAllowPolicy: description: IPAllowFilterPolicy is a list of ipv4/6 filter rules for which matching requests should be allowed. All other requests diff --git a/examples/render/contour-gateway-provisioner.yaml b/examples/render/contour-gateway-provisioner.yaml index b0097c823ca..99504b985dd 100644 --- a/examples/render/contour-gateway-provisioner.yaml +++ b/examples/render/contour-gateway-provisioner.yaml @@ -6944,6 +6944,17 @@ spec: to the fqdn. pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + httpVersions: + description: HTTPVersions specify the http versions to offer for + this HTTPProxy. If empty, the DefaultHTTPVersions from v1alpha1.EnvoyConfig + will be used. It is ignored when TCPProxy is set. + items: + description: HTTPVersion is an alias to enforce validation + enum: + - h2 + - http/1.1 + type: string + type: array ipAllowPolicy: description: IPAllowFilterPolicy is a list of ipv4/6 filter rules for which matching requests should be allowed. All other requests diff --git a/examples/render/contour-gateway.yaml b/examples/render/contour-gateway.yaml index 9843bce947b..53a22226f90 100644 --- a/examples/render/contour-gateway.yaml +++ b/examples/render/contour-gateway.yaml @@ -7155,6 +7155,17 @@ spec: to the fqdn. pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + httpVersions: + description: HTTPVersions specify the http versions to offer for + this HTTPProxy. If empty, the DefaultHTTPVersions from v1alpha1.EnvoyConfig + will be used. It is ignored when TCPProxy is set. + items: + description: HTTPVersion is an alias to enforce validation + enum: + - h2 + - http/1.1 + type: string + type: array ipAllowPolicy: description: IPAllowFilterPolicy is a list of ipv4/6 filter rules for which matching requests should be allowed. All other requests diff --git a/examples/render/contour.yaml b/examples/render/contour.yaml index f5fdc105ce2..ed32da3acfe 100644 --- a/examples/render/contour.yaml +++ b/examples/render/contour.yaml @@ -7152,6 +7152,17 @@ spec: to the fqdn. pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + httpVersions: + description: HTTPVersions specify the http versions to offer for + this HTTPProxy. If empty, the DefaultHTTPVersions from v1alpha1.EnvoyConfig + will be used. It is ignored when TCPProxy is set. + items: + description: HTTPVersion is an alias to enforce validation + enum: + - h2 + - http/1.1 + type: string + type: array ipAllowPolicy: description: IPAllowFilterPolicy is a list of ipv4/6 filter rules for which matching requests should be allowed. All other requests diff --git a/internal/dag/dag.go b/internal/dag/dag.go index aea888e4b16..fee93ac08fc 100644 --- a/internal/dag/dag.go +++ b/internal/dag/dag.go @@ -793,6 +793,9 @@ type SecureVirtualHost struct { // JWTProviders specify how to verify JWTs. JWTProviders []JWTProvider + + // AlpnProtos specify the HTTP version to offer for this vhost + HTTPVersions []string } type JWTProvider struct { diff --git a/internal/dag/httpproxy_processor.go b/internal/dag/httpproxy_processor.go index 255a1fa0b71..164e3d6189a 100644 --- a/internal/dag/httpproxy_processor.go +++ b/internal/dag/httpproxy_processor.go @@ -263,6 +263,7 @@ func (p *HTTPProxyProcessor) computeHTTPProxy(proxy *contour_api_v1.HTTPProxy) { svhost.Secret = sec svhost.MinTLSVersion = minTLSVer svhost.MaxTLSVersion = maxTLSVer + svhost.HTTPVersions = p.getSortedHTTPVersions(proxy) // Check if FallbackCertificate && ClientValidation are both enabled in the same vhost if tls.EnableFallbackCertificate && tls.ClientValidation != nil { @@ -1473,6 +1474,21 @@ func (p *HTTPProxyProcessor) GlobalAuthorizationContext() map[string]string { return nil } +// getSortedHTTPVersions returns and empty slice or ["h2", "http/1.1"] or ["http/1.1"]. +// This is done to conform with how envoy expects AlpnProtocols in tlsv3.CommonTlsContext. +func (p *HTTPProxyProcessor) getSortedHTTPVersions(proxy *contour_api_v1.HTTPProxy) []string { + proxyHTTPVersions := proxy.Spec.VirtualHost.HTTPVersions + if len(proxyHTTPVersions) == 0 { + return nil + } + for _, httpVersion := range proxyHTTPVersions { + if httpVersion == "h2" { + return []string{"h2", "http/1.1"} + } + } + return []string{"http/1.1"} +} + // expandPrefixMatches adds new Routes to account for the difference // between prefix replacement when matching on '/foo' and '/foo/'. // diff --git a/internal/xdscache/v3/listener.go b/internal/xdscache/v3/listener.go index c9cf6d04aaf..a08651847a4 100644 --- a/internal/xdscache/v3/listener.go +++ b/internal/xdscache/v3/listener.go @@ -502,7 +502,11 @@ func (c *ListenerCache) OnChange(root *dag.DAG) { filters = envoy_v3.Filters(cm) - alpnProtos = envoy_v3.ProtoNamesForVersions(cfg.DefaultHTTPVersions...) + if len(vh.HTTPVersions) != 0 { + alpnProtos = vh.HTTPVersions + } else { + alpnProtos = envoy_v3.ProtoNamesForVersions(cfg.DefaultHTTPVersions...) + } } else { filters = envoy_v3.Filters(envoy_v3.TCPProxy(listener.Name, vh.TCPProxy, cfg.newSecureAccessLog())) diff --git a/site/content/docs/main/config/api-reference.html b/site/content/docs/main/config/api-reference.html index b91773147ef..544cbb6a746 100644 --- a/site/content/docs/main/config/api-reference.html +++ b/site/content/docs/main/config/api-reference.html @@ -1842,6 +1842,15 @@

HTTPStatusRange +

HTTPVersion +(string alias)

+

+(Appears on: +VirtualHost) +

+

+

HTTPVersion is an alias to enforce validation

+

HeaderHashOptions

@@ -4859,6 +4868,22 @@

VirtualHost The rules defined here may be overridden in a Route.

+ + +httpVersions +
+ + +[]HTTPVersion + + + + +

HTTPVersions specify the http versions to offer for this HTTPProxy. +If empty, the DefaultHTTPVersions from v1alpha1.EnvoyConfig will be used. +It is ignored when TCPProxy is set.

+ +