diff --git a/.github/workflows/command.yaml b/.github/workflows/command.yaml new file mode 100644 index 00000000000..33b614d4d19 --- /dev/null +++ b/.github/workflows/command.yaml @@ -0,0 +1,41 @@ +name: Return Action on PR Comment + +on: + issue_comment: + types: [created] + +permissions: + contents: read + +jobs: + command: + if: | + ${{ + github.event.issue.pull_request + && github.repository == 'envoyproxy/gateway' + && github.actor != 'repokitteh-read-only[bot]' + && github.actor != 'dependabot[bot]' + }} + name: Retest + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + actions: write + steps: + - uses: envoyproxy/toolshed/gh-actions/github/command@actions-v0.2.18 + name: Parse command from comment + id: command + with: + text: ${{ github.event.comment.body }} + matching: >- + ^/(retest) + + # retest + - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.20 + if: ${{ steps.command.outputs.command == 'retest' }} + with: + token: ${{ secrets.GITHUB_TOKEN }} + comment-id: ${{ github.event.comment.id }} + pr-url: ${{ github.event.issue.pull_request.url }} + app-owner: "github-actions" + args: ${{ steps.command.outputs.args }} diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 0774165e0cb..20c3013dbba 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -56,7 +56,7 @@ jobs: # Upload docs for GitHub Pages - name: Upload GitHub Pages artifact - uses: actions/upload-pages-artifact@v2.0.0 + uses: actions/upload-pages-artifact@v3.0.0 with: # Path of the directory containing the static assets. path: site/public @@ -83,4 +83,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v3.0.1 + uses: actions/deploy-pages@v4.0.2 diff --git a/.github/workflows/retest.yaml b/.github/workflows/retest.yaml deleted file mode 100644 index 21da1529924..00000000000 --- a/.github/workflows/retest.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Return Action on PR Comment - -on: - issue_comment: - types: [created] - -permissions: - contents: read - -jobs: - retest: - if: | - ${{ - github.event.issue.pull_request - && github.repository == 'envoyproxy/gateway' - && github.actor != 'repokitteh-read-only[bot]' - && github.actor != 'dependabot[bot]' - }} - name: Retest - runs-on: ubuntu-22.04 - permissions: - pull-requests: write - actions: write - steps: - - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.17 - with: - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 822433892e4..5b1d7d597a1 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -34,6 +34,7 @@ type ClientTrafficPolicy struct { Status ClientTrafficPolicyStatus `json:"status,omitempty"` } +// +kubebuilder:validation:XValidation:rule="has(self.http3) && has(self.tls) && has(self.tls.alpnProtocols) ? self.tls.alpnProtocols.size() == 0 : true",message="alpn protocols can't be set if HTTP/3 is enabled" // ClientTrafficPolicySpec defines the desired state of ClientTrafficPolicy. type ClientTrafficPolicySpec struct { // +kubebuilder:validation:XValidation:rule="self.group == 'gateway.networking.k8s.io'", message="this policy can only have a targetRef.group of gateway.networking.k8s.io" @@ -52,6 +53,12 @@ type ClientTrafficPolicySpec struct { // // +optional TCPKeepalive *TCPKeepalive `json:"tcpKeepalive,omitempty"` + // SuppressEnvoyHeaders configures the Envoy Router filter to suppress the "x-envoy-' + // headers from both requests and responses. + // By default these headers are added to both requests and responses. + // + // +optional + SuppressEnvoyHeaders *bool `json:"suppressEnvoyHeaders,omitempty"` // EnableProxyProtocol interprets the ProxyProtocol header and adds the // Client Address into the X-Forwarded-For header. // Note Proxy Protocol must be present when this field is set, else the connection @@ -63,6 +70,10 @@ type ClientTrafficPolicySpec struct { // // +optional HTTP3 *HTTP3Settings `json:"http3,omitempty"` + // TLS settings configure TLS termination settings with the downstream client. + // + // +optional + TLS *TLSSettings `json:"tls,omitempty"` } // HTTP3Settings provides HTTP/3 configuration on the listener. diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index 7fa593ef186..3cf1b1ba951 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -117,6 +117,14 @@ type KubernetesPodSpec struct { // HostNetwork, If this is set to true, the pod will use host's network namespace. // +optional HostNetwork bool `json:"hostNetwork,omitempty"` + + // ImagePullSecrets is an optional list of references to secrets + // in the same namespace to use for pulling any of the images used by this PodSpec. + // If specified, these secrets will be passed to individual puller implementations for them to use. + // More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod + // + // +optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` } // KubernetesContainerSpec defines the desired state of the Kubernetes container resource. diff --git a/api/v1alpha1/tls_types.go b/api/v1alpha1/tls_types.go new file mode 100644 index 00000000000..a7d9e859439 --- /dev/null +++ b/api/v1alpha1/tls_types.go @@ -0,0 +1,99 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package v1alpha1 + +// +kubebuilder:validation:XValidation:rule="has(self.minVersion) && self.minVersion == 'v1_3' ? !has(self.ciphers) : true", message="setting ciphers has no effect if the minimum possible TLS version is 1.3" +// +kubebuilder:validation:XValidation:rule="has(self.minVersion) && has(self.maxVersion) ? {\"Auto\":0,\"v1_1\":1,\"v1_2\":2,\"v1_3\":3}[self.minVersion] <= {\"v1_1\":1,\"v1_2\":2,\"v1_3\":3,\"Auto\":4}[self.maxVersion] : !has(self.minVersion) && has(self.maxVersion) ? 2 <= {\"v1_1\":1,\"v1_2\":2,\"v1_3\":3,\"Auto\":4}[self.maxVersion] : true", message="minVersion must be smaller or equal to maxVersion" +type TLSSettings struct { + + // Min specifies the minimal TLS protocol version to allow. + // + // The default is TLS 1.2 if this is not specified. + // +optional + MinVersion *TLSVersion `json:"minVersion,omitempty"` + + // Max specifies the maximal TLS protocol version to allow + // + // The default is TLS 1.3 if this is not specified. + // +optional + MaxVersion *TLSVersion `json:"maxVersion,omitempty"` + + // Ciphers specifies the set of cipher suites supported when + // negotiating TLS 1.0 - 1.2. This setting has no effect for TLS 1.3. + // + // In non-FIPS Envoy Proxy builds the default cipher list is: + // - [ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305] + // - [ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305] + // - ECDHE-ECDSA-AES256-GCM-SHA384 + // - ECDHE-RSA-AES256-GCM-SHA384 + // + // In builds using BoringSSL FIPS the default cipher list is: + // - ECDHE-ECDSA-AES128-GCM-SHA256 + // - ECDHE-RSA-AES128-GCM-SHA256 + // - ECDHE-ECDSA-AES256-GCM-SHA384 + // - ECDHE-RSA-AES256-GCM-SHA384 + // + // +optional + Ciphers []string `json:"ciphers,omitempty"` + + // ECDHCurves specifies the set of supported ECDH curves. + // In non-FIPS Envoy Proxy builds the default curves are: + // - X25519 + // - P-256 + // + // In builds using BoringSSL FIPS the default curve is: + // - P-256 + // + // +optional + ECDHCurves []string `json:"ecdhCurves,omitempty"` + + // SignatureAlgorithms specifies which signature algorithms the listener should + // support. + // + // +optional + SignatureAlgorithms []string `json:"signatureAlgorithms,omitempty"` + + // ALPNProtocols supplies the list of ALPN protocols that should be + // exposed by the listener. By default http/2 and http/1.1 are enabled. + // + // Supported values are: + // - http/1.0 + // - http/1.1 + // - http/2 + // + // +optional + ALPNProtocols []ALPNProtocol `json:"alpnProtocols,omitempty"` +} + +// ALPNProtocol specifies the protocol to be negotiated using ALPN +// +kubebuilder:validation:Enum=http/1.0;http/1.1;http/2 +type ALPNProtocol string + +const ( + // HTTPProtocolVersion1_0 specifies that HTTP/1.0 should be negotiable with ALPN + HTTPProtocolVersion1_0 ALPNProtocol = "http/1.0" + // HTTPProtocolVersion1_1 specifies that HTTP/1.1 should be negotiable with ALPN + HTTPProtocolVersion1_1 ALPNProtocol = "http/1.1" + // HTTPProtocolVersion2 specifies that HTTP/2 should be negotiable with ALPN + HTTPProtocolVersion2 ALPNProtocol = "http/2" +) + +// TLSVersion specifies the TLS version +// +kubebuilder:validation:Enum=Auto;v1_0;v1_1;v1_2;v1_3 +type TLSVersion string + +const ( + // TLSAuto allows Envoy to choose the optimal TLS Version + TLSAuto TLSVersion = "Auto" + // TLSv1_0 specifies TLS version 1.0 + TLSv10 TLSVersion = "v1_0" + // TLSv1_1 specifies TLS version 1.1 + TLSv11 TLSVersion = "v1_1" + // TLSv1.2 specifies TLS version 1.2 + TLSv12 TLSVersion = "v1_2" + // TLSv1.3 specifies TLS version 1.3 + TLSv13 TLSVersion = "v1_3" +) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 87bc434fbb2..7dd724536bd 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -321,6 +321,11 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { *out = new(TCPKeepalive) (*in).DeepCopyInto(*out) } + if in.SuppressEnvoyHeaders != nil { + in, out := &in.SuppressEnvoyHeaders, &out.SuppressEnvoyHeaders + *out = new(bool) + **out = **in + } if in.EnableProxyProtocol != nil { in, out := &in.EnableProxyProtocol, &out.EnableProxyProtocol *out = new(bool) @@ -331,6 +336,11 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { *out = new(HTTP3Settings) **out = **in } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLSSettings) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTrafficPolicySpec. @@ -1657,6 +1667,11 @@ func (in *KubernetesPodSpec) DeepCopyInto(out *KubernetesPodSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]corev1.LocalObjectReference, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesPodSpec. @@ -2576,6 +2591,51 @@ func (in *TCPKeepalive) DeepCopy() *TCPKeepalive { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSSettings) DeepCopyInto(out *TLSSettings) { + *out = *in + if in.MinVersion != nil { + in, out := &in.MinVersion, &out.MinVersion + *out = new(TLSVersion) + **out = **in + } + if in.MaxVersion != nil { + in, out := &in.MaxVersion, &out.MaxVersion + *out = new(TLSVersion) + **out = **in + } + if in.Ciphers != nil { + in, out := &in.Ciphers, &out.Ciphers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ECDHCurves != nil { + in, out := &in.ECDHCurves, &out.ECDHCurves + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.SignatureAlgorithms != nil { + in, out := &in.SignatureAlgorithms, &out.SignatureAlgorithms + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ALPNProtocols != nil { + in, out := &in.ALPNProtocols, &out.ALPNProtocols + *out = make([]ALPNProtocol, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSettings. +func (in *TLSSettings) DeepCopy() *TLSSettings { + if in == nil { + return nil + } + out := new(TLSSettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TracingProvider) DeepCopyInto(out *TracingProvider) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index 5bb4fe6274d..23cee2ea799 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -53,6 +53,11 @@ spec: http3: description: HTTP3 provides HTTP/3 configuration on the listener. type: object + suppressEnvoyHeaders: + description: SuppressEnvoyHeaders configures the Envoy Router filter + to suppress the "x-envoy-' headers from both requests and responses. + By default these headers are added to both requests and responses. + type: boolean targetRef: description: TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the @@ -131,9 +136,89 @@ spec: format: int32 type: integer type: object + tls: + description: TLS settings configure TLS termination settings with + the downstream client. + properties: + alpnProtocols: + description: "ALPNProtocols supplies the list of ALPN protocols + that should be exposed by the listener. By default http/2 and + http/1.1 are enabled. \n Supported values are: - http/1.0 - + http/1.1 - http/2" + items: + description: ALPNProtocol specifies the protocol to be negotiated + using ALPN + enum: + - http/1.0 + - http/1.1 + - http/2 + type: string + type: array + ciphers: + description: "Ciphers specifies the set of cipher suites supported + when negotiating TLS 1.0 - 1.2. This setting has no effect for + TLS 1.3. \n In non-FIPS Envoy Proxy builds the default cipher + list is: - [ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305] + - [ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305] + - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 + \n In builds using BoringSSL FIPS the default cipher list is: + - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384" + items: + type: string + type: array + ecdhCurves: + description: "ECDHCurves specifies the set of supported ECDH curves. + In non-FIPS Envoy Proxy builds the default curves are: - X25519 + - P-256 \n In builds using BoringSSL FIPS the default curve + is: - P-256" + items: + type: string + type: array + maxVersion: + description: "Max specifies the maximal TLS protocol version to + allow \n The default is TLS 1.3 if this is not specified." + enum: + - Auto + - v1_0 + - v1_1 + - v1_2 + - v1_3 + type: string + minVersion: + description: "Min specifies the minimal TLS protocol version to + allow. \n The default is TLS 1.2 if this is not specified." + enum: + - Auto + - v1_0 + - v1_1 + - v1_2 + - v1_3 + type: string + signatureAlgorithms: + description: SignatureAlgorithms specifies which signature algorithms + the listener should support. + items: + type: string + type: array + type: object + x-kubernetes-validations: + - message: setting ciphers has no effect if the minimum possible TLS + version is 1.3 + rule: 'has(self.minVersion) && self.minVersion == ''v1_3'' ? !has(self.ciphers) + : true' + - message: minVersion must be smaller or equal to maxVersion + rule: 'has(self.minVersion) && has(self.maxVersion) ? {"Auto":0,"v1_1":1,"v1_2":2,"v1_3":3}[self.minVersion] + <= {"v1_1":1,"v1_2":2,"v1_3":3,"Auto":4}[self.maxVersion] : !has(self.minVersion) + && has(self.maxVersion) ? 2 <= {"v1_1":1,"v1_2":2,"v1_3":3,"Auto":4}[self.maxVersion] + : true' required: - targetRef type: object + x-kubernetes-validations: + - message: alpn protocols can't be set if HTTP/3 is enabled + rule: 'has(self.http3) && has(self.tls) && has(self.tls.alpnProtocols) + ? self.tls.alpnProtocols.size() == 0 : true' status: description: Status defines the current status of ClientTrafficPolicy. properties: diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index 11c48953e58..073dfcf4dfb 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -3260,6 +3260,27 @@ spec: description: HostNetwork, If this is set to true, the pod will use host's network namespace. type: boolean + imagePullSecrets: + description: 'ImagePullSecrets is an optional list + of references to secrets in the same namespace to + use for pulling any of the images used by this PodSpec. + If specified, these secrets will be passed to individual + puller implementations for them to use. More info: + https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod' + items: + description: LocalObjectReference contains enough + information to let you locate the referenced object + inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array labels: additionalProperties: type: string diff --git a/go.mod b/go.mod index 851d33e3e3d..896a1490d09 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 github.com/evanphx/json-patch/v5 v5.7.0 github.com/go-logfmt/logfmt v0.6.0 - github.com/go-logr/logr v1.3.0 + github.com/go-logr/logr v1.4.1 github.com/go-logr/zapr v1.3.0 github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.5.3 @@ -33,8 +33,8 @@ require ( go.opentelemetry.io/proto/otlp v1.0.0 go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d - google.golang.org/grpc v1.60.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.29.0 k8s.io/apiextensions-apiserver v0.29.0 diff --git a/go.sum b/go.sum index 86b524028af..e5df45d9faa 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,9 @@ github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= @@ -687,8 +688,8 @@ google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= -google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -700,8 +701,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 13bdd90e5a0..9f00272a630 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -291,6 +291,10 @@ func (t *Translator) translateClientTrafficPolicyForListener(policySpec *egv1a1. // Translate Proxy Protocol translateListenerProxyProtocol(policySpec.EnableProxyProtocol, httpIR) + + // Translate Suppress Envoy Headers + translateListenerSuppressEnvoyHeaders(policySpec.SuppressEnvoyHeaders, httpIR) + // enable http3 if set and TLS is enabled if httpIR.TLS != nil && policySpec.HTTP3 != nil { httpIR.HTTP3 = &ir.HTTP3Settings{} @@ -349,3 +353,9 @@ func translateListenerProxyProtocol(enableProxyProtocol *bool, httpIR *ir.HTTPLi httpIR.EnableProxyProtocol = true } } + +func translateListenerSuppressEnvoyHeaders(suppressEnvoyHeaders *bool, httpIR *ir.HTTPListener) { + if suppressEnvoyHeaders != nil { + httpIR.SuppressEnvoyHeaders = *suppressEnvoyHeaders + } +} diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.in.yaml new file mode 100644 index 00000000000..dead8c186b9 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.in.yaml @@ -0,0 +1,35 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1-section-http-1 + spec: + suppressEnvoyHeaders: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + sectionName: http-1 + namespace: envoy-gateway +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same + - name: http-2 + protocol: HTTP + port: 8080 + allowedRoutes: + namespaces: + from: Same diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.out.yaml new file mode 100755 index 00000000000..fc3e1cb3727 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.out.yaml @@ -0,0 +1,134 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1-section-http-1 + namespace: envoy-gateway + spec: + suppressEnvoyHeaders: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-1 + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 80 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8080 + protocol: HTTP + status: + listeners: + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10080 + name: http-1 + protocol: HTTP + servicePort: 80 + - address: null + name: envoy-gateway/gateway-1/http-2 + ports: + - containerPort: 8080 + name: http-2 + protocol: HTTP + servicePort: 8080 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-1 + port: 10080 + suppressEnvoyHeaders: true + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-2 + port: 8080 diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider.go b/internal/infrastructure/kubernetes/proxy/resource_provider.go index 3c7958b62ed..6e9cfda8d09 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider.go @@ -239,6 +239,7 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { Affinity: deploymentConfig.Pod.Affinity, Tolerations: deploymentConfig.Pod.Tolerations, Volumes: expectedDeploymentVolumes(r.infra.Name, deploymentConfig), + ImagePullSecrets: deploymentConfig.Pod.ImagePullSecrets, }, }, RevisionHistoryLimit: ptr.To[int32](10), diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go index 8444993ec40..e23db7fe1b6 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go @@ -375,6 +375,22 @@ func TestDeployment(t *testing.T) { }, }, }, + { + caseName: "with-image-pull-secrets", + infra: newTestInfra(), + deploy: &egv1a1.KubernetesDeploymentSpec{ + Pod: &egv1a1.KubernetesPodSpec{ + ImagePullSecrets: []corev1.LocalObjectReference{ + { + Name: "aaa", + }, + { + Name: "bbb", + }, + }, + }, + }, + }, } for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml new file mode 100644 index 00000000000..aaa51a879fa --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml @@ -0,0 +1,202 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + name: envoy-default-37a8eec1 + namespace: envoy-gateway-system +spec: + replicas: 1 + strategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + template: + metadata: + labels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + spec: + automountServiceAccountToken: false + containers: + - args: + - --service-cluster default + - --service-node $(ENVOY_POD_NAME) + - | + --config-yaml admin: + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: /dev/null + address: + socket_address: + address: 127.0.0.1 + port_value: 19000 + dynamic_resources: + ads_config: + api_type: DELTA_GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + lds_config: + ads: {} + resource_api_version: V3 + cds_config: + ads: {} + resource_api_version: V3 + static_resources: + listeners: + - name: envoy-gateway-proxy-ready-0.0.0.0-19001 + address: + socket_address: + address: 0.0.0.0 + port_value: 19001 + protocol: TCP + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: eg-ready-http + route_config: + name: local_route + http_filters: + - name: envoy.filters.http.health_check + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck + pass_through_mode: false + headers: + - name: ":path" + string_match: + exact: /ready + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + clusters: + - connect_timeout: 10s + load_assignment: + cluster_name: xds_cluster + endpoints: + - load_balancing_weight: 1 + lb_endpoints: + - load_balancing_weight: 1 + endpoint: + address: + socket_address: + address: envoy-gateway + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + explicit_http_config: + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s + name: xds_cluster + type: STRICT_DNS + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + tls_certificate_sds_secret_configs: + - name: xds_certificate + sds_config: + path_config_source: + path: "/sds/xds-certificate.json" + resource_api_version: V3 + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + path_config_source: + path: "/sds/xds-trusted-ca.json" + resource_api_version: V3 + - --log-level warn + - --cpuset-threads + command: + - envoy + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/envoy-dev:latest + imagePullPolicy: IfNotPresent + name: envoy + ports: + - containerPort: 8080 + name: EnvoyH-d76a15e2 + protocol: TCP + - containerPort: 8443 + name: EnvoyH-6658f727 + protocol: TCP + resources: + requests: + cpu: 100m + memory: 512Mi + readinessProbe: + httpGet: + path: /ready + port: 19001 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /certs + name: certs + readOnly: true + - mountPath: /sds + name: sds + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: envoy-default-37a8eec1 + terminationGracePeriodSeconds: 300 + imagePullSecrets: + - name: aaa + - name: bbb + volumes: + - name: certs + secret: + secretName: envoy + defaultMode: 420 + - configMap: + defaultMode: 420 + items: + - key: xds-trusted-ca.json + path: xds-trusted-ca.json + - key: xds-certificate.json + path: xds-certificate.json + name: envoy-default-37a8eec1 + optional: false + name: sds + revisionHistoryLimit: 10 + progressDeadlineSeconds: 600 diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_provider.go b/internal/infrastructure/kubernetes/ratelimit/resource_provider.go index 244b4f6b5bc..ad9d572c491 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource_provider.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource_provider.go @@ -182,6 +182,7 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { Volumes: expectedDeploymentVolumes(r.rateLimit, r.rateLimitDeployment), Affinity: r.rateLimitDeployment.Pod.Affinity, Tolerations: r.rateLimitDeployment.Pod.Tolerations, + ImagePullSecrets: r.rateLimitDeployment.Pod.ImagePullSecrets, }, }, RevisionHistoryLimit: ptr.To[int32](10), diff --git a/internal/ir/xds.go b/internal/ir/xds.go index ea45bc11744..54403633764 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -188,6 +188,9 @@ type HTTPListener struct { IsHTTP2 bool `json:"isHTTP2" yaml:"isHTTP2"` // TCPKeepalive configuration for the listener TCPKeepalive *TCPKeepalive `json:"tcpKeepalive,omitempty" yaml:"tcpKeepalive,omitempty"` + // SuppressEnvoyHeaders controls if "x-envoy-" headers are suppressed by the HTTP Router filter + // Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/router/v3/router.proto#extensions-filters-http-router-v3-router + SuppressEnvoyHeaders bool `json:"suppressEnvoyHeaders,omitempty" yaml:"suppressEnvoyHeaders,omitempty"` // EnableProxyProtocol enables the listener to interpret proxy protocol header EnableProxyProtocol bool `json:"enableProxyProtocol,omitempty" yaml:"enableProxyProtocol,omitempty"` // HTTP3 provides HTTP/3 configuration on the listener. diff --git a/internal/xds/filters/wellknown.go b/internal/xds/filters/wellknown.go index 3a14e093ec8..3ac7861edab 100644 --- a/internal/xds/filters/wellknown.go +++ b/internal/xds/filters/wellknown.go @@ -34,10 +34,15 @@ var ( }), }, } - HTTPRouter = &hcm.HttpFilter{ +) + +func GenerateRouterFilter(suppressEnvoyHeaders bool) *hcm.HttpFilter { + return &hcm.HttpFilter{ Name: wellknown.Router, ConfigType: &hcm.HttpFilter_TypedConfig{ - TypedConfig: protocov.ToAny(&httprouter.Router{}), + TypedConfig: protocov.ToAny(&httprouter.Router{ + SuppressEnvoyHeaders: suppressEnvoyHeaders, + }), }, } -) +} diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index 8bea1b0e99a..a6fc2c4bf63 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -166,7 +166,7 @@ func (t *Translator) patchHCMWithFilters( t.patchHCMWithRateLimit(mgr, irListener) // Add the router filter - mgr.HttpFilters = append(mgr.HttpFilters, filters.HTTPRouter) + mgr.HttpFilters = append(mgr.HttpFilters, filters.GenerateRouterFilter(irListener.SuppressEnvoyHeaders)) // Sort the filters in the correct order. mgr.HttpFilters = sortHTTPFilters(mgr.HttpFilters) diff --git a/internal/xds/translator/testdata/in/xds-ir/suppress-envoy-headers.yaml b/internal/xds/translator/testdata/in/xds-ir/suppress-envoy-headers.yaml new file mode 100644 index 00000000000..248a13a2ecd --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/suppress-envoy-headers.yaml @@ -0,0 +1,25 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "foo.com" + tls: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + suppressEnvoyHeaders: true + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.clusters.yaml new file mode 100644 index 00000000000..c8692b81602 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.clusters.yaml @@ -0,0 +1,14 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml new file mode 100644 index 00000000000..d6373f2d41b --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml @@ -0,0 +1,58 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + filterChains: + - filterChainMatch: + serverNames: + - foo.com + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + statPrefix: https + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + listenerFilters: + - name: envoy.filters.listener.tls_inspector + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.routes.yaml new file mode 100644 index 00000000000..2734c7cc42a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.routes.yaml @@ -0,0 +1,12 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/translator_test.go b/internal/xds/translator/translator_test.go index 80e6ca91432..1a040da62c8 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -221,6 +221,9 @@ func TestTranslateXds(t *testing.T) { { name: "circuit-breaker", }, + { + name: "suppress-envoy-headers", + }, } for _, tc := range testCases { diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 42ee35e2921..8f382fa2b11 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -27,6 +27,17 @@ API group. +#### ALPNProtocol + +_Underlying type:_ `string` + +ALPNProtocol specifies the protocol to be negotiated using ALPN + +_Appears in:_ +- [TLSSettings](#tlssettings) + + + #### BackendTrafficPolicy @@ -205,8 +216,10 @@ _Appears in:_ | --- | --- | | `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. TargetRef | | `tcpKeepalive` _[TCPKeepalive](#tcpkeepalive)_ | TcpKeepalive settings associated with the downstream client connection. If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives. Disabled by default. | +| `suppressEnvoyHeaders` _boolean_ | SuppressEnvoyHeaders configures the Envoy Router filter to suppress the "x-envoy-' headers from both requests and responses. By default these headers are added to both requests and responses. | | `enableProxyProtocol` _boolean_ | EnableProxyProtocol interprets the ProxyProtocol header and adds the Client Address into the X-Forwarded-For header. Note Proxy Protocol must be present when this field is set, else the connection is closed. | | `http3` _[HTTP3Settings](#http3settings)_ | HTTP3 provides HTTP/3 configuration on the listener. | +| `tls` _[TLSSettings](#tlssettings)_ | TLS settings configure TLS termination settings with the downstream client. | @@ -1089,6 +1102,7 @@ _Appears in:_ | `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#toleration-v1-core) array_ | If specified, the pod's tolerations. | | `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volume-v1-core) array_ | Volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes | | `hostNetwork` _boolean_ | HostNetwork, If this is set to true, the pod will use host's network namespace. | +| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#localobjectreference-v1-core) array_ | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod | #### KubernetesServiceSpec @@ -1854,6 +1868,42 @@ _Appears in:_ | `interval` _Duration_ | The duration between keep-alive probes. Defaults to `75s`. | +#### TLSSettings + + + + + +_Appears in:_ +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Description | +| --- | --- | +| `minVersion` _[TLSVersion](#tlsversion)_ | Min specifies the minimal TLS protocol version to allow. + The default is TLS 1.2 if this is not specified. | +| `maxVersion` _[TLSVersion](#tlsversion)_ | Max specifies the maximal TLS protocol version to allow + The default is TLS 1.3 if this is not specified. | +| `ciphers` _string array_ | Ciphers specifies the set of cipher suites supported when negotiating TLS 1.0 - 1.2. This setting has no effect for TLS 1.3. + In non-FIPS Envoy Proxy builds the default cipher list is: - [ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305] - [ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305] - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 + In builds using BoringSSL FIPS the default cipher list is: - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 | +| `ecdhCurves` _string array_ | ECDHCurves specifies the set of supported ECDH curves. In non-FIPS Envoy Proxy builds the default curves are: - X25519 - P-256 + In builds using BoringSSL FIPS the default curve is: - P-256 | +| `signatureAlgorithms` _string array_ | SignatureAlgorithms specifies which signature algorithms the listener should support. | +| `alpnProtocols` _[ALPNProtocol](#alpnprotocol) array_ | ALPNProtocols supplies the list of ALPN protocols that should be exposed by the listener. By default http/2 and http/1.1 are enabled. + Supported values are: - http/1.0 - http/1.1 - http/2 | + + +#### TLSVersion + +_Underlying type:_ `string` + +TLSVersion specifies the TLS version + +_Appears in:_ +- [TLSSettings](#tlssettings) + + + #### TracingProvider diff --git a/site/content/en/latest/user/rate-limit.md b/site/content/en/latest/user/global-rate-limit.md similarity index 95% rename from site/content/en/latest/user/rate-limit.md rename to site/content/en/latest/user/global-rate-limit.md index f74fbc4f6a2..1c44b356b13 100644 --- a/site/content/en/latest/user/rate-limit.md +++ b/site/content/en/latest/user/global-rate-limit.md @@ -1,5 +1,5 @@ --- -title: "Rate Limit" +title: "Global Rate Limit" --- Rate limit is a feature that allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. @@ -10,13 +10,19 @@ Here are some reasons why you may want to implement Rate limits * To prevent applications and its resources (such as a database) from getting overloaded. * To create API limits based on user entitlements. -Envoy Gateway supports [Global rate limiting][], where the rate limit is common across all the instances of Envoy proxies where its applied -i.e. if the data plane has 2 replicas of Envoy running, and the rate limit is 10 requests/second, this limit is common and will be hit +Envoy Gateway supports two types of rate limiting: [Global rate limiting][] and [Local rate limiting][]. + +[Global rate limiting][] applies a shared rate limit to the traffic flowing through all the instances of Envoy proxies where it is configured. +i.e. if the data plane has 2 replicas of Envoy running, and the rate limit is 10 requests/second, this limit is shared and will be hit if 5 requests pass through the first replica and 5 requests pass through the second replica within the same second. Envoy Gateway introduces a new CRD called [BackendTrafficPolicy][] that allows the user to describe their rate limit intent. This instantiated resource can be linked to a [Gateway][], [HTTPRoute][] or [GRPCRoute][] resource. +**Note:** Limit is applied per route. Even if a [BackendTrafficPolicy][] targets a gateway, each route in that gateway +still has a separate rate limit bucket. For example, if a gateway has 2 routes, and the limit is 100r/s, then each route +has its own 100r/s rate limit bucket. + ## Prerequisites ### Install Envoy Gateway @@ -192,7 +198,7 @@ Get the Gateway's address: export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Lets query `ratelimit.example/get` 4 times. We should receive a `200` response from the example Gateway for the first 3 requests +Let's query `ratelimit.example/get` 4 times. We should receive a `200` response from the example Gateway for the first 3 requests and then receive a `429` status code for the 4th request since the limit is set at 3 requests/Hour for the request which contains the header `x-user-id` and value `one`. @@ -818,7 +824,8 @@ kubectl rollout restart deployment envoy-gateway -n envoy-gateway-system ``` [Global Rate Limiting]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/other_features/global_rate_limiting -[BackendTrafficPolicy]: https://gateway.envoyproxy.io/latest/api/extension_types.html#backendtrafficpolicy +[Local rate limiting]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/other_features/local_rate_limiting +[BackendTrafficPolicy]: ../../api/extension_types#backendtrafficpolicy [Envoy Ratelimit]: https://github.com/envoyproxy/ratelimit [EnvoyGateway]: https://gateway.envoyproxy.io/latest/api/config_types.html#envoygateway [Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway/ diff --git a/site/content/en/latest/user/local-rate-limit.md b/site/content/en/latest/user/local-rate-limit.md new file mode 100644 index 00000000000..633d198015e --- /dev/null +++ b/site/content/en/latest/user/local-rate-limit.md @@ -0,0 +1,282 @@ +--- +title: "Local Rate Limit" +--- + +Rate limit is a feature that allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. + +Here are some reasons why you may want to implement Rate limits + +* To prevent malicious activity such as DDoS attacks. +* To prevent applications and its resources (such as a database) from getting overloaded. +* To create API limits based on user entitlements. + +Envoy Gateway supports two types of rate limiting: [Global rate limiting][] and [Local rate limiting][]. + +[Local rate limiting][] applies rate limits to the traffic flowing through a single instance of Envoy proxy. This means +that if the data plane has 2 replicas of Envoy running, and the rate limit is 10 requests/second, each replica will allow +10 requests/second. This is in contrast to [Global Rate Limiting][] which applies rate limits to the traffic flowing through +all instances of Envoy proxy. + +Envoy Gateway introduces a new CRD called [BackendTrafficPolicy][] that allows the user to describe their rate limit intent. +This instantiated resource can be linked to a [Gateway][], [HTTPRoute][] or [GRPCRoute][] resource. + +**Note:** Limit is applied per route. Even if a [BackendTrafficPolicy][] targets a gateway, each route in that gateway +still has a separate rate limit bucket. For example, if a gateway has 2 routes, and the limit is 100r/s, then each route +has its own 100r/s rate limit bucket. + +## Prerequisites + +### Install Envoy Gateway + +* Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the HTTPRoute example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +## Rate Limit Specific User + +Here is an example of a rate limit implemented by the application developer to limit a specific user by matching on a custom `x-user-id` header +with a value set to `one`. + +```shell +cat <