diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index f6030a45325..66bf96ebd77 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -20,32 +20,32 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - # Generate the install manifests first so it can checked + # Generate the installation manifests first, so it can check # for errors while running `make -k lint` - - run: make generate-manifests + - run: IMAGE_PULL_POLICY=Always make generate-manifests - run: make lint-deps - run: make -k lint gen-check: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - run: make -k gen-check license-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - run: make -k licensecheck coverage-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps # test @@ -63,14 +63,14 @@ jobs: runs-on: ubuntu-latest needs: [lint, gen-check, license-check, coverage-test] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Build EG Multiarch Binaries run: make build-multiarch PLATFORMS="linux_amd64 linux_arm64" - name: Upload EG Binaries - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: envoy-gateway path: bin/ @@ -82,11 +82,11 @@ jobs: matrix: version: [ v1.26.14, v1.27.11, v1.28.7, v1.29.2 ] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: name: envoy-gateway path: bin/ @@ -110,11 +110,11 @@ jobs: matrix: version: [ v1.26.14, v1.27.11, v1.28.7, v1.29.2 ] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: name: envoy-gateway path: bin/ @@ -135,11 +135,11 @@ jobs: runs-on: ubuntu-latest needs: [conformance-test, e2e-test] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: name: envoy-gateway path: bin/ @@ -174,4 +174,5 @@ jobs: - name: Build and Push EG Latest Helm Chart if: github.event_name == 'push' && github.ref == 'refs/heads/main' # use `0.0.0` as the default latest version. - run: OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=v0.0.0-latest TAG=latest make helm-package helm-push + # use `Always` image pull policy for latest version. + run: IMAGE_PULL_POLICY=Always OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=v0.0.0-latest TAG=latest make helm-package helm-push diff --git a/.github/workflows/cherrypick.yaml b/.github/workflows/cherrypick.yaml index d2e84d765ae..bda95da1b33 100644 --- a/.github/workflows/cherrypick.yaml +++ b/.github/workflows/cherrypick.yaml @@ -18,7 +18,7 @@ jobs: if: ${{ contains(github.event.pull_request.labels.*.name, 'cherrypick/release-v1.0') && github.event.pull_request.merged == true }} steps: - name: Checkout - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Cherry pick into release/v1.0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 340072d7949..bc69c913007 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,18 +32,18 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Initialize CodeQL - uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index fa5fbb46597..28ec10e0b6b 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Check out code - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: ref: ${{ github.event.pull_request.head.sha }} @@ -48,7 +48,7 @@ jobs: contents: write steps: - name: Git checkout - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: submodules: true ref: ${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/experimental_conformance.yaml b/.github/workflows/experimental_conformance.yaml index 508f7b5898e..c7f00139f2c 100644 --- a/.github/workflows/experimental_conformance.yaml +++ b/.github/workflows/experimental_conformance.yaml @@ -20,7 +20,7 @@ jobs: matrix: version: [ v1.26.14, v1.27.11, v1.28.7, v1.29.2 ] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps # gateway api experimental conformance @@ -32,7 +32,7 @@ jobs: run: make experimental-conformance - name: Upload Conformance Report - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: conformance-report-k8s-${{ matrix.version }} path: ./test/conformance/conformance-report-k8s-${{ matrix.version }}.yaml diff --git a/.github/workflows/latest_release.yaml b/.github/workflows/latest_release.yaml index aba8b07712f..9a3f8b46803 100644 --- a/.github/workflows/latest_release.yaml +++ b/.github/workflows/latest_release.yaml @@ -22,11 +22,12 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Generate Release Manifests - run: make generate-manifests IMAGE=envoyproxy/gateway-dev TAG=latest OUTPUT_DIR=release-artifacts + # Use `Always` image pull policy for latest version. + run: IMAGE_PULL_POLICY=Always make generate-manifests IMAGE=envoyproxy/gateway-dev TAG=latest OUTPUT_DIR=release-artifacts - name: Build egctl latest multiarch binaries run: | diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4f22eedb8ee..f69ef41648e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,7 +15,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Extract Release Tag and Commit SHA id: vars @@ -34,10 +34,10 @@ jobs: skopeo copy --all docker://docker.io/envoyproxy/gateway-dev:${{ env.sha_short }} docker://docker.io/envoyproxy/gateway:${{ env.release_tag }} - name: Generate Release Artifacts - run: make generate-artifacts IMAGE=envoyproxy/gateway TAG=${{ env.release_tag }} OUTPUT_DIR=release-artifacts + run: IMAGE_PULL_POLICY=IfNotPresent make generate-artifacts IMAGE=envoyproxy/gateway TAG=${{ env.release_tag }} OUTPUT_DIR=release-artifacts - name: Build and Push EG Release Helm Chart - run: OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=${{ env.release_tag }} IMAGE=docker.io/envoyproxy/gateway TAG=${{ env.release_tag }} make helm-package helm-push + run: IMAGE_PULL_POLICY=IfNotPresent OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=${{ env.release_tag }} IMAGE=docker.io/envoyproxy/gateway TAG=${{ env.release_tag }} make helm-package helm-push - name: Upload Release Manifests uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v0.1.15 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index dad78e90189..77c1a3dcb03 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -21,7 +21,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: persist-credentials: false @@ -33,13 +33,13 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: SARIF file path: results.sarif retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: results.sarif diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml new file mode 100644 index 00000000000..87a7483f6d5 --- /dev/null +++ b/.github/workflows/trivy.yml @@ -0,0 +1,31 @@ +name: Trivy + +on: + push: + branches: + - "main" + schedule: + - cron: '55 17 * * 5' + +permissions: + contents: read + +jobs: + image-scan: + permissions: + contents: read # for actions/checkout to fetch code + name: Image Scan + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + + - name: Build an image from Dockerfile + run: | + IMAGE=envoy-proxy/gateway-dev TAG=${{ github.sha }} make image + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 + with: + image-ref: envoy-proxy/gateway-dev:${{ github.sha }} + exit-code: '1' diff --git a/README.md b/README.md index 8529e20b15f..25fa9af8d94 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/envoyproxy/gateway/badge)](https://securityscorecards.dev/viewer/?uri=github.com/envoyproxy/gateway) [![Build and Test](https://github.com/envoyproxy/gateway/actions/workflows/build_and_test.yaml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/build_and_test.yaml) [![codecov](https://codecov.io/gh/envoyproxy/gateway/branch/main/graph/badge.svg)](https://codecov.io/gh/envoyproxy/gateway) +[![CodeQL](https://github.com/envoyproxy/gateway/actions/workflows/codeql.yml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/codeql.yml) +[![OSV-Scanner](https://github.com/envoyproxy/gateway/actions/workflows/osv-scanner.yml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/osv-scanner.yml) +[![Trivy](https://github.com/envoyproxy/gateway/actions/workflows/trivy.yml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/trivy.yml) Envoy Gateway is an open source project for managing Envoy Proxy as a standalone or Kubernetes-based application gateway. diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 19a854766bb..8f85d0617c7 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -66,7 +66,7 @@ type ClientTrafficPolicySpec struct { // TLS settings configure TLS termination settings with the downstream client. // // +optional - TLS *TLSSettings `json:"tls,omitempty"` + TLS *ClientTLSSettings `json:"tls,omitempty"` // Path enables managing how the incoming path set by clients can be normalized. // // +optional @@ -176,8 +176,7 @@ type CustomHeaderExtensionSettings struct { } // HTTP3Settings provides HTTP/3 configuration on the listener. -type HTTP3Settings struct { -} +type HTTP3Settings struct{} // HTTP1Settings provides HTTP/1 configuration on the listener. type HTTP1Settings struct { diff --git a/api/v1alpha1/compression_types.go b/api/v1alpha1/compression_types.go index 37c0ec8587b..73cb0109ae5 100644 --- a/api/v1alpha1/compression_types.go +++ b/api/v1alpha1/compression_types.go @@ -13,8 +13,7 @@ type CompressorType string // GzipCompressor defines the config for the Gzip compressor. // The default values can be found here: // https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/compression/gzip/compressor/v3/gzip.proto#extension-envoy-compression-gzip-compressor -type GzipCompressor struct { -} +type GzipCompressor struct{} // Compression defines the config of enabling compression. // This can help reduce the bandwidth at the expense of higher CPU. diff --git a/api/v1alpha1/envoygateway_types.go b/api/v1alpha1/envoygateway_types.go index ffc871b517c..b1de1937c61 100644 --- a/api/v1alpha1/envoygateway_types.go +++ b/api/v1alpha1/envoygateway_types.go @@ -510,7 +510,6 @@ type ExtensionTLS struct { // EnvoyGatewayAdmin defines the Envoy Gateway Admin configuration. type EnvoyGatewayAdmin struct { - // Address defines the address of Envoy Gateway Admin Server. // // +optional diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index e878c4a88a1..bcec1ff5837 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -7,6 +7,7 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) const ( @@ -116,6 +117,20 @@ type EnvoyProxySpec struct { // +optional // +notImplementedHide FilterOrder []FilterPosition `json:"filterOrder,omitempty"` + // BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends. + // These settings are applied on backends for which TLS policies are specified. + // +optional + BackendTLS *BackendTLSConfig `json:"backendTLS,omitempty"` +} + +// BackendTLSConfig describes the BackendTLS configuration for Envoy Proxy. +type BackendTLSConfig struct { + // ClientCertificateRef defines the reference to a Kubernetes Secret that contains + // the client certificate and private key for Envoy to use when connecting to + // backend services and external services, such as ExtAuth, ALS, OpenTelemetry, etc. + // +optional + ClientCertificateRef *gwapiv1.SecretObjectReference `json:"clientCertificateRef,omitempty"` + TLSSettings `json:",inline"` } // FilterPosition defines the position of an Envoy HTTP filter in the filter chain. diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go index ef5e409d9db..85f250c6314 100644 --- a/api/v1alpha1/ext_proc_types.go +++ b/api/v1alpha1/ext_proc_types.go @@ -45,18 +45,15 @@ type ExtProcProcessingMode struct { Response *ProcessingModeOptions `json:"response,omitempty"` } -// +kubebuilder:validation:XValidation:rule="has(self.backendRef) ? (!has(self.backendRef.group) || self.backendRef.group == \"\") : true", message="group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported" -// +kubebuilder:validation:XValidation:rule="has(self.backendRef) ? (!has(self.backendRef.kind) || self.backendRef.kind == 'Service') : true", message="kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported" -// // ExtProc defines the configuration for External Processing filter. type ExtProc struct { - // BackendRef defines the configuration of the external processing service - BackendRef ExtProcBackendRef `json:"backendRef"` - // BackendRefs defines the configuration of the external processing service // - // +optional - BackendRefs []BackendRef `json:"backendRefs,omitempty"` + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=1 + // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service kind.",rule="self.all(f, f.kind == 'Service')" + // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" + BackendRefs []BackendRef `json:"backendRefs"` // MessageTimeout is the timeout for a response to be returned from the external processor // Default: 200ms @@ -77,13 +74,3 @@ type ExtProc struct { // +optional ProcessingMode *ExtProcProcessingMode `json:"processingMode,omitempty"` } - -// ExtProcService defines the gRPC External Processing service using the envoy grpc client -// The processing request and response messages are defined in -// https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/ext_proc/v3/external_processor.proto -type ExtProcBackendRef struct { - // BackendObjectReference references a Kubernetes object that represents the - // backend server to which the processing requests will be sent. - // Only service Kind is supported for now. - gwapiv1.BackendObjectReference `json:",inline"` -} diff --git a/api/v1alpha1/fault_injection.go b/api/v1alpha1/fault_injection.go index d27a5c5ee12..a8b7e1f5412 100644 --- a/api/v1alpha1/fault_injection.go +++ b/api/v1alpha1/fault_injection.go @@ -13,7 +13,6 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // // +kubebuilder:validation:XValidation:rule=" has(self.delay) || has(self.abort) ",message="Delay and abort faults are set at least one." type FaultInjection struct { - // If specified, a delay will be injected into the request. // // +optional diff --git a/api/v1alpha1/healthcheck_types.go b/api/v1alpha1/healthcheck_types.go index 61172273e3d..cea83d2f5a1 100644 --- a/api/v1alpha1/healthcheck_types.go +++ b/api/v1alpha1/healthcheck_types.go @@ -22,7 +22,6 @@ type HealthCheck struct { // PassiveHealthCheck defines the configuration for passive health checks in the context of Envoy's Outlier Detection, // see https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/outlier type PassiveHealthCheck struct { - // SplitExternalLocalOriginErrors enables splitting of errors between external and local origin. // // +kubebuilder:default=false diff --git a/api/v1alpha1/jwt_types.go b/api/v1alpha1/jwt_types.go index 4f844b0e9fc..4bc8a994f5d 100644 --- a/api/v1alpha1/jwt_types.go +++ b/api/v1alpha1/jwt_types.go @@ -7,7 +7,6 @@ package v1alpha1 // JWT defines the configuration for JSON Web Token (JWT) authentication. type JWT struct { - // Optional determines whether a missing JWT is acceptable, defaulting to false if not specified. // Note: Even if optional is set to true, JWT authentication will still fail if an invalid JWT is presented. Optional *bool `json:"optional,omitempty"` @@ -91,7 +90,6 @@ type RemoteJWKS struct { // ClaimToHeader defines a configuration to convert JWT claims into HTTP headers type ClaimToHeader struct { - // Header defines the name of the HTTP request header that the JWT Claim will be saved into. Header string `json:"header"` diff --git a/api/v1alpha1/tls_types.go b/api/v1alpha1/tls_types.go index 448913af3eb..38c52761125 100644 --- a/api/v1alpha1/tls_types.go +++ b/api/v1alpha1/tls_types.go @@ -9,10 +9,17 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) +type ClientTLSSettings struct { + // ClientValidation specifies the configuration to validate the client + // initiating the TLS connection to the Gateway listener. + // +optional + ClientValidation *ClientValidationContext `json:"clientValidation,omitempty"` + TLSSettings `json:",inline"` +} + // +kubebuilder:validation:XValidation:rule="has(self.minVersion) && self.minVersion == '1.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,\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4}[self.minVersion] <= {\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4,\"Auto\":5}[self.maxVersion] : !has(self.minVersion) && has(self.maxVersion) ? 3 <= {\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4,\"Auto\":5}[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. // @@ -66,11 +73,6 @@ type TLSSettings struct { // // +optional ALPNProtocols []ALPNProtocol `json:"alpnProtocols,omitempty"` - - // ClientValidation specifies the configuration to validate the client - // initiating the TLS connection to the Gateway listener. - // +optional - ClientValidation *ClientValidationContext `json:"clientValidation,omitempty"` } // ALPNProtocol specifies the protocol to be negotiated using ALPN diff --git a/api/v1alpha1/validation/envoygateway_validate_test.go b/api/v1alpha1/validation/envoygateway_validate_test.go index 6978a52e35f..aa76a90ec7b 100644 --- a/api/v1alpha1/validation/envoygateway_validate_test.go +++ b/api/v1alpha1/validation/envoygateway_validate_test.go @@ -660,7 +660,8 @@ func TestEnvoyGatewayProvider(t *testing.T) { Replicas: nil, Pod: nil, Container: nil, - }} + }, + } assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas) assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod) assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container) @@ -674,7 +675,8 @@ func TestEnvoyGatewayProvider(t *testing.T) { SecurityContext: nil, Image: nil, }, - }} + }, + } assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources) envoyGatewayProvider.GetEnvoyGatewayKubeProvider() diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go index b885d8fadfc..0e4f7e22221 100644 --- a/api/v1alpha1/validation/envoyproxy_validate.go +++ b/api/v1alpha1/validation/envoyproxy_validate.go @@ -110,14 +110,12 @@ func validateService(spec *egv1a1.EnvoyProxySpec) []error { errs = append(errs, fmt.Errorf("unsupported envoy service type %v", serviceType)) } } - if serviceType, serviceAllocateLoadBalancerNodePorts := - spec.Provider.Kubernetes.EnvoyService.Type, spec.Provider.Kubernetes.EnvoyService.AllocateLoadBalancerNodePorts; serviceType != nil && serviceAllocateLoadBalancerNodePorts != nil { + if serviceType, serviceAllocateLoadBalancerNodePorts := spec.Provider.Kubernetes.EnvoyService.Type, spec.Provider.Kubernetes.EnvoyService.AllocateLoadBalancerNodePorts; serviceType != nil && serviceAllocateLoadBalancerNodePorts != nil { if *serviceType != egv1a1.ServiceTypeLoadBalancer { errs = append(errs, fmt.Errorf("allocateLoadBalancerNodePorts can only be set for %v type", egv1a1.ServiceTypeLoadBalancer)) } } - if serviceType, serviceLoadBalancerSourceRanges := - spec.Provider.Kubernetes.EnvoyService.Type, spec.Provider.Kubernetes.EnvoyService.LoadBalancerSourceRanges; serviceType != nil && serviceLoadBalancerSourceRanges != nil { + if serviceType, serviceLoadBalancerSourceRanges := spec.Provider.Kubernetes.EnvoyService.Type, spec.Provider.Kubernetes.EnvoyService.LoadBalancerSourceRanges; serviceType != nil && serviceLoadBalancerSourceRanges != nil { if *serviceType != egv1a1.ServiceTypeLoadBalancer { errs = append(errs, fmt.Errorf("loadBalancerSourceRanges can only be set for %v type", egv1a1.ServiceTypeLoadBalancer)) } diff --git a/api/v1alpha1/validation/envoyproxy_validate_test.go b/api/v1alpha1/validation/envoyproxy_validate_test.go index 27ab08f3091..6619888bdc8 100644 --- a/api/v1alpha1/validation/envoyproxy_validate_test.go +++ b/api/v1alpha1/validation/envoyproxy_validate_test.go @@ -447,7 +447,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: false, - }, { + }, + { name: "should invalid when metrics type is OpenTelemetry, but `OpenTelemetry` field being empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -467,7 +468,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: false, - }, { + }, + { name: "should valid when metrics type is OpenTelemetry and `OpenTelemetry` field being not empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -491,7 +493,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, - }, { + }, + { name: "should be invalid when service patch type is empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -514,7 +517,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, - }, { + }, + { name: "should be invalid when deployment patch type is empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -537,7 +541,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, - }, { + }, + { name: "should invalid when patch object is empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -558,7 +563,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: false, - }, { + }, + { name: "should valid when patch type and object are both not empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -582,7 +588,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, - }, { + }, + { name: "should valid when patch type is empty and object is not empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 6cfa9192f46..4e0ebe32dbf 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -192,6 +192,27 @@ func (in *BackendRef) DeepCopy() *BackendRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSConfig) DeepCopyInto(out *BackendTLSConfig) { + *out = *in + if in.ClientCertificateRef != nil { + in, out := &in.ClientCertificateRef, &out.ClientCertificateRef + *out = new(v1.SecretObjectReference) + (*in).DeepCopyInto(*out) + } + in.TLSSettings.DeepCopyInto(&out.TLSSettings) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSConfig. +func (in *BackendTLSConfig) DeepCopy() *BackendTLSConfig { + if in == nil { + return nil + } + out := new(BackendTLSConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendTrafficPolicy) DeepCopyInto(out *BackendTrafficPolicy) { *out = *in @@ -469,6 +490,27 @@ func (in *ClientIPDetectionSettings) DeepCopy() *ClientIPDetectionSettings { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientTLSSettings) DeepCopyInto(out *ClientTLSSettings) { + *out = *in + if in.ClientValidation != nil { + in, out := &in.ClientValidation, &out.ClientValidation + *out = new(ClientValidationContext) + (*in).DeepCopyInto(*out) + } + in.TLSSettings.DeepCopyInto(&out.TLSSettings) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTLSSettings. +func (in *ClientTLSSettings) DeepCopy() *ClientTLSSettings { + if in == nil { + return nil + } + out := new(ClientTLSSettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientTimeout) DeepCopyInto(out *ClientTimeout) { *out = *in @@ -569,7 +611,7 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { } if in.TLS != nil { in, out := &in.TLS, &out.TLS - *out = new(TLSSettings) + *out = new(ClientTLSSettings) (*in).DeepCopyInto(*out) } if in.Path != nil { @@ -1534,6 +1576,11 @@ func (in *EnvoyProxySpec) DeepCopyInto(out *EnvoyProxySpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.BackendTLS != nil { + in, out := &in.BackendTLS, &out.BackendTLS + *out = new(BackendTLSConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxySpec. @@ -1599,7 +1646,6 @@ func (in *ExtAuth) DeepCopy() *ExtAuth { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtProc) DeepCopyInto(out *ExtProc) { *out = *in - in.BackendRef.DeepCopyInto(&out.BackendRef) if in.BackendRefs != nil { in, out := &in.BackendRefs, &out.BackendRefs *out = make([]BackendRef, len(*in)) @@ -1634,22 +1680,6 @@ func (in *ExtProc) DeepCopy() *ExtProc { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtProcBackendRef) DeepCopyInto(out *ExtProcBackendRef) { - *out = *in - in.BackendObjectReference.DeepCopyInto(&out.BackendObjectReference) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtProcBackendRef. -func (in *ExtProcBackendRef) DeepCopy() *ExtProcBackendRef { - if in == nil { - return nil - } - out := new(ExtProcBackendRef) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtProcProcessingMode) DeepCopyInto(out *ExtProcProcessingMode) { *out = *in @@ -4094,11 +4124,6 @@ func (in *TLSSettings) DeepCopyInto(out *TLSSettings) { *out = make([]ALPNProtocol, len(*in)) copy(*out, *in) } - if in.ClientValidation != nil { - in, out := &in.ClientValidation, &out.ClientValidation - *out = new(ClientValidationContext) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSettings. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 257cc8372f8..f8c0135411b 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -54,83 +54,6 @@ spec: description: ExtProc defines the configuration for External Processing filter. properties: - backendRef: - description: BackendRef defines the configuration of the external - processing service - properties: - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - - Defaults to "Service" when not specified. - - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - - Support: Core (Services with a type other than ExternalName) - - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - required: - - name - type: object - x-kubernetes-validations: - - message: Must have port for Service reference - rule: '(size(self.group) == 0 && self.kind == ''Service'') - ? has(self.port) : true' backendRefs: description: BackendRefs defines the configuration of the external processing service @@ -211,7 +134,14 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 1 + minItems: 1 type: array + x-kubernetes-validations: + - message: BackendRefs only supports Service kind. + rule: self.all(f, f.kind == 'Service') + - message: BackendRefs only supports Core group. + rule: self.all(f, f.group == '') failOpen: description: |- FailOpen defines if requests or responses that cannot be processed due to connectivity to the @@ -257,18 +187,8 @@ spec: type: object type: object required: - - backendRef + - backendRefs type: object - x-kubernetes-validations: - - message: group is invalid, only the core API group (specified - by omitting the group field or setting it to an empty string) - is supported - rule: 'has(self.backendRef) ? (!has(self.backendRef.group) || - self.backendRef.group == "") : true' - - message: kind is invalid, only Service (specified by omitting - the kind field or setting it to 'Service') is supported - rule: 'has(self.backendRef) ? (!has(self.backendRef.kind) || self.backendRef.kind - == ''Service'') : true' type: array targetRef: description: |- 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 aea1c477d94..79328d5b80d 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -43,6 +43,142 @@ spec: spec: description: EnvoyProxySpec defines the desired state of EnvoyProxy. properties: + backendTLS: + description: |- + BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends. + These settings are applied on backends for which TLS policies are specified. + properties: + alpnProtocols: + description: |- + ALPNProtocols supplies the list of ALPN protocols that should be + exposed by the listener. By default h2 and http/1.1 are enabled. + Supported values are: + - http/1.0 + - http/1.1 + - h2 + items: + description: ALPNProtocol specifies the protocol to be negotiated + using ALPN + enum: + - http/1.0 + - http/1.1 + - h2 + 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. + 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 + items: + type: string + type: array + clientCertificateRef: + description: |- + ClientCertificateRef defines the reference to a Kubernetes Secret that contains + the client certificate and private key for Envoy to use when connecting to + backend services and external services, such as ExtAuth, ALS, OpenTelemetry, etc. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + ecdhCurves: + description: |- + 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 + items: + type: string + type: array + maxVersion: + description: |- + Max specifies the maximal TLS protocol version to allow + The default is TLS 1.3 if this is not specified. + enum: + - Auto + - "1.0" + - "1.1" + - "1.2" + - "1.3" + type: string + minVersion: + description: |- + Min specifies the minimal TLS protocol version to allow. + The default is TLS 1.2 if this is not specified. + enum: + - Auto + - "1.0" + - "1.1" + - "1.2" + - "1.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 == ''1.3'' ? !has(self.ciphers) + : true' + - message: minVersion must be smaller or equal to maxVersion + rule: 'has(self.minVersion) && has(self.maxVersion) ? {"Auto":0,"1.0":1,"1.1":2,"1.2":3,"1.3":4}[self.minVersion] + <= {"1.0":1,"1.1":2,"1.2":3,"1.3":4,"Auto":5}[self.maxVersion] + : !has(self.minVersion) && has(self.maxVersion) ? 3 <= {"1.0":1,"1.1":2,"1.2":3,"1.3":4,"Auto":5}[self.maxVersion] + : true' bootstrap: description: |- Bootstrap defines the Envoy Bootstrap as a YAML string. @@ -432,6 +568,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -445,6 +605,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -452,6 +613,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -605,6 +767,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a Volume. @@ -614,6 +778,29 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + + If ReadOnly is false, this field has no meaning and must be unspecified. + + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -709,11 +896,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -742,11 +931,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic weight: @@ -760,6 +951,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -805,11 +997,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -838,14 +1032,17 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array + x-kubernetes-list-type: atomic required: - nodeSelectorTerms type: object @@ -911,11 +1108,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -930,12 +1129,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -945,12 +1144,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -993,11 +1192,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1017,6 +1218,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1039,6 +1241,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -1090,11 +1293,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1109,12 +1314,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1124,12 +1329,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1171,11 +1376,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1195,6 +1402,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1207,6 +1415,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object podAntiAffinity: description: Describes pod anti-affinity scheduling @@ -1268,11 +1477,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1287,12 +1498,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1302,12 +1513,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1350,11 +1561,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1374,6 +1587,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1396,6 +1610,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the anti-affinity requirements specified by this field are not met at @@ -1447,11 +1662,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1466,12 +1683,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1481,12 +1698,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1528,11 +1745,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1552,6 +1771,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1564,6 +1784,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object type: object annotations: @@ -1613,6 +1834,29 @@ spec: SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. properties: + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object fsGroup: description: |- A special supplemental group that applies to all containers in a pod. @@ -1732,6 +1976,7 @@ spec: format: int64 type: integer type: array + x-kubernetes-list-type: atomic sysctls: description: |- Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported @@ -1752,6 +1997,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic windowsOptions: description: |- The Windows specific settings applied to all containers. @@ -1866,11 +2112,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1941,9 +2189,6 @@ spec: In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. - - - This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default). format: int32 type: integer nodeAffinityPolicy: @@ -2126,6 +2371,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic path: description: 'path is Optional: Used as the mounted root, rather than the full @@ -2255,6 +2501,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -2342,7 +2589,8 @@ spec: fieldRef: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace are supported.' + labels, name, namespace and uid + are supported.' properties: apiVersion: description: Version of the schema @@ -2408,6 +2656,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object emptyDir: description: |- @@ -2513,6 +2762,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic dataSource: description: |- dataSource field can be used to specify either: @@ -2660,11 +2910,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2692,7 +2944,7 @@ spec: If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. type: string volumeMode: @@ -2738,6 +2990,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic wwids: description: |- wwids Optional: FC volume world wide identifiers (wwids) @@ -2745,6 +2998,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object flexVolume: description: |- @@ -2969,6 +3223,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic readOnly: description: |- readOnly here will force the ReadOnly setting in VolumeMounts. @@ -3165,11 +3420,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -3250,6 +3507,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -3280,8 +3538,8 @@ spec: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace - are supported.' + labels, name, namespace + and uid are supported.' properties: apiVersion: description: Version @@ -3355,6 +3613,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object secret: description: secret information about @@ -3399,6 +3658,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -3444,6 +3704,7 @@ spec: type: object type: object type: array + x-kubernetes-list-type: atomic type: object quobyte: description: quobyte represents a Quobyte mount @@ -3514,6 +3775,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic pool: description: |- pool is the rados pool name. @@ -3673,6 +3935,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic optional: description: optional field specify whether the Secret or its keys must be defined @@ -4030,6 +4293,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -4043,6 +4330,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -4050,6 +4338,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -4203,6 +4492,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a Volume. @@ -4212,6 +4503,29 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + + If ReadOnly is false, this field has no meaning and must be unspecified. + + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -4251,6 +4565,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic command: description: |- Entrypoint array. Not executed within a shell. @@ -4264,6 +4579,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic env: description: |- List of environment variables to set in the container. @@ -4384,6 +4700,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map envFrom: description: |- List of sources to populate environment variables in the container. @@ -4433,6 +4752,7 @@ spec: x-kubernetes-map-type: atomic type: object type: array + x-kubernetes-list-type: atomic image: description: |- Container image name. @@ -4474,6 +4794,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http @@ -4507,6 +4828,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -4590,6 +4912,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http @@ -4623,6 +4946,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -4701,6 +5025,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -4757,6 +5082,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -4915,6 +5241,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -4971,6 +5298,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -5167,6 +5495,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -5180,6 +5532,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -5187,6 +5540,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -5344,6 +5698,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -5400,6 +5755,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -5543,6 +5899,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map volumeMounts: description: |- Pod volumes to mount into the container's filesystem. @@ -5562,6 +5921,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a @@ -5572,6 +5933,29 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + + If ReadOnly is false, this field has no meaning and must be unspecified. + + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -5589,6 +5973,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map workingDir: description: |- Container's working directory. @@ -5677,11 +6064,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -5710,11 +6099,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic weight: @@ -5728,6 +6119,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -5773,11 +6165,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -5806,14 +6200,17 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array + x-kubernetes-list-type: atomic required: - nodeSelectorTerms type: object @@ -5879,11 +6276,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -5898,12 +6297,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -5913,12 +6312,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -5961,11 +6360,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -5985,6 +6386,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -6007,6 +6409,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -6058,11 +6461,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6077,12 +6482,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6092,12 +6497,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6139,11 +6544,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6163,6 +6570,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -6175,6 +6583,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object podAntiAffinity: description: Describes pod anti-affinity scheduling @@ -6236,11 +6645,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6255,12 +6666,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6270,12 +6681,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6318,11 +6729,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6342,6 +6755,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -6364,6 +6778,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the anti-affinity requirements specified by this field are not met at @@ -6415,11 +6830,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6434,12 +6851,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6449,12 +6866,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6496,11 +6913,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6520,6 +6939,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -6532,6 +6952,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object type: object annotations: @@ -6581,6 +7002,29 @@ spec: SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. properties: + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object fsGroup: description: |- A special supplemental group that applies to all containers in a pod. @@ -6700,6 +7144,7 @@ spec: format: int64 type: integer type: array + x-kubernetes-list-type: atomic sysctls: description: |- Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported @@ -6720,6 +7165,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic windowsOptions: description: |- The Windows specific settings applied to all containers. @@ -6834,11 +7280,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6909,9 +7357,6 @@ spec: In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. - - - This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default). format: int32 type: integer nodeAffinityPolicy: @@ -7094,6 +7539,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic path: description: 'path is Optional: Used as the mounted root, rather than the full @@ -7223,6 +7669,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -7310,7 +7757,8 @@ spec: fieldRef: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace are supported.' + labels, name, namespace and uid + are supported.' properties: apiVersion: description: Version of the schema @@ -7376,6 +7824,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object emptyDir: description: |- @@ -7481,6 +7930,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic dataSource: description: |- dataSource field can be used to specify either: @@ -7628,11 +8078,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -7660,7 +8112,7 @@ spec: If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. type: string volumeMode: @@ -7706,6 +8158,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic wwids: description: |- wwids Optional: FC volume world wide identifiers (wwids) @@ -7713,6 +8166,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object flexVolume: description: |- @@ -7937,6 +8391,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic readOnly: description: |- readOnly here will force the ReadOnly setting in VolumeMounts. @@ -8133,11 +8588,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8218,6 +8675,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -8248,8 +8706,8 @@ spec: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace - are supported.' + labels, name, namespace + and uid are supported.' properties: apiVersion: description: Version @@ -8323,6 +8781,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object secret: description: secret information about @@ -8367,6 +8826,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -8412,6 +8872,7 @@ spec: type: object type: object type: array + x-kubernetes-list-type: atomic type: object quobyte: description: quobyte represents a Quobyte mount @@ -8482,6 +8943,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic pool: description: |- pool is the rados pool name. @@ -8641,6 +9103,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic optional: description: optional field specify whether the Secret or its keys must be defined @@ -9038,11 +9501,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -9164,11 +9629,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -9272,11 +9739,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string diff --git a/charts/gateway-helm/values.tmpl.yaml b/charts/gateway-helm/values.tmpl.yaml index d7d43391039..c0dbfaa762a 100644 --- a/charts/gateway-helm/values.tmpl.yaml +++ b/charts/gateway-helm/values.tmpl.yaml @@ -3,7 +3,7 @@ deployment: image: repository: ${ImageRepository} tag: '${ImageTag}' - imagePullPolicy: Always + imagePullPolicy: ${ImagePullPolicy} imagePullSecrets: [] resources: limits: diff --git a/go.mod b/go.mod index 697c2a1452b..bd953f83fe5 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,9 @@ require ( fortio.org/fortio v1.63.7 fortio.org/log v1.12.2 github.com/Masterminds/semver/v3 v3.2.1 - github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa + github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b github.com/davecgh/go-spew v1.1.1 - github.com/envoyproxy/go-control-plane v0.12.1-0.20240410145647-bdba4bba15fc + github.com/envoyproxy/go-control-plane v0.12.1-0.20240425230418-212e93054f1a github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 github.com/evanphx/json-patch/v5 v5.9.0 github.com/fatih/color v1.16.0 @@ -27,13 +27,13 @@ require ( github.com/stretchr/testify v1.9.0 github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7 github.com/tsaarni/certyaml v0.9.3 - go.opentelemetry.io/otel v1.25.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.25.0 - go.opentelemetry.io/otel/exporters/prometheus v0.47.0 - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.25.0 - go.opentelemetry.io/otel/metric v1.25.0 - go.opentelemetry.io/otel/sdk/metric v1.25.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/sdk/metric v1.26.0 go.opentelemetry.io/proto/otlp v1.2.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 @@ -42,20 +42,21 @@ require ( google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 helm.sh/helm/v3 v3.14.4 - k8s.io/api v0.29.3 - k8s.io/apiextensions-apiserver v0.29.3 - k8s.io/apimachinery v0.29.3 - k8s.io/cli-runtime v0.29.3 - k8s.io/client-go v0.29.3 - k8s.io/kubectl v0.29.3 + k8s.io/api v0.30.0 + k8s.io/apiextensions-apiserver v0.30.0 + k8s.io/apimachinery v0.30.0 + k8s.io/cli-runtime v0.30.0 + k8s.io/client-go v0.30.0 + k8s.io/kubectl v0.30.0 k8s.io/utils v0.0.0-20230726121419-3b25d923346b - sigs.k8s.io/controller-runtime v0.17.3 + sigs.k8s.io/controller-runtime v0.18.0 sigs.k8s.io/gateway-api v1.0.0 sigs.k8s.io/mcs-api v0.1.0 sigs.k8s.io/yaml v1.4.0 ) require ( + cel.dev/expr v0.15.0 // indirect fortio.org/dflag v1.7.1 // indirect fortio.org/sets v1.0.4 // indirect fortio.org/struct2env v0.4.0 // indirect @@ -109,7 +110,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect golang.org/x/crypto v0.22.0 // indirect - k8s.io/apiserver v0.29.3 // indirect + k8s.io/apiserver v0.30.0 // indirect oras.land/oras-go v1.2.4 // indirect ) @@ -166,8 +167,8 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/tsaarni/x500dn v1.0.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect - go.opentelemetry.io/otel/sdk v1.25.0 - go.opentelemetry.io/otel/trace v1.25.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.16.0 // indirect @@ -185,9 +186,9 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/component-base v0.29.3 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/component-base v0.30.0 // indirect + k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect diff --git a/go.sum b/go.sum index ee2b0823437..e831080cc91 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= +cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -96,8 +98,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= @@ -167,8 +169,8 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240410145647-bdba4bba15fc h1:FJoupBhZkbUXmzGxgAic3rEHeZf8jgvREB7uMfBI23w= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240410145647-bdba4bba15fc/go.mod h1:Dj0RQ153G7gNYzcQCihXUreYTQbuJNuL7IT7v9+jTr4= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240425230418-212e93054f1a h1:OmSlDWdXUzNgoMWOtrcEAmiO9BxTt6cGotwz7cZwIyw= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240425230418-212e93054f1a/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= @@ -213,7 +215,6 @@ 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/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= @@ -522,15 +523,15 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= -github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= +github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= @@ -685,24 +686,24 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= -go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= -go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 h1:hDKnobznDpcdTlNzO0S/owRB8tyVr1OoeZZhDoqY+Cs= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0/go.mod h1:kUDQaUs1h8iTIHbQTk+iJRiUvSfJYMMKTtMCaiVu7B0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.25.0 h1:Wc4hZuYXhVqq+TfRXLXlmNIL/awOanGx8ssq3ciDQxc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.25.0/go.mod h1:BydOvapRqVEc0DVz27qWBX2jq45Ca5TI9mhZBDIdweY= -go.opentelemetry.io/otel/exporters/prometheus v0.47.0 h1:OL6yk1Z/pEGdDnrBbxSsH+t4FY1zXfBRGd7bjwhlMLU= -go.opentelemetry.io/otel/exporters/prometheus v0.47.0/go.mod h1:xF3N4OSICZDVbbYZydz9MHFro1RjmkPUKEvar2utG+Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.25.0 h1:d7nHbdzU84STOiszaOxQ3kw5IwkSmHsU5Muol5/vL4I= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.25.0/go.mod h1:yiPA1iZbb/EHYnODXOxvtKuB0I2hV8ehfLTEWpl7BJU= -go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= -go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= -go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= -go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= -go.opentelemetry.io/otel/sdk/metric v1.25.0 h1:7CiHOy08LbrxMAp4vWpbiPcklunUshVpAvGBrdDRlGw= -go.opentelemetry.io/otel/sdk/metric v1.25.0/go.mod h1:LzwoKptdbBBdYfvtGCzGwk6GWMA3aUzBOwtQpR6Nz7o= -go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= -go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= @@ -943,46 +944,46 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4= -k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= -k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= +k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio= -k8s.io/apiextensions-apiserver v0.29.3 h1:9HF+EtZaVpFjStakF4yVufnXGPRppWFEQ87qnO91YeI= -k8s.io/apiextensions-apiserver v0.29.3/go.mod h1:po0XiY5scnpJfFizNGo6puNU6Fq6D70UJY2Cb2KwAVc= +k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs= +k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= -k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= +k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8= -k8s.io/apiserver v0.29.3 h1:xR7ELlJ/BZSr2n4CnD3lfA4gzFivh0wwfNfz9L0WZcE= -k8s.io/apiserver v0.29.3/go.mod h1:hrvXlwfRulbMbBgmWRQlFru2b/JySDpmzvQwwk4GUOs= -k8s.io/cli-runtime v0.29.3 h1:r68rephmmytoywkw2MyJ+CxjpasJDQY7AGc3XY2iv1k= -k8s.io/cli-runtime v0.29.3/go.mod h1:aqVUsk86/RhaGJwDhHXH0jcdqBrgdF3bZWk4Z9D4mkM= +k8s.io/apiserver v0.30.0 h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M= +k8s.io/apiserver v0.30.0/go.mod h1:smOIBq8t0MbKZi7O7SyIpjPsiKJ8qa+llcFCluKyqiY= +k8s.io/cli-runtime v0.30.0 h1:0vn6/XhOvn1RJ2KJOC6IRR2CGqrpT6QQF4+8pYpWQ48= +k8s.io/cli-runtime v0.30.0/go.mod h1:vATpDMATVTMA79sZ0YUCzlMelf6rUjoBzlp+RnoM+cg= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g= -k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= -k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= +k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk= -k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= -k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio= +k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o= +k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/kubectl v0.29.3 h1:RuwyyIU42MAISRIePaa8Q7A3U74Q9P4MoJbDFz9o3us= -k8s.io/kubectl v0.29.3/go.mod h1:yCxfY1dbwgVdEt2zkJ6d5NNLOhhWgTyrqACIoFhpdd4= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/kubectl v0.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk= +k8s.io/kubectl v0.30.0/go.mod h1:zgolRw2MQXLPwmic2l/+iHs239L49fhSeICuMhQQXTI= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= @@ -991,8 +992,8 @@ oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY= oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A= -sigs.k8s.io/controller-runtime v0.17.3 h1:65QmN7r3FWgTxDMz9fvGnO1kbf2nu+acg9p2R9oYYYk= -sigs.k8s.io/controller-runtime v0.17.3/go.mod h1:N0jpP5Lo7lMTF9aL56Z/B2oWBJjey6StQM0jRbKQXtY= +sigs.k8s.io/controller-runtime v0.18.0 h1:Z7jKuX784TQSUL1TIyeuF7j8KXZ4RtSX0YgtjKcSTME= +sigs.k8s.io/controller-runtime v0.18.0/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= sigs.k8s.io/gateway-api v1.0.0 h1:iPTStSv41+d9p0xFydll6d7f7MOBGuqXM6p2/zVYMAs= sigs.k8s.io/gateway-api v1.0.0/go.mod h1:4cUgr0Lnp5FZ0Cdq8FdRwCvpiWws7LVhLHGIudLlf4c= diff --git a/internal/admin/server.go b/internal/admin/server.go index 9c035b43816..29901814381 100644 --- a/internal/admin/server.go +++ b/internal/admin/server.go @@ -17,9 +17,7 @@ import ( "github.com/envoyproxy/gateway/internal/logging" ) -var ( - adminLogger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("admin") -) +var adminLogger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("admin") func Init(cfg *config.Server) error { if cfg.EnvoyGateway.GetEnvoyGatewayAdmin().EnableDumpConfig { diff --git a/internal/cmd/egctl/config_ratelimit.go b/internal/cmd/egctl/config_ratelimit.go index 376ff65cd06..089a52f1f69 100644 --- a/internal/cmd/egctl/config_ratelimit.go +++ b/internal/cmd/egctl/config_ratelimit.go @@ -32,10 +32,7 @@ var ( ) func ratelimitConfigCommand() *cobra.Command { - - var ( - namespace string - ) + var namespace string rlConfigCmd := &cobra.Command{ Use: "envoy-ratelimit", @@ -57,7 +54,6 @@ func ratelimitConfigCommand() *cobra.Command { } func runRateLimitConfig(c *cobra.Command, ns string) error { - cli, err := getCLIClient() if err != nil { return err @@ -73,7 +69,6 @@ func runRateLimitConfig(c *cobra.Command, ns string) error { } func retrieveRateLimitConfig(cli kubernetes.CLIClient, ns string) ([]byte, error) { - // Before retrieving the rate limit configuration // we make sure that the global rate limit feature is enabled if enable, err := checkEnableGlobalRateLimit(cli); !enable { @@ -103,7 +98,6 @@ func retrieveRateLimitConfig(cli kubernetes.CLIClient, ns string) ([]byte, error // fetchRunningRateLimitPods gets the rate limit Pods, based on the labelSelectors. // It further filters out only those rate limit Pods that are in "Running" state. func fetchRunningRateLimitPods(cli kubernetes.CLIClient, namespace string, labelSelector []string) ([]types.NamespacedName, error) { - // Since multiple replicas of the rate limit are configured to be equal, // we do not need to use the pod name to obtain the specified pod. rlPods, err := cli.PodsForSelector(namespace, labelSelector...) @@ -134,7 +128,6 @@ func fetchRunningRateLimitPods(cli kubernetes.CLIClient, namespace string, label // checkRateLimitPodStatusReady Check that the rate limit pod is ready func checkRateLimitPodStatusReady(status corev1.PodStatus) bool { - if status.Phase != corev1.PodRunning { return false } @@ -152,7 +145,6 @@ func checkRateLimitPodStatusReady(status corev1.PodStatus) bool { // extractRateLimitConfig After turning on port forwarding through PortForwarder, // construct a request and send it to the rate limit Pod to obtain relevant configuration information. func extractRateLimitConfig(fw kubernetes.PortForwarder, rlPod types.NamespacedName) ([]byte, error) { - if err := fw.Start(); err != nil { return nil, fmt.Errorf("failed to start port forwarding for pod %s/%s: %w", rlPod.Namespace, rlPod.Name, err) } @@ -168,7 +160,6 @@ func extractRateLimitConfig(fw kubernetes.PortForwarder, rlPod types.NamespacedN // checkEnableGlobalRateLimit Check whether the Global Rate Limit function is enabled func checkEnableGlobalRateLimit(cli kubernetes.CLIClient) (bool, error) { - kubeCli := cli.Kube() cm, err := kubeCli.CoreV1(). ConfigMaps(defaultRateLimitNamespace). diff --git a/internal/cmd/egctl/config_test.go b/internal/cmd/egctl/config_test.go index ff1ad2f8ace..8d1eb45b934 100644 --- a/internal/cmd/egctl/config_test.go +++ b/internal/cmd/egctl/config_test.go @@ -156,7 +156,8 @@ func TestExtractSubResourcesConfigDump(t *testing.T) { output: "yaml", resourceType: BootstrapEnvoyConfigType, expected: "out.bootstrap.yaml", - }, { + }, + { output: "json", resourceType: ClusterEnvoyConfigType, expected: "out.cluster.json", @@ -165,7 +166,8 @@ func TestExtractSubResourcesConfigDump(t *testing.T) { output: "yaml", resourceType: ClusterEnvoyConfigType, expected: "out.cluster.yaml", - }, { + }, + { output: "json", resourceType: ListenerEnvoyConfigType, expected: "out.listener.json", @@ -174,7 +176,8 @@ func TestExtractSubResourcesConfigDump(t *testing.T) { output: "yaml", resourceType: ListenerEnvoyConfigType, expected: "out.listener.yaml", - }, { + }, + { output: "json", resourceType: RouteEnvoyConfigType, expected: "out.route.json", @@ -303,7 +306,6 @@ func (f *fakeCLIClient) Kube() kubernetes.Interface { } func TestFetchRunningRateLimitPods(t *testing.T) { - cases := []struct { caseName string rlPods []corev1.Pod @@ -363,23 +365,18 @@ func TestFetchRunningRateLimitPods(t *testing.T) { } for _, tc := range cases { - t.Run(tc.caseName, func(t *testing.T) { - fakeCli := &fakeCLIClient{ pods: tc.rlPods, } _, err := fetchRunningRateLimitPods(fakeCli, tc.namespace, tc.labelSelector) require.Equal(t, tc.expectErr, err) - }) - } } func TestCheckEnableGlobalRateLimit(t *testing.T) { - cases := []struct { caseName string egConfigMap *corev1.ConfigMap @@ -433,9 +430,7 @@ gateway: } for _, tc := range cases { - t.Run(tc.caseName, func(t *testing.T) { - fakeCli := &fakeCLIClient{ cm: tc.egConfigMap, } @@ -443,14 +438,11 @@ gateway: actual, err := checkEnableGlobalRateLimit(fakeCli) require.Equal(t, tc.expect, actual) require.NoError(t, err) - }) - } } func TestExtractRateLimitConfig(t *testing.T) { - cases := []struct { caseName string responseBody []byte @@ -467,23 +459,18 @@ func TestExtractRateLimitConfig(t *testing.T) { } for _, tc := range cases { - t.Run(tc.caseName, func(t *testing.T) { - fw, err := newFakePortForwarder(tc.responseBody) require.NoError(t, err) out, err := extractRateLimitConfig(fw, tc.rlPod) require.NoError(t, err) require.NotEmpty(t, out) - }) - } } func TestCheckRateLimitPodStatusReady(t *testing.T) { - cases := []struct { caseName string status corev1.PodStatus @@ -538,5 +525,4 @@ func TestCheckRateLimitPodStatusReady(t *testing.T) { require.Equal(t, tc.expect, actual) }) } - } diff --git a/internal/cmd/egctl/envoy_stats.go b/internal/cmd/egctl/envoy_stats.go index c7701da0bcd..c8b22c8d05d 100644 --- a/internal/cmd/egctl/envoy_stats.go +++ b/internal/cmd/egctl/envoy_stats.go @@ -24,9 +24,7 @@ const ( prometheusOutput = "prom" ) -var ( - statsType, outputFormat string -) +var statsType, outputFormat string func newEnvoyStatsCmd() *cobra.Command { var podName, podNamespace string diff --git a/internal/cmd/egctl/install.go b/internal/cmd/egctl/install.go index 640dfca0bd0..076ecb8d2f2 100644 --- a/internal/cmd/egctl/install.go +++ b/internal/cmd/egctl/install.go @@ -13,7 +13,6 @@ import ( ) func newInstallCommand() *cobra.Command { - packageFlags := &helm.PackageOptions{} pt := helm.NewPackageTool() diff --git a/internal/cmd/egctl/translate.go b/internal/cmd/egctl/translate.go index a441378f52a..9d21b20105e 100644 --- a/internal/cmd/egctl/translate.go +++ b/internal/cmd/egctl/translate.go @@ -161,12 +161,14 @@ func getValidOutputTypesStr() string { } func validResourceTypes() []envoyConfigType { - return []envoyConfigType{BootstrapEnvoyConfigType, + return []envoyConfigType{ + BootstrapEnvoyConfigType, EndpointEnvoyConfigType, ClusterEnvoyConfigType, ListenerEnvoyConfigType, RouteEnvoyConfigType, - AllEnvoyConfigType} + AllEnvoyConfigType, + } } func isValidResourceType(outType envoyConfigType) bool { diff --git a/internal/cmd/egctl/translate_test.go b/internal/cmd/egctl/translate_test.go index 6159b832b41..96707159a99 100644 --- a/internal/cmd/egctl/translate_test.go +++ b/internal/cmd/egctl/translate_test.go @@ -26,9 +26,7 @@ import ( "github.com/envoyproxy/gateway/internal/utils/file" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") func TestTranslate(t *testing.T) { testCases := []struct { @@ -353,7 +351,6 @@ func TestTranslate(t *testing.T) { mustUnmarshal(t, requireTestDataOutFile(t, fn), want) opts := cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime") require.Empty(t, cmp.Diff(want, got, opts)) - }) } } diff --git a/internal/cmd/egctl/uninstall.go b/internal/cmd/egctl/uninstall.go index 769222fe271..9241db83197 100644 --- a/internal/cmd/egctl/uninstall.go +++ b/internal/cmd/egctl/uninstall.go @@ -13,7 +13,6 @@ import ( ) func newUnInstallCommand() *cobra.Command { - packageFlags := &helm.PackageOptions{} pt := helm.NewPackageTool() diff --git a/internal/cmd/envoy/shutdown_manager.go b/internal/cmd/envoy/shutdown_manager.go index 5f517365c74..257a3d323bc 100644 --- a/internal/cmd/envoy/shutdown_manager.go +++ b/internal/cmd/envoy/shutdown_manager.go @@ -23,9 +23,7 @@ import ( "github.com/envoyproxy/gateway/internal/xds/bootstrap" ) -var ( - logger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("shutdown-manager") -) +var logger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("shutdown-manager") const ( // ShutdownManagerPort is the port Envoy shutdown manager will listen on. @@ -88,7 +86,7 @@ func ShutdownManager(readyTimeout time.Duration) error { // container to block until ready to terminate. After the graceful drain process // has completed a file will be written to indicate shutdown readiness. func shutdownReadyHandler(w http.ResponseWriter, readyTimeout time.Duration, readyFile string) { - var startTime = time.Now() + startTime := time.Now() logger.Info("received shutdown ready request") @@ -119,8 +117,8 @@ func shutdownReadyHandler(w http.ResponseWriter, readyTimeout time.Duration, rea // it will initiate a graceful drain sequence on the Envoy proxy and block until // connections are drained or a timeout is exceeded. func Shutdown(drainTimeout time.Duration, minDrainDuration time.Duration, exitAtConnections int) error { - var startTime = time.Now() - var allowedToExit = false + startTime := time.Now() + allowedToExit := false // Reconfigure logger to write to stdout of main process if running in Kubernetes if _, k8s := os.LookupEnv("KUBERNETES_SERVICE_HOST"); k8s && os.Getpid() != 1 { diff --git a/internal/cmd/server.go b/internal/cmd/server.go index 6dc25a19946..e4bf36a5ae5 100644 --- a/internal/cmd/server.go +++ b/internal/cmd/server.go @@ -23,10 +23,8 @@ import ( xdstranslatorrunner "github.com/envoyproxy/gateway/internal/xds/translator/runner" ) -var ( - // cfgPath is the path to the EnvoyGateway configuration file. - cfgPath string -) +// cfgPath is the path to the EnvoyGateway configuration file. +var cfgPath string // getServerCommand returns the server cobra command to be executed. func getServerCommand() *cobra.Command { diff --git a/internal/cmd/server_test.go b/internal/cmd/server_test.go index b6608445e3d..dffe10670c9 100644 --- a/internal/cmd/server_test.go +++ b/internal/cmd/server_test.go @@ -71,5 +71,4 @@ func TestGetConfigValidate(t *testing.T) { } }) } - } diff --git a/internal/crypto/certgen.go b/internal/crypto/certgen.go index 6c6ef10ccbf..de5a6584843 100644 --- a/internal/crypto/certgen.go +++ b/internal/crypto/certgen.go @@ -225,7 +225,6 @@ func newCert(request *certificateRequest) ([]byte, []byte, error) { Bytes: newCert, }) return newCertPEM, newKeyPEM, nil - } // newCA generates a new CA, given the CA's CN and an expiry time. diff --git a/internal/crypto/certgen_test.go b/internal/crypto/certgen_test.go index eb09d6d2c34..429fea518e7 100644 --- a/internal/crypto/certgen_test.go +++ b/internal/crypto/certgen_test.go @@ -129,7 +129,6 @@ func TestGeneratedValidKubeCerts(t *testing.T) { require.NoErrorf(t, err, "Validating %s failed", tc.name) }) } - } func verifyCert(certPEM []byte, roots *x509.CertPool, dnsname string, currentTime time.Time) error { diff --git a/internal/envoygateway/config/decoder_test.go b/internal/envoygateway/config/decoder_test.go index d8c8e36a230..28ce394cb7c 100644 --- a/internal/envoygateway/config/decoder_test.go +++ b/internal/envoygateway/config/decoder_test.go @@ -18,9 +18,7 @@ import ( "github.com/envoyproxy/gateway/api/v1alpha1" ) -var ( - inPath = "./testdata/decoder/in/" -) +var inPath = "./testdata/decoder/in/" func TestDecode(t *testing.T) { testCases := []struct { diff --git a/internal/envoygateway/scheme.go b/internal/envoygateway/scheme.go index 911ae708351..78567e9208c 100644 --- a/internal/envoygateway/scheme.go +++ b/internal/envoygateway/scheme.go @@ -16,15 +16,13 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) -var ( - // scheme contains all the API types necessary for the provider's dynamic - // clients to work. Any new non-core types must be added here. - // - // NOTE: The discovery mechanism used by the client doesn't automatically - // refresh, so only add types here that are guaranteed to exist before the - // provider starts. - scheme = runtime.NewScheme() -) +// scheme contains all the API types necessary for the provider's dynamic +// clients to work. Any new non-core types must be added here. +// +// NOTE: The discovery mechanism used by the client doesn't automatically +// refresh, so only add types here that are guaranteed to exist before the +// provider starts. +var scheme = runtime.NewScheme() func init() { if err := clientgoscheme.AddToScheme(scheme); err != nil { diff --git a/internal/extension/registry/xds_hook.go b/internal/extension/registry/xds_hook.go index a7962d62e7f..e53d90dcd5e 100644 --- a/internal/extension/registry/xds_hook.go +++ b/internal/extension/registry/xds_hook.go @@ -53,7 +53,6 @@ func (h *XDSHook) PostRouteModifyHook(route *route.Route, routeHostnames []strin ExtensionResources: extensionResourceBytes, }, }) - if err != nil { return nil, err } @@ -69,7 +68,6 @@ func (h *XDSHook) PostVirtualHostModifyHook(vh *route.VirtualHost) (*route.Virtu VirtualHost: vh, PostVirtualHostContext: &extension.PostVirtualHostExtensionContext{}, }) - if err != nil { return nil, err } @@ -85,7 +83,6 @@ func (h *XDSHook) PostHTTPListenerModifyHook(l *listener.Listener) (*listener.Li Listener: l, PostListenerContext: &extension.PostHTTPListenerExtensionContext{}, }) - if err != nil { return nil, err } @@ -102,7 +99,6 @@ func (h *XDSHook) PostTranslateModifyHook(clusters []*cluster.Cluster, secrets [ Clusters: clusters, Secrets: secrets, }) - if err != nil { return nil, nil, err } diff --git a/internal/extension/testutils/hooks.go b/internal/extension/testutils/hooks.go index f6b699b34b8..b7b38c1660f 100644 --- a/internal/extension/testutils/hooks.go +++ b/internal/extension/testutils/hooks.go @@ -103,7 +103,6 @@ func (c *XDSHookClient) PostVirtualHostModifyHook(vh *routeV3.VirtualHost) (*rou // A more useful use-case for an extension would be looping through the FilterChains to find the // HTTPConnectionManager(s) and inject a custom HTTPFilter, but that for testing purposes we don't need to make a complex change func (c *XDSHookClient) PostHTTPListenerModifyHook(l *listenerV3.Listener) (*listenerV3.Listener, error) { - // Only make the change when the listener's name matches the expected testdata // This prevents us from having to update every single testfile.out if l.Name == "extension-post-xdslistener-hook-error" { @@ -120,7 +119,6 @@ func (c *XDSHookClient) PostHTTPListenerModifyHook(l *listenerV3.Listener) (*lis // PostTranslateModifyHook inserts and overrides some clusters/secrets func (c *XDSHookClient) PostTranslateModifyHook(clusters []*clusterV3.Cluster, secrets []*tlsV3.Secret) ([]*clusterV3.Cluster, []*tlsV3.Secret, error) { - extensionSvcEndpoint := &endpointV3.LbEndpoint_Endpoint{ Endpoint: &endpointV3.Endpoint{ Address: &coreV3.Address{ diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go index 3a137030a1e..3dcfc9ad214 100644 --- a/internal/gatewayapi/backendtlspolicy.go +++ b/internal/gatewayapi/backendtlspolicy.go @@ -21,7 +21,8 @@ func (t *Translator) processBackendTLSPolicy( backendRef gwapiv1.BackendObjectReference, backendNamespace string, parent gwapiv1a2.ParentReference, - resources *Resources) *ir.TLSUpstreamConfig { + resources *Resources, +) *ir.TLSUpstreamConfig { tlsBundle, err := getBackendTLSBundle(resources.BackendTLSPolicies, resources.ConfigMaps, backendRef, backendNamespace) if err == nil && tlsBundle == nil { return nil @@ -78,12 +79,36 @@ func (t *Translator) processBackendTLSPolicy( } status.SetAcceptedForPolicyAncestors(&policy.Status, ancestorRefs, t.GatewayControllerName) - + // apply defaults as per envoyproxy + if resources.EnvoyProxy != nil { + if resources.EnvoyProxy.Spec.BackendTLS != nil { + if len(resources.EnvoyProxy.Spec.BackendTLS.Ciphers) > 0 { + tlsBundle.Ciphers = resources.EnvoyProxy.Spec.BackendTLS.Ciphers + } + if len(resources.EnvoyProxy.Spec.BackendTLS.ECDHCurves) > 0 { + tlsBundle.ECDHCurves = resources.EnvoyProxy.Spec.BackendTLS.ECDHCurves + } + if len(resources.EnvoyProxy.Spec.BackendTLS.SignatureAlgorithms) > 0 { + tlsBundle.SignatureAlgorithms = resources.EnvoyProxy.Spec.BackendTLS.SignatureAlgorithms + } + if resources.EnvoyProxy.Spec.BackendTLS.MinVersion != nil { + tlsBundle.MinVersion = ptr.To(ir.TLSVersion(*resources.EnvoyProxy.Spec.BackendTLS.MinVersion)) + } + if resources.EnvoyProxy.Spec.BackendTLS.MinVersion != nil { + tlsBundle.MaxVersion = ptr.To(ir.TLSVersion(*resources.EnvoyProxy.Spec.BackendTLS.MaxVersion)) + } + if len(resources.EnvoyProxy.Spec.BackendTLS.ALPNProtocols) > 0 { + tlsBundle.ALPNProtocols = make([]string, len(resources.EnvoyProxy.Spec.BackendTLS.ALPNProtocols)) + for i := range resources.EnvoyProxy.Spec.BackendTLS.ALPNProtocols { + tlsBundle.ALPNProtocols[i] = string(resources.EnvoyProxy.Spec.BackendTLS.ALPNProtocols[i]) + } + } + } + } return tlsBundle } func backendTLSTargetMatched(policy gwapiv1a2.BackendTLSPolicy, target gwapiv1a2.PolicyTargetReferenceWithSectionName) bool { - policyTarget := policy.Spec.TargetRef if target.Group == policyTarget.Group && @@ -109,7 +134,6 @@ func getBackendTLSPolicy(policies []*gwapiv1a2.BackendTLSPolicy, backendRef gwap } func getBackendTLSBundle(policies []*gwapiv1a2.BackendTLSPolicy, configmaps []*corev1.ConfigMap, backendRef gwapiv1a2.BackendObjectReference, backendNamespace string) (*ir.TLSUpstreamConfig, error) { - backendTLSPolicy := getBackendTLSPolicy(policies, backendRef, backendNamespace) if backendTLSPolicy == nil { diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index 5748caee206..b77a551d439 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -31,7 +31,8 @@ import ( func (t *Translator) ProcessBackendTrafficPolicies(backendTrafficPolicies []*egv1a1.BackendTrafficPolicy, gateways []*GatewayContext, routes []RouteContext, - xdsIR XdsIRMap) []*egv1a1.BackendTrafficPolicy { + xdsIR XdsIRMap, +) []*egv1a1.BackendTrafficPolicy { var res []*egv1a1.BackendTrafficPolicy // Sort based on timestamp @@ -389,6 +390,10 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen } r.Timeout = to } + + if policy.Spec.UseClientProtocol != nil { + r.UseClientProtocol = policy.Spec.UseClientProtocol + } } } } @@ -560,6 +565,12 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back r.Timeout = ct } } + + if policy.Spec.UseClientProtocol != nil { + if r.UseClientProtocol == nil { + r.UseClientProtocol = policy.Spec.UseClientProtocol + } + } } } @@ -621,7 +632,7 @@ func (t *Translator) buildLocalRateLimit(policy *egv1a1.BackendTrafficPolicy) (* var err error var irRule *ir.RateLimitRule - var irRules = make([]*ir.RateLimitRule, 0) + irRules := make([]*ir.RateLimitRule, 0) for _, rule := range local.Rules { // We don't process the rule without clientSelectors here because it's // previously used as the default route-level limit. diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 866e9844289..d4d059dc462 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -41,7 +41,8 @@ func hasSectionName(policy *egv1a1.ClientTrafficPolicy) bool { func (t *Translator) ProcessClientTrafficPolicies(resources *Resources, gateways []*GatewayContext, - xdsIR XdsIRMap, infraIR InfraIRMap) []*egv1a1.ClientTrafficPolicy { + xdsIR XdsIRMap, infraIR InfraIRMap, +) []*egv1a1.ClientTrafficPolicy { var res []*egv1a1.ClientTrafficPolicy clientTrafficPolicies := resources.ClientTrafficPolicies @@ -362,7 +363,8 @@ func validatePortOverlapForClientTrafficPolicy(l *ListenerContext, xds *ir.Xds, } func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.ClientTrafficPolicy, l *ListenerContext, - xdsIR XdsIRMap, infraIR InfraIRMap, resources *Resources) error { + xdsIR XdsIRMap, infraIR InfraIRMap, resources *Resources, +) error { // Find IR irKey := t.getIRKey(l.gateway) // It must exist since we've already finished processing the gateways @@ -632,7 +634,8 @@ func translateHTTP2Settings(http2Settings *egv1a1.HTTP2Settings, httpIR *ir.HTTP } func (t *Translator) translateListenerTLSParameters(policy *egv1a1.ClientTrafficPolicy, - httpIR *ir.HTTPListener, resources *Resources) error { + httpIR *ir.HTTPListener, resources *Resources, +) error { // Return if this listener isn't a TLS listener. There has to be // at least one certificate defined, which would cause httpIR to // have a TLS structure. diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index 3c0305db71b..2e1fe34ffde 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -10,13 +10,13 @@ import ( "fmt" "sort" "strings" + "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/utils/ptr" - gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gwv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" @@ -30,7 +30,8 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv gateways []*GatewayContext, routes []RouteContext, resources *Resources, - xdsIR XdsIRMap) []*egv1a1.EnvoyExtensionPolicy { + xdsIR XdsIRMap, +) []*egv1a1.EnvoyExtensionPolicy { var res []*egv1a1.EnvoyExtensionPolicy // Sort based on timestamp @@ -293,7 +294,8 @@ func resolveEEPolicyRouteTargetRef(policy *egv1a1.EnvoyExtensionPolicy, routes m } func (t *Translator) translateEnvoyExtensionPolicyForRoute(policy *egv1a1.EnvoyExtensionPolicy, route RouteContext, - xdsIR XdsIRMap, resources *Resources) error { + xdsIR XdsIRMap, resources *Resources, +) error { var ( extProcs []ir.ExtProc wasms []ir.Wasm @@ -343,7 +345,8 @@ func (t *Translator) buildExtProcs(policy *egv1a1.EnvoyExtensionPolicy, resource } func (t *Translator) translateEnvoyExtensionPolicyForGateway(policy *egv1a1.EnvoyExtensionPolicy, - gateway *GatewayContext, xdsIR XdsIRMap, resources *Resources) error { + gateway *GatewayContext, xdsIR XdsIRMap, resources *Resources, +) error { var ( extProcs []ir.ExtProc wasms []ir.Wasm @@ -398,50 +401,81 @@ func (t *Translator) buildExtProc( policyNamespacedName types.NamespacedName, extProc egv1a1.ExtProc, extProcIdx int, - resources *Resources) (*ir.ExtProc, error) { + resources *Resources, +) (*ir.ExtProc, error) { var ( - backendRef *gwapiv1.BackendObjectReference - ds *ir.DestinationSetting - authority string - err error + ds *ir.DestinationSetting + authority string + err error ) - backendRef = &extProc.BackendRef.BackendObjectReference - - if err = t.validateExtServiceBackendReference( - backendRef, - policyNamespacedName.Namespace, - resources); err != nil { - return nil, err - } + var dsl []*ir.DestinationSetting + for i := range extProc.BackendRefs { + if err = t.validateExtServiceBackendReference( + &extProc.BackendRefs[i].BackendObjectReference, + policyNamespacedName.Namespace, + resources); err != nil { + return nil, err + } - authority = fmt.Sprintf( - "%s.%s:%d", - backendRef.Name, - NamespaceDerefOr(backendRef.Namespace, policyNamespacedName.Namespace), - *backendRef.Port) + ds, err = t.processExtServiceDestination( + &extProc.BackendRefs[i].BackendObjectReference, + policyNamespacedName, + egv1a1.KindEnvoyExtensionPolicy, + ir.GRPC, + resources) + if err != nil { + return nil, err + } - if ds, err = t.processExtServiceDestination( - backendRef, - policyNamespacedName, - egv1a1.KindEnvoyExtensionPolicy, - ir.GRPC, - resources); err != nil { - return nil, err + dsl = append(dsl, ds) } rd := ir.RouteDestination{ - Name: irIndexedExtServiceDestinationName(policyNamespacedName, egv1a1.KindEnvoyExtensionPolicy, - string(backendRef.Name), extProcIdx), - Settings: []*ir.DestinationSetting{ds}, + Name: irIndexedExtServiceDestinationName(policyNamespacedName, egv1a1.KindEnvoyExtensionPolicy, extProcIdx), + Settings: dsl, } + authority = fmt.Sprintf( + "%s.%s:%d", + extProc.BackendRefs[0].Name, + NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace), + *extProc.BackendRefs[0].Port) + extProcIR := &ir.ExtProc{ Name: name, Destination: rd, Authority: authority, } + if extProc.MessageTimeout != nil { + d, err := time.ParseDuration(string(*extProc.MessageTimeout)) + if err != nil { + return nil, fmt.Errorf("invalid ExtProc MessageTimeout value %v", extProc.MessageTimeout) + } + extProcIR.MessageTimeout = ptr.To(metav1.Duration{Duration: d}) + } + + if extProc.FailOpen != nil { + extProcIR.FailOpen = extProc.FailOpen + } + + if extProc.ProcessingMode != nil { + if extProc.ProcessingMode.Request != nil { + extProcIR.RequestHeaderProcessing = true + if extProc.ProcessingMode.Request.Body != nil { + extProcIR.RequestBodyProcessingMode = ptr.To(ir.ExtProcBodyProcessingMode(*extProc.ProcessingMode.Request.Body)) + } + } + + if extProc.ProcessingMode.Response != nil { + extProcIR.ResponseHeaderProcessing = true + if extProc.ProcessingMode.Response.Body != nil { + extProcIR.ResponseBodyProcessingMode = ptr.To(ir.ExtProcBodyProcessingMode(*extProc.ProcessingMode.Response.Body)) + } + } + } + return extProcIR, err } diff --git a/internal/gatewayapi/ext_service.go b/internal/gatewayapi/ext_service.go index a14e2b1258e..ec1c77063a0 100644 --- a/internal/gatewayapi/ext_service.go +++ b/internal/gatewayapi/ext_service.go @@ -26,7 +26,8 @@ func (t *Translator) processExtServiceDestination( policyNamespacedName types.NamespacedName, policyKind string, protocol ir.AppProtocol, - resources *Resources) (*ir.DestinationSetting, error) { + resources *Resources, +) (*ir.DestinationSetting, error) { var ( endpoints []*ir.DestinationEndpoint addrType *ir.DestinationAddressType @@ -93,12 +94,11 @@ func (t *Translator) processExtServiceDestination( } // TODO: also refer to extension type, as WASM may also introduce destinations -func irIndexedExtServiceDestinationName(policyNamespacedName types.NamespacedName, policyKind, service string, idx int) string { +func irIndexedExtServiceDestinationName(policyNamespacedName types.NamespacedName, policyKind string, idx int) string { return strings.ToLower(fmt.Sprintf( - "%s/%s/%s/%d/%s", + "%s/%s/%s/%d", policyKind, policyNamespacedName.Namespace, policyNamespacedName.Name, - idx, - service)) + idx)) } diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go index c728e1e863b..1cde4541f48 100644 --- a/internal/gatewayapi/filters.go +++ b/internal/gatewayapi/filters.go @@ -64,7 +64,8 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext, route RouteContext, filters []gwapiv1.HTTPRouteFilter, ruleIdx int, - resources *Resources) *HTTPFiltersContext { + resources *Resources, +) *HTTPFiltersContext { httpFiltersContext := &HTTPFiltersContext{ ParentRef: parentRef, Route: route, @@ -107,7 +108,8 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext, func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext, route RouteContext, filters []v1alpha2.GRPCRouteFilter, - resources *Resources) *HTTPFiltersContext { + resources *Resources, +) *HTTPFiltersContext { httpFiltersContext := &HTTPFiltersContext{ ParentRef: parentRef, Route: route, @@ -144,7 +146,8 @@ func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext, func (t *Translator) processURLRewriteFilter( rewrite *gwapiv1.HTTPURLRewriteFilter, - filterContext *HTTPFiltersContext) { + filterContext *HTTPFiltersContext, +) { if filterContext.URLRewrite != nil { filterContext.ParentRef.SetCondition(filterContext.Route, gwapiv1.RouteConditionAccepted, @@ -246,7 +249,8 @@ func (t *Translator) processURLRewriteFilter( func (t *Translator) processRedirectFilter( redirect *gwapiv1.HTTPRequestRedirectFilter, - filterContext *HTTPFiltersContext) { + filterContext *HTTPFiltersContext, +) { // Can't have two redirects for the same route if filterContext.RedirectResponse != nil { filterContext.ParentRef.SetCondition(filterContext.Route, @@ -347,7 +351,8 @@ func (t *Translator) processRedirectFilter( func (t *Translator) processRequestHeaderModifierFilter( headerModifier *gwapiv1.HTTPHeaderFilter, - filterContext *HTTPFiltersContext) { + filterContext *HTTPFiltersContext, +) { // Make sure the header modifier config actually exists if headerModifier == nil { return @@ -500,7 +505,8 @@ func (t *Translator) processRequestHeaderModifierFilter( func (t *Translator) processResponseHeaderModifierFilter( headerModifier *gwapiv1.HTTPHeaderFilter, - filterContext *HTTPFiltersContext) { + filterContext *HTTPFiltersContext, +) { // Make sure the header modifier config actually exists if headerModifier == nil { return @@ -693,8 +699,8 @@ func (t *Translator) processRequestMirrorFilter( filterIdx int, mirrorFilter *gwapiv1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, - resources *Resources) { - + resources *Resources, +) { // Make sure the config actually exists if mirrorFilter == nil { return diff --git a/internal/gatewayapi/resource.go b/internal/gatewayapi/resource.go index f930801c2bf..7ba85502b99 100644 --- a/internal/gatewayapi/resource.go +++ b/internal/gatewayapi/resource.go @@ -22,8 +22,10 @@ import ( "github.com/envoyproxy/gateway/internal/ir" ) -type XdsIRMap map[string]*ir.Xds -type InfraIRMap map[string]*ir.Infra +type ( + XdsIRMap map[string]*ir.Xds + InfraIRMap map[string]*ir.Infra +) // Resources holds the Gateway API and related // resources that the translators needs as inputs. diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 1b0ac613bdd..ce2efc55be6 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -132,7 +132,7 @@ func (t *Translator) processHTTPRouteParentRefs(httpRoute *HTTPRouteContext, res continue } - var hasHostnameIntersection = t.processHTTPRouteParentRefListener(httpRoute, routeRoutes, parentRef, xdsIR) + hasHostnameIntersection := t.processHTTPRouteParentRefListener(httpRoute, routeRoutes, parentRef, xdsIR) if !hasHostnameIntersection { parentRef.SetCondition(httpRoute, gwapiv1.RouteConditionAccepted, @@ -391,7 +391,6 @@ func applyHTTPFiltersContextToIRRoute(httpFiltersContext *HTTPFiltersContext, ir if len(httpFiltersContext.ExtensionRefs) > 0 { irRoute.ExtensionRefs = httpFiltersContext.ExtensionRefs } - } func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, resources *Resources, xdsIR XdsIRMap) { @@ -424,7 +423,7 @@ func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, res if parentRef.HasCondition(grpcRoute, gwapiv1.RouteConditionAccepted, metav1.ConditionFalse) { continue } - var hasHostnameIntersection = t.processHTTPRouteParentRefListener(grpcRoute, routeRoutes, parentRef, xdsIR) + hasHostnameIntersection := t.processHTTPRouteParentRefListener(grpcRoute, routeRoutes, parentRef, xdsIR) if !hasHostnameIntersection { parentRef.SetCondition(grpcRoute, gwapiv1.RouteConditionAccepted, @@ -801,7 +800,8 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour } func (t *Translator) ProcessUDPRoutes(udpRoutes []*gwapiv1a2.UDPRoute, gateways []*GatewayContext, resources *Resources, - xdsIR XdsIRMap) []*UDPRouteContext { + xdsIR XdsIRMap, +) []*UDPRouteContext { var relevantUDPRoutes []*UDPRouteContext for _, u := range udpRoutes { @@ -932,7 +932,8 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour } func (t *Translator) ProcessTCPRoutes(tcpRoutes []*gwapiv1a2.TCPRoute, gateways []*GatewayContext, resources *Resources, - xdsIR XdsIRMap) []*TCPRouteContext { + xdsIR XdsIRMap, +) []*TCPRouteContext { var relevantTCPRoutes []*TCPRouteContext for _, tcp := range tcpRoutes { @@ -1068,7 +1069,8 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour func (t *Translator) processDestination(backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, - resources *Resources) (ds *ir.DestinationSetting, backendWeight uint32) { + resources *Resources, +) (ds *ir.DestinationSetting, backendWeight uint32) { routeType := GetRouteType(route) weight := uint32(1) backendRef := GetBackendRef(backendRefContext) diff --git a/internal/gatewayapi/runner/runner_test.go b/internal/gatewayapi/runner/runner_test.go index 772f0372a3c..a48188cccb7 100644 --- a/internal/gatewayapi/runner/runner_test.go +++ b/internal/gatewayapi/runner/runner_test.go @@ -59,7 +59,6 @@ func TestRunner(t *testing.T) { // Ensure ir is empty return (reflect.DeepEqual(xdsIR.LoadAll(), map[string]*ir.Xds{})) && (reflect.DeepEqual(infraIR.LoadAll(), map[string]*ir.Infra{})) }, time.Second*1, time.Millisecond*20) - } func TestGetIRKeysToDelete(t *testing.T) { @@ -75,7 +74,8 @@ func TestGetIRKeysToDelete(t *testing.T) { newKeys: []string{}, delKeys: []string{}, }, - {name: "no new keys", + { + name: "no new keys", curKeys: []string{"one", "two"}, newKeys: []string{}, delKeys: []string{"one", "two"}, diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index f03e46590db..6723376c00c 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -45,7 +45,8 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security gateways []*GatewayContext, routes []RouteContext, resources *Resources, - xdsIR XdsIRMap) []*egv1a1.SecurityPolicy { + xdsIR XdsIRMap, +) []*egv1a1.SecurityPolicy { var res []*egv1a1.SecurityPolicy // Sort based on timestamp @@ -225,7 +226,8 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security func resolveSecurityPolicyGatewayTargetRef( policy *egv1a1.SecurityPolicy, - gateways map[types.NamespacedName]*policyGatewayTargetContext) (*GatewayContext, *status.PolicyResolveError) { + gateways map[types.NamespacedName]*policyGatewayTargetContext, +) (*GatewayContext, *status.PolicyResolveError) { targetNs := policy.Spec.TargetRef.Namespace // If empty, default to namespace of policy if targetNs == nil { @@ -278,7 +280,8 @@ func resolveSecurityPolicyGatewayTargetRef( func resolveSecurityPolicyRouteTargetRef( policy *egv1a1.SecurityPolicy, - routes map[policyTargetRouteKey]*policyRouteTargetContext) (RouteContext, *status.PolicyResolveError) { + routes map[policyTargetRouteKey]*policyRouteTargetContext, +) (RouteContext, *status.PolicyResolveError) { targetNs := policy.Spec.TargetRef.Namespace // If empty, default to namespace of policy if targetNs == nil { @@ -333,7 +336,8 @@ func resolveSecurityPolicyRouteTargetRef( func (t *Translator) translateSecurityPolicyForRoute( policy *egv1a1.SecurityPolicy, route RouteContext, - resources *Resources, xdsIR XdsIRMap) error { + resources *Resources, xdsIR XdsIRMap, +) error { // Build IR var ( cors *ir.CORS @@ -404,7 +408,8 @@ func (t *Translator) translateSecurityPolicyForRoute( func (t *Translator) translateSecurityPolicyForGateway( policy *egv1a1.SecurityPolicy, gateway *GatewayContext, - resources *Resources, xdsIR XdsIRMap) error { + resources *Resources, xdsIR XdsIRMap, +) error { // Build IR var ( cors *ir.CORS @@ -534,7 +539,8 @@ func (t *Translator) buildJWT(jwt *egv1a1.JWT) *ir.JWT { func (t *Translator) buildOIDC( policy *egv1a1.SecurityPolicy, - resources *Resources) (*ir.OIDC, error) { + resources *Resources, +) (*ir.OIDC, error) { var ( oidc = policy.Spec.OIDC clientSecret *v1.Secret @@ -726,7 +732,8 @@ func validateTokenEndpoint(tokenEndpoint string) error { func (t *Translator) buildBasicAuth( policy *egv1a1.SecurityPolicy, - resources *Resources) (*ir.BasicAuth, error) { + resources *Resources, +) (*ir.BasicAuth, error) { var ( basicAuth = policy.Spec.BasicAuth usersSecret *v1.Secret @@ -758,7 +765,8 @@ func (t *Translator) buildBasicAuth( func (t *Translator) buildExtAuth( policy *egv1a1.SecurityPolicy, - resources *Resources) (*ir.ExtAuth, error) { + resources *Resources, +) (*ir.ExtAuth, error) { var ( http = policy.Spec.ExtAuth.HTTP grpc = policy.Spec.ExtAuth.GRPC diff --git a/internal/gatewayapi/sort.go b/internal/gatewayapi/sort.go index 75d9ebc503a..c11787a60dc 100644 --- a/internal/gatewayapi/sort.go +++ b/internal/gatewayapi/sort.go @@ -16,7 +16,6 @@ type XdsIRRoutes []*ir.HTTPRoute func (x XdsIRRoutes) Len() int { return len(x) } func (x XdsIRRoutes) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func (x XdsIRRoutes) Less(i, j int) bool { - // 1. Sort based on path match type // Exact > RegularExpression > PathPrefix if x[i].PathMatch != nil && x[i].PathMatch.Exact != nil { diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.in.yaml new file mode 100644 index 00000000000..5cb15cfc3c6 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.in.yaml @@ -0,0 +1,49 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: envoy-gateway + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + useClientProtocol: true + diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.out.yaml new file mode 100644 index 00000000000..e2f632b1a52 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.out.yaml @@ -0,0 +1,160 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + useClientProtocol: true + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +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: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + 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 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + 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 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + useClientProtocol: true diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.in.yaml index 0f6d26cf62c..6f4ed53ab78 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.in.yaml @@ -26,6 +26,6 @@ envoyExtensionPolicies: name: gateway-1 namespace: envoy-gateway extProc: - - backendRef: - name: grpc-backend-4 + - backendRefs: + - name: grpc-backend-4 port: 4000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.out.yaml index 1deb8ca6b25..a545e58625b 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend-4 + - backendRefs: + - name: grpc-backend-4 port: 4000 targetRef: group: gateway.networking.k8s.io diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml index ce4ecde3766..1d4c61cc7f7 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml @@ -86,8 +86,8 @@ envoyExtensionPolicies: name: gateway-1 namespace: envoy-gateway extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend port: 9000 - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyExtensionPolicy @@ -101,6 +101,6 @@ envoyExtensionPolicies: name: httproute-1 namespace: default extProc: - - backendRef: - name: grpc-backend-2 + - backendRefs: + - name: grpc-backend-2 port: 8000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml index 0fd8d36b3ca..cc9921a6bd7 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend-2 + - backendRefs: + - name: grpc-backend-2 port: 8000 targetRef: group: gateway.networking.k8s.io @@ -38,8 +38,8 @@ envoyExtensionPolicies: namespace: envoy-gateway spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend port: 9000 targetRef: group: gateway.networking.k8s.io @@ -231,7 +231,7 @@ xdsIR: extProc: - authority: grpc-backend-2.default:8000 destination: - name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + name: envoyextensionpolicy/default/policy-for-route-1/0 settings: - protocol: GRPC weight: 1 @@ -258,7 +258,7 @@ xdsIR: extProc: - authority: grpc-backend.envoy-gateway:9000 destination: - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0 settings: - protocol: GRPC weight: 1 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.in.yaml index 78989127328..982d7da84e6 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.in.yaml @@ -55,6 +55,6 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend port: 4000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml index 55e0b661896..740230fbf21 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend port: 4000 targetRef: group: gateway.networking.k8s.io diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.in.yaml index b2420abfa9d..abb0bf36596 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.in.yaml @@ -55,5 +55,5 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml index 05db4b4438c..50c1a7371d4 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.in.yaml index 6d3ec1fdd7e..71f453ec95b 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.in.yaml @@ -55,7 +55,7 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 9000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml index c4ad278a6c4..f62b31daa94 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 9000 targetRef: diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.in.yaml index eff5a17efd2..b58eeee0978 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.in.yaml @@ -46,7 +46,7 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 9000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml index 7155bfe7243..3ea2c40f4d9 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 9000 targetRef: diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.in.yaml index 21c6fab4506..fb3d3cab153 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.in.yaml @@ -201,10 +201,17 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - Name: grpc-backend + - backendRefs: + - Name: grpc-backend Namespace: envoy-gateway Port: 8000 + processingMode: + request: + body: Buffered + response: + body: Streamed + messageTimeout: 5s + failOpen: true - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyExtensionPolicy metadata: @@ -217,6 +224,9 @@ envoyExtensionPolicies: name: httproute-1 namespace: default extProc: - - backendRef: - Name: grpc-backend-2 + - backendRefs: + - Name: grpc-backend-2 Port: 9000 + processingMode: + request: {} + response: {} diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml index c8eb952e580..e33b83f0ec4 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml @@ -73,9 +73,12 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend-2 + - backendRefs: + - name: grpc-backend-2 port: 9000 + processingMode: + request: {} + response: {} targetRef: group: gateway.networking.k8s.io kind: HTTPRoute @@ -104,10 +107,17 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 8000 + failOpen: true + messageTimeout: 5s + processingMode: + request: + body: Buffered + response: + body: Streamed targetRef: group: gateway.networking.k8s.io kind: Gateway @@ -298,7 +308,7 @@ xdsIR: extProc: - authority: grpc-backend-2.default:9000 destination: - name: envoyextensionpolicy/default/policy-for-http-route/0/grpc-backend-2 + name: envoyextensionpolicy/default/policy-for-http-route/0 settings: - addressType: IP endpoints: @@ -312,6 +322,8 @@ xdsIR: sni: grpc-backend-2 weight: 1 name: envoyextensionpolicy/default/policy-for-http-route/0 + requestHeaderProcessing: true + responseHeaderProcessing: true hostname: www.foo.com isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/www_foo_com @@ -334,7 +346,7 @@ xdsIR: extProc: - authority: grpc-backend.envoy-gateway:8000 destination: - name: envoyextensionpolicy/default/policy-for-gateway/0/grpc-backend + name: envoyextensionpolicy/default/policy-for-gateway/0 settings: - addressType: IP protocol: GRPC @@ -344,7 +356,13 @@ xdsIR: name: policy-btls-grpc/default-ca sni: grpc-backend weight: 1 + failOpen: true + messageTimeout: 5s name: envoyextensionpolicy/default/policy-for-gateway/0 + requestBodyProcessingMode: Buffered + requestHeaderProcessing: true + responseBodyProcessingMode: Streamed + responseHeaderProcessing: true hostname: www.bar.com isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/www_bar_com diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml new file mode 100644 index 00000000000..a278b45a903 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml @@ -0,0 +1,192 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: default + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - www.foo.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /foo + backendRefs: + - name: service-1 + port: 8080 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + hostnames: + - www.bar.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /bar + backendRefs: + - name: service-1 + port: 8080 +services: +- apiVersion: v1 + kind: Service + metadata: + namespace: envoy-gateway + name: grpc-backend + spec: + ports: + - port: 8000 + name: grpc + protocol: TCP +- apiVersion: v1 + kind: Service + metadata: + namespace: default + name: grpc-backend-2 + spec: + ports: + - port: 9000 + name: grpc + protocol: TCP +endpointSlices: +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend + namespace: envoy-gateway + labels: + kubernetes.io/service-name: grpc-backend + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 8000 + endpoints: + - addresses: + - 7.7.7.7 + conditions: + ready: true +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend-2 + namespace: default + labels: + kubernetes.io/service-name: grpc-backend-2 + addressType: IPv4 + ports: + - name: grpc + protocol: TCP + port: 9000 + endpoints: + - addresses: + - 8.8.8.8 + conditions: + ready: true +referenceGrants: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: ReferenceGrant + metadata: + namespace: envoy-gateway + name: referencegrant-1 + spec: + from: + - group: gateway.envoyproxy.io + kind: SecurityPolicy + namespace: default + - group: gateway.networking.k8s.io + kind: BackendTLSPolicy + namespace: default + to: + - group: '' + kind: Service +configMaps: +- apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-cmap + namespace: default + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDJzCCAg+gAwIBAgIUAl6UKIuKmzte81cllz5PfdN2IlIwDQYJKoZIhvcNAQEL + BQAwIzEQMA4GA1UEAwwHbXljaWVudDEPMA0GA1UECgwGa3ViZWRiMB4XDTIzMTAw + MjA1NDE1N1oXDTI0MTAwMTA1NDE1N1owIzEQMA4GA1UEAwwHbXljaWVudDEPMA0G + A1UECgwGa3ViZWRiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSTc + 1yj8HW62nynkFbXo4VXKv2jC0PM7dPVky87FweZcTKLoWQVPQE2p2kLDK6OEszmM + yyr+xxWtyiveremrWqnKkNTYhLfYPhgQkczib7eUalmFjUbhWdLvHakbEgCodn3b + kz57mInX2VpiDOKg4kyHfiuXWpiBqrCx0KNLpxo3DEQcFcsQTeTHzh4752GV04RU + Ti/GEWyzIsl4Rg7tGtAwmcIPgUNUfY2Q390FGqdH4ahn+mw/6aFbW31W63d9YJVq + ioyOVcaMIpM5B/c7Qc8SuhCI1YGhUyg4cRHLEw5VtikioyE3X04kna3jQAj54YbR + bpEhc35apKLB21HOUQIDAQABo1MwUTAdBgNVHQ4EFgQUyvl0VI5vJVSuYFXu7B48 + 6PbMEAowHwYDVR0jBBgwFoAUyvl0VI5vJVSuYFXu7B486PbMEAowDwYDVR0TAQH/ + BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAMLxrgFVMuNRq2wAwcBt7SnNR5Cfz + 2MvXq5EUmuawIUi9kaYjwdViDREGSjk7JW17vl576HjDkdfRwi4E28SydRInZf6J + i8HZcZ7caH6DxR335fgHVzLi5NiTce/OjNBQzQ2MJXVDd8DBmG5fyatJiOJQ4bWE + A7FlP0RdP3CO3GWE0M5iXOB2m1qWkE2eyO4UHvwTqNQLdrdAXgDQlbam9e4BG3Gg + d/6thAkWDbt/QNT+EJHDCvhDRKh1RuGHyg+Y+/nebTWWrFWsktRrbOoHCZiCpXI1 + 3eXE6nt0YkgtDxG22KqnhpAg9gUSs2hlhoxyvkzyF0mu6NhPlwAgnq7+/Q== + -----END CERTIFICATE----- +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-grpc + namespace: default + spec: + targetRef: + group: '' + kind: Service + name: grpc-backend + namespace: envoy-gateway + sectionName: "8000" + tls: + caCertRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: grpc-backend +envoyExtensionPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + namespace: default + name: policy-for-http-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + extProc: + - backendRefs: + - Name: grpc-backend + Namespace: envoy-gateway + Port: 8000 + - Name: grpc-backend-2 + Port: 9000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml new file mode 100755 index 00000000000..a26a321d6e6 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml @@ -0,0 +1,277 @@ +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-grpc + namespace: default + spec: + targetRef: + group: "" + kind: Service + name: grpc-backend + namespace: envoy-gateway + sectionName: "8000" + tls: + caCertRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: grpc-backend + status: + ancestors: + - ancestorRef: + group: gateway.envoyproxy.io + kind: EnvoyExtensionPolicy + name: policy-for-http-route + namespace: default + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +envoyExtensionPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + creationTimestamp: null + name: policy-for-http-route + namespace: default + spec: + extProc: + - backendRefs: + - name: grpc-backend + namespace: envoy-gateway + port: 8000 + - name: grpc-backend-2 + port: 9000 + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: default + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 2 + 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 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - www.foo.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /foo + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: default + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + hostnames: + - www.bar.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /bar + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: default + sectionName: http +infraIR: + default/gateway-1: + proxy: + listeners: + - address: null + name: default/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: default + name: default/gateway-1 +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + extProc: + - authority: grpc-backend.envoy-gateway:8000 + destination: + name: envoyextensionpolicy/default/policy-for-http-route/0 + settings: + - addressType: IP + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-grpc/default-ca + sni: grpc-backend + weight: 1 + - addressType: IP + endpoints: + - host: 8.8.8.8 + port: 9000 + protocol: GRPC + weight: 1 + name: envoyextensionpolicy/default/policy-for-http-route/0 + hostname: www.foo.com + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.bar.com + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings.in.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings.in.yaml new file mode 100644 index 00000000000..f46ecc052e2 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings.in.yaml @@ -0,0 +1,136 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-tls + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + namespace: envoy-gateway + group: "" + name: default-cert +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-tls + namespace: envoy-gateway + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-tls + rules: + - backendRefs: + - name: https-backend + namespace: default + port: 443 +referenceGrants: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: ReferenceGrant + metadata: + name: refg-route-svc + namespace: default + spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: envoy-gateway + - group: gateway.networking.k8s.io + kind: Gateway + namespace: envoy-gateway + - group: gateway.networking.k8s.io + kind: BackendTLSPolicy + namespace: default + to: + - group: "" + kind: Service +services: + - apiVersion: v1 + kind: Service + metadata: + name: https-backend + namespace: default + spec: + clusterIP: 10.11.12.13 + ports: + - port: 443 + name: https + protocol: TCP + targetPort: 443 + +endpointSlices: + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-https-backend + namespace: default + labels: + kubernetes.io/service-name: https-backend + addressType: IPv4 + ports: + - name: https + protocol: TCP + port: 443 + endpoints: + - addresses: + - "10.244.0.11" + conditions: + ready: true +backendTLSPolicies: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-tls + namespace: default + spec: + targetRef: + group: '' + kind: Service + name: https-backend + tls: + wellKnownCACerts: System + hostname: example.com +envoyproxy: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + namespace: envoy-gateway-system + name: test + spec: + backendTLS: + clientCertificateRef: + group: "" + kind: Secret + namespace: default + name: secret.yaml + ciphers: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + ecdhCurves: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + maxVersion: tls1.3 + minVersion: tls1.2 + SignatureAlgorithms: + - RSA-PSS-RSAE-SHA256 + - ECDSA-SECP256R1-SHA256 + alpnProtocols: + - HTTP/1.1 + - HTTP/2 +secrets: + - apiVersion: v1 + kind: Secret + metadata: + name: default-cert + namespace: envoy-gateway + type: kubernetes.io/tls + data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKRENDQWd5Z0F3SUJBZ0lVU3JTYktMZjBiTEVHb2dXeC9nQ3cyR0N0dnhFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0V6RVJNQThHQTFVRUF3d0lWR1Z6ZENCSmJtTXdIaGNOTWpRd01qSTVNRGt6TURFd1doY05NelF3TWpJMgpNRGt6TURFd1dqQVRNUkV3RHdZRFZRUUREQWhVWlhOMElFbHVZekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBSzFKempQSWlXZzNxb0hTckFkZGtlSmphTVA5aXlNVGkvQlBvOWNKUG9SRThaaTcKV2FwVXJYTC85QTlyK2pITXlHSVpOWk5kY1o1Y1kyWHYwTFA4WnhWeTJsazArM3d0WXpIbnBHWUdWdHlxMnRldApEaEZzaVBsODJZUmpDMG16V2E0UU16NFNYekZITmdJRHBSZGhmcm92bXNldVdHUUU4cFY0VWQ5VUsvU0tpbE1PCnF0QjVKaXJMUDJWczVUMW9XaWNXTFF2ZmJHd3Y3c0ZEZHI5YkcwWHRTUXAxN0hTZ281MFNERTUrQmpTbXB0RncKMVZjS0xscWFoTVhCRERpb3Jnd2hJaEdHS3BFU2VNMFA3YkZoVm1rTTNhc2gyeFNUQnVGVUJEbEU0Sk9haHp3cwpEWHJ1cFVoRGRTMWhkYzJmUHJqaEZBbEpmV0VZWjZCbFpqeXNpVlVDQXdFQUFhTndNRzR3SFFZRFZSME9CQllFCkZCUXVmSzFMaWJ1Vm05VHMvVmpCeDhMM3VpTmVNQjhHQTFVZEl3UVlNQmFBRkJRdWZLMUxpYnVWbTlUcy9WakIKeDhMM3VpTmVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdHd1lEVlIwUkJCUXdFb0lCS29JTktpNWxlR0Z0Y0d4bApMbU52YlRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWZQUzQxYWdldldNVjNaWHQwQ09GRzN1WWZQRlhuVnc2ClA0MXA5TzZHa2RZc3VxRnZQZVR5eUgyL2RBSUtLd1N6TS9wdGhnOEtuOExabG1KeUZObkExc3RKeG41WGRiVjEKcFBxajhVdllDQnp5ak1JcW1SeW9peUxpUWxib2hNYTBVZEVCS2NIL1BkTEU5SzhUR0pyWmdvR1hxcTFXbWl0RAozdmNQalNlUEtFaVVKVlM5bENoeVNzMEtZNUIraFVRRDBKajZucEZENFprMHhxZHhoMHJXdWVDcXE3dmpxRVl6CnBqNFB3cnVmbjFQQlRtZnhNdVYvVUpWNWViaWtldVpQMzVrV3pMUjdaV0FMN3d1RGRXcC82bzR5azNRTGFuRFEKQ3dnQ0ZjWCtzcyswVnl1TTNZZXJUT1VVOFFWSkp4NFVaQU5aeDYrNDNwZEpaT2NudFBaNENBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV1Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktRd2dnU2dBZ0VBQW9JQkFRQ1pTT21NUlBXWkFqN08KcVFrTVc2d3Bub3NmVCtRMzhmVWJ1U3crRXlablZ1eUNuYlVGZjhIeTVyYkx1K2dmbWszUW8xbnRBVTMzamprUQpXMGQzRHdCdWhKVUM0bkpVRks3cDk2dm9MQ2FTdmlPM0NQbytjUENPdkZ4K1ZrTzYxVkxXOEI2YW04UG5GWndhCmlGRGk0aUdyWXlIK3lsK2RUTmJoZlhIeEJ4T0E1M0IrcTI2K2ZmMFJXUWJKSWNiT1RzOENTSDZJWk1yeGNIcmsKOE1TdjFhWXlQdXpuT1BBQVFsNlRUdlEvNmhJZnF6bXJvd0RIRjRCMENFNUFvb2xFM0ZLT2kwaC9ieTJUN1dxbgo4NkdhdXA0VEtxVnV1Uk5hUU1CZDQ4azA4V3VTUENYSDBoWTVJbm1kdEMxRURKK3pQRk9NUjQycVA0THg5QWdICjNRZTBTMU5yQWdNQkFBRUNnZjk2Zy9QWXh2YVp5NEJuMU5ySkJkOExaT2djYlpjMmdueDZJa3YvVVhaME5obHgKRVlpS2plRmpWNkhXNW9FWHJaKy9tUGY0ZHVzVmFMNzRVOVZvanVQSmNlQWVScmpMM2VPaGJIdGN4KzBnY0dMZwpYeEY5VFJhcDY1VHVVZDFhaTA0aEd3WWY3NXNiUDdSS2JQaXZ3WmdVQWUwQ3BWdWZjaG5YcXJzWXI4cEpZNTFPCldWa1NxejRSWTlXbTBrNUcxSkZ5SXlFQzl1bURsdWpjSE50UlZtYWZrTmZBdENsaVByRktjL245bkpmTzZSRlAKN2c3Vi9JdnFudUlyN1BFM0duNlBhVCtCZ2c0NDh0ZDVKelBwVEE1WkJjQm8yb3J6L2t4WVBGcHIvZ1BVQnFRZApvNm5XcXc3Nlp4d1BsZHdMaEorWFlOWDdvdWN0VVNDTDl1NzdmeUVDZ1lFQXl2N0RseGYrS1FsZkR3bW8vcjFUCjBMMVpuSDQ3MmhpSWVkU2hleVZCSGJFVlRTbXI0MkJSbGpXNERiUmNRTTRWY3h4RGtHclI3NlJHZTlvZzZtemMKUnY4K1ZsQ1gyK3F5OXA1bTZaWHJiQXczMHpDLzVtUGtSV3ViaFVoaSs5ZUNNWmEvaEFJL1JGdjI2OURyQkQyLwo2a2cwRjhYME8vNndJK1dwYXRLM1cwY0NnWUVBd1U5QTZiSnBmYVhLS1hQR21PRy9uVXhUeXp5cVlqS05aSmQvCjlHaEVudUdqSzVDQUVWUEphOGtadmZRemxXbXdaYWZxMERocUk4dkxhRkNEZjhZOEU5OU1hbjNHV2hVYjNWL0oKcU5RUVMzNTZOQ2ZadzdseG9LS0JJdlQ2Y3dpaFRuc0UvUjRIQ3NhbDJ3d040Wmw5SFdOQmdhbVM3VExrejFMaApmd1JEa0wwQ2dZQlo0OWorNW53QTlncG5JVkw1Z3lORGN5WGtlNjNMVlVQU0YwdHV1YitOQTJhNFpiU2RHb0RtCmNHRlJpRVcxMk14OHpjNUpmRlA4dDVVU3NUUVVPeUtNT2VrRDFlcDVVd1B1MjVRYzZldDNUQzNJVW5VWDg3SVkKMzU3ZHRZRkhubFlqMldwemJYOVFxUnk5cmlUMEd0Z0tTZkR2ZWhRK0lQa2szRVZhYlhjT2J3S0JnR0d4QzcwTwp6UUVTcC9nSzZuS1lvNTE2MVY0QWFwcjFzVDhFMFVWUzdGcmU3UGMzTDRHU05saWlhTC8yaVpzWXJteXhUNW1xCjZQanVKUDJ5c3NJQURKeCtYTC8wa0NrMlFiNitpY3NvWUpQR2R6dWthQWpoenVxL05VUFZTanlZUCt6SmZ0dnMKTU9MaFFUQlNCekhidjc3NlNrQ2MwZ1BObEpTeDdnT2l4QUtCQW9HQUpCR1VuM2U1QWZDb21BMUUxRHhSeUxaagpUMFBrQUNlUGpEK3hrRkpod0RoQ2dzd2htNFVKZzFmQW8xaEJRUkZ0dHBWQy91QkxjazE4TUVBSTF2ZGZTeVB2CmtTZzVrVnFQanUzc2czOVRNZ09WZXdqUDNFM0FNUUd1ZzFQNzFZazJ6WUpQbGg5NWRMVTVISlZubzZvdkIrUG0KTHF5K016eDN3a0YwZDhlUFhRND0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml new file mode 100644 index 00000000000..36ecc443361 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml @@ -0,0 +1,204 @@ +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-tls + namespace: default + spec: + targetRef: + group: "" + kind: Service + name: https-backend + tls: + hostname: example.com + wellKnownCACerts: System + status: + ancestors: + - ancestorRef: + name: gateway-tls + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-tls + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: "" + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: default-cert + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 1 + 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: "" + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-tls + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-tls + namespace: envoy-gateway + rules: + - backendRefs: + - name: https-backend + namespace: default + port: 443 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-tls + namespace: envoy-gateway +infraIR: + envoy-gateway/gateway-tls: + proxy: + config: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + creationTimestamp: null + name: test + namespace: envoy-gateway-system + spec: + backendTLS: + alpnProtocols: + - HTTP/1.1 + - HTTP/2 + ciphers: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + clientCertificateRef: + group: "" + kind: Secret + name: secret.yaml + namespace: default + ecdhCurves: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + maxVersion: tls1.3 + minVersion: tls1.2 + signatureAlgorithms: + - RSA-PSS-RSAE-SHA256 + - ECDSA-SECP256R1-SHA256 + logging: {} + status: {} + listeners: + - address: null + name: envoy-gateway/gateway-tls/ + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-tls + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-tls +xdsIR: + envoy-gateway/gateway-tls: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-tls/ + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/envoy-gateway/httproute-tls/rule/0 + settings: + - addressType: IP + endpoints: + - host: 10.244.0.11 + port: 443 + protocol: HTTP + tls: + alpnProtocols: + - HTTP/1.1 + - HTTP/2 + ciphers: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + ecdhCurves: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + maxVersion: tls1.3 + minVersion: tls1.2 + signatureAlgorithms: + - RSA-PSS-RSAE-SHA256 + - ECDSA-SECP256R1-SHA256 + sni: example.com + useSystemTrustStore: true + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/envoy-gateway/httproute-tls/rule/0/match/-1/* + tls: + certificates: + - name: envoy-gateway/default-cert + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV1Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktRd2dnU2dBZ0VBQW9JQkFRQ1pTT21NUlBXWkFqN08KcVFrTVc2d3Bub3NmVCtRMzhmVWJ1U3crRXlablZ1eUNuYlVGZjhIeTVyYkx1K2dmbWszUW8xbnRBVTMzamprUQpXMGQzRHdCdWhKVUM0bkpVRks3cDk2dm9MQ2FTdmlPM0NQbytjUENPdkZ4K1ZrTzYxVkxXOEI2YW04UG5GWndhCmlGRGk0aUdyWXlIK3lsK2RUTmJoZlhIeEJ4T0E1M0IrcTI2K2ZmMFJXUWJKSWNiT1RzOENTSDZJWk1yeGNIcmsKOE1TdjFhWXlQdXpuT1BBQVFsNlRUdlEvNmhJZnF6bXJvd0RIRjRCMENFNUFvb2xFM0ZLT2kwaC9ieTJUN1dxbgo4NkdhdXA0VEtxVnV1Uk5hUU1CZDQ4azA4V3VTUENYSDBoWTVJbm1kdEMxRURKK3pQRk9NUjQycVA0THg5QWdICjNRZTBTMU5yQWdNQkFBRUNnZjk2Zy9QWXh2YVp5NEJuMU5ySkJkOExaT2djYlpjMmdueDZJa3YvVVhaME5obHgKRVlpS2plRmpWNkhXNW9FWHJaKy9tUGY0ZHVzVmFMNzRVOVZvanVQSmNlQWVScmpMM2VPaGJIdGN4KzBnY0dMZwpYeEY5VFJhcDY1VHVVZDFhaTA0aEd3WWY3NXNiUDdSS2JQaXZ3WmdVQWUwQ3BWdWZjaG5YcXJzWXI4cEpZNTFPCldWa1NxejRSWTlXbTBrNUcxSkZ5SXlFQzl1bURsdWpjSE50UlZtYWZrTmZBdENsaVByRktjL245bkpmTzZSRlAKN2c3Vi9JdnFudUlyN1BFM0duNlBhVCtCZ2c0NDh0ZDVKelBwVEE1WkJjQm8yb3J6L2t4WVBGcHIvZ1BVQnFRZApvNm5XcXc3Nlp4d1BsZHdMaEorWFlOWDdvdWN0VVNDTDl1NzdmeUVDZ1lFQXl2N0RseGYrS1FsZkR3bW8vcjFUCjBMMVpuSDQ3MmhpSWVkU2hleVZCSGJFVlRTbXI0MkJSbGpXNERiUmNRTTRWY3h4RGtHclI3NlJHZTlvZzZtemMKUnY4K1ZsQ1gyK3F5OXA1bTZaWHJiQXczMHpDLzVtUGtSV3ViaFVoaSs5ZUNNWmEvaEFJL1JGdjI2OURyQkQyLwo2a2cwRjhYME8vNndJK1dwYXRLM1cwY0NnWUVBd1U5QTZiSnBmYVhLS1hQR21PRy9uVXhUeXp5cVlqS05aSmQvCjlHaEVudUdqSzVDQUVWUEphOGtadmZRemxXbXdaYWZxMERocUk4dkxhRkNEZjhZOEU5OU1hbjNHV2hVYjNWL0oKcU5RUVMzNTZOQ2ZadzdseG9LS0JJdlQ2Y3dpaFRuc0UvUjRIQ3NhbDJ3d040Wmw5SFdOQmdhbVM3VExrejFMaApmd1JEa0wwQ2dZQlo0OWorNW53QTlncG5JVkw1Z3lORGN5WGtlNjNMVlVQU0YwdHV1YitOQTJhNFpiU2RHb0RtCmNHRlJpRVcxMk14OHpjNUpmRlA4dDVVU3NUUVVPeUtNT2VrRDFlcDVVd1B1MjVRYzZldDNUQzNJVW5VWDg3SVkKMzU3ZHRZRkhubFlqMldwemJYOVFxUnk5cmlUMEd0Z0tTZkR2ZWhRK0lQa2szRVZhYlhjT2J3S0JnR0d4QzcwTwp6UUVTcC9nSzZuS1lvNTE2MVY0QWFwcjFzVDhFMFVWUzdGcmU3UGMzTDRHU05saWlhTC8yaVpzWXJteXhUNW1xCjZQanVKUDJ5c3NJQURKeCtYTC8wa0NrMlFiNitpY3NvWUpQR2R6dWthQWpoenVxL05VUFZTanlZUCt6SmZ0dnMKTU9MaFFUQlNCekhidjc3NlNrQ2MwZ1BObEpTeDdnT2l4QUtCQW9HQUpCR1VuM2U1QWZDb21BMUUxRHhSeUxaagpUMFBrQUNlUGpEK3hrRkpod0RoQ2dzd2htNFVKZzFmQW8xaEJRUkZ0dHBWQy91QkxjazE4TUVBSTF2ZGZTeVB2CmtTZzVrVnFQanUzc2czOVRNZ09WZXdqUDNFM0FNUUd1ZzFQNzFZazJ6WUpQbGg5NWRMVTVISlZubzZvdkIrUG0KTHF5K016eDN3a0YwZDhlUFhRND0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKRENDQWd5Z0F3SUJBZ0lVU3JTYktMZjBiTEVHb2dXeC9nQ3cyR0N0dnhFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0V6RVJNQThHQTFVRUF3d0lWR1Z6ZENCSmJtTXdIaGNOTWpRd01qSTVNRGt6TURFd1doY05NelF3TWpJMgpNRGt6TURFd1dqQVRNUkV3RHdZRFZRUUREQWhVWlhOMElFbHVZekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBSzFKempQSWlXZzNxb0hTckFkZGtlSmphTVA5aXlNVGkvQlBvOWNKUG9SRThaaTcKV2FwVXJYTC85QTlyK2pITXlHSVpOWk5kY1o1Y1kyWHYwTFA4WnhWeTJsazArM3d0WXpIbnBHWUdWdHlxMnRldApEaEZzaVBsODJZUmpDMG16V2E0UU16NFNYekZITmdJRHBSZGhmcm92bXNldVdHUUU4cFY0VWQ5VUsvU0tpbE1PCnF0QjVKaXJMUDJWczVUMW9XaWNXTFF2ZmJHd3Y3c0ZEZHI5YkcwWHRTUXAxN0hTZ281MFNERTUrQmpTbXB0RncKMVZjS0xscWFoTVhCRERpb3Jnd2hJaEdHS3BFU2VNMFA3YkZoVm1rTTNhc2gyeFNUQnVGVUJEbEU0Sk9haHp3cwpEWHJ1cFVoRGRTMWhkYzJmUHJqaEZBbEpmV0VZWjZCbFpqeXNpVlVDQXdFQUFhTndNRzR3SFFZRFZSME9CQllFCkZCUXVmSzFMaWJ1Vm05VHMvVmpCeDhMM3VpTmVNQjhHQTFVZEl3UVlNQmFBRkJRdWZLMUxpYnVWbTlUcy9WakIKeDhMM3VpTmVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdHd1lEVlIwUkJCUXdFb0lCS29JTktpNWxlR0Z0Y0d4bApMbU52YlRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWZQUzQxYWdldldNVjNaWHQwQ09GRzN1WWZQRlhuVnc2ClA0MXA5TzZHa2RZc3VxRnZQZVR5eUgyL2RBSUtLd1N6TS9wdGhnOEtuOExabG1KeUZObkExc3RKeG41WGRiVjEKcFBxajhVdllDQnp5ak1JcW1SeW9peUxpUWxib2hNYTBVZEVCS2NIL1BkTEU5SzhUR0pyWmdvR1hxcTFXbWl0RAozdmNQalNlUEtFaVVKVlM5bENoeVNzMEtZNUIraFVRRDBKajZucEZENFprMHhxZHhoMHJXdWVDcXE3dmpxRVl6CnBqNFB3cnVmbjFQQlRtZnhNdVYvVUpWNWViaWtldVpQMzVrV3pMUjdaV0FMN3d1RGRXcC82bzR5azNRTGFuRFEKQ3dnQ0ZjWCtzcyswVnl1TTNZZXJUT1VVOFFWSkp4NFVaQU5aeDYrNDNwZEpaT2NudFBaNENBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= diff --git a/internal/gatewayapi/tls.go b/internal/gatewayapi/tls.go index f37c53b9526..cc01c4c56c1 100644 --- a/internal/gatewayapi/tls.go +++ b/internal/gatewayapi/tls.go @@ -57,7 +57,6 @@ func validateTLSSecretsData(secrets []*corev1.Secret, host *v1.Hostname) error { if matchedFQDN, ok := pkaSecretSet[pkaSecretKey]; ok { return fmt.Errorf("%s/%s public key algorithm must be unique, matched certificate FQDN %s has a conflicting algorithm [%s]", secret.Namespace, secret.Name, matchedFQDN, publicKeyAlgorithm) - } pkaSecretSet[pkaSecretKey] = matchedFQDN diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index 9dc93532479..1827d962d57 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -115,7 +115,8 @@ func newTranslateResult(gateways []*GatewayContext, securityPolicies []*egv1a1.SecurityPolicy, backendTLSPolicies []*egv1a2.BackendTLSPolicy, envoyExtensionPolicies []*egv1a1.EnvoyExtensionPolicy, - xdsIR XdsIRMap, infraIR InfraIRMap) *TranslateResult { + xdsIR XdsIRMap, infraIR InfraIRMap, +) *TranslateResult { translateResult := &TranslateResult{ XdsIR: xdsIR, InfraIR: infraIR, @@ -220,7 +221,6 @@ func (t *Translator) Translate(resources *Resources) *TranslateResult { tcpRoutes, udpRoutes, clientTrafficPolicies, backendTrafficPolicies, securityPolicies, resources.BackendTLSPolicies, envoyExtensionPolicies, xdsIR, infraIR) - } // GetRelevantGateways returns GatewayContexts, containing a copy of the original diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go index a22b69b534f..23ade13da9b 100644 --- a/internal/gatewayapi/translator_test.go +++ b/internal/gatewayapi/translator_test.go @@ -34,9 +34,7 @@ import ( "github.com/envoyproxy/gateway/internal/utils/file" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") func mustUnmarshal(t *testing.T, val []byte, out interface{}) { require.NoError(t, yaml.UnmarshalStrict(val, out, yaml.DisallowUnknownFields)) @@ -444,7 +442,7 @@ func TestTranslateWithExtensionKinds(t *testing.T) { func overrideOutputConfig(t *testing.T, data string, filepath string) { t.Helper() - file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) + file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755) require.NoError(t, err) defer file.Close() write := bufio.NewWriter(file) diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index e7ddb427a15..09561698c66 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -23,7 +23,8 @@ import ( ) func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, - resources *Resources, backendNamespace string, routeKind gwapiv1.Kind) bool { + resources *Resources, backendNamespace string, routeKind gwapiv1.Kind, +) bool { if !t.validateBackendRefFilters(backendRefContext, parentRef, route, routeKind) { return false } @@ -112,7 +113,8 @@ func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, par } func (t *Translator) validateBackendNamespace(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext, - resources *Resources, routeKind gwapiv1.Kind) bool { + resources *Resources, routeKind gwapiv1.Kind, +) bool { if backendRef.Namespace != nil && string(*backendRef.Namespace) != "" && string(*backendRef.Namespace) != route.GetNamespace() { if !t.validateCrossNamespaceRef( crossNamespaceFrom{ @@ -152,8 +154,10 @@ func (t *Translator) validateBackendPort(backendRef *gwapiv1a2.BackendRef, paren } return true } + func (t *Translator) validateBackendService(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, resources *Resources, - serviceNamespace string, route RouteContext, protocol v1.Protocol) bool { + serviceNamespace string, route RouteContext, protocol v1.Protocol, +) bool { service := resources.GetService(serviceNamespace, string(backendRef.Name)) if service == nil { parentRef.SetCondition(route, @@ -191,7 +195,8 @@ func (t *Translator) validateBackendService(backendRef *gwapiv1a2.BackendRef, pa } func (t *Translator) validateBackendServiceImport(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, resources *Resources, - serviceImportNamespace string, route RouteContext, protocol v1.Protocol) bool { + serviceImportNamespace string, route RouteContext, protocol v1.Protocol, +) bool { serviceImport := resources.GetServiceImport(serviceImportNamespace, string(backendRef.Name)) if serviceImport == nil { parentRef.SetCondition(route, @@ -767,8 +772,8 @@ func (t *Translator) validateSecretRef( allowCrossNamespace bool, from crossNamespaceFrom, secretObjRef gwapiv1b1.SecretObjectReference, - resources *Resources) (*v1.Secret, error) { - + resources *Resources, +) (*v1.Secret, error) { if err := t.validateSecretObjectRef(allowCrossNamespace, from, secretObjRef, resources); err != nil { return nil, err } @@ -791,8 +796,8 @@ func (t *Translator) validateConfigMapRef( allowCrossNamespace bool, from crossNamespaceFrom, secretObjRef gwapiv1b1.SecretObjectReference, - resources *Resources) (*v1.ConfigMap, error) { - + resources *Resources, +) (*v1.ConfigMap, error) { if err := t.validateSecretObjectRef(allowCrossNamespace, from, secretObjRef, resources); err != nil { return nil, err } @@ -815,7 +820,8 @@ func (t *Translator) validateSecretObjectRef( allowCrossNamespace bool, from crossNamespaceFrom, secretRef gwapiv1b1.SecretObjectReference, - resources *Resources) error { + resources *Resources, +) error { var kind string if secretRef.Group != nil && string(*secretRef.Group) != "" { return errors.New("secret ref group must be unspecified/empty") @@ -875,8 +881,8 @@ func (t *Translator) validateSecretObjectRef( func (t *Translator) validateExtServiceBackendReference( backendRef *gwapiv1.BackendObjectReference, ownerNamespace string, - resources *Resources) error { - + resources *Resources, +) error { // These are sanity checks, they should never happen because the API server // should have caught them if backendRef.Group != nil && *backendRef.Group != "" { diff --git a/internal/infrastructure/kubernetes/proxy/resource.go b/internal/infrastructure/kubernetes/proxy/resource.go index 47050998405..b8f601c0ccb 100644 --- a/internal/infrastructure/kubernetes/proxy/resource.go +++ b/internal/infrastructure/kubernetes/proxy/resource.go @@ -103,7 +103,8 @@ func enablePrometheus(infra *ir.ProxyInfra) bool { func expectedProxyContainers(infra *ir.ProxyInfra, containerSpec *egv1a1.KubernetesContainerSpec, shutdownConfig *egv1a1.ShutdownConfig, - shutdownManager *egv1a1.ShutdownManager) ([]corev1.Container, error) { + shutdownManager *egv1a1.ShutdownManager, +) ([]corev1.Container, error) { // Define slice to hold container ports var ports []corev1.ContainerPort diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go index fbe629d6507..2ec5b2c696e 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go @@ -30,9 +30,7 @@ import ( "github.com/envoyproxy/gateway/internal/ir" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") const ( // envoyHTTPPort is the container port number of Envoy's HTTP endpoint. @@ -574,7 +572,7 @@ func TestDeployment(t *testing.T) { deploymentYAML, err := yaml.Marshal(dp) require.NoError(t, err) // nolint: gosec - err = os.WriteFile(fmt.Sprintf("testdata/deployments/%s.yaml", tc.caseName), deploymentYAML, 0644) + err = os.WriteFile(fmt.Sprintf("testdata/deployments/%s.yaml", tc.caseName), deploymentYAML, 0o644) require.NoError(t, err) return } @@ -995,7 +993,7 @@ func TestDaemonSet(t *testing.T) { deploymentYAML, err := yaml.Marshal(ds) require.NoError(t, err) // nolint: gosec - err = os.WriteFile(fmt.Sprintf("testdata/daemonsets/%s.yaml", tc.caseName), deploymentYAML, 0644) + err = os.WriteFile(fmt.Sprintf("testdata/daemonsets/%s.yaml", tc.caseName), deploymentYAML, 0o644) require.NoError(t, err) return } @@ -1159,7 +1157,6 @@ func loadConfigmap(tc string) (*corev1.ConfigMap, error) { } func TestServiceAccount(t *testing.T) { - cfg, err := config.New() require.NoError(t, err) cases := []struct { @@ -1285,7 +1282,6 @@ func loadHPA(caseName string) (*autoscalingv2.HorizontalPodAutoscaler, error) { } func TestOwningGatewayLabelsAbsent(t *testing.T) { - cases := []struct { caseName string labels map[string]string @@ -1333,5 +1329,4 @@ func TestOwningGatewayLabelsAbsent(t *testing.T) { require.Equal(t, tc.expect, actual) }) } - } diff --git a/internal/infrastructure/kubernetes/proxy_infra_test.go b/internal/infrastructure/kubernetes/proxy_infra_test.go index d39f8059799..5c8a8d34695 100644 --- a/internal/infrastructure/kubernetes/proxy_infra_test.go +++ b/internal/infrastructure/kubernetes/proxy_infra_test.go @@ -192,7 +192,6 @@ func TestCreateProxyInfra(t *testing.T) { } func TestDeleteProxyInfra(t *testing.T) { - testCases := []struct { name string in *ir.Infra diff --git a/internal/infrastructure/kubernetes/ratelimit/resource.go b/internal/infrastructure/kubernetes/ratelimit/resource.go index 9f6303247cd..6ab5b19433f 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource.go @@ -115,7 +115,6 @@ func GetServiceURL(namespace string, dnsDomain string) string { // LabelSelector returns the string slice form labels used for all envoy rate limit resources. func LabelSelector() []string { - rlLabelMap := rateLimitLabels() retLabels := make([]string, 0, len(rlLabelMap)) @@ -138,7 +137,8 @@ func rateLimitLabels() map[string]string { // expectedRateLimitContainers returns expected rateLimit containers. func expectedRateLimitContainers(rateLimit *egv1a1.RateLimit, rateLimitDeployment *egv1a1.KubernetesDeploymentSpec, - namespace string) []corev1.Container { + namespace string, +) []corev1.Container { ports := []corev1.ContainerPort{ { Name: "grpc", @@ -289,7 +289,8 @@ func expectedDeploymentVolumes(rateLimit *egv1a1.RateLimit, rateLimitDeployment // expectedRateLimitContainerEnv returns expected rateLimit container envs. func expectedRateLimitContainerEnv(rateLimit *egv1a1.RateLimit, rateLimitDeployment *egv1a1.KubernetesDeploymentSpec, - namespace string) []corev1.EnvVar { + namespace string, +) []corev1.EnvVar { env := []corev1.EnvVar{ { Name: RuntimeRootEnvVar, @@ -399,7 +400,7 @@ func expectedRateLimitContainerEnv(rateLimit *egv1a1.RateLimit, rateLimitDeploym } if enableTracing(rateLimit) { - var sampleRate = 1.0 + sampleRate := 1.0 if rateLimit.Telemetry.Tracing.SamplingRate != nil { sampleRate = float64(*rateLimit.Telemetry.Tracing.SamplingRate) / 100.0 } diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go index 03d794d0ed1..6345aebdc55 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go @@ -27,9 +27,7 @@ import ( "github.com/envoyproxy/gateway/internal/envoygateway/config" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") const ( // RedisAuthEnvVar is the redis auth. @@ -43,7 +41,6 @@ var ownerReferenceUID = map[string]types.UID{ } func TestRateLimitLabelSelector(t *testing.T) { - cases := []struct { name string expected []string @@ -65,7 +62,6 @@ func TestRateLimitLabelSelector(t *testing.T) { require.ElementsMatch(t, tc.expected, got) }) } - } func TestRateLimitLabels(t *testing.T) { @@ -126,7 +122,6 @@ func loadServiceAccount() (*corev1.ServiceAccount, error) { } func TestService(t *testing.T) { - cfg, err := config.New() require.NoError(t, err) @@ -209,7 +204,7 @@ func TestConfigmap(t *testing.T) { cmYAML, err := yaml.Marshal(cm) require.NoError(t, err) // nolint:gosec - err = os.WriteFile("testdata/envoy-ratelimit-configmap.yaml", cmYAML, 0644) + err = os.WriteFile("testdata/envoy-ratelimit-configmap.yaml", cmYAML, 0o644) require.NoError(t, err) return } @@ -694,7 +689,8 @@ func TestDeployment(t *testing.T) { Type: egv1a1.ProviderTypeKubernetes, Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{ RateLimitDeployment: tc.deploy, - }} + }, + } r := NewResourceRender(cfg.Namespace, cfg.EnvoyGateway, ownerReferenceUID) dp, err := r.Deployment() require.NoError(t, err) @@ -703,7 +699,7 @@ func TestDeployment(t *testing.T) { deploymentYAML, err := yaml.Marshal(dp) require.NoError(t, err) // nolint:gosec - err = os.WriteFile(fmt.Sprintf("testdata/deployments/%s.yaml", tc.caseName), deploymentYAML, 0644) + err = os.WriteFile(fmt.Sprintf("testdata/deployments/%s.yaml", tc.caseName), deploymentYAML, 0o644) require.NoError(t, err) return } diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_test.go b/internal/infrastructure/kubernetes/ratelimit/resource_test.go index 71179c8c7c4..61d24eac8da 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource_test.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource_test.go @@ -12,7 +12,6 @@ import ( ) func TestCheckTraceEndpointScheme(t *testing.T) { - cases := []struct { caseName string actualURL string @@ -36,5 +35,4 @@ func TestCheckTraceEndpointScheme(t *testing.T) { require.Equal(t, tc.expectedURL, actual) }) } - } diff --git a/internal/infrastructure/kubernetes/resource/resource_test.go b/internal/infrastructure/kubernetes/resource/resource_test.go index 14df266e187..b65549911c7 100644 --- a/internal/infrastructure/kubernetes/resource/resource_test.go +++ b/internal/infrastructure/kubernetes/resource/resource_test.go @@ -213,7 +213,8 @@ func TestCompareSvc(t *testing.T) { Type: "NodePort", }, }, - }, { + }, + { // Only Spec.Ports[*].Port is different ExpectRet: false, NewSvc: &corev1.Service{ @@ -298,7 +299,8 @@ func TestCompareSvc(t *testing.T) { Type: "ClusterIP", }, }, - }, { + }, + { // Finalizers field differs ExpectRet: true, NewSvc: &corev1.Service{ diff --git a/internal/infrastructure/runner/runner.go b/internal/infrastructure/runner/runner.go index 8da18e46443..d9376eb8499 100644 --- a/internal/infrastructure/runner/runner.go +++ b/internal/infrastructure/runner/runner.go @@ -44,7 +44,7 @@ func (r *Runner) Start(ctx context.Context) (err error) { return err } - var initInfra = func() { + initInfra := func() { go r.subscribeToProxyInfraIR(ctx) // Enable global ratelimit if it has been configured. diff --git a/internal/ir/xds.go b/internal/ir/xds.go index de192170e2e..337720f7fb0 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -502,6 +502,8 @@ type HTTPRoute struct { // Security holds the features associated with SecurityPolicy Security *SecurityFeatures `json:"security,omitempty" yaml:"security,omitempty"` + // UseClientProtocol enables using the same protocol upstream that was used downstream + UseClientProtocol *bool `json:"useClientProtocol,omitempty" yaml:"useClientProtocol,omitempty"` } // SecurityFeatures holds the information associated with the Security Policy. @@ -1883,6 +1885,7 @@ type TLSUpstreamConfig struct { SNI string `json:"sni,omitempty" yaml:"sni,omitempty"` UseSystemTrustStore bool `json:"useSystemTrustStore,omitempty" yaml:"useSystemTrustStore,omitempty"` CACertificate *TLSCACertificate `json:"caCertificate,omitempty" yaml:"caCertificate,omitempty"` + TLSConfig `json:",inline"` } // Connection settings for downstream connections @@ -1906,6 +1909,17 @@ type ConnectionLimit struct { CloseDelay *metav1.Duration `json:"closeDelay,omitempty" yaml:"closeDelay,omitempty"` } +type ExtProcBodyProcessingMode egv1a1.ExtProcBodyProcessingMode + +const ( + // ExtProcBodyStreamed sets the streamed body processing mode + ExtProcBodyStreamed = ExtProcBodyProcessingMode(egv1a1.StreamedExtProcBodyProcessingMode) + // ExtProcBodyBuffered sets the buffered body processing mode + ExtProcBodyBuffered = ExtProcBodyProcessingMode(egv1a1.BufferedExtProcBodyProcessingMode) + // ExtProcBodyBufferedPartial sets the partial buffered body processing mode + ExtProcBodyBufferedPartial = ExtProcBodyProcessingMode(egv1a1.BufferedPartialExtBodyHeaderProcessingMode) +) + // ExtProc holds the information associated with the ExtProc extensions. // +k8s:deepcopy-gen=true type ExtProc struct { @@ -1914,10 +1928,29 @@ type ExtProc struct { Name string `json:"name" yaml:"name"` // Destination defines the destination for the gRPC External Processing service. - Destination RouteDestination `json:"destination"` + Destination RouteDestination `json:"destination" yaml:"destination"` // Authority is the hostname:port of the HTTP External Processing service. - Authority string `json:"authority"` + Authority string `json:"authority" yaml:"authority"` + + // MessageTimeout is the timeout for a response to be returned from the external processor + MessageTimeout *metav1.Duration `json:"messageTimeout,omitempty" yaml:"messageTimeout,omitempty"` + + // FailOpen defines if requests or responses that cannot be processed due to connectivity to the + // external processor are terminated or passed-through. + FailOpen *bool `json:"failOpen,omitempty" yaml:"failOpen,omitempty"` + + // RequestHeaderProcessing Defines if request headers are processed + RequestHeaderProcessing bool `json:"requestHeaderProcessing,omitempty" yaml:"requestHeaderProcessing,omitempty"` + + // RequestBodyProcessingMode Defines request body processing + RequestBodyProcessingMode *ExtProcBodyProcessingMode `json:"requestBodyProcessingMode,omitempty" yaml:"requestBodyProcessingMode,omitempty"` + + // ResponseHeaderProcessingMode Defines if response headers are processed + ResponseHeaderProcessing bool `json:"responseHeaderProcessing,omitempty" yaml:"responseHeaderProcessing,omitempty"` + + // ResponseBodyProcessingMode Defines response body processing + ResponseBodyProcessingMode *ExtProcBodyProcessingMode `json:"responseBodyProcessingMode,omitempty" yaml:"responseBodyProcessingMode,omitempty"` } // Wasm holds the information associated with the Wasm extensions. diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index 8b16cf6e9a4..30c07a70001 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -35,11 +35,11 @@ var ( Hostnames: []string{"example.com"}, TLS: &TLSConfig{ Certificates: []TLSCertificate{{ - Name: "happy", ServerCertificate: []byte{1, 2, 3}, PrivateKey: []byte{1, 2, 3}, - }}}, + }}, + }, Routes: []*HTTPRoute{&happyHTTPRoute}, } redactedHappyHTTPSListener = HTTPListener{ @@ -49,11 +49,11 @@ var ( Hostnames: []string{"example.com"}, TLS: &TLSConfig{ Certificates: []TLSCertificate{{ - Name: "happy", ServerCertificate: []byte{1, 2, 3}, PrivateKey: redacted, - }}}, + }}, + }, Routes: []*HTTPRoute{&happyHTTPRoute}, } invalidAddrHTTPListener = HTTPListener{ @@ -96,7 +96,8 @@ var ( Name: "happy", ServerCertificate: []byte("server-cert"), PrivateKey: []byte("priv-key"), - }}}}, + }}, + }}, Destination: &happyRouteDestination, } @@ -658,7 +659,8 @@ func TestValidateTLSListenerConfig(t *testing.T) { Certificates: []TLSCertificate{{ ServerCertificate: []byte("server-cert"), PrivateKey: []byte("priv-key"), - }}}, + }}, + }, want: nil, }, { @@ -666,7 +668,8 @@ func TestValidateTLSListenerConfig(t *testing.T) { input: TLSConfig{ Certificates: []TLSCertificate{{ PrivateKey: []byte("priv-key"), - }}}, + }}, + }, want: ErrTLSServerCertEmpty, }, { @@ -674,7 +677,8 @@ func TestValidateTLSListenerConfig(t *testing.T) { input: TLSConfig{ Certificates: []TLSCertificate{{ ServerCertificate: []byte("server-cert"), - }}}, + }}, + }, want: ErrTLSPrivateKey, }, } @@ -1253,231 +1257,244 @@ func TestValidateHealthCheck(t *testing.T) { }{ { name: "invalid timeout", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Duration(0)}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Duration(0)}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckTimeoutInvalid, }, { name: "invalid interval", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Duration(0)}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodGet), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Duration(0)}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodGet), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckIntervalInvalid, }, { name: "invalid unhealthy threshold", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](0), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodPatch), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](0), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodPatch), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckUnhealthyThresholdInvalid, }, { name: "invalid healthy threshold", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](0), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodPost), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](0), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodPost), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckHealthyThresholdInvalid, }, { name: "http-health-check: invalid host", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Path: "/healthz", - Method: ptr.To(http.MethodPut), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Path: "/healthz", + Method: ptr.To(http.MethodPut), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHCHTTPHostInvalid, }, { name: "http-health-check: invalid path", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "", - Method: ptr.To(http.MethodPut), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "", + Method: ptr.To(http.MethodPut), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHCHTTPPathInvalid, }, { name: "http-health-check: invalid method", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodConnect), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodConnect), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHCHTTPMethodInvalid, }, { name: "http-health-check: invalid expected-statuses", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodDelete), - ExpectedStatuses: []HTTPStatus{}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodDelete), + ExpectedStatuses: []HTTPStatus{}, + }, }, - }, &OutlierDetection{}, }, want: ErrHCHTTPExpectedStatusesInvalid, }, { name: "http-health-check: invalid range", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodHead), - ExpectedStatuses: []HTTPStatus{100, 600}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodHead), + ExpectedStatuses: []HTTPStatus{100, 600}, + }, }, - }, &OutlierDetection{}, }, want: ErrHTTPStatusInvalid, }, { name: "http-health-check: invalid expected-responses", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodOptions), - ExpectedStatuses: []HTTPStatus{200, 300}, - ExpectedResponse: &HealthCheckPayload{ - Text: ptr.To("foo"), - Binary: []byte{'f', 'o', 'o'}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodOptions), + ExpectedStatuses: []HTTPStatus{200, 300}, + ExpectedResponse: &HealthCheckPayload{ + Text: ptr.To("foo"), + Binary: []byte{'f', 'o', 'o'}, + }, }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, { name: "tcp-health-check: invalid send payload", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - TCP: &TCPHealthChecker{ - Send: &HealthCheckPayload{ - Text: ptr.To("foo"), - Binary: []byte{'f', 'o', 'o'}, - }, - Receive: &HealthCheckPayload{ - Text: ptr.To("foo"), + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + TCP: &TCPHealthChecker{ + Send: &HealthCheckPayload{ + Text: ptr.To("foo"), + Binary: []byte{'f', 'o', 'o'}, + }, + Receive: &HealthCheckPayload{ + Text: ptr.To("foo"), + }, }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, { name: "tcp-health-check: invalid receive payload", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - TCP: &TCPHealthChecker{ - Send: &HealthCheckPayload{ - Text: ptr.To("foo"), - }, - Receive: &HealthCheckPayload{ - Text: ptr.To("foo"), - Binary: []byte{'f', 'o', 'o'}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + TCP: &TCPHealthChecker{ + Send: &HealthCheckPayload{ + Text: ptr.To("foo"), + }, + Receive: &HealthCheckPayload{ + Text: ptr.To("foo"), + Binary: []byte{'f', 'o', 'o'}, + }, }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, { name: "OutlierDetection invalid interval", - input: HealthCheck{&ActiveHealthCheck{}, + input: HealthCheck{ + &ActiveHealthCheck{}, &OutlierDetection{ Interval: &metav1.Duration{Duration: time.Duration(0)}, BaseEjectionTime: &metav1.Duration{Duration: time.Second}, @@ -1487,7 +1504,8 @@ func TestValidateHealthCheck(t *testing.T) { }, { name: "OutlierDetection invalid BaseEjectionTime", - input: HealthCheck{&ActiveHealthCheck{}, + input: HealthCheck{ + &ActiveHealthCheck{}, &OutlierDetection{ Interval: &metav1.Duration{Duration: time.Second}, BaseEjectionTime: &metav1.Duration{Duration: time.Duration(0)}, diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index bffc4639cb6..5430ef9ce6b 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -532,6 +532,26 @@ func (in *ExtAuth) DeepCopy() *ExtAuth { func (in *ExtProc) DeepCopyInto(out *ExtProc) { *out = *in in.Destination.DeepCopyInto(&out.Destination) + if in.MessageTimeout != nil { + in, out := &in.MessageTimeout, &out.MessageTimeout + *out = new(v1.Duration) + **out = **in + } + if in.FailOpen != nil { + in, out := &in.FailOpen, &out.FailOpen + *out = new(bool) + **out = **in + } + if in.RequestBodyProcessingMode != nil { + in, out := &in.RequestBodyProcessingMode, &out.RequestBodyProcessingMode + *out = new(ExtProcBodyProcessingMode) + **out = **in + } + if in.ResponseBodyProcessingMode != nil { + in, out := &in.ResponseBodyProcessingMode, &out.ResponseBodyProcessingMode + *out = new(ExtProcBodyProcessingMode) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtProc. @@ -1071,6 +1091,11 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = new(SecurityFeatures) (*in).DeepCopyInto(*out) } + if in.UseClientProtocol != nil { + in, out := &in.UseClientProtocol, &out.UseClientProtocol + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. @@ -2283,6 +2308,7 @@ func (in *TLSUpstreamConfig) DeepCopyInto(out *TLSUpstreamConfig) { *out = new(TLSCACertificate) (*in).DeepCopyInto(*out) } + in.TLSConfig.DeepCopyInto(&out.TLSConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSUpstreamConfig. diff --git a/internal/kubernetes/port_forwarder.go b/internal/kubernetes/port_forwarder.go index ceb439d7721..176610dab3e 100644 --- a/internal/kubernetes/port_forwarder.go +++ b/internal/kubernetes/port_forwarder.go @@ -86,7 +86,6 @@ func (f *localForwarder) Start() error { readyCh = nil } - }() select { diff --git a/internal/logging/log.go b/internal/logging/log.go index 0d6d36f8f95..8f90a9c8e0a 100644 --- a/internal/logging/log.go +++ b/internal/logging/log.go @@ -34,7 +34,7 @@ func NewLogger(logging *v1alpha1.EnvoyGatewayLogging) Logger { } func FileLogger(file string, name string, level v1alpha1.LogLevel) Logger { - writer, err := os.OpenFile(file, os.O_WRONLY, 0666) + writer, err := os.OpenFile(file, os.O_WRONLY, 0o666) if err != nil { panic(err) } diff --git a/internal/message/watchutil.go b/internal/message/watchutil.go index b938f276b7d..bd7829f3cbd 100644 --- a/internal/message/watchutil.go +++ b/internal/message/watchutil.go @@ -49,7 +49,7 @@ func HandleSubscription[K comparable, V any]( subscription <-chan watchable.Snapshot[K, V], handle func(updateFunc Update[K, V], errChans chan error), ) { - //TODO: find a suitable value + // TODO: find a suitable value errChans := make(chan error, 10) go func() { for err := range errChans { diff --git a/internal/metrics/metadata.go b/internal/metrics/metadata.go index f2ab8498407..255619bbd11 100644 --- a/internal/metrics/metadata.go +++ b/internal/metrics/metadata.go @@ -94,7 +94,8 @@ func (d *store) preAddOptions() []metric.Option { metric.Stream{ Aggregation: metric.AggregationExplicitBucketHistogram{ Boundaries: store.Bounds, - }}, + }, + }, )) opts = append(opts, v) } diff --git a/internal/metrics/metrics_test.go b/internal/metrics/metrics_test.go index 560141c6266..9b1aafcd5e2 100644 --- a/internal/metrics/metrics_test.go +++ b/internal/metrics/metrics_test.go @@ -29,12 +29,9 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.17.0" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") func TestCounter(t *testing.T) { - name := "counter_metric" var writer io.ReadWriter = bytes.NewBuffer(nil) @@ -87,7 +84,6 @@ func TestCounter(t *testing.T) { } func TestGauge(t *testing.T) { - name := "gauge_metric" var writer io.ReadWriter = bytes.NewBuffer(nil) @@ -130,7 +126,6 @@ func TestGauge(t *testing.T) { } func TestHistogram(t *testing.T) { - name := "histogram_metric" var writer io.ReadWriter = bytes.NewBuffer(nil) @@ -219,7 +214,7 @@ func exporterWriter(name string, origin io.ReadWriter) (io.ReadWriter, error) { fname := fmt.Sprintf("testdata/%s.json", name) // nolint:gosec - f, err := os.OpenFile(fname, os.O_CREATE|os.O_RDWR, 0644) + f, err := os.OpenFile(fname, os.O_CREATE|os.O_RDWR, 0o644) if err != nil { return nil, err } diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 571a45c5764..0cdbe5c8f7f 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -59,7 +59,8 @@ type gatewayAPIReconciler struct { // newGatewayAPIController func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status.Updater, - resources *message.ProviderResources) error { + resources *message.ProviderResources, +) error { ctx := context.Background() // Gather additional resources to watch from registered extensions @@ -374,7 +375,8 @@ func (r *gatewayAPIReconciler) processBackendRefs(ctx context.Context, gwcResour // - Secrets for OIDC and BasicAuth // - BackendRefs for ExAuth func (r *gatewayAPIReconciler) processSecurityPolicyObjectRefs( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) { // we don't return errors from this method, because we want to continue reconciling // the rest of the SecurityPolicies despite that one reference is invalid. This // allows Envoy Gateway to continue serving traffic even if some SecurityPolicies @@ -477,7 +479,6 @@ func (r *gatewayAPIReconciler) processOIDCHMACSecret(ctx context.Context, resour types.NamespacedName{Namespace: r.namespace, Name: oidcHMACSecretName}, &secret, ) - // We don't return an error here, because we want to continue reconciling // despite that the OIDC HMAC secret can't be found. // If the OIDC HMAC Secret is missing, the SecurityPolicy with OIDC will be @@ -550,7 +551,8 @@ func (r *gatewayAPIReconciler) processSecretRef( // processCtpConfigMapRefs adds the referenced ConfigMaps in ClientTrafficPolicies // to the resourceTree func (r *gatewayAPIReconciler) processCtpConfigMapRefs( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) { for _, policy := range resourceTree.ClientTrafficPolicies { tls := policy.Spec.TLS @@ -734,7 +736,6 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g gtw.Namespace, gtw.Name, certRef); err != nil { - r.log.Error(err, "failed to process TLS SecretRef for gateway", "gateway", gtw, "secretRef", certRef) @@ -799,7 +800,8 @@ func (r *gatewayAPIReconciler) processEnvoyPatchPolicies(ctx context.Context, re // processClientTrafficPolicies adds ClientTrafficPolicies to the resourceTree func (r *gatewayAPIReconciler) processClientTrafficPolicies( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) error { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) error { clientTrafficPolicies := egv1a1.ClientTrafficPolicyList{} if err := r.client.List(ctx, &clientTrafficPolicies); err != nil { return fmt.Errorf("error listing ClientTrafficPolicies: %w", err) @@ -837,7 +839,8 @@ func (r *gatewayAPIReconciler) processBackendTrafficPolicies(ctx context.Context // processSecurityPolicies adds SecurityPolicies and their referenced resources to the resourceTree func (r *gatewayAPIReconciler) processSecurityPolicies( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) error { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) error { securityPolicies := egv1a1.SecurityPolicyList{} if err := r.client.List(ctx, &securityPolicies); err != nil { return fmt.Errorf("error listing SecurityPolicies: %w", err) @@ -861,7 +864,8 @@ func (r *gatewayAPIReconciler) processSecurityPolicies( // processBackendTLSPolicies adds BackendTLSPolicies and their referenced resources to the resourceTree func (r *gatewayAPIReconciler) processBackendTLSPolicies( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) error { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) error { backendTLSPolicies := gwapiv1a2.BackendTLSPolicyList{} if err := r.client.List(ctx, &backendTLSPolicies); err != nil { return fmt.Errorf("error listing BackendTLSPolicies: %w", err) @@ -909,51 +913,57 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Upon leader election, we retrigger the reconciliation process to allow the elected leader to // process status updates and infrastructure changes. This step is crucial for synchronizing resources // that may have been altered or introduced while there was no elected leader. - if err := c.Watch( - NewWatchAndReconcileSource(mgr.Elected(), &gwapiv1.GatewayClass{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass)); err != nil { + if err := c.Watch(NewWatchAndReconcileSource(mgr.Elected(), &gwapiv1.GatewayClass{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass))); err != nil { return err } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1.GatewayClass{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.hasMatchingController), - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1.GatewayClass{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, gc *gwapiv1.GatewayClass) []reconcile.Request { + return r.enqueueClass(ctx, gc) + }), + &predicate.TypedGenerationChangedPredicate[*gwapiv1.GatewayClass]{}, + predicate.NewTypedPredicateFuncs[*gwapiv1.GatewayClass](r.hasMatchingController))); err != nil { return err } // Only enqueue EnvoyProxy objects that match this Envoy Gateway's GatewayClass. - epPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.ResourceVersionChangedPredicate{}, - predicate.NewPredicateFuncs(r.hasManagedClass), + epPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyProxy]{ + &predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyProxy]{}, + predicate.NewTypedPredicateFuncs[*egv1a1.EnvoyProxy](r.hasManagedClass), } if r.namespaceLabel != nil { - epPredicates = append(epPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + epPredicates = append(epPredicates, predicate.NewTypedPredicateFuncs(func(ep *egv1a1.EnvoyProxy) bool { + return r.hasMatchingNamespaceLabels(ep) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyProxy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - epPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.EnvoyProxy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, t *egv1a1.EnvoyProxy) []reconcile.Request { + return r.enqueueClass(ctx, t) + }), + epPredicates...)); err != nil { return err } // Watch Gateway CRUDs and reconcile affected GatewayClass. - gPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateGatewayForReconcile), + gPredicates := []predicate.TypedPredicate[*gwapiv1.Gateway]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1.Gateway]{}, + predicate.NewTypedPredicateFuncs(func(gtw *gwapiv1.Gateway) bool { + return r.validateGatewayForReconcile(gtw) + }), } if r.namespaceLabel != nil { - gPredicates = append(gPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + gPredicates = append(gPredicates, predicate.NewTypedPredicateFuncs(func(gtw *gwapiv1.Gateway) bool { + return r.hasMatchingNamespaceLabels(gtw) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1.Gateway{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - gPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1.Gateway{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, gtw *gwapiv1.Gateway) []reconcile.Request { + return r.enqueueClass(ctx, gtw) + }), + gPredicates...)); err != nil { return err } if err := addGatewayIndexers(ctx, mgr); err != nil { @@ -961,15 +971,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch HTTPRoute CRUDs and process affected Gateways. - httprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + httprPredicates := []predicate.TypedPredicate[*gwapiv1.HTTPRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1.HTTPRoute]{}, + } if r.namespaceLabel != nil { - httprPredicates = append(httprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + httprPredicates = append(httprPredicates, predicate.NewTypedPredicateFuncs(func(hr *gwapiv1.HTTPRoute) bool { + return r.hasMatchingNamespaceLabels(hr) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1.HTTPRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - httprPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1.HTTPRoute{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, t *gwapiv1.HTTPRoute) []reconcile.Request { + return r.enqueueClass(ctx, t) + }), + httprPredicates...)); err != nil { return err } if err := addHTTPRouteIndexers(ctx, mgr); err != nil { @@ -977,15 +992,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch GRPCRoute CRUDs and process affected Gateways. - grpcrPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + grpcrPredicates := []predicate.TypedPredicate[*gwapiv1a2.GRPCRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.GRPCRoute]{}, + } if r.namespaceLabel != nil { - grpcrPredicates = append(grpcrPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + grpcrPredicates = append(grpcrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.GRPCRoute](func(grpc *gwapiv1a2.GRPCRoute) bool { + return r.hasMatchingNamespaceLabels(grpc) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.GRPCRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - grpcrPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.GRPCRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.GRPCRoute](func(ctx context.Context, route *gwapiv1a2.GRPCRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + grpcrPredicates...)); err != nil { return err } if err := addGRPCRouteIndexers(ctx, mgr); err != nil { @@ -993,15 +1013,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch TLSRoute CRUDs and process affected Gateways. - tlsrPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + tlsrPredicates := []predicate.TypedPredicate[*gwapiv1a2.TLSRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TLSRoute]{}, + } if r.namespaceLabel != nil { - tlsrPredicates = append(tlsrPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + tlsrPredicates = append(tlsrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TLSRoute](func(route *gwapiv1a2.TLSRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.TLSRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - tlsrPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.TLSRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.TLSRoute](func(ctx context.Context, route *gwapiv1a2.TLSRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + tlsrPredicates...)); err != nil { return err } if err := addTLSRouteIndexers(ctx, mgr); err != nil { @@ -1009,15 +1034,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch UDPRoute CRUDs and process affected Gateways. - udprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + udprPredicates := []predicate.TypedPredicate[*gwapiv1a2.UDPRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.UDPRoute]{}, + } if r.namespaceLabel != nil { - udprPredicates = append(udprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + udprPredicates = append(udprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.UDPRoute](func(route *gwapiv1a2.UDPRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.UDPRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - udprPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.UDPRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.UDPRoute](func(ctx context.Context, route *gwapiv1a2.UDPRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + udprPredicates...)); err != nil { return err } if err := addUDPRouteIndexers(ctx, mgr); err != nil { @@ -1025,15 +1055,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch TCPRoute CRUDs and process affected Gateways. - tcprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + tcprPredicates := []predicate.TypedPredicate[*gwapiv1a2.TCPRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TCPRoute]{}, + } if r.namespaceLabel != nil { - tcprPredicates = append(tcprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + tcprPredicates = append(tcprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TCPRoute](func(route *gwapiv1a2.TCPRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.TCPRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - tcprPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.TCPRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.TCPRoute](func(ctx context.Context, route *gwapiv1a2.TCPRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + tcprPredicates...)); err != nil { return err } if err := addTCPRouteIndexers(ctx, mgr); err != nil { @@ -1041,15 +1076,22 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch Service CRUDs and process affected *Route objects. - servicePredicates := []predicate.Predicate{predicate.NewPredicateFuncs(r.validateServiceForReconcile)} + servicePredicates := []predicate.TypedPredicate[*corev1.Service]{ + predicate.NewTypedPredicateFuncs[*corev1.Service](func(svc *corev1.Service) bool { + return r.validateServiceForReconcile(svc) + }), + } if r.namespaceLabel != nil { - servicePredicates = append(servicePredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + servicePredicates = append(servicePredicates, predicate.NewTypedPredicateFuncs[*corev1.Service](func(svc *corev1.Service) bool { + return r.hasMatchingNamespaceLabels(svc) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &corev1.Service{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - servicePredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &corev1.Service{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, svc *corev1.Service) []reconcile.Request { + return r.enqueueClass(ctx, svc) + }), + servicePredicates...)); err != nil { return err } @@ -1061,91 +1103,120 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch ServiceImport CRUDs and process affected *Route objects. if serviceImportCRDExists { if err := c.Watch( - source.Kind(mgr.GetCache(), &mcsapi.ServiceImport{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateServiceImportForReconcile)); err != nil { + source.Kind(mgr.GetCache(), &mcsapi.ServiceImport{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *mcsapi.ServiceImport) []reconcile.Request { + return r.enqueueClass(ctx, si) + }), + predicate.TypedGenerationChangedPredicate[*mcsapi.ServiceImport]{}, + predicate.NewTypedPredicateFuncs[*mcsapi.ServiceImport](func(si *mcsapi.ServiceImport) bool { + return r.validateServiceImportForReconcile(si) + }))); err != nil { // ServiceImport is not available in the cluster, skip the watch and not throw error. r.log.Info("unable to watch ServiceImport: %s", err.Error()) } } // Watch EndpointSlice CRUDs and process affected *Route objects. - esPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateEndpointSliceForReconcile), + esPredicates := []predicate.TypedPredicate[*discoveryv1.EndpointSlice]{ + predicate.TypedGenerationChangedPredicate[*discoveryv1.EndpointSlice]{}, + predicate.NewTypedPredicateFuncs[*discoveryv1.EndpointSlice](func(eps *discoveryv1.EndpointSlice) bool { + return r.validateEndpointSliceForReconcile(eps) + }), } if r.namespaceLabel != nil { - esPredicates = append(esPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + esPredicates = append(esPredicates, predicate.NewTypedPredicateFuncs[*discoveryv1.EndpointSlice](func(eps *discoveryv1.EndpointSlice) bool { + return r.hasMatchingNamespaceLabels(eps) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &discoveryv1.EndpointSlice{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - esPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &discoveryv1.EndpointSlice{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *discoveryv1.EndpointSlice) []reconcile.Request { + return r.enqueueClass(ctx, si) + }), + esPredicates...)); err != nil { return err } // Watch Node CRUDs to update Gateway Address exposed by Service of type NodePort. // Node creation/deletion and ExternalIP updates would require update in the Gateway - nPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.handleNode), + nPredicates := []predicate.TypedPredicate[*corev1.Node]{ + predicate.TypedGenerationChangedPredicate[*corev1.Node]{}, + predicate.NewTypedPredicateFuncs[*corev1.Node](func(node *corev1.Node) bool { + return r.handleNode(node) + }), } if r.namespaceLabel != nil { - nPredicates = append(nPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + nPredicates = append(nPredicates, predicate.NewTypedPredicateFuncs[*corev1.Node](func(node *corev1.Node) bool { + return r.hasMatchingNamespaceLabels(node) + })) } // resource address. if err := c.Watch( - source.Kind(mgr.GetCache(), &corev1.Node{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - nPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &corev1.Node{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *corev1.Node) []reconcile.Request { + return r.enqueueClass(ctx, si) + }), + nPredicates...)); err != nil { return err } // Watch Secret CRUDs and process affected EG CRs (Gateway, SecurityPolicy, more in the future). - secretPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateSecretForReconcile), + secretPredicates := []predicate.TypedPredicate[*corev1.Secret]{ + predicate.TypedGenerationChangedPredicate[*corev1.Secret]{}, + predicate.NewTypedPredicateFuncs(func(s *corev1.Secret) bool { + return r.validateSecretForReconcile(s) + }), } if r.namespaceLabel != nil { - secretPredicates = append(secretPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + secretPredicates = append(secretPredicates, predicate.NewTypedPredicateFuncs(func(s *corev1.Secret) bool { + return r.hasMatchingNamespaceLabels(s) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &corev1.Secret{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - secretPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &corev1.Secret{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, s *corev1.Secret) []reconcile.Request { + return r.enqueueClass(ctx, s) + }), + secretPredicates...)); err != nil { return err } // Watch ConfigMap CRUDs and process affected ClienTraffiPolicies and BackendTLSPolicies. - configMapPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateConfigMapForReconcile), + configMapPredicates := []predicate.TypedPredicate[*corev1.ConfigMap]{ + predicate.TypedGenerationChangedPredicate[*corev1.ConfigMap]{}, + predicate.NewTypedPredicateFuncs[*corev1.ConfigMap](func(cm *corev1.ConfigMap) bool { + return r.validateConfigMapForReconcile(cm) + }), } if r.namespaceLabel != nil { - configMapPredicates = append(configMapPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + configMapPredicates = append(configMapPredicates, predicate.NewTypedPredicateFuncs[*corev1.ConfigMap](func(cm *corev1.ConfigMap) bool { + return r.hasMatchingNamespaceLabels(cm) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &corev1.ConfigMap{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - configMapPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &corev1.ConfigMap{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, cm *corev1.ConfigMap) []reconcile.Request { + return r.enqueueClass(ctx, cm) + }), + configMapPredicates...)); err != nil { return err } // Watch ReferenceGrant CRUDs and process affected Gateways. - rgPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + rgPredicates := []predicate.TypedPredicate[*gwapiv1b1.ReferenceGrant]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1b1.ReferenceGrant]{}, + } if r.namespaceLabel != nil { - rgPredicates = append(rgPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + rgPredicates = append(rgPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1b1.ReferenceGrant](func(rg *gwapiv1b1.ReferenceGrant) bool { + return r.hasMatchingNamespaceLabels(rg) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1b1.ReferenceGrant{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - rgPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1b1.ReferenceGrant{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, rg *gwapiv1b1.ReferenceGrant) []reconcile.Request { + return r.enqueueClass(ctx, rg) + }), + rgPredicates...)); err != nil { return err } if err := addReferenceGrantIndexers(ctx, mgr); err != nil { @@ -1153,45 +1224,62 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch Deployment CRUDs and process affected Gateways. - dPredicates := []predicate.Predicate{predicate.NewPredicateFuncs(r.validateDeploymentForReconcile)} + dPredicates := []predicate.TypedPredicate[*appsv1.Deployment]{ + predicate.NewTypedPredicateFuncs[*appsv1.Deployment](func(deploy *appsv1.Deployment) bool { + return r.validateDeploymentForReconcile(deploy) + }), + } if r.namespaceLabel != nil { - dPredicates = append(dPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + dPredicates = append(dPredicates, predicate.NewTypedPredicateFuncs[*appsv1.Deployment](func(deploy *appsv1.Deployment) bool { + return r.hasMatchingNamespaceLabels(deploy) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &appsv1.Deployment{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - dPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &appsv1.Deployment{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, deploy *appsv1.Deployment) []reconcile.Request { + return r.enqueueClass(ctx, deploy) + }), + dPredicates...)); err != nil { return err } - // Watch EnvoyPatchPolicy if enabled in config - eppPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if r.namespaceLabel != nil { - eppPredicates = append(eppPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) - } if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy { + // Watch EnvoyPatchPolicy if enabled in config + eppPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyPatchPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyPatchPolicy]{}, + } + if r.namespaceLabel != nil { + eppPredicates = append(eppPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.EnvoyPatchPolicy](func(epp *egv1a1.EnvoyPatchPolicy) bool { + return r.hasMatchingNamespaceLabels(epp) + })) + } // Watch EnvoyPatchPolicy CRUDs if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyPatchPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - eppPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.EnvoyPatchPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, epp *egv1a1.EnvoyPatchPolicy) []reconcile.Request { + return r.enqueueClass(ctx, epp) + }), + eppPredicates...)); err != nil { return err } } // Watch ClientTrafficPolicy - ctpPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + ctpPredicates := []predicate.TypedPredicate[*egv1a1.ClientTrafficPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.ClientTrafficPolicy]{}, + } if r.namespaceLabel != nil { - ctpPredicates = append(ctpPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + ctpPredicates = append(ctpPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.ClientTrafficPolicy](func(ctp *egv1a1.ClientTrafficPolicy) bool { + return r.hasMatchingNamespaceLabels(ctp) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.ClientTrafficPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - ctpPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.ClientTrafficPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, ctp *egv1a1.ClientTrafficPolicy) []reconcile.Request { + return r.enqueueClass(ctx, ctp) + }), + ctpPredicates...)); err != nil { return err } @@ -1200,30 +1288,40 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch BackendTrafficPolicy - btpPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + btpPredicates := []predicate.TypedPredicate[*egv1a1.BackendTrafficPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.BackendTrafficPolicy]{}, + } if r.namespaceLabel != nil { - btpPredicates = append(btpPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + btpPredicates = append(btpPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.BackendTrafficPolicy](func(btp *egv1a1.BackendTrafficPolicy) bool { + return r.hasMatchingNamespaceLabels(btp) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.BackendTrafficPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - btpPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.BackendTrafficPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, btp *egv1a1.BackendTrafficPolicy) []reconcile.Request { + return r.enqueueClass(ctx, btp) + }), + btpPredicates...)); err != nil { return err } // Watch SecurityPolicy - spPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + spPredicates := []predicate.TypedPredicate[*egv1a1.SecurityPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.SecurityPolicy]{}, + } if r.namespaceLabel != nil { - spPredicates = append(spPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + spPredicates = append(spPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.SecurityPolicy](func(sp *egv1a1.SecurityPolicy) bool { + return r.hasMatchingNamespaceLabels(sp) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.SecurityPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - spPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.SecurityPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, sp *egv1a1.SecurityPolicy) []reconcile.Request { + return r.enqueueClass(ctx, sp) + }), + spPredicates...)); err != nil { return err } if err := addSecurityPolicyIndexers(ctx, mgr); err != nil { @@ -1231,16 +1329,21 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch BackendTLSPolicy - btlsPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + btlsPredicates := []predicate.TypedPredicate[*gwapiv1a2.BackendTLSPolicy]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.BackendTLSPolicy]{}, + } if r.namespaceLabel != nil { - btlsPredicates = append(btlsPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + btlsPredicates = append(btlsPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.BackendTLSPolicy](func(btp *gwapiv1a2.BackendTLSPolicy) bool { + return r.hasMatchingNamespaceLabels(btp) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.BackendTLSPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - btlsPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.BackendTLSPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, btp *gwapiv1a2.BackendTLSPolicy) []reconcile.Request { + return r.enqueueClass(ctx, btp) + }), + btlsPredicates...)); err != nil { return err } @@ -1249,17 +1352,22 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch EnvoyExtensionPolicy - eepPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + eepPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyExtensionPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyExtensionPolicy]{}, + } if r.namespaceLabel != nil { - eepPredicates = append(eepPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + eepPredicates = append(eepPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.EnvoyExtensionPolicy](func(eep *egv1a1.EnvoyExtensionPolicy) bool { + return r.hasMatchingNamespaceLabels(eep) + })) } // Watch EnvoyExtensionPolicy CRUDs if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyExtensionPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - eepPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.EnvoyExtensionPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, eep *egv1a1.EnvoyExtensionPolicy) []reconcile.Request { + return r.enqueueClass(ctx, eep) + }), + eepPredicates...)); err != nil { return err } if err := addEnvoyExtensionPolicyIndexers(ctx, mgr); err != nil { @@ -1269,17 +1377,22 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M r.log.Info("Watching gatewayAPI related objects") // Watch any additional GVKs from the registered extension. - uPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + uPredicates := []predicate.TypedPredicate[*unstructured.Unstructured]{ + predicate.TypedGenerationChangedPredicate[*unstructured.Unstructured]{}, + } if r.namespaceLabel != nil { - uPredicates = append(uPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + uPredicates = append(uPredicates, predicate.NewTypedPredicateFuncs[*unstructured.Unstructured](func(obj *unstructured.Unstructured) bool { + return r.hasMatchingNamespaceLabels(obj) + })) } for _, gvk := range r.extGVKs { u := &unstructured.Unstructured{} u.SetGroupVersionKind(gvk) - if err := c.Watch(source.Kind(mgr.GetCache(), u), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - uPredicates..., - ); err != nil { + if err := c.Watch(source.Kind(mgr.GetCache(), u, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *unstructured.Unstructured) []reconcile.Request { + return r.enqueueClass(ctx, si) + }), + uPredicates...)); err != nil { return err } r.log.Info("Watching additional resource", "resource", gvk.String()) @@ -1293,12 +1406,7 @@ func (r *gatewayAPIReconciler) enqueueClass(_ context.Context, _ client.Object) }}} } -func (r *gatewayAPIReconciler) hasManagedClass(obj client.Object) bool { - ep, ok := obj.(*egv1a1.EnvoyProxy) - if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) - } - +func (r *gatewayAPIReconciler) hasManagedClass(ep *egv1a1.EnvoyProxy) bool { // The EnvoyProxy must be in the same namespace as EG. if ep.Namespace != r.namespace { r.log.Info("envoyproxy namespace does not match Envoy Gateway's namespace", @@ -1435,7 +1543,8 @@ func (r *gatewayAPIReconciler) processBackendTLSPolicyConfigMapRefs(ctx context. // processEnvoyExtensionPolicies adds EnvoyExtensionPolicies and their referenced resources to the resourceTree func (r *gatewayAPIReconciler) processEnvoyExtensionPolicies( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) error { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) error { envoyExtensionPolicies := egv1a1.EnvoyExtensionPolicyList{} if err := r.client.List(ctx, &envoyExtensionPolicies); err != nil { return fmt.Errorf("error listing EnvoyExtensionPolicies: %w", err) @@ -1459,7 +1568,8 @@ func (r *gatewayAPIReconciler) processEnvoyExtensionPolicies( // to the resourceTree // - BackendRefs for ExtProcs func (r *gatewayAPIReconciler) processEnvoyExtensionPolicyObjectRefs( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) { // we don't return errors from this method, because we want to continue reconciling // the rest of the EnvoyExtensionPolicies despite that one reference is invalid. This // allows Envoy Gateway to continue serving traffic even if some EnvoyExtensionPolicies @@ -1470,38 +1580,40 @@ func (r *gatewayAPIReconciler) processEnvoyExtensionPolicyObjectRefs( for _, policy := range resourceTree.EnvoyExtensionPolicies { // Add the referenced BackendRefs and ReferenceGrants in ExtAuth to Maps for later processing for _, ep := range policy.Spec.ExtProc { - backendRef := ep.BackendRef.BackendObjectReference - - backendNamespace := gatewayapi.NamespaceDerefOr(backendRef.Namespace, policy.Namespace) - resourceMap.allAssociatedBackendRefs[gwapiv1.BackendObjectReference{ - Group: backendRef.Group, - Kind: backendRef.Kind, - Namespace: gatewayapi.NamespacePtrV1Alpha2(backendNamespace), - Name: backendRef.Name, - }] = struct{}{} - - if backendNamespace != policy.Namespace { - from := ObjectKindNamespacedName{ - kind: gatewayapi.KindHTTPRoute, - namespace: policy.Namespace, - name: policy.Name, - } - to := ObjectKindNamespacedName{ - kind: gatewayapi.KindDerefOr(backendRef.Kind, gatewayapi.KindService), - namespace: backendNamespace, - name: string(backendRef.Name), - } - refGrant, err := r.findReferenceGrant(ctx, from, to) - switch { - case err != nil: - r.log.Error(err, "failed to find ReferenceGrant") - case refGrant == nil: - r.log.Info("no matching ReferenceGrants found", "from", from.kind, - "from namespace", from.namespace, "target", to.kind, "target namespace", to.namespace) - default: - resourceTree.ReferenceGrants = append(resourceTree.ReferenceGrants, refGrant) - r.log.Info("added ReferenceGrant to resource map", "namespace", refGrant.Namespace, - "name", refGrant.Name) + for _, br := range ep.BackendRefs { + backendRef := br.BackendObjectReference + + backendNamespace := gatewayapi.NamespaceDerefOr(backendRef.Namespace, policy.Namespace) + resourceMap.allAssociatedBackendRefs[gwapiv1.BackendObjectReference{ + Group: backendRef.Group, + Kind: backendRef.Kind, + Namespace: gatewayapi.NamespacePtrV1Alpha2(backendNamespace), + Name: backendRef.Name, + }] = struct{}{} + + if backendNamespace != policy.Namespace { + from := ObjectKindNamespacedName{ + kind: gatewayapi.KindHTTPRoute, + namespace: policy.Namespace, + name: policy.Name, + } + to := ObjectKindNamespacedName{ + kind: gatewayapi.KindDerefOr(backendRef.Kind, gatewayapi.KindService), + namespace: backendNamespace, + name: string(backendRef.Name), + } + refGrant, err := r.findReferenceGrant(ctx, from, to) + switch { + case err != nil: + r.log.Error(err, "failed to find ReferenceGrant") + case refGrant == nil: + r.log.Info("no matching ReferenceGrants found", "from", from.kind, + "from namespace", from.namespace, "target", to.kind, "target namespace", to.namespace) + default: + resourceTree.ReferenceGrants = append(resourceTree.ReferenceGrants, refGrant) + r.log.Info("added ReferenceGrant to resource map", "namespace", refGrant.Namespace, + "name", refGrant.Name) + } } } } diff --git a/internal/provider/kubernetes/controller_test.go b/internal/provider/kubernetes/controller_test.go index 1aa58a1d533..8e3a5f9b56f 100644 --- a/internal/provider/kubernetes/controller_test.go +++ b/internal/provider/kubernetes/controller_test.go @@ -156,7 +156,7 @@ func TestHasManagedClass(t *testing.T) { testCases := []struct { name string - ep client.Object + ep *egv1a1.EnvoyProxy classes []*gwapiv1.GatewayClass expected bool }{ diff --git a/internal/provider/kubernetes/helpers.go b/internal/provider/kubernetes/helpers.go index 00029f1cb92..d3a1d972a42 100644 --- a/internal/provider/kubernetes/helpers.go +++ b/internal/provider/kubernetes/helpers.go @@ -36,8 +36,8 @@ type ObjectKindNamespacedName struct { // is a Gateway. func validateParentRefs(ctx context.Context, client client.Client, namespace string, gatewayClassController gwapiv1.GatewayController, - routeParentReferences []gwapiv1.ParentReference) ([]gwapiv1.Gateway, error) { - + routeParentReferences []gwapiv1.ParentReference, +) ([]gwapiv1.Gateway, error) { var gateways []gwapiv1.Gateway for i := range routeParentReferences { ref := routeParentReferences[i] diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go index ac1132b31d5..511802e2e38 100644 --- a/internal/provider/kubernetes/indexers.go +++ b/internal/provider/kubernetes/indexers.go @@ -38,7 +38,7 @@ const ( configMapCtpIndex = "configMapCtpIndex" secretCtpIndex = "secretCtpIndex" configMapBtlsIndex = "configMapBtlsIndex" - backendEnvoyExtensionPolicyIndex = "backendSecurityPolicyIndex" + backendEnvoyExtensionPolicyIndex = "backendEnvoyExtensionPolicyIndex" ) func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error { @@ -535,12 +535,14 @@ func backendEnvoyExtensionPolicyIndexFunc(rawObj client.Object) []string { var ret []string for _, ep := range envoyExtensionPolicy.Spec.ExtProc { - backendRef := ep.BackendRef.BackendObjectReference - ret = append(ret, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOr(backendRef.Namespace, envoyExtensionPolicy.Namespace), - Name: string(backendRef.Name), - }.String()) + for _, br := range ep.BackendRefs { + backendRef := br.BackendObjectReference + ret = append(ret, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(backendRef.Namespace, envoyExtensionPolicy.Namespace), + Name: string(backendRef.Name), + }.String()) + } } return ret diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index 2187e5b5df1..c0ca5d094bb 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -442,7 +442,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour rewriteHostname := gwapiv1.PreciseHostname("rewrite.hostname.local") - var testCases = []struct { + testCases := []struct { name string route gwapiv1.HTTPRoute }{ @@ -986,7 +986,7 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc require.NoError(t, cli.Delete(ctx, svc)) }() - var testCases = []struct { + testCases := []struct { name string route gwapiv1a2.TLSRoute }{ @@ -1149,13 +1149,17 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov }}, }, Hostnames: []gwapiv1a2.Hostname{"test-tls.hostname.local"}, - Rules: []gwapiv1a2.TLSRouteRule{{ - BackendRefs: []gwapiv1a2.BackendRef{{ - BackendObjectReference: gwapiv1a2.BackendObjectReference{ - Name: "test-common-svc", - Port: ptr.To(gwapiv1.PortNumber(90)), - }}, - }}, + Rules: []gwapiv1a2.TLSRouteRule{ + { + BackendRefs: []gwapiv1a2.BackendRef{ + { + BackendObjectReference: gwapiv1a2.BackendObjectReference{ + Name: "test-common-svc", + Port: ptr.To(gwapiv1.PortNumber(90)), + }, + }, + }, + }, }, }, } @@ -1585,7 +1589,6 @@ func TestNamespaceSelectorProvider(t *testing.T) { } return res != nil && len(res.GRPCRoutes) == 1 }, defaultWait, defaultTick) - } func waitUntilGatewayClassResourcesAreReady(resources *message.ProviderResources, gatewayClassName string) (*gatewayapi.Resources, bool) { diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index f25c0092326..1c0668f1a9b 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -33,13 +33,7 @@ const oidcHMACSecretName = "envoy-oidc-hmac" // hasMatchingController returns true if the provided object is a GatewayClass // with a Spec.Controller string matching this Envoy Gateway's controller string, // or false otherwise. -func (r *gatewayAPIReconciler) hasMatchingController(obj client.Object) bool { - gc, ok := obj.(*gwapiv1.GatewayClass) - if !ok { - r.log.Info("bypassing reconciliation due to unexpected object type", "type", obj) - return false - } - +func (r *gatewayAPIReconciler) hasMatchingController(gc *gwapiv1.GatewayClass) bool { if gc.Spec.ControllerName == r.classController { r.log.Info("gatewayclass has matching controller name, processing", "name", gc.Name) return true @@ -69,7 +63,6 @@ type NamespaceGetter interface { // checkObjectNamespaceLabels checks if labels of namespace of the object is a subset of namespaceLabels func (r *gatewayAPIReconciler) checkObjectNamespaceLabels(obj metav1.Object) (bool, error) { - var nsString string // TODO: it requires extra condition validate cluster resources or resources without namespace? if nsString = obj.GetNamespace(); len(nsString) == 0 { diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index e9f24d6e51f..6f327b0c23a 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -33,18 +33,18 @@ import ( func TestGatewayClassHasMatchingController(t *testing.T) { testCases := []struct { name string - obj client.Object + gc *gwapiv1.GatewayClass client client.Client expect bool }{ { name: "matching controller name", - obj: test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), + gc: test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), expect: true, }, { name: "non-matching controller name", - obj: test.GetGatewayClass("test-gc", "not.configured/controller", nil), + gc: test.GetGatewayClass("test-gc", "not.configured/controller", nil), expect: false, }, } @@ -60,7 +60,7 @@ func TestGatewayClassHasMatchingController(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { - res := r.hasMatchingController(tc.obj) + res := r.hasMatchingController(tc.gc) require.Equal(t, tc.expect, res) }) } @@ -530,9 +530,11 @@ func TestValidateServiceForReconcile(t *testing.T) { }, ExtProc: []v1alpha1.ExtProc{ { - BackendRef: v1alpha1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "ext-proc-service", + BackendRefs: []v1alpha1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "ext-proc-service", + }, }, }, }, @@ -559,9 +561,11 @@ func TestValidateServiceForReconcile(t *testing.T) { }, ExtProc: []v1alpha1.ExtProc{ { - BackendRef: v1alpha1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "ext-proc-service", + BackendRefs: []v1alpha1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "ext-proc-service", + }, }, }, }, diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index 20d690f574a..b1b2524e25a 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -23,7 +23,8 @@ import ( // processTLSRoutes finds TLSRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the TLSRoutes to the resourceTree. func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { tlsRouteList := &gwapiv1a2.TLSRouteList{} if err := r.client.List(ctx, tlsRouteList, &client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayTLSRouteIndex, gatewayNamespaceName), @@ -93,7 +94,8 @@ func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayName // processGRPCRoutes finds GRPCRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the GRPCRoutes to the resourceTree. func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { grpcRouteList := &gwapiv1a2.GRPCRouteList{} if err := r.client.List(ctx, grpcRouteList, &client.ListOptions{ @@ -203,7 +205,8 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam // processHTTPRoutes finds HTTPRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the HTTPRoutes to the resourceTree. func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { httpRouteList := &gwapiv1.HTTPRouteList{} extensionRefFilters, err := r.getExtensionRefFilters(ctx) @@ -376,7 +379,8 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam // processTCPRoutes finds TCPRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the TCPRoutes to the resourceTree. func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { tcpRouteList := &gwapiv1a2.TCPRouteList{} if err := r.client.List(ctx, tcpRouteList, &client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayTCPRouteIndex, gatewayNamespaceName), @@ -446,7 +450,8 @@ func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayName // processUDPRoutes finds UDPRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the UDPRoutes to the resourceTree. func (r *gatewayAPIReconciler) processUDPRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { udpRouteList := &gwapiv1a2.UDPRouteList{} if err := r.client.List(ctx, udpRouteList, &client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayUDPRouteIndex, gatewayNamespaceName), diff --git a/internal/provider/kubernetes/secrets.go b/internal/provider/kubernetes/secrets.go index ab67f6e1608..953127e781b 100644 --- a/internal/provider/kubernetes/secrets.go +++ b/internal/provider/kubernetes/secrets.go @@ -20,9 +20,7 @@ import ( "github.com/envoyproxy/gateway/internal/utils" ) -var ( - ErrSecretExists = errors.New("skipped creating secret since it already exists") -) +var ErrSecretExists = errors.New("skipped creating secret since it already exists") // caCertificateKey is the key name for accessing TLS CA certificate bundles // in Kubernetes Secrets. diff --git a/internal/provider/kubernetes/sources.go b/internal/provider/kubernetes/sources.go index 66d93acb0d5..e19259f77ca 100644 --- a/internal/provider/kubernetes/sources.go +++ b/internal/provider/kubernetes/sources.go @@ -13,22 +13,22 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/source" ) // watchAndReconcileSource is a concrete implementation of the Source interface. type watchAndReconcileSource struct { - condition <-chan struct{} - object client.Object + condition <-chan struct{} + object client.Object + eventHandler handler.EventHandler } -func NewWatchAndReconcileSource(cond <-chan struct{}, obj client.Object) source.Source { - return &watchAndReconcileSource{condition: cond, object: obj} +func NewWatchAndReconcileSource(cond <-chan struct{}, obj client.Object, eh handler.EventHandler) source.Source { + return &watchAndReconcileSource{condition: cond, object: obj, eventHandler: eh} } // Start implements the Source interface. It registers the EventHandler with the Informer. -func (s *watchAndReconcileSource) Start(ctx context.Context, eh handler.EventHandler, queue workqueue.RateLimitingInterface, _ ...predicate.Predicate) error { +func (s *watchAndReconcileSource) Start(ctx context.Context, queue workqueue.RateLimitingInterface) error { if s.object == nil { return errors.New("object to queue is required") } @@ -39,7 +39,7 @@ func (s *watchAndReconcileSource) Start(ctx context.Context, eh handler.EventHan return case <-s.condition: // Triggers a reconcile - eh.Generic(ctx, event.GenericEvent{Object: s.object}, queue) + s.eventHandler.Generic(ctx, event.GenericEvent{Object: s.object}, queue) } }() return nil diff --git a/internal/provider/kubernetes/sources_test.go b/internal/provider/kubernetes/sources_test.go index adae9f8f854..aafc74bd2b6 100644 --- a/internal/provider/kubernetes/sources_test.go +++ b/internal/provider/kubernetes/sources_test.go @@ -59,8 +59,8 @@ func TestSources(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { cond := make(chan struct{}) - store := NewWatchAndReconcileSource(cond, tc.obj) - err := store.Start(tc.ctx, tc.handler, tc.queue) + store := NewWatchAndReconcileSource(cond, tc.obj, tc.handler) + err := store.Start(tc.ctx, tc.queue) if !tc.expected { require.Error(t, err) } else { diff --git a/internal/provider/kubernetes/status.go b/internal/provider/kubernetes/status.go index 5aa8af4fa57..33988675073 100644 --- a/internal/provider/kubernetes/status.go +++ b/internal/provider/kubernetes/status.go @@ -447,7 +447,8 @@ func (r *gatewayAPIReconciler) updateStatusForGatewayClass( gc *gwapiv1.GatewayClass, accepted bool, reason, - msg string) error { + msg string, +) error { if r.statusUpdater != nil { r.statusUpdater.Send(status.Update{ NamespacedName: types.NamespacedName{Name: gc.Name}, diff --git a/internal/status/conditions.go b/internal/status/conditions.go index 092513184bb..955dc26a7ab 100644 --- a/internal/status/conditions.go +++ b/internal/status/conditions.go @@ -34,7 +34,8 @@ const ( // computeGatewayClassAcceptedCondition computes the GatewayClass Accepted status condition. func computeGatewayClassAcceptedCondition(gatewayClass *gwapiv1.GatewayClass, accepted bool, - reason, msg string) metav1.Condition { + reason, msg string, +) metav1.Condition { switch accepted { case true: return metav1.Condition{ diff --git a/internal/status/policy.go b/internal/status/policy.go index e60b52d40db..a5c7a21a92f 100644 --- a/internal/status/policy.go +++ b/internal/status/policy.go @@ -59,15 +59,16 @@ func setAcceptedForPolicyAncestor(policyStatus *gwv1a2.PolicyStatus, ancestorRef } func SetConditionForPolicyAncestors(policyStatus *gwv1a2.PolicyStatus, ancestorRefs []gwv1a2.ParentReference, controllerName string, - conditionType gwv1a2.PolicyConditionType, status metav1.ConditionStatus, reason gwv1a2.PolicyConditionReason, message string, generation int64) { + conditionType gwv1a2.PolicyConditionType, status metav1.ConditionStatus, reason gwv1a2.PolicyConditionReason, message string, generation int64, +) { for _, ancestorRef := range ancestorRefs { SetConditionForPolicyAncestor(policyStatus, ancestorRef, controllerName, conditionType, status, reason, message, generation) } } func SetConditionForPolicyAncestor(policyStatus *gwv1a2.PolicyStatus, ancestorRef gwv1a2.ParentReference, controllerName string, - conditionType gwv1a2.PolicyConditionType, status metav1.ConditionStatus, reason gwv1a2.PolicyConditionReason, message string, generation int64) { - + conditionType gwv1a2.PolicyConditionType, status metav1.ConditionStatus, reason gwv1a2.PolicyConditionReason, message string, generation int64, +) { if policyStatus.Ancestors == nil { policyStatus.Ancestors = []gwv1a2.PolicyAncestorStatus{} } diff --git a/internal/utils/field/field_test.go b/internal/utils/field/field_test.go index fe8460973b3..8e8322d9ad3 100644 --- a/internal/utils/field/field_test.go +++ b/internal/utils/field/field_test.go @@ -19,22 +19,25 @@ func TestSetValue(t *testing.T) { fieldValue any expect any expectedErr bool - }{{ - name: "field name cannot be empty", - input: "", - expectedErr: true, - }, + }{ + { + name: "field name cannot be empty", + input: "", + expectedErr: true, + }, { name: "input cannot be a string", input: "", fieldName: "K", expectedErr: true, - }, { + }, + { name: "input cannot be a struct", input: struct{}{}, fieldName: "K", expectedErr: true, - }, { + }, + { name: "field cannot be unexported", input: &struct { name string @@ -45,7 +48,8 @@ func TestSetValue(t *testing.T) { expectedErr: true, fieldName: "name", fieldValue: "test1", - }, { + }, + { name: "simple struct set value", input: &struct { Name string @@ -56,7 +60,8 @@ func TestSetValue(t *testing.T) { expectedErr: false, fieldName: "Name", fieldValue: "test1", - }, { + }, + { name: "simple recursive struct set value", input: &struct { Name string @@ -77,7 +82,8 @@ func TestSetValue(t *testing.T) { expectedErr: false, fieldName: "Name", fieldValue: "test1", - }, { + }, + { name: "simple recursive child struct in slice set value", input: &struct { Name string @@ -100,7 +106,8 @@ func TestSetValue(t *testing.T) { expectedErr: false, fieldName: "Name", fieldValue: "test1", - }, { + }, + { name: "simple recursive child struct in map set value", input: &struct { Name string diff --git a/internal/utils/file/file.go b/internal/utils/file/file.go index 369920b0f9a..51a02571493 100644 --- a/internal/utils/file/file.go +++ b/internal/utils/file/file.go @@ -11,7 +11,7 @@ import ( ) func Write(data string, filepath string) error { - file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644) if err != nil { return err } diff --git a/internal/utils/helm/package.go b/internal/utils/helm/package.go index f057b0744c3..4cbf81eff4c 100644 --- a/internal/utils/helm/package.go +++ b/internal/utils/helm/package.go @@ -77,7 +77,6 @@ func NewPackageTool() *PackageTool { // Setup Configuration required to initialize helm action. func (pt *PackageTool) Setup() error { - // Since envoy-gateway uses docker's oci to store charts, // we need to create a registry client to make sure we can retrieve envoy-gateway chart registryCli, err := registry.NewClient() @@ -112,7 +111,6 @@ func (pt *PackageTool) Setup() error { // SetInstallEnvSettings set the installation flags we are interested in func (pt *PackageTool) SetInstallEnvSettings(installCmd *cobra.Command, opts *PackageOptions) { - // add helm flags // we use a temporary flag to be set by helm env flags, // from which we can retrieve the flags we are interested @@ -139,12 +137,10 @@ func (pt *PackageTool) SetInstallEnvSettings(installCmd *cobra.Command, opts *Pa installCmd.Flags().StringSliceVarP(&pt.valuesOpts.ValueFiles, "values", "f", []string{}, "Specify values in a YAML file or a URL (can specify multiple)") installCmd.Flags().StringArrayVar(&pt.valuesOpts.Values, "set", []string{}, "Set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - } // SetUninstallEnvSetting set the uninstallation flags we are interested in func (pt *PackageTool) SetUninstallEnvSetting(uninstallCmd *cobra.Command, opts *PackageOptions) { - uninstallCmd.Flags().DurationVar(&opts.Timeout, "timeout", helmOperateTimeout, "time to wait for any individual Kubernetes operation") uninstallCmd.Flags().StringVar(&opts.ReleaseName, "name", egReleaseName, "name of the envoy-gateway release to uninstall") uninstallCmd.Flags().StringVarP(&opts.ReleaseNamespace, "namespace", "n", "", "if set, specify the namespace where envoy gateway is uninstalled") @@ -152,12 +148,10 @@ func (pt *PackageTool) SetUninstallEnvSetting(uninstallCmd *cobra.Command, opts uninstallCmd.Flags().BoolVar(&opts.DryRun, "dry-run", false, "console output only, make no changes") uninstallCmd.Flags().BoolVar(&opts.WithCRD, "with-crds", false, "if set, the CRDs will also be removed") uninstallCmd.Flags().Bool("debug", false, "if set, the will output detailed execution logs") - } // loadChart Load the chart instance according to the chart name and version func (pt *PackageTool) loadChart(opts *PackageOptions) (*chart.Chart, error) { - pt.actionInstall.Version = opts.Version chartName, err := pt.actionInstall.LocateChart(pt.chartName, pt.envSettings) if err != nil { @@ -182,7 +176,6 @@ func (pt *PackageTool) loadChart(opts *PackageOptions) (*chart.Chart, error) { // extractCRDs Extract the CRDs part of the chart func (pt *PackageTool) extractCRDs(ch *chart.Chart) ([]*resource.Info, error) { - crdResInfo := make([]*resource.Info, 0, len(ch.CRDObjects())) for _, crd := range ch.CRDObjects() { @@ -204,7 +197,6 @@ func (pt *PackageTool) extractCRDs(ch *chart.Chart) ([]*resource.Info, error) { // This is done to avoid garbage collection on CRs in the cluster during uninstallation, // preventing the potential loss of crucial CR instances. func (pt *PackageTool) RunInstall(opts *PackageOptions) error { - if opts.Version == "v0.0.0-latest" { warningMarker := color.New(color.FgYellow).Add(color.Bold).Sprintf("WARNING") pt.logger.Println(fmt.Sprintf("%s: Currently using the latest version of envoy gateway chart, it is recommended to use the fixed version", @@ -270,7 +262,7 @@ func (pt *PackageTool) RunInstall(opts *PackageOptions) error { var outputErr error var outputFile *os.File - if outputFile, outputErr = os.OpenFile(opts.Output, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666); outputErr == nil { + if outputFile, outputErr = os.OpenFile(opts.Output, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0o666); outputErr == nil { _, outputErr = fmt.Fprint(outputFile, release.Manifest) } if outputErr != nil { @@ -290,7 +282,6 @@ func (pt *PackageTool) RunInstall(opts *PackageOptions) error { // RunUninstall By default, we only uninstall instances of the Envoy Gateway resources. func (pt *PackageTool) RunUninstall(opts *PackageOptions) error { - pt.setUninstallOptions(opts) resp, err := pt.actionUninstall.Run(opts.ReleaseName) @@ -304,7 +295,6 @@ func (pt *PackageTool) RunUninstall(opts *PackageOptions) error { } if opts.WithCRD { - if crdInfo, err := pt.extractCRDs(resp.Release.Chart); err != nil { return err } else if len(crdInfo) == 0 { @@ -312,7 +302,6 @@ func (pt *PackageTool) RunUninstall(opts *PackageOptions) error { } else if _, errors := pt.actionConfig.KubeClient.Delete(crdInfo); len(errors) != 0 { return fmt.Errorf("failed to delete CRDs error: %s", util.MultipleErrors("", errors)) } - } successMarker := color.New(color.FgGreen).Add(color.Bold).Sprintf("SUCCESS") @@ -330,7 +319,6 @@ func (pt *PackageTool) setCommonValue() { // setInstallOptions Sets the options required before install func (pt *PackageTool) setInstallOptions(opts *PackageOptions) { - if opts.DryRun { // When dry-run is set up, we do not need to connect to k8s-api server. // Since the kubernetes version needs to be higher than the value in the Helm library @@ -375,7 +363,6 @@ func (pt *PackageTool) setUninstallOptions(opts *PackageOptions) { func (pt *PackageTool) SetPreRun(cmd *cobra.Command) { existPreRunE := cmd.PreRunE cmd.PreRunE = func(cmd *cobra.Command, args []string) error { - pt.setPrinter(cmd) pt.setNamespace(cmd) @@ -426,7 +413,6 @@ func createDummyK8sVersion() *chartutil.KubeVersion { // detectExistCRDs Check if envoy-gateway and gateway-api CRDs already exist in the cluster func detectExistCRDs(crdResInfo []*resource.Info) (*bool, error) { - exist := false existObj := make([]runtime.Object, 0, len(crdResInfo)) @@ -455,7 +441,6 @@ func detectExistCRDs(crdResInfo []*resource.Info) (*bool, error) { // installCRDs Install CRDs to the cluster func installCRDs(crds []*resource.Info, actionConfig *action.Configuration) error { - // Create all CRDs in the envoy gateway chart result, err := actionConfig.KubeClient.Create(crds) if err != nil { diff --git a/internal/utils/protocov/protocov.go b/internal/utils/protocov/protocov.go index 52bb952269e..6533f84c543 100644 --- a/internal/utils/protocov/protocov.go +++ b/internal/utils/protocov/protocov.go @@ -16,9 +16,7 @@ const ( APIPrefix = "type.googleapis.com/" ) -var ( - marshalOpts = proto.MarshalOptions{} -) +var marshalOpts = proto.MarshalOptions{} func ToAnyWithError(msg proto.Message) (*anypb.Any, error) { if msg == nil { diff --git a/internal/xds/bootstrap/bootstrap_test.go b/internal/xds/bootstrap/bootstrap_test.go index a913fbb082c..54ee52f3d4e 100644 --- a/internal/xds/bootstrap/bootstrap_test.go +++ b/internal/xds/bootstrap/bootstrap_test.go @@ -145,7 +145,7 @@ func TestGetRenderedBootstrapConfig(t *testing.T) { if *overrideTestData { // nolint:gosec - err = os.WriteFile(path.Join("testdata", "render", fmt.Sprintf("%s.yaml", tc.name)), []byte(got), 0644) + err = os.WriteFile(path.Join("testdata", "render", fmt.Sprintf("%s.yaml", tc.name)), []byte(got), 0o644) require.NoError(t, err) return } diff --git a/internal/xds/bootstrap/util_test.go b/internal/xds/bootstrap/util_test.go index b0d27460093..5591d0e4f53 100644 --- a/internal/xds/bootstrap/util_test.go +++ b/internal/xds/bootstrap/util_test.go @@ -18,9 +18,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") func TestApplyBootstrapConfig(t *testing.T) { str, _ := readTestData("enable-prometheus") @@ -56,7 +54,7 @@ func TestApplyBootstrapConfig(t *testing.T) { if *overrideTestData { // nolint:gosec - err = os.WriteFile(path.Join("testdata", "merge", fmt.Sprintf("%s.out.yaml", tc.name)), []byte(data), 0644) + err = os.WriteFile(path.Join("testdata", "merge", fmt.Sprintf("%s.out.yaml", tc.name)), []byte(data), 0o644) require.NoError(t, err) return } diff --git a/internal/xds/translator/accesslog.go b/internal/xds/translator/accesslog.go index 63e6d46c9fd..9f1f17a09d9 100644 --- a/internal/xds/translator/accesslog.go +++ b/internal/xds/translator/accesslog.go @@ -48,14 +48,12 @@ const ( otelAccessLog = "envoy.access_loggers.open_telemetry" ) -var ( - // for the case when a route does not exist to upstream, hcm logs will not be present - listenerAccessLogFilter = &accesslog.AccessLogFilter{ - FilterSpecifier: &accesslog.AccessLogFilter_ResponseFlagFilter{ - ResponseFlagFilter: &accesslog.ResponseFlagFilter{Flags: []string{"NR"}}, - }, - } -) +// for the case when a route does not exist to upstream, hcm logs will not be present +var listenerAccessLogFilter = &accesslog.AccessLogFilter{ + FilterSpecifier: &accesslog.AccessLogFilter_ResponseFlagFilter{ + ResponseFlagFilter: &accesslog.ResponseFlagFilter{Flags: []string{"NR"}}, + }, +} func buildXdsAccessLog(al *ir.AccessLog, forListener bool) []*accesslog.AccessLog { if al == nil { diff --git a/internal/xds/translator/basicauth.go b/internal/xds/translator/basicauth.go index 5733cc34209..e22febfca4b 100644 --- a/internal/xds/translator/basicauth.go +++ b/internal/xds/translator/basicauth.go @@ -27,8 +27,7 @@ func init() { registerHTTPFilter(&basicAuth{}) } -type basicAuth struct { -} +type basicAuth struct{} var _ httpFilter = &basicAuth{} diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 6cbe45def02..bb18a7e0286 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -38,18 +38,19 @@ const ( ) type xdsClusterArgs struct { - name string - settings []*ir.DestinationSetting - tSocket *corev3.TransportSocket - endpointType EndpointType - loadBalancer *ir.LoadBalancer - proxyProtocol *ir.ProxyProtocol - circuitBreaker *ir.CircuitBreaker - healthCheck *ir.HealthCheck - http1Settings *ir.HTTP1Settings - timeout *ir.Timeout - tcpkeepalive *ir.TCPKeepalive - metrics *ir.Metrics + name string + settings []*ir.DestinationSetting + tSocket *corev3.TransportSocket + endpointType EndpointType + loadBalancer *ir.LoadBalancer + proxyProtocol *ir.ProxyProtocol + circuitBreaker *ir.CircuitBreaker + healthCheck *ir.HealthCheck + http1Settings *ir.HTTP1Settings + timeout *ir.Timeout + tcpkeepalive *ir.TCPKeepalive + metrics *ir.Metrics + useClientProtocol bool } type EndpointType int @@ -81,7 +82,9 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { DnsLookupFamily: clusterv3.Cluster_V4_ONLY, CommonLbConfig: &clusterv3.Cluster_CommonLbConfig{ LocalityConfigSpecifier: &clusterv3.Cluster_CommonLbConfig_LocalityWeightedLbConfig_{ - LocalityWeightedLbConfig: &clusterv3.Cluster_CommonLbConfig_LocalityWeightedLbConfig{}}}, + LocalityWeightedLbConfig: &clusterv3.Cluster_CommonLbConfig_LocalityWeightedLbConfig{}, + }, + }, OutlierDetection: &clusterv3.OutlierDetection{}, PerConnectionBufferLimitBytes: wrapperspb.UInt32(tcpClusterPerConnectionBufferLimitBytes), } @@ -190,7 +193,6 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { if args.healthCheck != nil && args.healthCheck.Passive != nil { cluster.OutlierDetection = buildXdsOutlierDetection(args.healthCheck.Passive) - } cluster.CircuitBreakers = buildXdsClusterCircuitBreaker(args.circuitBreaker) @@ -447,7 +449,7 @@ func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb. requiresHTTP1Options := args.http1Settings != nil && (args.http1Settings.EnableTrailers || args.http1Settings.PreserveHeaderCase || args.http1Settings.HTTP10 != nil) - if !(requiresCommonHTTPOptions || requiresHTTP1Options || requiresHTTP2Options) { + if !(requiresCommonHTTPOptions || requiresHTTP1Options || requiresHTTP2Options || args.useClientProtocol) { return nil } @@ -458,13 +460,11 @@ func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb. if args.timeout != nil && args.timeout.HTTP != nil { if args.timeout.HTTP.ConnectionIdleTimeout != nil { - protocolOptions.CommonHttpProtocolOptions.IdleTimeout = - durationpb.New(args.timeout.HTTP.ConnectionIdleTimeout.Duration) + protocolOptions.CommonHttpProtocolOptions.IdleTimeout = durationpb.New(args.timeout.HTTP.ConnectionIdleTimeout.Duration) } if args.timeout.HTTP.MaxConnectionDuration != nil { - protocolOptions.CommonHttpProtocolOptions.MaxConnectionDuration = - durationpb.New(args.timeout.HTTP.MaxConnectionDuration.Duration) + protocolOptions.CommonHttpProtocolOptions.MaxConnectionDuration = durationpb.New(args.timeout.HTTP.MaxConnectionDuration.Duration) } } @@ -473,25 +473,11 @@ func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb. Value: *args.circuitBreaker.MaxRequestsPerConnection, } } - } - // When setting any Typed Extension Protocol Options, UpstreamProtocolOptions are mandatory - // If translation requires HTTP2 enablement or HTTP1 trailers, set appropriate setting - // Default to http1 otherwise - // TODO: If the cluster is TLS enabled, use AutoHTTPConfig instead of ExplicitHttpConfig - // so that when ALPN is supported then enabling http1 options doesn't force HTTP/1.1 - switch { - case requiresHTTP2Options: - protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ - ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ - ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{}, - }, - } - case requiresHTTP1Options: - http1opts := &corev3.Http1ProtocolOptions{ - EnableTrailers: args.http1Settings.EnableTrailers, - } + http1opts := &corev3.Http1ProtocolOptions{} + if args.http1Settings != nil { + http1opts.EnableTrailers = args.http1Settings.EnableTrailers if args.http1Settings.PreserveHeaderCase { preservecaseAny, _ := anypb.New(&preservecasev3.PreserveCaseFormatterConfig{}) http1opts.HeaderKeyFormat = &corev3.Http1ProtocolOptions_HeaderKeyFormat{ @@ -507,6 +493,28 @@ func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb. http1opts.AcceptHttp_10 = true http1opts.DefaultHostForHttp_10 = ptr.Deref(args.http1Settings.HTTP10.DefaultHost, "") } + } + + // When setting any Typed Extension Protocol Options, UpstreamProtocolOptions are mandatory + // If translation requires HTTP2 enablement or HTTP1 trailers, set appropriate setting + // Default to http1 otherwise + // TODO: If the cluster is TLS enabled, use AutoHTTPConfig instead of ExplicitHttpConfig + // so that when ALPN is supported then enabling http1 options doesn't force HTTP/1.1 + switch { + case args.useClientProtocol: + protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_UseDownstreamProtocolConfig{ + UseDownstreamProtocolConfig: &httpv3.HttpProtocolOptions_UseDownstreamHttpConfig{ + HttpProtocolOptions: http1opts, + Http2ProtocolOptions: &corev3.Http2ProtocolOptions{}, + }, + } + case requiresHTTP2Options: + protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ + ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ + ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{}, + }, + } + case requiresHTTP1Options: protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_HttpProtocolOptions{ @@ -617,5 +625,4 @@ func buildXdsClusterUpstreamOptions(tcpkeepalive *ir.TCPKeepalive) *clusterv3.Up } return ka - } diff --git a/internal/xds/translator/cors.go b/internal/xds/translator/cors.go index cd46b6f41a6..f5a83308722 100644 --- a/internal/xds/translator/cors.go +++ b/internal/xds/translator/cors.go @@ -16,8 +16,8 @@ import ( hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" - "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/wrapperspb" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" @@ -27,8 +27,7 @@ func init() { registerHTTPFilter(&cors{}) } -type cors struct { -} +type cors struct{} var _ httpFilter = &cors{} @@ -36,7 +35,8 @@ var _ httpFilter = &cors{} // applicable. func (*cors) patchHCM( mgr *hcmv3.HttpConnectionManager, - irListener *ir.HTTPListener) error { + irListener *ir.HTTPListener, +) error { if mgr == nil { return errors.New("hcm is nil") } @@ -125,7 +125,7 @@ func (*cors) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { allowHeaders string exposeHeaders string maxAge string - allowCredentials *wrappers.BoolValue + allowCredentials *wrapperspb.BoolValue c = irRoute.Security.CORS ) @@ -141,7 +141,7 @@ func (*cors) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { if c.MaxAge != nil { maxAge = strconv.Itoa(int(c.MaxAge.Seconds())) } - allowCredentials = &wrappers.BoolValue{Value: c.AllowCredentials} + allowCredentials = &wrapperspb.BoolValue{Value: c.AllowCredentials} routeCfgProto := &corsv3.CorsPolicy{ AllowOriginStringMatch: allowOrigins, @@ -150,7 +150,7 @@ func (*cors) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { ExposeHeaders: exposeHeaders, MaxAge: maxAge, AllowCredentials: allowCredentials, - ForwardNotMatchingPreflights: &wrappers.BoolValue{Value: false}, + ForwardNotMatchingPreflights: &wrapperspb.BoolValue{Value: false}, } routeCfgAny, err := anypb.New(routeCfgProto) diff --git a/internal/xds/translator/extauth.go b/internal/xds/translator/extauth.go index 43712564e16..0d8edfce242 100644 --- a/internal/xds/translator/extauth.go +++ b/internal/xds/translator/extauth.go @@ -14,8 +14,8 @@ import ( extauthv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - "github.com/golang/protobuf/ptypes/duration" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" @@ -29,8 +29,7 @@ func init() { registerHTTPFilter(&extAuth{}) } -type extAuth struct { -} +type extAuth struct{} var _ httpFilter = &extAuth{} @@ -133,7 +132,7 @@ func extAuthConfig(extAuth *ir.ExtAuth) *extauthv3.ExtAuthz { TargetSpecifier: &corev3.GrpcService_EnvoyGrpc_{ EnvoyGrpc: grpcService(extAuth.GRPC), }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, }, @@ -169,7 +168,7 @@ func httpService(http *ir.HTTPExtAuthService) *extauthv3.HttpService { HttpUpstreamType: &corev3.HttpUri_Cluster{ Cluster: http.Destination.Name, }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, } @@ -212,7 +211,8 @@ func routeContainsExtAuth(irRoute *ir.HTTPRoute) bool { // patchResources patches the cluster resources for the external auth services. func (*extAuth) patchResources(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if tCtx == nil || tCtx.XdsResources == nil { return errors.New("xds resource table is nil") } diff --git a/internal/xds/translator/extproc.go b/internal/xds/translator/extproc.go index ac03a49d08e..9a397484ed9 100644 --- a/internal/xds/translator/extproc.go +++ b/internal/xds/translator/extproc.go @@ -12,11 +12,12 @@ import ( routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" extprocv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_proc/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "github.com/golang/protobuf/ptypes/duration" - "google.golang.org/protobuf/types/known/anypb" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" + + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" ) const ( @@ -27,8 +28,7 @@ func init() { registerHTTPFilter(&extProc{}) } -type extProc struct { -} +type extProc struct{} var _ httpFilter = &extProc{} @@ -103,10 +103,42 @@ func extProcConfig(extProc ir.ExtProc) *extprocv3.ExternalProcessor { TargetSpecifier: &corev3.GrpcService_EnvoyGrpc_{ EnvoyGrpc: grpcExtProcService(extProc), }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, }, + ProcessingMode: &extprocv3.ProcessingMode{ + RequestHeaderMode: extprocv3.ProcessingMode_SKIP, + ResponseHeaderMode: extprocv3.ProcessingMode_SKIP, + RequestBodyMode: extprocv3.ProcessingMode_NONE, + ResponseBodyMode: extprocv3.ProcessingMode_NONE, + RequestTrailerMode: extprocv3.ProcessingMode_SKIP, + ResponseTrailerMode: extprocv3.ProcessingMode_SKIP, + }, + } + + if extProc.FailOpen != nil { + config.FailureModeAllow = *extProc.FailOpen + } + + if extProc.MessageTimeout != nil { + config.MessageTimeout = durationpb.New(extProc.MessageTimeout.Duration) + } + + if extProc.RequestBodyProcessingMode != nil { + config.ProcessingMode.RequestBodyMode = buildExtProcBodyProcessingMode(extProc.RequestBodyProcessingMode) + } + + if extProc.RequestHeaderProcessing { + config.ProcessingMode.RequestHeaderMode = extprocv3.ProcessingMode_SEND + } + + if extProc.ResponseBodyProcessingMode != nil { + config.ProcessingMode.ResponseBodyMode = buildExtProcBodyProcessingMode(extProc.ResponseBodyProcessingMode) + } + + if extProc.ResponseHeaderProcessing { + config.ProcessingMode.ResponseHeaderMode = extprocv3.ProcessingMode_SEND } return config @@ -130,7 +162,8 @@ func routeContainsExtProc(irRoute *ir.HTTPRoute) bool { // patchResources patches the cluster resources for the external services. func (*extProc) patchResources(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if tCtx == nil || tCtx.XdsResources == nil { return errors.New("xds resource table is nil") } @@ -173,3 +206,15 @@ func (*extProc) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { } return nil } + +func buildExtProcBodyProcessingMode(mode *ir.ExtProcBodyProcessingMode) extprocv3.ProcessingMode_BodySendMode { + lookup := map[ir.ExtProcBodyProcessingMode]extprocv3.ProcessingMode_BodySendMode{ + ir.ExtProcBodyBuffered: extprocv3.ProcessingMode_BUFFERED, + ir.ExtProcBodyBufferedPartial: extprocv3.ProcessingMode_BUFFERED_PARTIAL, + ir.ExtProcBodyStreamed: extprocv3.ProcessingMode_STREAMED, + } + if r, found := lookup[*mode]; found { + return r + } + return extprocv3.ProcessingMode_NONE +} diff --git a/internal/xds/translator/fault.go b/internal/xds/translator/fault.go index ae01b566c84..46642934ce1 100644 --- a/internal/xds/translator/fault.go +++ b/internal/xds/translator/fault.go @@ -30,8 +30,7 @@ func init() { registerHTTPFilter(&fault{}) } -type fault struct { -} +type fault struct{} var _ httpFilter = &fault{} @@ -39,7 +38,6 @@ var _ httpFilter = &fault{} // if applicable, and it does not already exist. // Note: this method creates an fault filter for each route that contains an Fault config. func (*fault) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error { - if mgr == nil { return errors.New("hcm is nil") } @@ -179,7 +177,6 @@ func (*fault) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { route.TypedPerFilterConfig[wellknown.Fault] = routeCfgAny return nil - } // translatePercentToFractionalPercent translates an v1alpha3 Percent instance diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index 143c8d77320..0b8f6dbeff9 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -159,7 +159,8 @@ func sortHTTPFilters(filters []*hcmv3.HttpFilter) []*hcmv3.HttpFilter { // newOrderedHTTPFilter method. func (t *Translator) patchHCMWithFilters( mgr *hcmv3.HttpConnectionManager, - irListener *ir.HTTPListener) error { + irListener *ir.HTTPListener, +) error { // The order of filter patching is not relevant here. // All the filters will be sorted in correct order after the patching is done. // @@ -197,8 +198,8 @@ func (t *Translator) patchHCMWithFilters( // provided route. func patchRouteWithPerRouteConfig( route *routev3.Route, - irRoute *ir.HTTPRoute) error { - + irRoute *ir.HTTPRoute, +) error { for _, filter := range httpFilters { if err := filter.patchRoute(route, irRoute); err != nil { return err @@ -207,8 +208,7 @@ func patchRouteWithPerRouteConfig( // RateLimit filter is handled separately because it relies on the global // rate limit server configuration. - if err := - patchRouteWithRateLimit(route.GetRoute(), irRoute); err != nil { + if err := patchRouteWithRateLimit(route.GetRoute(), irRoute); err != nil { return nil } diff --git a/internal/xds/translator/jwt.go b/internal/xds/translator/jwt.go index b6bf2275efa..27697043a46 100644 --- a/internal/xds/translator/jwt.go +++ b/internal/xds/translator/jwt.go @@ -34,8 +34,7 @@ func init() { registerHTTPFilter(&jwt{}) } -type jwt struct { -} +type jwt struct{} var _ httpFilter = &jwt{} @@ -134,7 +133,8 @@ func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, for _, claimToHeader := range irProvider.ClaimToHeaders { claimToHeader := &jwtauthnv3.JwtClaimToHeader{ HeaderName: claimToHeader.Header, - ClaimName: claimToHeader.Claim} + ClaimName: claimToHeader.Claim, + } claimToHeaders = append(claimToHeaders, claimToHeader) } jwtProvider := &jwtauthnv3.JwtProvider{ @@ -242,7 +242,8 @@ func (*jwt) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { } routeCfgProto := &jwtauthnv3.PerRouteConfig{ - RequirementSpecifier: &jwtauthnv3.PerRouteConfig_RequirementName{RequirementName: irRoute.Name}} + RequirementSpecifier: &jwtauthnv3.PerRouteConfig_RequirementName{RequirementName: irRoute.Name}, + } routeCfgAny, err := anypb.New(routeCfgProto) if err != nil { diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 55b29d168eb..64004c9460b 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -24,7 +24,6 @@ import ( typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" "github.com/envoyproxy/go-control-plane/pkg/resource/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" - "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" @@ -85,13 +84,13 @@ func http2ProtocolOptions(opts *ir.HTTP2Settings) *corev3.Http2ProtocolOptions { } return &corev3.Http2ProtocolOptions{ - MaxConcurrentStreams: &wrappers.UInt32Value{ + MaxConcurrentStreams: &wrapperspb.UInt32Value{ Value: ptr.Deref(opts.MaxConcurrentStreams, http2MaxConcurrentStreamsLimit), }, - InitialStreamWindowSize: &wrappers.UInt32Value{ + InitialStreamWindowSize: &wrapperspb.UInt32Value{ Value: ptr.Deref(opts.InitialStreamWindowSize, http2InitialStreamWindowSize), }, - InitialConnectionWindowSize: &wrappers.UInt32Value{ + InitialConnectionWindowSize: &wrapperspb.UInt32Value{ Value: ptr.Deref(opts.InitialConnectionWindowSize, http2InitialConnectionWindowSize), }, } @@ -209,7 +208,8 @@ func buildXdsQuicListener(name, address string, port uint32, accesslog *ir.Acces // The newly created TCP filter chain is configured with a filter chain match to // match the server names(SNI) based on the listener's hostnames. func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irListener *ir.HTTPListener, - accesslog *ir.AccessLog, tracing *ir.Tracing, http3Listener bool, connection *ir.Connection) error { + accesslog *ir.AccessLog, tracing *ir.Tracing, http3Listener bool, connection *ir.Connection, +) error { al := buildXdsAccessLog(accesslog, false) hcmTracing, err := buildHCMTracing(tracing) @@ -226,8 +226,8 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis } // Client IP detection - var useRemoteAddress = true - var originalIPDetectionExtensions = originalIPDetectionExtensions(irListener.ClientIPDetection) + useRemoteAddress := true + originalIPDetectionExtensions := originalIPDetectionExtensions(irListener.ClientIPDetection) if originalIPDetectionExtensions != nil { useRemoteAddress = false } @@ -250,7 +250,7 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis // Set it by default to also support HTTP1.1 to HTTP2 Upgrades Http2ProtocolOptions: http2ProtocolOptions(irListener.HTTP2), // https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for - UseRemoteAddress: &wrappers.BoolValue{Value: useRemoteAddress}, + UseRemoteAddress: &wrapperspb.BoolValue{Value: useRemoteAddress}, XffNumTrustedHops: xffNumTrustedHops(irListener.ClientIPDetection), OriginalIpDetectionExtensions: originalIPDetectionExtensions, // normalize paths according to RFC 3986 @@ -507,7 +507,7 @@ func buildDownstreamQUICTransportSocket(tlsConfig *ir.TLSConfig) (*corev3.Transp } if tlsConfig.CACertificate != nil { - tlsCtx.DownstreamTlsContext.RequireClientCertificate = &wrappers.BoolValue{Value: true} + tlsCtx.DownstreamTlsContext.RequireClientCertificate = &wrapperspb.BoolValue{Value: true} tlsCtx.DownstreamTlsContext.CommonTlsContext.ValidationContextType = &tlsv3.CommonTlsContext_ValidationContextSdsSecretConfig{ ValidationContextSdsSecretConfig: &tlsv3.SdsSecretConfig{ Name: tlsConfig.CACertificate.Name, @@ -547,7 +547,7 @@ func buildXdsDownstreamTLSSocket(tlsConfig *ir.TLSConfig) (*corev3.TransportSock } if tlsConfig.CACertificate != nil { - tlsCtx.RequireClientCertificate = &wrappers.BoolValue{Value: tlsConfig.RequireClientCertificate} + tlsCtx.RequireClientCertificate = &wrapperspb.BoolValue{Value: tlsConfig.RequireClientCertificate} tlsCtx.CommonTlsContext.ValidationContextType = &tlsv3.CommonTlsContext_ValidationContextSdsSecretConfig{ ValidationContextSdsSecretConfig: &tlsv3.SdsSecretConfig{ Name: tlsConfig.CACertificate.Name, @@ -720,7 +720,6 @@ func makeConfigSource() *corev3.ConfigSource { } func translateEscapePath(in ir.PathEscapedSlashAction) hcmv3.HttpConnectionManager_PathWithEscapedSlashesAction { - lookup := map[ir.PathEscapedSlashAction]hcmv3.HttpConnectionManager_PathWithEscapedSlashesAction{ ir.KeepUnchangedAction: hcmv3.HttpConnectionManager_KEEP_UNCHANGED, ir.RejectRequestAction: hcmv3.HttpConnectionManager_REJECT_REQUEST, diff --git a/internal/xds/translator/local_ratelimit.go b/internal/xds/translator/local_ratelimit.go index a3110cbf98e..688461e9fa2 100644 --- a/internal/xds/translator/local_ratelimit.go +++ b/internal/xds/translator/local_ratelimit.go @@ -15,9 +15,8 @@ import ( localrlv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/local_ratelimit/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" - "github.com/golang/protobuf/ptypes/duration" - "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" @@ -35,8 +34,7 @@ func init() { registerHTTPFilter(&localRateLimit{}) } -type localRateLimit struct { -} +type localRateLimit struct{} var _ httpFilter = &localRateLimit{} @@ -106,7 +104,8 @@ func routeContainsLocalRateLimit(irRoute *ir.HTTPRoute) bool { } func (*localRateLimit) patchResources(*types.ResourceVersionTable, - []*ir.HTTPRoute) error { + []*ir.HTTPRoute, +) error { return nil } @@ -169,7 +168,7 @@ func (*localRateLimit) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) e // won't consume the default token bucket. This means that a request only // counts towards the default token bucket if it does not match any of the // descriptors. - AlwaysConsumeDefaultTokenBucket: &wrappers.BoolValue{ + AlwaysConsumeDefaultTokenBucket: &wrapperspb.BoolValue{ Value: false, }, } @@ -188,7 +187,8 @@ func (*localRateLimit) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) e } func buildRouteLocalRateLimits(local *ir.LocalRateLimit) ( - []*routev3.RateLimit, []*rlv3.LocalRateLimitDescriptor, error) { + []*routev3.RateLimit, []*rlv3.LocalRateLimitDescriptor, error, +) { var rateLimits []*routev3.RateLimit var descriptors []*rlv3.LocalRateLimitDescriptor @@ -284,7 +284,7 @@ func buildRouteLocalRateLimits(local *ir.LocalRateLimit) ( return rateLimits, descriptors, nil } -func ratelimitUnitToDuration(unit ir.RateLimitUnit) *duration.Duration { +func ratelimitUnitToDuration(unit ir.RateLimitUnit) *durationpb.Duration { var seconds int64 switch egv1a1.RateLimitUnit(unit) { @@ -297,7 +297,7 @@ func ratelimitUnitToDuration(unit ir.RateLimitUnit) *duration.Duration { case egv1a1.RateLimitUnitDay: seconds = 60 * 60 * 24 } - return &duration.Duration{ + return &durationpb.Duration{ Seconds: seconds, } } diff --git a/internal/xds/translator/oidc.go b/internal/xds/translator/oidc.go index f7202a7f407..183fb7944aa 100644 --- a/internal/xds/translator/oidc.go +++ b/internal/xds/translator/oidc.go @@ -15,8 +15,8 @@ import ( hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - "github.com/golang/protobuf/ptypes/duration" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "k8s.io/utils/ptr" "github.com/envoyproxy/gateway/internal/ir" @@ -31,8 +31,7 @@ func init() { registerHTTPFilter(&oidc{}) } -type oidc struct { -} +type oidc struct{} var _ httpFilter = &oidc{} @@ -122,7 +121,7 @@ func oauth2Config(oidc *ir.OIDC) (*oauth2v3.OAuth2, error) { HttpUpstreamType: &corev3.HttpUri_Cluster{ Cluster: cluster.name, }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, }, @@ -187,7 +186,8 @@ func routeContainsOIDC(irRoute *ir.HTTPRoute) bool { } func (*oidc) patchResources(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if err := createOAuth2TokenEndpointClusters(tCtx, routes); err != nil { return err } @@ -200,7 +200,8 @@ func (*oidc) patchResources(tCtx *types.ResourceVersionTable, // createOAuth2TokenEndpointClusters creates token endpoint clusters from the // provided routes, if needed. func createOAuth2TokenEndpointClusters(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if tCtx == nil || tCtx.XdsResources == nil { return errors.New("xds resource table is nil") } @@ -236,9 +237,10 @@ func createOAuth2TokenEndpointClusters(tCtx *types.ResourceVersionTable, ds = &ir.DestinationSetting{ Weight: ptr.To[uint32](1), - Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint( - cluster.hostname, - cluster.port), + Endpoints: []*ir.DestinationEndpoint{ + ir.NewDestEndpoint( + cluster.hostname, + cluster.port), }, } diff --git a/internal/xds/translator/runner/runner_test.go b/internal/xds/translator/runner/runner_test.go index 9f3d7035bd6..a7be53236c8 100644 --- a/internal/xds/translator/runner/runner_test.go +++ b/internal/xds/translator/runner/runner_test.go @@ -98,7 +98,6 @@ func TestRunner(t *testing.T) { // Ensure that xds has no key, value pairs return len(out) == 0 }, time.Second*5, time.Millisecond*50) - } func TestRunner_withExtensionManager(t *testing.T) { diff --git a/internal/xds/translator/tcpkeepalive.go b/internal/xds/translator/tcpkeepalive.go index 9d4c71d6d30..fcdd2a46992 100644 --- a/internal/xds/translator/tcpkeepalive.go +++ b/internal/xds/translator/tcpkeepalive.go @@ -62,5 +62,4 @@ func buildTCPSocketOptions(keepAlive *ir.TCPKeepalive) []*corev3.SocketOption { } return socketOptions - } diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml index 170f1a3f2ea..90fd067480b 100644 --- a/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml @@ -21,22 +21,30 @@ http: port: 8080 protocol: HTTP weight: 1 - envoyExtensionFeatures: - extProc: - - name: envoyextensionpolicy/default/policy-for-route-2/0 - authority: grpc-backend-4.default:4000 - destination: - name: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 - settings: - - protocol: GRPC - weight: 1 - - name: envoyextensionpolicy/default/policy-for-route-1/0 - authority: grpc-backend-2.default:8000 - destination: - name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 - settings: - - protocol: GRPC - weight: 1 + extProc: + - name: envoyextensionpolicy/default/policy-for-route-2/0 + failOpen: true + messageTimeout: 5s + requestHeaderProcessing: true + requestBodyProcessingMode: Buffered + responseBodyProcessingMode: Streamed + authority: grpc-backend-4.default:4000 + destination: + name: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + settings: + - protocol: GRPC + weight: 1 + - name: envoyextensionpolicy/default/policy-for-route-1/0 + failOpen: true + messageTimeout: 5s + responseHeaderProcessing: true + requestBodyProcessingMode: BufferedPartial + authority: grpc-backend-2.default:8000 + destination: + name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + settings: + - protocol: GRPC + weight: 1 hostname: gateway.envoyproxy.io isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io @@ -56,22 +64,23 @@ http: port: 8080 protocol: HTTP weight: 1 - envoyExtensionFeatures: - extProc: - - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0 - authority: grpc-backend-3.envoy-gateway:3000 - destination: - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 - settings: - - protocol: GRPC - weight: 1 - - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0 - authority: grpc-backend.envoy-gateway:9000 - destination: - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend - settings: - - protocol: GRPC - weight: 1 + extProc: + - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0 + authority: grpc-backend-3.envoy-gateway:3000 + destination: + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + settings: + - protocol: GRPC + weight: 1 + - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0 + failOpen: false + messageTimeout: 15s + authority: grpc-backend.envoy-gateway:9000 + destination: + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + settings: + - protocol: GRPC + weight: 1 hostname: gateway.envoyproxy.io isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/xds/translator/testdata/in/xds-ir/http-preserve-client-protocol.yaml b/internal/xds/translator/testdata/in/xds-ir/http-preserve-client-protocol.yaml new file mode 100644 index 00000000000..bfafbc5b96d --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-preserve-client-protocol.yaml @@ -0,0 +1,31 @@ +http: +- address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + useClientProtocol: true diff --git a/internal/xds/translator/testdata/in/xds-ir/mixed-tls-jwt-authn.yaml b/internal/xds/translator/testdata/in/xds-ir/mixed-tls-jwt-authn.yaml index 36984ea69f6..e77e1262245 100644 --- a/internal/xds/translator/testdata/in/xds-ir/mixed-tls-jwt-authn.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/mixed-tls-jwt-authn.yaml @@ -8,11 +8,12 @@ http: mergeSlashes: true escapedSlashesAction: UnescapeAndRedirect tls: - - name: first-listener - # byte slice representation of "cert-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] + certificates: + - name: first-listener + # byte slice representation of "cert-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] routes: - name: "first-route" hostname: "*" diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.clusters.yaml index 6a277bb94f6..08b38495e69 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.clusters.yaml @@ -32,3 +32,91 @@ outlierDetection: {} perConnectionBufferLimitBytes: 32768 type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.endpoints.yaml index 05442a9a15b..4ec680ce7fd 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.endpoints.yaml @@ -22,3 +22,23 @@ loadBalancingWeight: 1 locality: region: httproute/default/httproute-2/rule/0/backend/0 +- clusterName: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4/backend/0 +- clusterName: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2/backend/0 +- clusterName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3/backend/0 +- clusterName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml index a593a50af36..f822447967e 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml @@ -14,6 +14,70 @@ initialStreamWindowSize: 65536 maxConcurrentStreams: 100 httpFilters: + - disabled: true + name: envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-route-2/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + failureModeAllow: true + grpcService: + envoyGrpc: + authority: grpc-backend-4.default:4000 + clusterName: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + timeout: 10s + messageTimeout: 5s + processingMode: + requestBodyMode: BUFFERED + requestHeaderMode: SEND + requestTrailerMode: SKIP + responseBodyMode: STREAMED + responseHeaderMode: SKIP + responseTrailerMode: SKIP + - disabled: true + name: envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-route-1/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + failureModeAllow: true + grpcService: + envoyGrpc: + authority: grpc-backend-2.default:8000 + clusterName: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + timeout: 10s + messageTimeout: 5s + processingMode: + requestBodyMode: BUFFERED_PARTIAL + requestHeaderMode: SKIP + requestTrailerMode: SKIP + responseHeaderMode: SEND + responseTrailerMode: SKIP + - disabled: true + name: envoy.filters.http.ext_proc/envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + grpcService: + envoyGrpc: + authority: grpc-backend-3.envoy-gateway:3000 + clusterName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + timeout: 10s + processingMode: + requestHeaderMode: SKIP + requestTrailerMode: SKIP + responseHeaderMode: SKIP + responseTrailerMode: SKIP + - disabled: true + name: envoy.filters.http.ext_proc/envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + grpcService: + envoyGrpc: + authority: grpc-backend.envoy-gateway:9000 + clusterName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + timeout: 10s + messageTimeout: 15s + processingMode: + requestHeaderMode: SKIP + requestTrailerMode: SKIP + responseHeaderMode: SKIP + responseTrailerMode: SKIP - name: envoy.filters.http.router typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.routes.yaml index a7002b63f87..0daf1919cb2 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.routes.yaml @@ -12,6 +12,13 @@ cluster: httproute/default/httproute-1/rule/0 upgradeConfigs: - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-route-1/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-route-2/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} - match: pathSeparatedPrefix: /bar name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io @@ -19,3 +26,10 @@ cluster: httproute/default/httproute-2/rule/0 upgradeConfigs: - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_proc/envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + envoy.filters.http.ext_proc/envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.clusters.yaml new file mode 100644 index 00000000000..5de1d1cce34 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.clusters.yaml @@ -0,0 +1,23 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-1/rule/0 + lbPolicy: LEAST_REQUEST + name: httproute/default/httproute-1/rule/0 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + useDownstreamProtocolConfig: + http2ProtocolOptions: {} + httpProtocolOptions: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.endpoints.yaml new file mode 100644 index 00000000000..29bb6b4e444 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: httproute/default/httproute-1/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-1/rule/0/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.listeners.yaml new file mode 100644 index 00000000000..a593a50af36 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.listeners.yaml @@ -0,0 +1,34 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + 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: envoy-gateway/gateway-1/http + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + useRemoteAddress: true + drainType: MODIFY_ONLY + name: envoy-gateway/gateway-1/http + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.routes.yaml new file mode 100644 index 00000000000..19e1921fb1e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.routes.yaml @@ -0,0 +1,14 @@ +- ignorePortInHostMatching: true + name: envoy-gateway/gateway-1/http + virtualHosts: + - domains: + - gateway.envoyproxy.io + name: envoy-gateway/gateway-1/http/gateway_envoyproxy_io + routes: + - match: + prefix: / + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.secrets.yaml new file mode 100644 index 00000000000..ad88ffe43cd --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.secrets.yaml @@ -0,0 +1,12 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.clusters.yaml index 7a0c933174e..d53a7a1b2ce 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.clusters.yaml @@ -1,4 +1,7 @@ -- commonLbConfig: +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: localityWeightedLbConfig: {} connectTimeout: 10s dnsLookupFamily: V4_ONLY @@ -12,34 +15,3 @@ outlierDetection: {} perConnectionBufferLimitBytes: 32768 type: EDS -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - dnsRefreshRate: 30s - lbPolicy: LEAST_REQUEST - loadAssignment: - clusterName: localhost_443 - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: localhost - portValue: 443 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} - name: localhost_443 - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - respectDnsTtl: true - transportSocket: - name: envoy.transport_sockets.tls - typedConfig: - '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - commonTlsContext: - validationContext: - trustedCa: - filename: /etc/ssl/certs/ca-certificates.crt - type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.endpoints.yaml index 0d68b430c20..3b3f2d09076 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.endpoints.yaml @@ -8,4 +8,5 @@ portValue: 50000 loadBalancingWeight: 1 loadBalancingWeight: 1 - locality: {} + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml index 85bb8b4ac73..5fa3f9246df 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -14,26 +15,6 @@ initialStreamWindowSize: 65536 maxConcurrentStreams: 100 httpFilters: - - name: envoy.filters.http.jwt_authn - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication - providers: - first-route/example: - audiences: - - foo.com - issuer: https://www.example.com - payloadInMetadata: https://www.example.com - remoteJwks: - asyncFetch: {} - cacheDuration: 300s - httpUri: - cluster: localhost_443 - timeout: 5s - uri: https://localhost/jwt/public-key/jwks.json - retryPolicy: {} - requirementMap: - first-route: - providerName: first-route/example - name: envoy.filters.http.router typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router @@ -48,8 +29,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.routes.yaml index c73bec09093..75d30a0592a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.routes.yaml @@ -10,7 +10,5 @@ name: first-route route: cluster: first-route-dest - typedPerFilterConfig: - envoy.filters.http.jwt_authn: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig - requirementName: first-route + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.secrets.yaml new file mode 100644 index 00000000000..81afea10735 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.secrets.yaml @@ -0,0 +1,8 @@ +- genericSecret: + secret: + inlineBytes: Y2xpZW50MTpzZWNyZXQK + name: oauth2/client_secret/securitypolicy/default/policy-for-gateway-2 +- genericSecret: + secret: + inlineBytes: "" + name: oauth2/hmac_secret/securitypolicy/default/policy-for-gateway-2 diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.secrets.yaml new file mode 100644 index 00000000000..ad88ffe43cd --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.secrets.yaml @@ -0,0 +1,12 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.secrets.yaml new file mode 100644 index 00000000000..d4d502ac098 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.secrets.yaml @@ -0,0 +1,6 @@ +- name: envoy-gateway-tls-secret-1 + tlsCertificate: + certificateChain: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + privateKey: + inlineBytes: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.secrets.yaml new file mode 100644 index 00000000000..ad88ffe43cd --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.secrets.yaml @@ -0,0 +1,12 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 2d5945d2e96..eaef03e97b5 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -24,6 +24,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/wrapperspb" + "k8s.io/utils/ptr" extensionTypes "github.com/envoyproxy/gateway/internal/extension/types" "github.com/envoyproxy/gateway/internal/ir" @@ -300,7 +301,8 @@ func (t *Translator) addRouteToRouteConfig( xdsRouteCfg *routev3.RouteConfiguration, httpListener *ir.HTTPListener, metrics *ir.Metrics, - http3Enabled bool) error { + http3Enabled bool, +) error { var ( vHosts = map[string]*routev3.VirtualHost{} // store virtual hosts by domain vHostList []*routev3.VirtualHost // keep track of order by using a list as well as the map @@ -554,7 +556,8 @@ func processUDPListenerXdsTranslation(tCtx *types.ResourceVersionTable, udpListe // findXdsListenerByHostPort finds a xds listener with the same address, port and protocol, and returns nil if there is no match. func findXdsListenerByHostPort(tCtx *types.ResourceVersionTable, address string, port uint32, - protocol corev3.SocketAddress_Protocol) *listenerv3.Listener { + protocol corev3.SocketAddress_Protocol, +) *listenerv3.Listener { if tCtx == nil || tCtx.XdsResources == nil || tCtx.XdsResources[resourcev3.ListenerType] == nil { return nil } @@ -638,18 +641,19 @@ func findXdsEndpoint(tCtx *types.ResourceVersionTable, name string) *endpointv3. // processXdsCluster processes a xds cluster by its endpoint address type. func processXdsCluster(tCtx *types.ResourceVersionTable, httpRoute *ir.HTTPRoute, http1Settings *ir.HTTP1Settings, metrics *ir.Metrics) error { if err := addXdsCluster(tCtx, &xdsClusterArgs{ - name: httpRoute.Destination.Name, - settings: httpRoute.Destination.Settings, - tSocket: nil, - endpointType: buildEndpointType(httpRoute.Destination.Settings), - loadBalancer: httpRoute.LoadBalancer, - proxyProtocol: httpRoute.ProxyProtocol, - circuitBreaker: httpRoute.CircuitBreaker, - healthCheck: httpRoute.HealthCheck, - http1Settings: http1Settings, - timeout: httpRoute.Timeout, - tcpkeepalive: httpRoute.TCPKeepalive, - metrics: metrics, + name: httpRoute.Destination.Name, + settings: httpRoute.Destination.Settings, + tSocket: nil, + endpointType: buildEndpointType(httpRoute.Destination.Settings), + loadBalancer: httpRoute.LoadBalancer, + proxyProtocol: httpRoute.ProxyProtocol, + circuitBreaker: httpRoute.CircuitBreaker, + healthCheck: httpRoute.HealthCheck, + http1Settings: http1Settings, + timeout: httpRoute.Timeout, + tcpkeepalive: httpRoute.TCPKeepalive, + metrics: metrics, + useClientProtocol: ptr.Deref(httpRoute.UseClientProtocol, false), }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err } @@ -657,29 +661,6 @@ func processXdsCluster(tCtx *types.ResourceVersionTable, httpRoute *ir.HTTPRoute return nil } -// processTLSSocket generates a xDS TransportSocket for a given TLS config. -// It also adds the necessary secrets to the resource version table. -func processTLSSocket(tlsConfig *ir.TLSUpstreamConfig, tCtx *types.ResourceVersionTable) (*corev3.TransportSocket, error) { - if tlsConfig == nil { - return nil, nil - } - // Create a secret for the CA certificate only if it's not using the system trust store - if !tlsConfig.UseSystemTrustStore { - CaSecret := buildXdsUpstreamTLSCASecret(tlsConfig) - if err := tCtx.AddXdsResource(resourcev3.SecretType, CaSecret); err != nil { - return nil, err - } - } - - // for upstreamTLS , a fixed sni can be used. use auto_sni otherwise - // https://www.envoyproxy.io/docs/envoy/latest/faq/configuration/sni#faq-how-to-setup-sni:~:text=For%20clusters%2C%20a,for%20trust%20anchor. - tlsSocket, err := buildXdsUpstreamTLSSocketWthCert(tlsConfig) - if err != nil { - return nil, err - } - return tlsSocket, nil -} - // findXdsSecret finds a xds secret with the same name, and returns nil if there is no match. func findXdsSecret(tCtx *types.ResourceVersionTable, name string) *tlsv3.Secret { if tCtx == nil || tCtx.XdsResources == nil || tCtx.XdsResources[resourcev3.SecretType] == nil { @@ -766,12 +747,11 @@ func buildXdsUpstreamTLSCASecret(tlsConfig *ir.TLSUpstreamConfig) *tlsv3.Secret } func buildXdsUpstreamTLSSocketWthCert(tlsConfig *ir.TLSUpstreamConfig) (*corev3.TransportSocket, error) { - var tlsCtx *tlsv3.UpstreamTlsContext - if tlsConfig.UseSystemTrustStore { tlsCtx = &tlsv3.UpstreamTlsContext{ CommonTlsContext: &tlsv3.CommonTlsContext{ + TlsCertificates: nil, ValidationContextType: &tlsv3.CommonTlsContext_ValidationContext{ ValidationContext: &tlsv3.CertificateValidationContext{ TrustedCa: &corev3.DataSource{ @@ -805,6 +785,14 @@ func buildXdsUpstreamTLSSocketWthCert(tlsConfig *ir.TLSUpstreamConfig) (*corev3. } } + tlsParams := buildTLSParams(&tlsConfig.TLSConfig) + if tlsParams != nil { + tlsCtx.CommonTlsContext.TlsParams = tlsParams + } + + if len(tlsConfig.ALPNProtocols) > 0 { + tlsCtx.CommonTlsContext.AlpnProtocols = buildALPNProtocols(tlsConfig.ALPNProtocols) + } tlsCtxAny, err := anypb.New(tlsCtx) if err != nil { return nil, err diff --git a/internal/xds/translator/translator_test.go b/internal/xds/translator/translator_test.go index da07465099f..28868500b68 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -41,325 +41,96 @@ var ( overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") ) -func TestTranslateXds(t *testing.T) { - testCases := []struct { - name string - dnsDomain string - requireSecrets bool - requireEnvoyPatchPolicies bool - err bool - }{ - { - name: "empty", - }, - { - name: "http-route", - }, - { - name: "http-route-regex", - }, - { - name: "http-route-redirect", - }, - { - name: "http-route-mirror", - }, - { - name: "http-route-multiple-mirrors", - }, - { - name: "http-route-multiple-matches", - }, - { - name: "http-route-direct-response", - }, - { - name: "http-route-request-headers", - }, - { - name: "http-route-response-add-headers", - }, - { - name: "http-route-response-remove-headers", - }, - { - name: "http-route-response-add-remove-headers", - }, - { - name: "http-route-weighted-invalid-backend", - }, - { - name: "http-route-dns-cluster", - }, - { - name: "http-route-with-tls-system-truststore", - requireSecrets: true, - }, - { - name: "http-route-with-tlsbundle", - requireSecrets: true, - }, - { - name: "http-route-with-tlsbundle-multiple-certs", - requireSecrets: true, - }, - { - name: "simple-tls", - requireSecrets: true, - }, - { - name: "mutual-tls", - requireSecrets: true, - }, - { - name: "mutual-tls-required-client-certificate-disabled", - requireSecrets: true, - }, - { - name: "http3", - requireSecrets: true, - }, - { - name: "tls-route-passthrough", - }, - { - name: "tcp-route-simple", - }, - { - name: "tcp-route-complex", - }, - { - name: "tcp-route-tls-terminate", - }, - { - name: "multiple-simple-tcp-route-same-port", - }, - { - name: "http-route-weighted-backend", - }, - { - name: "tcp-route-weighted-backend", - }, - { - name: "multiple-listeners-same-port", - requireSecrets: true, - }, - { - name: "udp-route", - }, - { - name: "http2-route", - }, - { - name: "http-route-rewrite-url-prefix", - }, - { - name: "http-route-rewrite-root-path-url-prefix", - }, - { - name: "http-route-rewrite-url-fullpath", - }, - { - name: "http-route-rewrite-url-host", - }, - { - name: "http-route-timeout", - }, +type testFileConfig struct { + requireEnvoyPatchPolicies bool + dnsDomain string + errMsg string +} - { - name: "ratelimit", - }, - { - name: "ratelimit-custom-domain", +func TestTranslateXds(t *testing.T) { + testConfigs := map[string]testFileConfig{ + "ratelimit-custom-domain": { dnsDomain: "example-cluster.local", }, - { - name: "ratelimit-sourceip", - }, - { - name: "accesslog", - }, - { - name: "tracing", - }, - { - name: "metrics-virtual-host", - }, - { - name: "jsonpatch", + "jsonpatch": { requireEnvoyPatchPolicies: true, - requireSecrets: true, - err: true, }, - { - name: "jsonpatch-missing-resource", + "jsonpatch-missing-resource": { requireEnvoyPatchPolicies: true, - err: true, }, - { - name: "jsonpatch-invalid-patch", + "jsonpatch-invalid-patch": { requireEnvoyPatchPolicies: true, - err: true, + errMsg: "unable to unmarshal xds resource", }, - { - name: "jsonpatch-add-op-without-value", + "jsonpatch-add-op-without-value": { requireEnvoyPatchPolicies: true, - err: true, + errMsg: "the add operation requires a value", }, - { - name: "jsonpatch-move-op-with-value", + "jsonpatch-move-op-with-value": { requireEnvoyPatchPolicies: true, - err: true, - }, - { - name: "listener-tcp-keepalive", - }, - { - name: "load-balancer", - }, - { - name: "cors", - }, - { - name: "jwt-multi-route-multi-provider", - }, - { - name: "jwt-multi-route-single-provider", - }, - { - name: "jwt-ratelimit", - }, - { - name: "jwt-single-route-single-match", - }, - { - name: "oidc", - requireSecrets: true, - }, - { - name: "http-route-partial-invalid", - }, - { - name: "listener-proxy-protocol", - }, - { - name: "jwt-custom-extractor", - }, - { - name: "proxy-protocol-upstream", - }, - { - name: "basic-auth", - }, - { - name: "health-check", - }, - { - name: "local-ratelimit", - }, - { - name: "circuit-breaker", - }, - { - name: "suppress-envoy-headers", - }, - { - name: "fault-injection", - }, - { - name: "headers-with-underscores-action", - }, - { - name: "tls-with-ciphers-versions-alpn", - }, - { - name: "path-settings", - }, - { - name: "client-ip-detection", + errMsg: "the value field can not be set for the remove operation", }, - { - name: "http1-trailers", + "http-route-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "http1-preserve-case", + "tcp-route-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "timeout", + "tcp-route-invalid-endpoint": { + errMsg: "validation failed for xds resource", }, - { - name: "ext-auth", + "udp-route-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "http10", + "jsonpatch-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "upstream-tcpkeepalive", + "jsonpatch-invalid-listener": { + errMsg: "validation failed for xds resource", }, - { - name: "client-timeout", + "accesslog-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "client-buffer-limit", - }, - { - name: "retry-partial-invalid", - }, - { - name: "multiple-listeners-same-port-with-different-filters", - }, - { - name: "listener-connection-limit", - }, - { - name: "ext-proc", - }, - { - name: "http-endpoint-stats", - }, - { - name: "tcp-endpoint-stats", - }, - { - name: "udp-endpoint-stats", - }, - { - name: "tracing-endpoint-stats", - }, - { - name: "accesslog-endpoint-stats", - }, - { - name: "ratelimit-endpoint-stats", - }, - { - name: "wasm", - }, - { - name: "jwt-optional", - }, - { - name: "http2", + "tracing-invalid": { + errMsg: "validation failed for xds resource", }, } - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - dnsDomain := tc.dnsDomain - if dnsDomain == "" { + inputFiles, err := filepath.Glob(filepath.Join("testdata", "in", "xds-ir", "*.yaml")) + require.NoError(t, err) + + for _, inputFile := range inputFiles { + inputFile := inputFile + inputFileName := testName(inputFile) + t.Run(inputFileName, func(t *testing.T) { + cfg, ok := testConfigs[inputFileName] + if !ok { + cfg = testFileConfig{ + requireEnvoyPatchPolicies: false, + dnsDomain: "", + errMsg: "", + } + } + + dnsDomain := cfg.dnsDomain + if len(dnsDomain) == 0 { dnsDomain = "cluster.local" } - ir := requireXdsIRFromInputTestData(t, "xds-ir", tc.name+".yaml") + + x := requireXdsIRFromInputTestData(t, inputFile) tr := &Translator{ GlobalRateLimit: &GlobalRateLimitSettings{ ServiceURL: ratelimit.GetServiceURL("envoy-gateway-system", dnsDomain), }, } - tCtx, err := tr.Translate(ir) - if !strings.HasSuffix(tc.name, "partial-invalid") && !tc.err { + tCtx, err := tr.Translate(x) + if !strings.HasSuffix(inputFileName, "partial-invalid") && len(cfg.errMsg) == 0 { require.NoError(t, err) + } else if len(cfg.errMsg) > 0 { + require.Error(t, err) + require.Contains(t, err.Error(), cfg.errMsg) + return } listeners := tCtx.XdsResources[resourcev3.ListenerType] @@ -367,23 +138,25 @@ func TestTranslateXds(t *testing.T) { clusters := tCtx.XdsResources[resourcev3.ClusterType] endpoints := tCtx.XdsResources[resourcev3.EndpointType] if *overrideTestData { - require.NoError(t, file.Write(requireResourcesToYAMLString(t, listeners), filepath.Join("testdata", "out", "xds-ir", tc.name+".listeners.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, routes), filepath.Join("testdata", "out", "xds-ir", tc.name+".routes.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, clusters), filepath.Join("testdata", "out", "xds-ir", tc.name+".clusters.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, endpoints), filepath.Join("testdata", "out", "xds-ir", tc.name+".endpoints.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, listeners), filepath.Join("testdata", "out", "xds-ir", inputFileName+".listeners.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, routes), filepath.Join("testdata", "out", "xds-ir", inputFileName+".routes.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, clusters), filepath.Join("testdata", "out", "xds-ir", inputFileName+".clusters.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, endpoints), filepath.Join("testdata", "out", "xds-ir", inputFileName+".endpoints.yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".listeners.yaml"), requireResourcesToYAMLString(t, listeners)) - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".routes.yaml"), requireResourcesToYAMLString(t, routes)) - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".clusters.yaml"), requireResourcesToYAMLString(t, clusters)) - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".endpoints.yaml"), requireResourcesToYAMLString(t, endpoints)) - if tc.requireSecrets { - secrets := tCtx.XdsResources[resourcev3.SecretType] + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".listeners.yaml"), requireResourcesToYAMLString(t, listeners)) + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".routes.yaml"), requireResourcesToYAMLString(t, routes)) + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".clusters.yaml"), requireResourcesToYAMLString(t, clusters)) + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".endpoints.yaml"), requireResourcesToYAMLString(t, endpoints)) + + secrets, ok := tCtx.XdsResources[resourcev3.SecretType] + if ok && len(secrets) > 0 { if *overrideTestData { - require.NoError(t, file.Write(requireResourcesToYAMLString(t, secrets), filepath.Join("testdata", "out", "xds-ir", tc.name+".secrets.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, secrets), filepath.Join("testdata", "out", "xds-ir", inputFileName+".secrets.yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".secrets.yaml"), requireResourcesToYAMLString(t, secrets)) + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".secrets.yaml"), requireResourcesToYAMLString(t, secrets)) } - if tc.requireEnvoyPatchPolicies { + + if cfg.requireEnvoyPatchPolicies { got := tCtx.EnvoyPatchPolicyStatuses for _, e := range got { require.NoError(t, field.SetValue(e, "LastTransitionTime", metav1.NewTime(time.Time{}))) @@ -391,10 +164,10 @@ func TestTranslateXds(t *testing.T) { if *overrideTestData { out, err := yaml.Marshal(got) require.NoError(t, err) - require.NoError(t, file.Write(string(out), filepath.Join("testdata", "out", "xds-ir", tc.name+".envoypatchpolicies.yaml"))) + require.NoError(t, file.Write(string(out), filepath.Join("testdata", "out", "xds-ir", inputFileName+".envoypatchpolicies.yaml"))) } - in := requireTestDataOutFile(t, "xds-ir", tc.name+".envoypatchpolicies.yaml") + in := requireTestDataOutFile(t, "xds-ir", inputFileName+".envoypatchpolicies.yaml") want := xtypes.EnvoyPatchPolicyStatuses{} require.NoError(t, yaml.Unmarshal([]byte(in), &want)) opts := cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime") @@ -404,152 +177,52 @@ func TestTranslateXds(t *testing.T) { } } -func TestTranslateXdsNegative(t *testing.T) { - testCases := []struct { - name string - dnsDomain string - requireSecrets bool - }{ - { - name: "http-route-invalid", - }, - { - name: "tcp-route-invalid", - }, - { - name: "tcp-route-invalid-endpoint", - }, - { - name: "udp-route-invalid", - }, - { - name: "jsonpatch-invalid", - }, - { - name: "jsonpatch-invalid-listener", - }, - { - name: "accesslog-invalid", - }, - { - name: "tracing-invalid", - }, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - dnsDomain := tc.dnsDomain - if dnsDomain == "" { - dnsDomain = "cluster.local" - } - ir := requireXdsIRFromInputTestData(t, "xds-ir", tc.name+".yaml") - tr := &Translator{ - GlobalRateLimit: &GlobalRateLimitSettings{ - ServiceURL: ratelimit.GetServiceURL("envoy-gateway-system", dnsDomain), - }, - } - - _, err := tr.Translate(ir) - require.Error(t, err) - if tc.name != "jsonpatch-invalid" { - require.Contains(t, err.Error(), "validation failed for xds resource") - } - }) - } -} - func TestTranslateRateLimitConfig(t *testing.T) { - testCases := []struct { - name string - }{ - { - name: "empty-header-matches", - }, - { - name: "distinct-match", - }, - { - name: "distinct-remote-address-match", - }, - { - name: "value-match", - }, - { - name: "multiple-matches", - }, - { - name: "multiple-rules", - }, - { - name: "multiple-routes", - }, - { - name: "masked-remote-address-match", - }, - { - name: "multiple-masked-remote-address-match-with-same-cidr", - }, - } + inputFiles, err := filepath.Glob(filepath.Join("testdata", "in", "ratelimit-config", "*.yaml")) + require.NoError(t, err) - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - in := requireXdsIRListenerFromInputTestData(t, "ratelimit-config", tc.name+".yaml") + for _, inputFile := range inputFiles { + inputFile := inputFile + inputFileName := testName(inputFile) + t.Run(inputFileName, func(t *testing.T) { + in := requireXdsIRListenerFromInputTestData(t, inputFile) out := BuildRateLimitServiceConfig(in) if *overrideTestData { - require.NoError(t, file.Write(requireYamlRootToYAMLString(t, out), filepath.Join("testdata", "out", "ratelimit-config", tc.name+".yaml"))) + require.NoError(t, file.Write(requireYamlRootToYAMLString(t, out), filepath.Join("testdata", "out", "ratelimit-config", inputFileName+".yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "ratelimit-config", tc.name+".yaml"), requireYamlRootToYAMLString(t, out)) + require.Equal(t, requireTestDataOutFile(t, "ratelimit-config", inputFileName+".yaml"), requireYamlRootToYAMLString(t, out)) }) } } func TestTranslateXdsWithExtension(t *testing.T) { - testCases := []struct { - name string - requireSecrets bool - err string - }{ - // Require secrets for all the tests since the extension for testing always injects one - { - name: "empty", - requireSecrets: true, - err: "", - }, - { - name: "http-route", - requireSecrets: true, - err: "", - }, - { - name: "http-route-extension-filter", - requireSecrets: true, - err: "", - }, - { - name: "http-route-extension-route-error", - requireSecrets: true, - err: "route hook resource error", + testConfigs := map[string]testFileConfig{ + "http-route-extension-route-error": { + errMsg: "route hook resource error", }, - { - name: "http-route-extension-virtualhost-error", - requireSecrets: true, - err: "extension post xds virtual host hook error", + "http-route-extension-virtualhost-error": { + errMsg: "extension post xds virtual host hook error", }, - { - name: "http-route-extension-listener-error", - requireSecrets: true, - err: "extension post xds listener hook error", + "http-route-extension-listener-error": { + errMsg: "extension post xds listener hook error", }, } - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - // Testdata for the extension tests is similar to the ir test dat + inputFiles, err := filepath.Glob(filepath.Join("testdata", "in", "extension-xds-ir", "*.yaml")) + require.NoError(t, err) + + for _, inputFile := range inputFiles { + inputFile := inputFile + inputFileName := testName(inputFile) + t.Run(inputFileName, func(t *testing.T) { + cfg, ok := testConfigs[inputFileName] + if !ok { + cfg = testFileConfig{} + } + + // Testdata for the extension tests is similar to the ir test data // New directory is just to keep them separate and easy to understand - ir := requireXdsIRFromInputTestData(t, "extension-xds-ir", tc.name+".yaml") + x := requireXdsIRFromInputTestData(t, inputFile) tr := &Translator{ GlobalRateLimit: &GlobalRateLimitSettings{ ServiceURL: ratelimit.GetServiceURL("envoy-gateway-system", "cluster.local"), @@ -577,10 +250,9 @@ func TestTranslateXdsWithExtension(t *testing.T) { extMgr := testutils.NewManager(ext) tr.ExtensionManager = &extMgr - tCtx, err := tr.Translate(ir) - - if tc.err != "" { - require.EqualError(t, err, tc.err) + tCtx, err := tr.Translate(x) + if len(cfg.errMsg) > 0 { + require.EqualError(t, err, cfg.errMsg) } else { require.NoError(t, err) listeners := tCtx.XdsResources[resourcev3.ListenerType] @@ -588,42 +260,46 @@ func TestTranslateXdsWithExtension(t *testing.T) { clusters := tCtx.XdsResources[resourcev3.ClusterType] endpoints := tCtx.XdsResources[resourcev3.EndpointType] if *overrideTestData { - require.NoError(t, file.Write(requireResourcesToYAMLString(t, listeners), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".listeners.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, routes), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".routes.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, clusters), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".clusters.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, endpoints), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".endpoints.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, listeners), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".listeners.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, routes), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".routes.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, clusters), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".clusters.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, endpoints), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".endpoints.yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".listeners.yaml"), requireResourcesToYAMLString(t, listeners)) - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".routes.yaml"), requireResourcesToYAMLString(t, routes)) - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".clusters.yaml"), requireResourcesToYAMLString(t, clusters)) - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".endpoints.yaml"), requireResourcesToYAMLString(t, endpoints)) - if tc.requireSecrets { - secrets := tCtx.XdsResources[resourcev3.SecretType] + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".listeners.yaml"), requireResourcesToYAMLString(t, listeners)) + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".routes.yaml"), requireResourcesToYAMLString(t, routes)) + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".clusters.yaml"), requireResourcesToYAMLString(t, clusters)) + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".endpoints.yaml"), requireResourcesToYAMLString(t, endpoints)) + + secrets, ok := tCtx.XdsResources[resourcev3.SecretType] + if ok { if *overrideTestData { - require.NoError(t, file.Write(requireResourcesToYAMLString(t, secrets), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".secrets.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, secrets), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".secrets.yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".secrets.yaml"), requireResourcesToYAMLString(t, secrets)) + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".secrets.yaml"), requireResourcesToYAMLString(t, secrets)) } } }) } } -func requireXdsIRFromInputTestData(t *testing.T, name ...string) *ir.Xds { +func testName(inputFile string) string { + _, fileName := filepath.Split(inputFile) + return strings.TrimSuffix(fileName, ".yaml") +} + +func requireXdsIRFromInputTestData(t *testing.T, name string) *ir.Xds { t.Helper() - elems := append([]string{"testdata", "in"}, name...) - content, err := inFiles.ReadFile(filepath.Join(elems...)) + content, err := inFiles.ReadFile(name) require.NoError(t, err) - ir := &ir.Xds{} - err = yaml.Unmarshal(content, ir) + x := &ir.Xds{} + err = yaml.Unmarshal(content, x) require.NoError(t, err) - return ir + return x } -func requireXdsIRListenerFromInputTestData(t *testing.T, name ...string) *ir.HTTPListener { +func requireXdsIRListenerFromInputTestData(t *testing.T, name string) *ir.HTTPListener { t.Helper() - elems := append([]string{"testdata", "in"}, name...) - content, err := inFiles.ReadFile(filepath.Join(elems...)) + content, err := inFiles.ReadFile(name) require.NoError(t, err) listener := &ir.HTTPListener{} err = yaml.Unmarshal(content, listener) diff --git a/internal/xds/translator/utils.go b/internal/xds/translator/utils.go index f4d24c9965d..b4f60b1ae30 100644 --- a/internal/xds/translator/utils.go +++ b/internal/xds/translator/utils.go @@ -13,16 +13,14 @@ import ( "strconv" "strings" - "k8s.io/utils/ptr" - - "github.com/envoyproxy/gateway/internal/ir" - "github.com/envoyproxy/gateway/internal/xds/types" - corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "google.golang.org/protobuf/types/known/anypb" + "k8s.io/utils/ptr" + + "github.com/envoyproxy/gateway/internal/ir" + "github.com/envoyproxy/gateway/internal/xds/types" ) const ( @@ -146,13 +144,6 @@ func createExtServiceXDSCluster(rd *ir.RouteDestination, tCtx *types.ResourceVer endpointType = EndpointTypeStatic } - if rd.Settings[0].TLS != nil { - tSocket, err = processTLSSocket(rd.Settings[0].TLS, tCtx) - if err != nil { - return err - } - } - if err = addXdsCluster(tCtx, &xdsClusterArgs{ name: rd.Name, settings: rd.Settings, diff --git a/internal/xds/translator/wasm.go b/internal/xds/translator/wasm.go index 1c8c03951ca..1e096318df8 100644 --- a/internal/xds/translator/wasm.go +++ b/internal/xds/translator/wasm.go @@ -13,8 +13,8 @@ import ( wasmfilterv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" wasmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/wasm/v3" - "github.com/golang/protobuf/ptypes/duration" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" "github.com/envoyproxy/gateway/internal/ir" @@ -30,8 +30,7 @@ func init() { registerHTTPFilter(&wasm{}) } -type wasm struct { -} +type wasm struct{} var _ httpFilter = &wasm{} @@ -139,7 +138,7 @@ func wasmConfig(wasm ir.Wasm) (*wasmfilterv3.Wasm, error) { HttpUpstreamType: &corev3.HttpUri_Cluster{ Cluster: uc.name, }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, }, @@ -172,7 +171,8 @@ func routeContainsWasm(irRoute *ir.HTTPRoute) bool { // patchResources patches the cluster resources for the http wasm code source. func (*wasm) patchResources(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if tCtx == nil || tCtx.XdsResources == nil { return errors.New("xds resource table is nil") } diff --git a/internal/xds/types/resourceversiontable.go b/internal/xds/types/resourceversiontable.go index 672096e6ab7..2f7a7926bd8 100644 --- a/internal/xds/types/resourceversiontable.go +++ b/internal/xds/types/resourceversiontable.go @@ -46,7 +46,7 @@ func (t *ResourceVersionTable) DeepCopyInto(out *ResourceVersionTable) { (*out)[key] = nil } else { // Snippet was generated by controller-gen - //G601: Implicit memory aliasing in for loop. + // G601: Implicit memory aliasing in for loop. in, out := &val, &outVal //nolint:gosec,scopelint *out = make([]types.Resource, len(*in)) for i := range *in { diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index bcfb313ba7b..cc5aaf69fc7 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -36,6 +36,8 @@ _Underlying type:_ _string_ ALPNProtocol specifies the protocol to be negotiated using ALPN _Appears in:_ +- [BackendTLSConfig](#backendtlsconfig) +- [ClientTLSSettings](#clienttlssettings) - [TLSSettings](#tlssettings) | Value | Description | @@ -206,6 +208,26 @@ _Appears in:_ | `port` | _[PortNumber](#portnumber)_ | false | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | +#### BackendTLSConfig + + + +BackendTLSConfig describes the BackendTLS configuration for Envoy Proxy. + +_Appears in:_ +- [EnvoyProxySpec](#envoyproxyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `clientCertificateRef` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | false | ClientCertificateRef defines the reference to a Kubernetes Secret that contains
the client certificate and private key for Envoy to use when connecting to
backend services and external services, such as ExtAuth, ALS, OpenTelemetry, etc. | +| `minVersion` | _[TLSVersion](#tlsversion)_ | false | Min specifies the minimal TLS protocol version to allow.
The default is TLS 1.2 if this is not specified. | +| `maxVersion` | _[TLSVersion](#tlsversion)_ | false | Max specifies the maximal TLS protocol version to allow
The default is TLS 1.3 if this is not specified. | +| `ciphers` | _string array_ | false | 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_ | false | 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_ | false | SignatureAlgorithms specifies which signature algorithms the listener should
support. | +| `alpnProtocols` | _[ALPNProtocol](#alpnprotocol) array_ | false | ALPNProtocols supplies the list of ALPN protocols that should be
exposed by the listener. By default h2 and http/1.1 are enabled.
Supported values are:
- http/1.0
- http/1.1
- h2 | + + #### BackendTrafficPolicy @@ -360,6 +382,26 @@ _Appears in:_ | `customHeader` | _[CustomHeaderExtensionSettings](#customheaderextensionsettings)_ | false | CustomHeader provides configuration for determining the client IP address for a request based on
a trusted custom HTTP header. This uses the the custom_header original IP detection extension.
Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/original_ip_detection/custom_header/v3/custom_header.proto
for more details. | +#### ClientTLSSettings + + + + + +_Appears in:_ +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `clientValidation` | _[ClientValidationContext](#clientvalidationcontext)_ | false | ClientValidation specifies the configuration to validate the client
initiating the TLS connection to the Gateway listener. | +| `minVersion` | _[TLSVersion](#tlsversion)_ | false | Min specifies the minimal TLS protocol version to allow.
The default is TLS 1.2 if this is not specified. | +| `maxVersion` | _[TLSVersion](#tlsversion)_ | false | Max specifies the maximal TLS protocol version to allow
The default is TLS 1.3 if this is not specified. | +| `ciphers` | _string array_ | false | 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_ | false | 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_ | false | SignatureAlgorithms specifies which signature algorithms the listener should
support. | +| `alpnProtocols` | _[ALPNProtocol](#alpnprotocol) array_ | false | ALPNProtocols supplies the list of ALPN protocols that should be
exposed by the listener. By default h2 and http/1.1 are enabled.
Supported values are:
- http/1.0
- http/1.1
- h2 | + + #### ClientTimeout @@ -423,7 +465,7 @@ _Appears in:_ | `tcpKeepalive` | _[TCPKeepalive](#tcpkeepalive)_ | false | TcpKeepalive settings associated with the downstream client connection.
If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives.
Disabled by default. | | `enableProxyProtocol` | _boolean_ | false | 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. | | `clientIPDetection` | _[ClientIPDetectionSettings](#clientipdetectionsettings)_ | false | ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. | -| `tls` | _[TLSSettings](#tlssettings)_ | false | TLS settings configure TLS termination settings with the downstream client. | +| `tls` | _[ClientTLSSettings](#clienttlssettings)_ | false | TLS settings configure TLS termination settings with the downstream client. | | `path` | _[PathSettings](#pathsettings)_ | false | Path enables managing how the incoming path set by clients can be normalized. | | `headers` | _[HeaderSettings](#headersettings)_ | false | HeaderSettings provides configuration for header management. | | `timeout` | _[ClientTimeout](#clienttimeout)_ | false | Timeout settings for the client connections. | @@ -442,7 +484,7 @@ to the Gateway. By default, no client specific configuration is validated. _Appears in:_ -- [TLSSettings](#tlssettings) +- [ClientTLSSettings](#clienttlssettings) | Field | Type | Required | Description | | --- | --- | --- | --- | @@ -1119,6 +1161,7 @@ _Appears in:_ | `extraArgs` | _string array_ | false | ExtraArgs defines additional command line options that are provided to Envoy.
More info: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#command-line-options
Note: some command line options are used internally(e.g. --log-level) so they cannot be provided here. | | `mergeGateways` | _boolean_ | false | MergeGateways defines if Gateway resources should be merged onto the same Envoy Proxy Infrastructure.
Setting this field to true would merge all Gateway Listeners under the parent Gateway Class.
This means that the port, protocol and hostname tuple must be unique for every listener.
If a duplicate listener is detected, the newer listener (based on timestamp) will be rejected and its status will be updated with a "Accepted=False" condition. | | `shutdown` | _[ShutdownConfig](#shutdownconfig)_ | false | Shutdown defines configuration for graceful envoy shutdown process. | +| `backendTLS` | _[BackendTLSConfig](#backendtlsconfig)_ | false | BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends.
These settings are applied on backends for which TLS policies are specified. | @@ -1168,33 +1211,12 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `backendRef` | _[ExtProcBackendRef](#extprocbackendref)_ | true | BackendRef defines the configuration of the external processing service | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs defines the configuration of the external processing service | +| `backendRefs` | _[BackendRef](#backendref) array_ | true | BackendRefs defines the configuration of the external processing service | | `messageTimeout` | _[Duration](#duration)_ | false | MessageTimeout is the timeout for a response to be returned from the external processor
Default: 200ms | | `failOpen` | _boolean_ | false | FailOpen defines if requests or responses that cannot be processed due to connectivity to the
external processor are terminated or passed-through.
Default: false | | `processingMode` | _[ExtProcProcessingMode](#extprocprocessingmode)_ | false | ProcessingMode defines how request and response body is processed
Default: header and body are not sent to the external processor | -#### ExtProcBackendRef - - - -ExtProcService defines the gRPC External Processing service using the envoy grpc client -The processing request and response messages are defined in -https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/ext_proc/v3/external_processor.proto - -_Appears in:_ -- [ExtProc](#extproc) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `group` | _[Group](#group)_ | false | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When unspecified or empty string, core API group is inferred. | -| `kind` | _[Kind](#kind)_ | false | Kind is the Kubernetes resource kind of the referent. For example
"Service".

Defaults to "Service" when not specified.

ExternalName services can refer to CNAME DNS records that may live
outside of the cluster and as such are difficult to reason about in
terms of conformance. They also may not be safe to forward to (see
CVE-2021-25740 for more information). Implementations SHOULD NOT
support ExternalName Services.

Support: Core (Services with a type other than ExternalName)

Support: Implementation-specific (Services with type ExternalName) | -| `name` | _[ObjectName](#objectname)_ | true | Name is the name of the referent. | -| `namespace` | _[Namespace](#namespace)_ | false | Namespace is the namespace of the backend. When unspecified, the local
namespace is inferred.

Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details.

Support: Core | -| `port` | _[PortNumber](#portnumber)_ | false | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | - - #### ExtProcBodyProcessingMode _Underlying type:_ _string_ @@ -3078,7 +3100,8 @@ _Appears in:_ _Appears in:_ -- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) +- [BackendTLSConfig](#backendtlsconfig) +- [ClientTLSSettings](#clienttlssettings) | Field | Type | Required | Description | | --- | --- | --- | --- | @@ -3088,7 +3111,6 @@ _Appears in:_ | `ecdhCurves` | _string array_ | false | 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_ | false | SignatureAlgorithms specifies which signature algorithms the listener should
support. | | `alpnProtocols` | _[ALPNProtocol](#alpnprotocol) array_ | false | ALPNProtocols supplies the list of ALPN protocols that should be
exposed by the listener. By default h2 and http/1.1 are enabled.
Supported values are:
- http/1.0
- http/1.1
- h2 | -| `clientValidation` | _[ClientValidationContext](#clientvalidationcontext)_ | false | ClientValidation specifies the configuration to validate the client
initiating the TLS connection to the Gateway listener. | #### TLSVersion @@ -3098,6 +3120,8 @@ _Underlying type:_ _string_ TLSVersion specifies the TLS version _Appears in:_ +- [BackendTLSConfig](#backendtlsconfig) +- [ClientTLSSettings](#clienttlssettings) - [TLSSettings](#tlssettings) | Value | Description | diff --git a/site/content/en/latest/install/api.md b/site/content/en/latest/install/api.md index 944a31f1e2e..36fe24f6e5b 100644 --- a/site/content/en/latest/install/api.md +++ b/site/content/en/latest/install/api.md @@ -33,9 +33,9 @@ The Helm chart for Envoy Gateway | config.envoyGateway.logging.level.default | string | `"info"` | | | config.envoyGateway.provider.type | string | `"Kubernetes"` | | | createNamespace | bool | `false` | | -| deployment.envoyGateway.image.repository | string | `"${ImageRepository}"` | | -| deployment.envoyGateway.image.tag | string | `"${ImageTag}"` | | -| deployment.envoyGateway.imagePullPolicy | string | `"Always"` | | +| deployment.envoyGateway.image.repository | string | `"docker.io/envoyproxy/gateway"` | | +| deployment.envoyGateway.image.tag | string | `"latest"` | | +| deployment.envoyGateway.imagePullPolicy | string | `"IfNotPresent"` | | | deployment.envoyGateway.imagePullSecrets | list | `[]` | | | deployment.envoyGateway.resources.limits.cpu | string | `"500m"` | | | deployment.envoyGateway.resources.limits.memory | string | `"1024Mi"` | | diff --git a/site/content/en/latest/tasks/quickstart.md b/site/content/en/latest/tasks/quickstart.md index 3d857e53dd5..4f345fa289a 100644 --- a/site/content/en/latest/tasks/quickstart.md +++ b/site/content/en/latest/tasks/quickstart.md @@ -48,44 +48,43 @@ consideration when debugging. ## Testing the Configuration {{< tabpane text=true >}} -{{% tab header="Without LoadBalancer Support" %}} +{{% tab header="With External LoadBalancer Support" %}} -Get the name of the Envoy service created the by the example Gateway: +You can also test the same functionality by sending traffic to the External IP. To get the external IP of the +Envoy service, run: ```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +export GATEWAY_HOST=$(kubectl get svc/${ENVOY_SERVICE} -n envoy-gateway-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ``` -Port forward to the Envoy service: - -```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 & -``` +In certain environments, the load balancer may be exposed using a hostname, instead of an IP address. If so, replace +`ip` in the above command with `hostname`. Curl the example app through Envoy proxy: ```shell -curl --verbose --header "Host: www.example.com" http://localhost:8888/get +curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/get ``` {{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} -{{% tab header="External LoadBalancer Support" %}} - -You can also test the same functionality by sending traffic to the External IP. To get the external IP of the -Envoy service, run: +Get the name of the Envoy service created the by the example Gateway: ```shell -export GATEWAY_HOST=$(kubectl get svc/${ENVOY_SERVICE} -n envoy-gateway-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -In certain environments, the load balancer may be exposed using a hostname, instead of an IP address. If so, replace -`ip` in the above command with `hostname`. +Port forward to the Envoy service: + +```shell +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 & +``` Curl the example app through Envoy proxy: ```shell -curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/get +curl --verbose --header "Host: www.example.com" http://localhost:8888/get ``` {{% /tab %}} diff --git a/site/content/en/latest/tasks/security/backend-tls.md b/site/content/en/latest/tasks/security/backend-tls.md index 706d25ae60d..aeedcd503d4 100644 --- a/site/content/en/latest/tasks/security/backend-tls.md +++ b/site/content/en/latest/tasks/security/backend-tls.md @@ -208,24 +208,19 @@ kubectl get HTTPRoute backend -o yaml ## Testing -### Clusters without External LoadBalancer Support - -Get the name of the Envoy service created the by the example Gateway: - -```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') -``` +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} -Port forward to the Envoy service: +Get the External IP of the Gateway: ```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 80:80 & +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Query the TLS-enabled backend through Envoy proxy: +Query the example app through the Gateway: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:80:127.0.0.1" \ +curl -v -HHost:www.example.com --resolve "www.example.com:80:${GATEWAY_HOST}" \ http://www.example.com:80/get ``` @@ -242,18 +237,25 @@ Inspect the output and see that the response contains the details of the TLS han } ``` -### Clusters with External LoadBalancer Support +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} -Get the External IP of the Gateway: +Get the name of the Envoy service created the by the example Gateway: ```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -Query the example app through the Gateway: +Port forward to the Envoy service: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:80:${GATEWAY_HOST}" \ +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 80:80 & +``` + +Query the TLS-enabled backend through Envoy proxy: + +```shell +curl -v -HHost:www.example.com --resolve "www.example.com:80:127.0.0.1" \ http://www.example.com:80/get ``` @@ -270,4 +272,7 @@ Inspect the output and see that the response contains the details of the TLS han } ``` +{{% /tab %}} +{{< /tabpane >}} + [BackendTLSPolicy]: https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/ diff --git a/site/content/en/latest/tasks/security/mutual-tls.md b/site/content/en/latest/tasks/security/mutual-tls.md index a848d8334cf..64f471ba19d 100644 --- a/site/content/en/latest/tasks/security/mutual-tls.md +++ b/site/content/en/latest/tasks/security/mutual-tls.md @@ -133,49 +133,54 @@ spec: ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} -Get the name of the Envoy service created the by the example Gateway: +Get the External IP of the Gateway: ```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Port forward to the Envoy service: +Query the example app through the Gateway: ```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 & +curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ +--cert client.example.com.crt --key client.example.com.key \ +--cacert example.com.crt https://www.example.com/get ``` -Query the example app through Envoy proxy: +Don't specify the client key and certificate in the above command, and ensure that the connection fails: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ ---cert client.example.com.crt --key client.example.com.key \ ---cacert example.com.crt https://www.example.com:8443/get +curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ +--cacert example.com.crt https://www.example.com/get ``` -### Clusters with External LoadBalancer Support +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} -Get the External IP of the Gateway: +Get the name of the Envoy service created the by the example Gateway: ```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -Query the example app through the Gateway: +Port forward to the Envoy service: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ ---cert client.example.com.crt --key client.example.com.key \ ---cacert example.com.crt https://www.example.com/get +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 & ``` -Dont specify the client key and certificate in the above command, and ensure that the connection fails +Query the example app through Envoy proxy: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ ---cacert example.com.crt https://www.example.com/get +curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ +--cert client.example.com.crt --key client.example.com.key \ +--cacert example.com.crt https://www.example.com:8443/get ``` +{{% /tab %}} +{{< /tabpane >}} + [ClientTrafficPolicy]: ../../../api/extension_types#clienttrafficpolicy diff --git a/site/content/en/latest/tasks/security/oidc.md b/site/content/en/latest/tasks/security/oidc.md index 0360ccd496f..ac7d6d60ba9 100644 --- a/site/content/en/latest/tasks/security/oidc.md +++ b/site/content/en/latest/tasks/security/oidc.md @@ -4,7 +4,7 @@ title: "OIDC Authentication" This task provides instructions for configuring [OpenID Connect (OIDC)][oidc] authentication. OpenID Connect (OIDC) is an authentication standard built on top of OAuth 2.0. -It enables client applications to rely on authentication that is performed by an OpenID Connect Provider (OP) +It enables EG to rely on authentication that is performed by an OpenID Connect Provider (OP) to verify the identity of a user. Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure OIDC @@ -16,17 +16,15 @@ This instantiated resource can be linked to a [Gateway][Gateway] and [HTTPRoute] Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. +EG OIDC authentication requires the redirect URL to be HTTPS. Follow the [Secure Gateways](../secure-gateways) guide +to generate the TLS certificates and update the Gateway configuration to add an HTTPS listener. + Verify the Gateway status: ```shell kubectl get gateway/eg -o yaml ``` -OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with -the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. - -This task demonstrates the configuration of OIDC at the HTTPRoute level. - Let's create an HTTPRoute that represents an application protected by OIDC. {{< tabpane text=true >}} @@ -86,16 +84,21 @@ Verify the HTTPRoute status: kubectl get httproute/myapp -o yaml ``` -## Configuration +## OIDC Authentication for a HTTPRoute -This task uses Google as the OIDC provider to demonstrate the configuration of OIDC. However, EG works with any OIDC -providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, etc. +OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with +the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. + +This section demonstrates how to configure OIDC authentication for a specific HTTPRoute. ### Register an OIDC application +This task uses Google as the OIDC provider to demonstrate the configuration of OIDC. However, EG works with any OIDC +providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, etc. + Follow the steps in the [Google OIDC documentation][google-oidc] to register an OIDC application. Please make sure the redirect URL is set to the one you configured in the SecurityPolicy that you will create in the step below. In this example, -the redirect URL is `http://www.example.com:8080/myapp/oauth2/callback`. +the redirect URL is `http://www.example.com:8443/myapp/oauth2/callback`. After registering the application, you should have the following information: * Client ID: The client ID of the OIDC application. @@ -109,15 +112,14 @@ and the Client Secret must be stored in the key "client-secret". Note: please replace the ${CLIENT_SECRET} with the actual Client Secret that you got from the previous step. ```shell -$ kubectl create secret generic my-app-client-secret --from-literal=client-secret=${CLIENT_SECRET} -secret "my-app-client-secret" created +kubectl create secret generic my-app-client-secret --from-literal=client-secret=${CLIENT_SECRET} ``` ### Create a SecurityPolicy -Please notice that the `redirectURL` and `logoutPath` must match the target HTTPRoute. In this example, the target +**Please notice that the `redirectURL` and `logoutPath` must match the target HTTPRoute.** In this example, the target HTTPRoute is configured to match the host `www.example.com` and the path `/myapp`, so the `redirectURL` must be prefixed -with `http://www.example.com:8080/myapp`, and `logoutPath` must be prefixed with`/myapp`, otherwise the OIDC authentication +with `https://www.example.com:8443/myapp`, and `logoutPath` must be prefixed with`/myapp`, otherwise the OIDC authentication will fail because the redirect and logout requests will not match the target HTTPRoute and therefore can't be processed by the OAuth2 filter on that HTTPRoute. @@ -143,7 +145,7 @@ spec: clientID: "${CLIENT_ID}" clientSecret: name: "my-app-client-secret" - redirectURL: "http://www.example.com:8080/myapp/oauth2/callback" + redirectURL: "https://www.example.com:8443/myapp/oauth2/callback" logoutPath: "/myapp/logout" EOF ``` @@ -169,7 +171,7 @@ spec: clientID: "${CLIENT_ID}" clientSecret: name: "my-app-client-secret" - redirectURL: "http://www.example.com:8080/myapp/oauth2/callback" + redirectURL: "https://www.example.com:8443/myapp/oauth2/callback" logoutPath: "/myapp/logout" ``` @@ -182,14 +184,14 @@ Verify the SecurityPolicy configuration: kubectl get securitypolicy/oidc-example -o yaml ``` -## Testing +### Testing Port forward gateway port to localhost: ```shell export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8080:80 +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 ``` Put www.example.com in the /etc/hosts file in your test machine, so we can use this host name to access the gateway from a browser: @@ -199,9 +201,104 @@ Put www.example.com in the /etc/hosts file in your test machine, so we can use t 127.0.0.1 www.example.com ``` -Open a browser and navigate to the `http://www.example.com:8080/myapp` address. You should be redirected to the Google +Open a browser and navigate to the `https://www.example.com:8443/myapp` address. You should be redirected to the Google +login page. After you successfully login, you should see the response from the backend service. + +Clean the cookies in the browser and try to access `https://www.example.com:8443/foo` address. You should be able to see +this page since the path `/foo` is not protected by the OIDC policy. + +## OIDC Authentication for a Gateway + +OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with +the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. + +This section demonstrates how to configure OIDC authentication for a Gateway. + +### Register an OIDC application + +If you haven't registered an OIDC application, follow the steps in the previous section to register an OIDC application. + +### Create a kubernetes secret + +If you haven't created a kubernetes secret, follow the steps in the previous section to create a kubernetes secret. + +### Create a SecurityPolicy + +Create or update the SecurityPolicy to target the Gateway instead of the HTTPRoute. **Please notice that the `redirectURL` +and `logoutPath` must match one of the HTTPRoutes associated with the Gateway.** In this example, the target Gateway has +two HTTPRoutes associated with it, one with the host `www.example.com` and the path `/myapp`, and the other with the host +`www.example.com` and the path `/`. Either one of the HTTPRoutes can be used to match the `redirectURL` and `logoutPath`. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +Verify the SecurityPolicy configuration: + +```shell +kubectl get securitypolicy/oidc-example -o yaml +``` + +### Testing + +If you haven't done so, follow the steps in the previous section to port forward gateway port to localhost and put +www.example.com in the /etc/hosts file in your test machine. + +Open a browser and navigate to the `https://www.example.com:8443/foo` address. You should be redirected to the Google login page. After you successfully login, you should see the response from the backend service. +You can also try to access `https://www.example.com:8443/myapp` address. You should be able to see this page since the +path `/myapp` is protected by the same OIDC policy. + ## Clean-Up Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. @@ -216,10 +313,10 @@ kubectl delete httproute/myapp ## Next Steps -Checkout the [Developer Guide](../../../contributions/develop) to get involved in the project. +Checkout the [Developer Guide](../../../../contributions/develop) to get involved in the project. [oidc]: https://openid.net/connect/ [google-oidc]: https://developers.google.com/identity/protocols/oauth2/openid-connect -[SecurityPolicy]: ../../../contributions/design/security-policy +[SecurityPolicy]: ../../../../contributions/design/security-policy [Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway [HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute diff --git a/site/content/en/latest/tasks/security/secure-gateways.md b/site/content/en/latest/tasks/security/secure-gateways.md index e57b1236389..af5e922412d 100644 --- a/site/content/en/latest/tasks/security/secure-gateways.md +++ b/site/content/en/latest/tasks/security/secure-gateways.md @@ -65,7 +65,24 @@ kubectl get gateway/eg -o yaml ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} + +Get the External IP of the Gateway: + +```shell +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +``` + +Query the example app through the Gateway: + +```shell +curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ +--cacert example.com.crt https://www.example.com/get +``` + +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} Get the name of the Envoy service created the by the example Gateway: @@ -86,20 +103,9 @@ curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ --cacert example.com.crt https://www.example.com:8443/get ``` -### Clusters with External LoadBalancer Support - -Get the External IP of the Gateway: - -```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') -``` - -Query the example app through the Gateway: +{{% /tab %}} +{{< /tabpane >}} -```shell -curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ ---cacert example.com.crt https://www.example.com/get -``` ## Multiple HTTPS Listeners @@ -297,7 +303,7 @@ Lastly, test connectivity using the above [Testing section](#testing). ## Clean-Up -Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the Secrets: @@ -423,7 +429,7 @@ This sections gives a walkthrough to generate multiple certificates correspondin ## Prerequisites -Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. Follow the steps in the [TLS Certificates](#tls-certificates) section to generate self-signed RSA derived Server certificate and private key, and configure those in the Gateway listener configuration to terminate HTTPS traffic. @@ -467,7 +473,14 @@ kubectl patch httproute backend --type=json --patch ' ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} + +Refer to the steps mentioned earlier under [Testing in clusters with External LoadBalancer Support](#testing) + + +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} Get the name of the Envoy service created the by the example Gateway: @@ -497,9 +510,8 @@ curl -v -HHost:www.sample.com --resolve "www.sample.com:8443:127.0.0.1" \ Since the multiple certificates are configured on the same Gateway listener, Envoy was able to provide the client with appropriate certificate based on the SNI in the client request. -### Clusters with External LoadBalancer Support - -Refer to the steps mentioned earlier under [Testing in clusters with External LoadBalancer Support](#clusters-with-external-loadbalancer-support) +{{% /tab %}} +{{< /tabpane >}} ## Next Steps diff --git a/site/content/en/latest/tasks/security/tls-passthrough.md b/site/content/en/latest/tasks/security/tls-passthrough.md index 2683f568332..4f9665d6763 100644 --- a/site/content/en/latest/tasks/security/tls-passthrough.md +++ b/site/content/en/latest/tasks/security/tls-passthrough.md @@ -68,42 +68,47 @@ kubectl patch gateway eg --type=json --patch ' ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} -Get the name of the Envoy service created the by the example Gateway: +You can also test the same functionality by sending traffic to the External IP of the Gateway: ```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Port forward to the Envoy service: +Curl the example app through the Gateway, e.g. Envoy proxy: ```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 6043:6443 & +curl -v -HHost:passthrough.example.com --resolve "passthrough.example.com:6443:${GATEWAY_HOST}" \ +--cacert example.com.crt https://passthrough.example.com:6443/get ``` -Curl the example app through Envoy proxy: +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} + +Get the name of the Envoy service created the by the example Gateway: ```shell -curl -v --resolve "passthrough.example.com:6043:127.0.0.1" https://passthrough.example.com:6043 \ ---cacert passthrough.example.com.crt +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -### Clusters with External LoadBalancer Support - -You can also test the same functionality by sending traffic to the External IP of the Gateway: +Port forward to the Envoy service: ```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 6043:6443 & ``` -Curl the example app through the Gateway, e.g. Envoy proxy: +Curl the example app through Envoy proxy: ```shell -curl -v -HHost:passthrough.example.com --resolve "passthrough.example.com:6443:${GATEWAY_HOST}" \ ---cacert example.com.crt https://passthrough.example.com:6443/get +curl -v --resolve "passthrough.example.com:6043:127.0.0.1" https://passthrough.example.com:6043 \ +--cacert passthrough.example.com.crt ``` +{{% /tab %}} +{{< /tabpane >}} + ## Clean-Up Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. diff --git a/site/content/en/latest/tasks/security/tls-termination.md b/site/content/en/latest/tasks/security/tls-termination.md index 77a701a443a..e4534dd57e1 100644 --- a/site/content/en/latest/tasks/security/tls-termination.md +++ b/site/content/en/latest/tasks/security/tls-termination.md @@ -49,38 +49,43 @@ kubectl get gateway/eg -o yaml ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} -Get the name of the Envoy service created the by the example Gateway: +Get the External IP of the Gateway: ```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Port forward to the Envoy service: +Query the example app through the Gateway: ```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 & +curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ +--cacert example.com.crt https://www.example.com/get ``` -Query the example app through Envoy proxy: +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} + +Get the name of the Envoy service created the by the example Gateway: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ ---cacert example.com.crt https://www.example.com:8443/get +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -### Clusters with External LoadBalancer Support - -Get the External IP of the Gateway: +Port forward to the Envoy service: ```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 & ``` -Query the example app through the Gateway: +Query the example app through Envoy proxy: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ ---cacert example.com.crt https://www.example.com/get +curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ +--cacert example.com.crt https://www.example.com:8443/get ``` + +{{% /tab %}} +{{< /tabpane >}} diff --git a/site/content/en/latest/tasks/traffic/http3.md b/site/content/en/latest/tasks/traffic/http3.md index 502c37496b6..af95ab8ba57 100644 --- a/site/content/en/latest/tasks/traffic/http3.md +++ b/site/content/en/latest/tasks/traffic/http3.md @@ -108,13 +108,8 @@ kubectl get gateway/eg -o yaml ## Testing -### Clusters without External LoadBalancer Support - -It is not possible at the moment to port-forward UDP protocol in kubernetes service -check out https://github.com/kubernetes/kubernetes/issues/47862. -Hence we need external loadbalancer to test this feature out. - -### Clusters with External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} Get the External IP of the Gateway: @@ -124,8 +119,18 @@ export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0]. Query the example app through the Gateway: -Below example uses a custom docker image with custom curl binary with built-in http3. +The below example uses a custom docker image with custom `curl` binary with built-in http3. ```shell docker run --net=host --rm ghcr.io/macbre/curl-http3 curl -kv --http3 -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" https://www.example.com/get ``` + +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} + +It is not possible at the moment to port-forward UDP protocol in kubernetes service +check out https://github.com/kubernetes/kubernetes/issues/47862. +Hence we need external loadbalancer to test this feature out. + +{{% /tab %}} +{{< /tabpane >}} diff --git a/site/content/en/v1.0.1/tasks/operations/customize-envoyproxy.md b/site/content/en/v1.0.1/tasks/operations/customize-envoyproxy.md index abf8d7ed4da..152f9e7ff44 100644 --- a/site/content/en/v1.0.1/tasks/operations/customize-envoyproxy.md +++ b/site/content/en/v1.0.1/tasks/operations/customize-envoyproxy.md @@ -15,6 +15,9 @@ Before proceeding, you should be able to query the example backend using HTTP. First, you need to add ParametersRef in GatewayClass, and refer to EnvoyProxy Config: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + ## Customize EnvoyProxy Deployment Replicas You can customize the EnvoyProxy Deployment Replicas via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After you apply the config, you should see the replicas of envoyproxy changes to 2. And also you can dynamically change the value. @@ -62,6 +112,9 @@ kubectl get deployment -l gateway.envoyproxy.io/owning-gateway-name=eg -n envoy- You can customize the EnvoyProxy Image via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, you can get the deployment image, and see it has changed. ## Customize EnvoyProxy Pod Annotations You can customize the EnvoyProxy Pod Annotations via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, you can get the envoyproxy pods, and see new annotations has been added. ## Customize EnvoyProxy Deployment Resources You can customize the EnvoyProxy Deployment Resources via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + ## Customize EnvoyProxy Deployment Env You can customize the EnvoyProxy Deployment Env via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + > Envoy Gateway has provided two initial `env` `ENVOY_GATEWAY_NAMESPACE` and `ENVOY_POD_NAME` for envoyproxy container. After applying the config, you can get the envoyproxy deployment, and see resources has been changed. @@ -166,6 +332,9 @@ After applying the config, you can get the envoyproxy deployment, and see resour You can customize the EnvoyProxy Deployment Volumes or VolumeMounts via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, you can get the envoyproxy deployment, and see resources has been changed. ## Customize EnvoyProxy Service Annotations You can customize the EnvoyProxy Service Annotations via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, you can get the envoyproxy service, and see annotations has been added. ## Customize EnvoyProxy Bootstrap Config @@ -226,6 +452,9 @@ There are two ways to customize it: * Replace: the whole bootstrap config will be replaced by the config you provided. * Merge: the config you provided will be merged into the default bootstrap config. +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + You can use [egctl translate][] to get the default xDS Bootstrap configuration used by Envoy Gateway. @@ -323,6 +642,9 @@ You can enable [Horizontal Pod Autoscaler](https://github.com/envoyproxy/gateway Once confirmed, you can apply it via EnvoyProxy Config as shown below: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, the EnvoyProxy HPA (Horizontal Pod Autoscaler) is generated. However, upon activating the EnvoyProxy's HPA, the Envoy Gateway will no longer reference the `replicas` field specified in the `envoyDeployment`, as outlined [here](#customize-envoyproxy-deployment-replicas). ## Customize EnvoyProxy Command line options @@ -354,6 +706,9 @@ After applying the config, the EnvoyProxy HPA (Horizontal Pod Autoscaler) is gen You can customize the EnvoyProxy Command line options via `spec.extraArgs` in EnvoyProxy Config. For example, the following configuration will add `--disable-extensions` arg in order to disable `envoy.access_loggers/envoy.access_loggers.wasm` extension: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + +## Customize EnvoyProxy with Patches + +You can customize the EnvoyProxy using patches. + +For example, the following configuration will add resource limits to the `envoy` and the `shutdown-manager` containers in the `envoyproxy` deployment: + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +After applying the configuration, you will see the change in both containers in the `envoyproxy` deployment. + [Gateway API documentation]: https://gateway-api.sigs.k8s.io/ [EnvoyProxy]: ../../../api/extension_types#envoyproxy [egctl translate]: ../egctl/#validating-gateway-api-configuration + diff --git a/site/content/en/v1.0.1/tasks/security/oidc.md b/site/content/en/v1.0.1/tasks/security/oidc.md index 81bdaa882ac..c11a52bbfef 100644 --- a/site/content/en/v1.0.1/tasks/security/oidc.md +++ b/site/content/en/v1.0.1/tasks/security/oidc.md @@ -2,9 +2,9 @@ title: "OIDC Authentication" --- -This guide provides instructions for configuring [OpenID Connect (OIDC)][oidc] authentication. +This task provides instructions for configuring [OpenID Connect (OIDC)][oidc] authentication. OpenID Connect (OIDC) is an authentication standard built on top of OAuth 2.0. -It enables client applications to rely on authentication that is performed by an OpenID Connect Provider (OP) +It enables EG to rely on authentication that is performed by an OpenID Connect Provider (OP) to verify the identity of a user. Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure OIDC @@ -13,22 +13,23 @@ This instantiated resource can be linked to a [Gateway][Gateway] and [HTTPRoute] ## Prerequisites -Follow the steps from the [Quickstart](../../quickstart) guide to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. +EG OIDC authentication requires the redirect URL to be HTTPS. Follow the [Secure Gateways](../secure-gateways) guide +to generate the TLS certificates and update the Gateway configuration to add an HTTPS listener. + Verify the Gateway status: ```shell kubectl get gateway/eg -o yaml ``` -OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with -the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. - -This guide demonstrates the configuration of OIDC at the HTTPRoute level. - Let's create an HTTPRoute that represents an application protected by OIDC. +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + Verify the HTTPRoute status: ```shell kubectl get httproute/myapp -o yaml ``` -## Configuration +## OIDC Authentication for a HTTPRoute -This guide uses Google as the OIDC provider to demonstrate the configuration of OIDC. However, EG works with any OIDC -providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, etc. +OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with +the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. + +This section demonstrates how to configure OIDC authentication for a specific HTTPRoute. ### Register an OIDC application +This task uses Google as the OIDC provider to demonstrate the configuration of OIDC. However, EG works with any OIDC +providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, etc. + Follow the steps in the [Google OIDC documentation][google-oidc] to register an OIDC application. Please make sure the redirect URL is set to the one you configured in the SecurityPolicy that you will create in the step below. In this example, -the redirect URL is `http://www.example.com:8080/myapp/oauth2/callback`. +the redirect URL is `http://www.example.com:8443/myapp/oauth2/callback`. After registering the application, you should have the following information: * Client ID: The client ID of the OIDC application. @@ -79,20 +112,22 @@ and the Client Secret must be stored in the key "client-secret". Note: please replace the ${CLIENT_SECRET} with the actual Client Secret that you got from the previous step. ```shell -$ kubectl create secret generic my-app-client-secret --from-literal=client-secret=${CLIENT_SECRET} -secret "my-app-client-secret" created +kubectl create secret generic my-app-client-secret --from-literal=client-secret=${CLIENT_SECRET} ``` ### Create a SecurityPolicy -Please notice that the `redirectURL` and `logoutPath` must match the target HTTPRoute. In this example, the target -HTTPRoute is configured to match the host `www.example.com` and the path `/myapp`, so the `redirectURL` must be prefixed -with `http://www.example.com:8080/myapp`, and `logoutPath` must be prefixed with`/myapp`, otherwise the OIDC authentication -will fail because the redirect and logout requests will not match the target HTTPRoute and therefore can't be processed +**Please notice that the `redirectURL` and `logoutPath` must match the target HTTPRoute.** In this example, the target +HTTPRoute is configured to match the host `www.example.com` and the path `/myapp`, so the `redirectURL` must be prefixed +with `https://www.example.com:8443/myapp`, and `logoutPath` must be prefixed with`/myapp`, otherwise the OIDC authentication +will fail because the redirect and logout requests will not match the target HTTPRoute and therefore can't be processed by the OAuth2 filter on that HTTPRoute. Note: please replace the ${CLIENT_ID} in the below yaml snippet with the actual Client ID that you got from the OIDC provider. +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + Verify the SecurityPolicy configuration: ```shell kubectl get securitypolicy/oidc-example -o yaml ``` -## Testing +### Testing Port forward gateway port to localhost: ```shell export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8080:80 +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 ``` Put www.example.com in the /etc/hosts file in your test machine, so we can use this host name to access the gateway from a browser: @@ -138,12 +201,107 @@ Put www.example.com in the /etc/hosts file in your test machine, so we can use t 127.0.0.1 www.example.com ``` -Open a browser and navigate to the `http://www.example.com:8080/myapp` address. You should be redirected to the Google +Open a browser and navigate to the `https://www.example.com:8443/myapp` address. You should be redirected to the Google login page. After you successfully login, you should see the response from the backend service. +Clean the cookies in the browser and try to access `https://www.example.com:8443/foo` address. You should be able to see +this page since the path `/foo` is not protected by the OIDC policy. + +## OIDC Authentication for a Gateway + +OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with +the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. + +This section demonstrates how to configure OIDC authentication for a Gateway. + +### Register an OIDC application + +If you haven't registered an OIDC application, follow the steps in the previous section to register an OIDC application. + +### Create a kubernetes secret + +If you haven't created a kubernetes secret, follow the steps in the previous section to create a kubernetes secret. + +### Create a SecurityPolicy + +Create or update the SecurityPolicy to target the Gateway instead of the HTTPRoute. **Please notice that the `redirectURL` +and `logoutPath` must match one of the HTTPRoutes associated with the Gateway.** In this example, the target Gateway has +two HTTPRoutes associated with it, one with the host `www.example.com` and the path `/myapp`, and the other with the host +`www.example.com` and the path `/`. Either one of the HTTPRoutes can be used to match the `redirectURL` and `logoutPath`. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +Verify the SecurityPolicy configuration: + +```shell +kubectl get securitypolicy/oidc-example -o yaml +``` + +### Testing + +If you haven't done so, follow the steps in the previous section to port forward gateway port to localhost and put +www.example.com in the /etc/hosts file in your test machine. + +Open a browser and navigate to the `https://www.example.com:8443/foo` address. You should be redirected to the Google +login page. After you successfully login, you should see the response from the backend service. + +You can also try to access `https://www.example.com:8443/myapp` address. You should be able to see this page since the +path `/myapp` is protected by the same OIDC policy. + ## Clean-Up -Follow the steps from the [Quickstart](../../quickstart) guide to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the SecurityPolicy, the secret and the HTTPRoute: @@ -155,10 +313,10 @@ kubectl delete httproute/myapp ## Next Steps -Checkout the [Developer Guide](../../../contributions/develop) to get involved in the project. +Checkout the [Developer Guide](../../../../contributions/develop) to get involved in the project. [oidc]: https://openid.net/connect/ [google-oidc]: https://developers.google.com/identity/protocols/oauth2/openid-connect -[SecurityPolicy]: ../../../contributions/design/security-policy +[SecurityPolicy]: ../../../../contributions/design/security-policy [Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway [HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute diff --git a/site/content/en/v1.0.1/tasks/security/secure-gateways.md b/site/content/en/v1.0.1/tasks/security/secure-gateways.md index e56a496e022..52bf8c9cb78 100644 --- a/site/content/en/v1.0.1/tasks/security/secure-gateways.md +++ b/site/content/en/v1.0.1/tasks/security/secure-gateways.md @@ -236,7 +236,7 @@ Lastly, test connectivity using the above [Testing section](#testing). ## Clean-Up -Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the Secrets: @@ -362,7 +362,7 @@ This sections gives a walkthrough to generate multiple certificates correspondin ## Prerequisites -Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. Follow the steps in the [TLS Certificates](#tls-certificates) section to generate self-signed RSA derived Server certificate and private key, and configure those in the Gateway listener configuration to terminate HTTPS traffic. diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 64968c9e009..2cefef85e3e 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -810,7 +810,6 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { { desc: "valid count of Global rate limit rules items", mutate: func(btp *egv1a1.BackendTrafficPolicy) { - rules := make([]egv1a1.RateLimitRule, 64) rule := egv1a1.RateLimitRule{ Limit: egv1a1.RateLimitValue{ @@ -843,7 +842,6 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { { desc: "invalid count of Global rate limit rules items", mutate: func(btp *egv1a1.BackendTrafficPolicy) { - rules := make([]egv1a1.RateLimitRule, 65) rule := egv1a1.RateLimitRule{ Limit: egv1a1.RateLimitValue{ diff --git a/test/cel-validation/clienttrafficpolicy_test.go b/test/cel-validation/clienttrafficpolicy_test.go index 554d6240d8e..2b132ea969e 100644 --- a/test/cel-validation/clienttrafficpolicy_test.go +++ b/test/cel-validation/clienttrafficpolicy_test.go @@ -16,7 +16,6 @@ import ( "time" "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" @@ -150,9 +149,11 @@ func TestClientTrafficPolicyTarget(t *testing.T) { Name: gwapiv1a2.ObjectName("eg"), }, }, - TLS: &egv1a1.TLSSettings{ - MinVersion: ptr.To(egv1a1.TLSv12), - MaxVersion: ptr.To(egv1a1.TLSv11), + TLS: &egv1a1.ClientTLSSettings{ + TLSSettings: egv1a1.TLSSettings{ + MinVersion: ptr.To(egv1a1.TLSv12), + MaxVersion: ptr.To(egv1a1.TLSv11), + }, }, } }, @@ -171,8 +172,10 @@ func TestClientTrafficPolicyTarget(t *testing.T) { Name: gwapiv1a2.ObjectName("eg"), }, }, - TLS: &egv1a1.TLSSettings{ - MaxVersion: ptr.To(egv1a1.TLSv11), + TLS: &egv1a1.ClientTLSSettings{ + TLSSettings: egv1a1.TLSSettings{ + MaxVersion: ptr.To(egv1a1.TLSv11), + }, }, } }, @@ -217,8 +220,10 @@ func TestClientTrafficPolicyTarget(t *testing.T) { }, }, HTTP3: &egv1a1.HTTP3Settings{}, - TLS: &egv1a1.TLSSettings{ - Ciphers: []string{"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]"}, + TLS: &egv1a1.ClientTLSSettings{ + TLSSettings: egv1a1.TLSSettings{ + Ciphers: []string{"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]"}, + }, }, } }, @@ -235,9 +240,11 @@ func TestClientTrafficPolicyTarget(t *testing.T) { Name: gwapiv1a2.ObjectName("eg"), }, }, - TLS: &egv1a1.TLSSettings{ - MinVersion: ptr.To(egv1a1.TLSv13), - Ciphers: []string{"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]"}, + TLS: &egv1a1.ClientTLSSettings{ + TLSSettings: egv1a1.TLSSettings{ + MinVersion: ptr.To(egv1a1.TLSv13), + Ciphers: []string{"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]"}, + }, }, } }, diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go index 67200306a34..efad71d74f8 100644 --- a/test/cel-validation/envoyextensionpolicy_test.go +++ b/test/cel-validation/envoyextensionpolicy_test.go @@ -162,10 +162,12 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRef: egv1a1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -187,11 +189,13 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRef: egv1a1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Group: ptr.To(gwapiv1.Group("unsupported")), - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Group: ptr.To(gwapiv1.Group("unsupported")), + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -205,7 +209,7 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{"spec.extProc[0]: Invalid value: \"object\": group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported"}, + wantErrors: []string{" spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Core group."}, }, { desc: "ExtProc with invalid BackendRef Kind", @@ -213,11 +217,13 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRef: egv1a1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Kind: ptr.To(gwapiv1.Kind("unsupported")), - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Kind: ptr.To(gwapiv1.Kind("unsupported")), + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -231,7 +237,7 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{"spec.extProc[0]: Invalid value: \"object\": kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported"}, + wantErrors: []string{"spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Service kind."}, }, { desc: "ExtProc with invalid fields", @@ -239,10 +245,12 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRef: egv1a1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, ProcessingMode: &egv1a1.ExtProcProcessingMode{ diff --git a/test/conformance/conformance_test.go b/test/conformance/conformance_test.go index 149909e2ce4..7eca6ea9d26 100644 --- a/test/conformance/conformance_test.go +++ b/test/conformance/conformance_test.go @@ -54,5 +54,4 @@ func TestGatewayAPIConformance(t *testing.T) { }) cSuite.Setup(t) cSuite.Run(t, tests.ConformanceTests) - } diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index b6d6b19e953..fa3598be1e0 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -129,7 +129,7 @@ func experimentalConformanceReport(logf func(string, ...any), report confv1a1.Co } if output != "" { - if err = os.WriteFile(output, rawReport, 0600); err != nil { + if err = os.WriteFile(output, rawReport, 0o600); err != nil { return err } } diff --git a/test/e2e/base/manifests.yaml b/test/e2e/base/manifests.yaml index 1f456581e47..92a1c6e0a9d 100644 --- a/test/e2e/base/manifests.yaml +++ b/test/e2e/base/manifests.yaml @@ -94,7 +94,12 @@ spec: ports: - protocol: TCP port: 8080 + name: http11 targetPort: 3000 + - protocol: TCP + port: 8081 + name: http2 + targetPort: 3001 --- apiVersion: apps/v1 kind: Deployment diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 46e0fb30bec..3159f0bd2a4 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -51,6 +51,9 @@ func TestE2E(t *testing.T) { CleanupBaseResources: *flags.CleanupBaseResources, FS: &Manifests, RunTest: *flags.RunTest, + SkipTests: []string{ + tests.ClientTimeoutTest.ShortName, // https://github.com/envoyproxy/gateway/issues/2720 + }, }) cSuite.Setup(t) diff --git a/test/e2e/merge_gateways/merge_gateways_test.go b/test/e2e/merge_gateways/merge_gateways_test.go index 30e82aa6cdd..9c056875c32 100644 --- a/test/e2e/merge_gateways/merge_gateways_test.go +++ b/test/e2e/merge_gateways/merge_gateways_test.go @@ -52,14 +52,16 @@ func TestMergeGateways(t *testing.T) { Debug: *flags.ShowDebug, CleanupBaseResources: *flags.CleanupBaseResources, RunTest: *flags.RunTest, + SkipTests: []string{ + tests.MergeGatewaysTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3290 + }, }) // Setting up the necessary arguments for the suite instead of calling Suite.Setup method again, // since this test suite reuse the base resources of previous test suite. cSuite.Applier.FS = e2e.Manifests cSuite.Applier.GatewayClass = *flags.GatewayClassName - cSuite.ControllerName = kubernetes.GWCMustHaveAcceptedConditionTrue(t, - cSuite.Client, cSuite.TimeoutConfig, cSuite.GatewayClassName) + cSuite.ControllerName = kubernetes.GWCMustHaveAcceptedConditionTrue(t, cSuite.Client, cSuite.TimeoutConfig, cSuite.GatewayClassName) t.Logf("Running %d MergeGateways tests", len(tests.MergeGatewaysTests)) cSuite.Run(t, tests.MergeGatewaysTests) diff --git a/test/e2e/testdata/connection-limit.yaml b/test/e2e/testdata/connection-limit.yaml index 998a26191fd..3edb268aad8 100644 --- a/test/e2e/testdata/connection-limit.yaml +++ b/test/e2e/testdata/connection-limit.yaml @@ -11,7 +11,7 @@ spec: namespace: gateway-conformance-infra connection: connectionLimit: - value: 5 + value: 3 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute diff --git a/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml b/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml index 5119ac22c1f..e88657fee1b 100644 --- a/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml +++ b/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml @@ -20,7 +20,7 @@ spec: apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: - name: http-without-ext-proc + name: http-without-procmode namespace: gateway-conformance-infra spec: parentRefs: @@ -46,8 +46,27 @@ spec: kind: HTTPRoute name: http-with-ext-proc extProc: - - backendRef: - name: grpc-ext-proc + - backendRefs: + - name: grpc-ext-proc + namespace: gateway-conformance-infra + port: 9002 + processingMode: + request: {} + response: {} +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyExtensionPolicy +metadata: + name: ext-proc-no-procmode-test + namespace: gateway-conformance-infra +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: http-without-procmode + extProc: + - backendRefs: + - name: grpc-ext-proc namespace: gateway-conformance-infra port: 9002 --- diff --git a/test/e2e/testdata/ext-proc-service.yaml b/test/e2e/testdata/ext-proc-service.yaml index 594cf14edef..665779e96e4 100644 --- a/test/e2e/testdata/ext-proc-service.yaml +++ b/test/e2e/testdata/ext-proc-service.yaml @@ -8,74 +8,73 @@ data: go.mod: | module github.com/envoyproxy/gateway - go 1.21 + go 1.22 require ( - github.com/envoyproxy/go-control-plane v0.12.0 + github.com/envoyproxy/go-control-plane v0.12.1-0.20240322155512-db0b36a50fa8 google.golang.org/grpc v1.62.1 ) require ( - github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect - github.com/golang/protobuf v1.5.3 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/protobuf v1.32.0 // indirect + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/planetscale/vtprotobuf v0.5.1-0.20231212170721-e7d721933795 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/protobuf v1.33.0 // indirect ) go.sum: | github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= - github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= - github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= + github.com/envoyproxy/go-control-plane v0.12.1-0.20240322155512-db0b36a50fa8 h1:Zghtu+wdlGvrmutCyhU9Ew5ozU18PVpxP+zGSgyUpFs= + github.com/envoyproxy/go-control-plane v0.12.1-0.20240322155512-db0b36a50fa8/go.mod h1:YtsM9q/kVkKyvmemY+BF/ZK7I93OWsx4uk4Do2Mr/OA= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= - github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= - github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= - github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= - github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= + github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= + github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= + github.com/planetscale/vtprotobuf v0.5.1-0.20231212170721-e7d721933795 h1:pH+U6pJP0BhxqQ4njBUjOg0++WMMvv3eByWzB+oATBY= + github.com/planetscale/vtprotobuf v0.5.1-0.20231212170721-e7d721933795/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= - 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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= - google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= + google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= + google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= main.go: | package main import ( - "context" - "crypto/tls" - "crypto/x509" - "flag" - "fmt" - "google.golang.org/grpc/credentials" - "io" - "log" - "net" - "net/http" - "os" - "strings" - - envoy_api_v3_core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_service_proc_v3 "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" - - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "context" + "crypto/tls" + "crypto/x509" + "flag" + "fmt" + "io" + "log" + "net" + "net/http" + "os" + "strings" + + "google.golang.org/grpc/credentials" + + envoy_api_v3_core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + envoy_service_proc_v3 "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type extProcServer struct{} @@ -103,7 +102,6 @@ data: envoy_service_proc_v3.RegisterExternalProcessorServer(gs, &extProcServer{}) - go func() { err = gs.Serve(lis) if err != nil { @@ -227,13 +225,23 @@ data: resp := &envoy_service_proc_v3.ProcessingResponse{} switch v := req.Request.(type) { case *envoy_service_proc_v3.ProcessingRequest_RequestHeaders: + xrch := "" + if v.RequestHeaders != nil { + hdrs := v.RequestHeaders.Headers.GetHeaders() + for _, hdr := range hdrs { + if hdr.Key == "x-request-client-header" { + xrch = string(hdr.RawValue) + } + } + } + rhq := &envoy_service_proc_v3.HeadersResponse{ Response: &envoy_service_proc_v3.CommonResponse{ HeaderMutation: &envoy_service_proc_v3.HeaderMutation{ SetHeaders: []*envoy_api_v3_core.HeaderValueOption{ { Header: &envoy_api_v3_core.HeaderValue{ - Key: "x-request-ext-processed", + Key: "x-request-ext-processed", RawValue: []byte("true"), }, }, @@ -242,6 +250,23 @@ data: }, } + if xrch != "" { + rhq.Response.HeaderMutation.SetHeaders = append(rhq.Response.HeaderMutation.SetHeaders, + &envoy_api_v3_core.HeaderValueOption{ + Header: &envoy_api_v3_core.HeaderValue{ + Key: "x-request-client-header", + RawValue: []byte("mutated"), + }, + }) + rhq.Response.HeaderMutation.SetHeaders = append(rhq.Response.HeaderMutation.SetHeaders, + &envoy_api_v3_core.HeaderValueOption{ + Header: &envoy_api_v3_core.HeaderValue{ + Key: "x-request-client-header-received", + RawValue: []byte(xrch), + }, + }) + } + resp = &envoy_service_proc_v3.ProcessingResponse{ Response: &envoy_service_proc_v3.ProcessingResponse_RequestHeaders{ RequestHeaders: rhq, @@ -255,7 +280,7 @@ data: SetHeaders: []*envoy_api_v3_core.HeaderValueOption{ { Header: &envoy_api_v3_core.HeaderValue{ - Key: "x-response-ext-processed", + Key: "x-response-ext-processed", RawValue: []byte("true"), }, }, @@ -352,7 +377,7 @@ spec: - sh - "-c" - "cp -a /app /app-live && cd /app-live && go run . --certPath=/app-live/certs/ " - image: golang:1.21.3-alpine + image: golang:1.22.1-alpine ports: - containerPort: 8000 volumeMounts: diff --git a/test/e2e/testdata/use-client-protocol.yaml b/test/e2e/testdata/use-client-protocol.yaml new file mode 100644 index 00000000000..c624da1bc17 --- /dev/null +++ b/test/e2e/testdata/use-client-protocol.yaml @@ -0,0 +1,36 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: use-client-protocol-btp + namespace: gateway-conformance-infra +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: use-client-protocol + namespace: gateway-conformance-infra + useClientProtocol: true +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: use-client-protocol + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /http11 + backendRefs: + - name: infra-backend-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /http2 + backendRefs: + - name: infra-backend-v1 + port: 8081 diff --git a/test/e2e/tests/backend_tls.go b/test/e2e/tests/backend_tls.go index 1c556a0bb78..dea222b477f 100644 --- a/test/e2e/tests/backend_tls.go +++ b/test/e2e/tests/backend_tls.go @@ -63,6 +63,5 @@ var BackendTLSTest = suite.ConformanceTest{ http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) }) - }, } diff --git a/test/e2e/tests/client_timeout.go b/test/e2e/tests/client_timeout.go index c3edf9cf1cc..5ae5f00d106 100644 --- a/test/e2e/tests/client_timeout.go +++ b/test/e2e/tests/client_timeout.go @@ -22,9 +22,7 @@ import ( ) func init() { - // This test cause too much flakiness, so we disable it for now. - // TODO: find a better way to test client timeout. - // ConformanceTests = append(ConformanceTests, ClientTimeoutTest) + ConformanceTests = append(ConformanceTests, ClientTimeoutTest) } var largeSizeHeader = func() string { @@ -35,7 +33,6 @@ var largeSizeHeader = func() string { return b.String() } -// nolint var ClientTimeoutTest = suite.ConformanceTest{ ShortName: "ClientTimeout", Description: "Test that the ClientTrafficPolicy API implementation supports client timeout", diff --git a/test/e2e/tests/connection_limit.go b/test/e2e/tests/connection_limit.go index 220be1a5616..952a6086da6 100644 --- a/test/e2e/tests/connection_limit.go +++ b/test/e2e/tests/connection_limit.go @@ -9,21 +9,21 @@ package tests import ( - "errors" + "fmt" "net" - "net/url" "testing" "time" - "github.com/envoyproxy/gateway/internal/gatewayapi" - + "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/types" - gwv1 "sigs.k8s.io/gateway-api/apis/v1" gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" + + "github.com/envoyproxy/gateway/internal/gatewayapi" + "github.com/envoyproxy/gateway/test/e2e/utils/prometheus" ) func init() { @@ -49,40 +49,50 @@ var ConnectionLimitTest = suite.ConformanceTest{ } ClientTrafficPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "connection-limit-ctp", Namespace: ns}, suite.ControllerName, ancestorRef) - // open some connections - for i := 0; i < 10; i++ { - conn, err := net.DialTimeout("tcp", gwAddr, 100*time.Millisecond) - if err == nil { - defer conn.Close() - } else { + promAddr, err := prometheus.Address(suite.Client, + types.NamespacedName{Name: "prometheus", Namespace: "monitoring"}, + ) + require.NoError(t, err) + + // we make the number of connections equal to the number of connectionLimit connections + 3 + // avoid partial connection errors or interruptions + for i := 0; i < 6; i++ { + conn, err := net.Dial("tcp", gwAddr) + if err != nil { t.Errorf("failed to open connection: %v", err) + } else { + defer conn.Close() } } - // make a request, expect a failure - expectedResponse := http.ExpectedResponse{ - Request: http.Request{ - Path: "/", - }, - Response: http.Response{ - StatusCode: 200, - }, - Namespace: ns, - } + prefix := "http" + gtwName := "connection-limit-gateway" + promQL := fmt.Sprintf(`envoy_connection_limit_limited_connections{envoy_connection_limit_prefix="%s",gateway_envoyproxy_io_owning_gateway_name="%s"}`, prefix, gtwName) - req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") - _, _, err := suite.RoundTripper.CaptureRoundTrip(req) + http.AwaitConvergence( + t, + suite.TimeoutConfig.RequiredConsecutiveSuccesses, + suite.TimeoutConfig.MaxTimeToConsistency, + func(_ time.Duration) bool { + // check connection_limit stats from Prometheus + v, err := prometheus.QuerySum(promAddr, promQL) + if err != nil { + // wait until Prometheus sync stats + return false + } + t.Logf("connection_limit stats query count: %v", v) - // expect error - if err != nil { - urlError := &url.Error{} - if !errors.As(err, &urlError) { - t.Errorf("expected net/url error when connection limit is reached") - } - } else { - t.Errorf("expected error when connection limit is reached") - } + // connection interruptions or other connection errors may occur + // we just need to determine whether there is a connection limit stats + if v == 0 { + t.Error("connection is not limited as expected") + } else { + t.Log("connection is limited as expected") + } + return true + }, + ) }) }, } diff --git a/test/e2e/tests/ext_proc.go b/test/e2e/tests/ext_proc.go index aa9978e92ea..eb069380b7b 100644 --- a/test/e2e/tests/ext_proc.go +++ b/test/e2e/tests/ext_proc.go @@ -26,10 +26,10 @@ func init() { ConformanceTests = append(ConformanceTests, ExtProcTest) } -// ExtProcTest tests ExtProcs authentication for an http route with ExtProcs configured. +// ExtProcTest tests ExtProc authentication for an http route with ExtProc configured. var ExtProcTest = suite.ConformanceTest{ - ShortName: "ExtProcs", - Description: "Test ExtProcs service that adds request and response headers", + ShortName: "ExtProc", + Description: "Test ExtProc service that adds request and response headers", Manifests: []string{"testdata/ext-proc-service.yaml", "testdata/ext-proc-envoyextensionpolicy.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { t.Run("http route with ext proc", func(t *testing.T) { @@ -56,19 +56,25 @@ var ExtProcTest = suite.ConformanceTest{ Host: "www.example.com", Path: "/processor", Headers: map[string]string{ - "x-request-ext-processed": "true", // header added by ext-processor to request + "x-request-ext-processed": "true", // header added by ext-processor to backend-bound request + "x-request-client-header-received": "original", // this is the original client header preserved by ext-proc in a new header + "x-request-client-header": "mutated", // this is the mutated value expected to reach upstream }, }, Response: http.Response{ StatusCode: 200, Headers: map[string]string{ - "x-response-ext-processed": "true", // header added by ext-processor to request + "x-response-ext-processed": "true", // header added by ext-processor to client-bound response }, }, Namespace: ns, } req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + + // add a request header that will be mutated by ext-proc + req.Headers["x-request-client-header"] = []string{"original"} + cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req) if err != nil { t.Errorf("failed to get expected response: %v", err) @@ -79,9 +85,9 @@ var ExtProcTest = suite.ConformanceTest{ } }) - t.Run("http route without ext proc", func(t *testing.T) { + t.Run("http route without proc mode", func(t *testing.T) { ns := "gateway-conformance-infra" - routeNN := types.NamespacedName{Name: "http-with-ext-proc", Namespace: ns} + routeNN := types.NamespacedName{Name: "http-without-procmode", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) @@ -91,7 +97,7 @@ var ExtProcTest = suite.ConformanceTest{ Namespace: gatewayapi.NamespacePtr(gwNN.Namespace), Name: gwv1.ObjectName(gwNN.Name), } - EnvoyExtensionPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "ext-proc-test", Namespace: ns}, suite.ControllerName, ancestorRef) + EnvoyExtensionPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "ext-proc-no-procmode-test", Namespace: ns}, suite.ControllerName, ancestorRef) podReady := corev1.PodCondition{Type: corev1.PodReady, Status: corev1.ConditionTrue} @@ -102,6 +108,9 @@ var ExtProcTest = suite.ConformanceTest{ Request: http.Request{ Host: "www.example.com", Path: "/no-processor", + Headers: map[string]string{ + "x-request-client-header": "original", + }, }, Response: http.Response{ StatusCode: 200, @@ -111,6 +120,10 @@ var ExtProcTest = suite.ConformanceTest{ } req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + + // add a request header that will be mutated by ext-proc if the request headers are sent + req.Headers["x-request-client-header"] = []string{"original"} + cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req) if err != nil { t.Errorf("failed to get expected response: %v", err) diff --git a/test/e2e/tests/gateway_infra_resource.go b/test/e2e/tests/gateway_infra_resource.go index 864cc4b1b11..c14cb145050 100644 --- a/test/e2e/tests/gateway_infra_resource.go +++ b/test/e2e/tests/gateway_infra_resource.go @@ -25,7 +25,7 @@ import ( func init() { // nolint - //ConformanceTests = append(ConformanceTests, GatewayInfraResourceTest) + // ConformanceTests = append(ConformanceTests, GatewayInfraResourceTest) } // nolint diff --git a/test/e2e/tests/jwt.go b/test/e2e/tests/jwt.go index 73de072e62a..fc7e826dd46 100644 --- a/test/e2e/tests/jwt.go +++ b/test/e2e/tests/jwt.go @@ -170,6 +170,5 @@ var OptionalJWTTest = suite.ConformanceTest{ http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } - }, } diff --git a/test/e2e/tests/merge_gateways.go b/test/e2e/tests/merge_gateways.go index 9b725cb40f2..abcd809f70d 100644 --- a/test/e2e/tests/merge_gateways.go +++ b/test/e2e/tests/merge_gateways.go @@ -146,6 +146,5 @@ var MergeGatewaysTest = suite.ConformanceTest{ Namespace: ns, }) }) - }, } diff --git a/test/e2e/tests/preservecase.go b/test/e2e/tests/preservecase.go index 59d54c2f84e..458bebd8219 100644 --- a/test/e2e/tests/preservecase.go +++ b/test/e2e/tests/preservecase.go @@ -135,6 +135,5 @@ var PreserveCaseTest = suite.ConformanceTest{ t.Errorf("case was not preserved for test header: %+v", respBody) } }) - }, } diff --git a/test/e2e/tests/ratelimit.go b/test/e2e/tests/ratelimit.go index c02802abe1f..0115dbe0089 100644 --- a/test/e2e/tests/ratelimit.go +++ b/test/e2e/tests/ratelimit.go @@ -284,7 +284,6 @@ var RateLimitBasedJwtClaimsTest = suite.ConformanceTest{ if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, noTokenReq, noTokenResp); err != nil { t.Errorf("failed to get expected response: %v", err) } - }) }, } diff --git a/test/e2e/tests/redirect_replaceprefixmatch_slash.go b/test/e2e/tests/redirect_replaceprefixmatch_slash.go index 3dcc4e90873..c1986809000 100644 --- a/test/e2e/tests/redirect_replaceprefixmatch_slash.go +++ b/test/e2e/tests/redirect_replaceprefixmatch_slash.go @@ -19,7 +19,6 @@ import ( func init() { ConformanceTests = append(ConformanceTests, RedirectTrailingSlashTest) - } // RedirectTrailingSlashTest tests that only one slash in the redirect URL diff --git a/test/e2e/tests/retry.go b/test/e2e/tests/retry.go index c2acfecf34c..c067df3752d 100644 --- a/test/e2e/tests/retry.go +++ b/test/e2e/tests/retry.go @@ -24,7 +24,6 @@ import ( func init() { ConformanceTests = append(ConformanceTests, RetryTest) - } var RetryTest = suite.ConformanceTest{ diff --git a/test/e2e/tests/tcp_route.go b/test/e2e/tests/tcp_route.go index 0aa8b609e79..f09521db010 100644 --- a/test/e2e/tests/tcp_route.go +++ b/test/e2e/tests/tcp_route.go @@ -77,7 +77,6 @@ var TCPRouteTest = suite.ConformanceTest{ // Send a request to an valid path and expect a successful response http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, OkResp) }) - }, } @@ -124,7 +123,6 @@ func GatewayAndTCPRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutCon } return gwAddr - } // WaitForGatewayAddress waits until at least one IP Address has been set in the diff --git a/test/e2e/tests/tracing.go b/test/e2e/tests/tracing.go index 880b166b4f8..9ded2662cf9 100644 --- a/test/e2e/tests/tracing.go +++ b/test/e2e/tests/tracing.go @@ -119,7 +119,6 @@ func QueryTraceFromTempo(t *testing.T, c client.Client, tags map[string]string) req, err := http.NewRequest("GET", tempoURL.String(), nil) if err != nil { - return -1, err } diff --git a/test/e2e/tests/use_client_protocol.go b/test/e2e/tests/use_client_protocol.go new file mode 100644 index 00000000000..1ea6029bf4f --- /dev/null +++ b/test/e2e/tests/use_client_protocol.go @@ -0,0 +1,129 @@ +// 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. + +//go:build e2e +// +build e2e + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, UseClientProtocolTest) +} + +var UseClientProtocolTest = suite.ConformanceTest{ + ShortName: "UseClientProtocol", + Description: "Test that the UseClientProtocol knob does what it's supposed to", + Manifests: []string{"testdata/use-client-protocol.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("use client protocol", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "use-client-protocol", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + // Send an http/1.1 request to the /http11 path + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/http11/headers", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + if cReq.Protocol != "HTTP/1.1" { + t.Errorf("expected http/1.1 protocol, got %s", cReq.Protocol) + } + + // Send an http/1.1 request to the http/2 path + expectedResponse = http.ExpectedResponse{ + Request: http.Request{ + Path: "/http2/headers", + }, + Response: http.Response{ + StatusCode: 400, + }, + Namespace: ns, + } + + req = http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err = suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + + // Send an http/2 request to the /http2 path + expectedResponse = http.ExpectedResponse{ + Request: http.Request{ + Path: "/http2/headers", + Protocol: roundtripper.H2CPriorKnowledgeProtocol, + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + req = http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err = suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + if cReq.Protocol != "HTTP/2.0" { + t.Errorf("expected http/2.0 protocol, got %s", cReq.Protocol) + } + + // Send an http/2 request to the http/1.1 path + expectedResponse = http.ExpectedResponse{ + Request: http.Request{ + Path: "/http11/headers", + Protocol: roundtripper.H2CPriorKnowledgeProtocol, + }, + Response: http.Response{ + StatusCode: 502, + }, + Namespace: ns, + } + + req = http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err = suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + }) + }, +} diff --git a/test/e2e/tests/weighted_backend.go b/test/e2e/tests/weighted_backend.go index b31dce8f04f..250c6ef4cc3 100644 --- a/test/e2e/tests/weighted_backend.go +++ b/test/e2e/tests/weighted_backend.go @@ -70,7 +70,6 @@ var WeightEqualTest = suite.ConformanceTest{ if len(podName) == 0 { // it shouldn't be missing here t.Errorf("failed to get pod header in response: %v", err) - } else { // all we need is the pod Name prefix podNamePrefix := ExtractPodNamePrefix(podName) @@ -135,7 +134,6 @@ var WeightBlueGreenTest = suite.ConformanceTest{ if len(podName) == 0 { // it shouldn't be missing here t.Errorf("failed to get pod header in response: %v", err) - } else { // all we need is the pod Name prefix podNamePrefix := ExtractPodNamePrefix(podName) @@ -200,7 +198,6 @@ var WeightCompleteRolloutTest = suite.ConformanceTest{ if len(podName) == 0 { // it shouldn't be missing here t.Errorf("failed to get pod header in response: %v", err) - } else { // all we need is the pod Name prefix podNamePrefix := ExtractPodNamePrefix(podName) @@ -222,7 +219,6 @@ var WeightCompleteRolloutTest = suite.ConformanceTest{ // ExtractPodNamePrefix Extract the Pod Name prefix func ExtractPodNamePrefix(podName string) string { - pattern := regexp.MustCompile(`infra-backend-(.+?)-`) match := pattern.FindStringSubmatch(podName) if len(match) > 1 { diff --git a/test/e2e/upgrade/eg_upgrade_test.go b/test/e2e/upgrade/eg_upgrade_test.go index a1be622cb0f..999a85ccc53 100644 --- a/test/e2e/upgrade/eg_upgrade_test.go +++ b/test/e2e/upgrade/eg_upgrade_test.go @@ -52,6 +52,10 @@ func TestEGUpgrade(t *testing.T) { CleanupBaseResources: *flags.CleanupBaseResources, FS: &e2e.Manifests, RunTest: *flags.RunTest, + SkipTests: []string{ + tests.EnvoyShutdownTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3262 + tests.EGUpgradeTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3311 + }, }) cSuite.Setup(t) diff --git a/test/helm/default.yaml b/test/helm/default.yaml index 2feb28c1373..5bebac04aad 100644 --- a/test/helm/default.yaml +++ b/test/helm/default.yaml @@ -369,7 +369,7 @@ spec: - name: KUBERNETES_CLUSTER_DOMAIN value: cluster.local image: docker.io/envoyproxy/gateway-dev:latest - imagePullPolicy: Always + imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthz @@ -517,7 +517,7 @@ spec: - name: KUBERNETES_CLUSTER_DOMAIN value: cluster.local image: docker.io/envoyproxy/gateway-dev:latest - imagePullPolicy: Always + imagePullPolicy: IfNotPresent name: envoy-gateway-certgen restartPolicy: Never securityContext: diff --git a/tools/docker/envoy-gateway/Dockerfile b/tools/docker/envoy-gateway/Dockerfile index 9109a33e7ea..074320308eb 100644 --- a/tools/docker/envoy-gateway/Dockerfile +++ b/tools/docker/envoy-gateway/Dockerfile @@ -1,6 +1,6 @@ # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot@sha256:f41b84cda410b05cc690c2e33d1973a31c6165a2721e2b5343aab50fecb63441 +FROM gcr.io/distroless/static:nonroot@sha256:e9ac71e2b8e279a8372741b7a0293afda17650d926900233ec3a7b2b7c22a246 ARG TARGETPLATFORM COPY $TARGETPLATFORM/envoy-gateway /usr/local/bin/ diff --git a/tools/linter/golangci-lint/.golangci.yml b/tools/linter/golangci-lint/.golangci.yml index 36ed0cb1ff2..267fbc46c9a 100644 --- a/tools/linter/golangci-lint/.golangci.yml +++ b/tools/linter/golangci-lint/.golangci.yml @@ -8,6 +8,7 @@ linters: - errorlint - exportloopref - gofmt + - gofumpt - goimports - goheader - gocritic diff --git a/tools/make/common.mk b/tools/make/common.mk index 7c5ffa85cda..84865267e6c 100644 --- a/tools/make/common.mk +++ b/tools/make/common.mk @@ -26,7 +26,7 @@ RELEASE_VERSION=$(shell cat VERSION) # Set Root Directory Path ifeq ($(origin ROOT_DIR),undefined) -ROOT_DIR := $(abspath $(shell pwd -P)) +ROOT_DIR := $(abspath $(shell pwd -P)) endif # Set Output Directory Path @@ -119,7 +119,7 @@ export USAGE_OPTIONS .PHONY: generate generate: ## Generate go code from templates and tags -generate: kube-generate helm-generate helm-template go.generate docs-api +generate: kube-generate docs-api helm-generate helm-template go.generate ## help: Show this help info. .PHONY: help diff --git a/tools/make/docs.mk b/tools/make/docs.mk index d280c2c1410..4cec8e458bd 100644 --- a/tools/make/docs.mk +++ b/tools/make/docs.mk @@ -37,7 +37,8 @@ docs-api: docs-api-gen helm-readme-gen docs-api-headings .PHONY: helm-readme-gen helm-readme-gen: $(tools/helm-docs) @$(LOG_TARGET) - $(tools/helm-docs) charts/gateway-helm/ -f values.tmpl.yaml -o api.md + @ImageRepository=docker.io/envoyproxy/gateway ImageTag=latest ImagePullPolicy=IfNotPresent envsubst < charts/gateway-helm/values.tmpl.yaml > ./charts/gateway-helm/values.yaml # use production ENV to generate helm api doc + $(tools/helm-docs) charts/gateway-helm/ -f values.yaml -o api.md mv charts/gateway-helm/api.md site/content/en/latest/install/api.md .PHONY: docs-api-gen diff --git a/tools/make/helm.mk b/tools/make/helm.mk index 6687e0fccc3..5ca7d1c8612 100644 --- a/tools/make/helm.mk +++ b/tools/make/helm.mk @@ -4,6 +4,7 @@ include tools/make/env.mk +IMAGE_PULL_POLICY ?= IfNotPresent OCI_REGISTRY ?= oci://docker.io/envoyproxy CHART_NAME ?= gateway-helm CHART_VERSION ?= ${RELEASE_VERSION} @@ -25,8 +26,9 @@ helm-install: helm-generate ## Install envoy gateway helm chart from OCI registr @$(LOG_TARGET) helm install eg ${OCI_REGISTRY}/${CHART_NAME} --version ${CHART_VERSION} -n envoy-gateway-system --create-namespace +.PHONY: helm-generate helm-generate: - ImageRepository=${IMAGE} ImageTag=${TAG} envsubst < charts/gateway-helm/values.tmpl.yaml > ./charts/gateway-helm/values.yaml + ImageRepository=${IMAGE} ImageTag=${TAG} ImagePullPolicy=${IMAGE_PULL_POLICY} envsubst < charts/gateway-helm/values.tmpl.yaml > ./charts/gateway-helm/values.yaml helm lint charts/gateway-helm helm-template: ## Template envoy gateway helm chart. diff --git a/tools/make/kube.mk b/tools/make/kube.mk index 8d8c96a76d2..eec42ea2395 100644 --- a/tools/make/kube.mk +++ b/tools/make/kube.mk @@ -62,8 +62,6 @@ ifndef ignore-not-found ignore-not-found = true endif -IMAGE_PULL_POLICY ?= Always - .PHONY: kube-deploy kube-deploy: manifests helm-generate ## Install Envoy Gateway into the Kubernetes cluster specified in ~/.kube/config. @$(LOG_TARGET) @@ -225,7 +223,7 @@ generate-manifests: helm-generate ## Generate Kubernetes release manifests. @$(LOG_TARGET) @$(call log, "Generating kubernetes manifests") mkdir -p $(OUTPUT_DIR)/ - helm template --set createNamespace=true eg charts/gateway-helm --include-crds --set deployment.envoyGateway.imagePullPolicy=$(IMAGE_PULL_POLICY) --namespace envoy-gateway-system > $(OUTPUT_DIR)/install.yaml + helm template --set createNamespace=true eg charts/gateway-helm --include-crds --namespace envoy-gateway-system > $(OUTPUT_DIR)/install.yaml @$(call log, "Added: $(OUTPUT_DIR)/install.yaml") cp examples/kubernetes/quickstart.yaml $(OUTPUT_DIR)/quickstart.yaml @$(call log, "Added: $(OUTPUT_DIR)/quickstart.yaml") diff --git a/tools/src/protoc-gen-go-grpc/go.mod b/tools/src/protoc-gen-go-grpc/go.mod index 77ab0f34488..df13e99fa8f 100644 --- a/tools/src/protoc-gen-go-grpc/go.mod +++ b/tools/src/protoc-gen-go-grpc/go.mod @@ -4,4 +4,4 @@ go 1.22.2 require google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 -require google.golang.org/protobuf v1.28.1 // indirect +require google.golang.org/protobuf v1.33.0 // indirect diff --git a/tools/src/protoc-gen-go-grpc/go.sum b/tools/src/protoc-gen-go-grpc/go.sum index 8d750cf2b44..310db1131fb 100644 --- a/tools/src/protoc-gen-go-grpc/go.sum +++ b/tools/src/protoc-gen-go-grpc/go.sum @@ -1,10 +1,8 @@ -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/tools/src/sphinx-build/requirements.txt b/tools/src/sphinx-build/requirements.txt index 9434d0ace8d..16fc53701bf 100644 --- a/tools/src/sphinx-build/requirements.txt +++ b/tools/src/sphinx-build/requirements.txt @@ -1,2 +1,2 @@ Sphinx==7.3.7 -myst-parser==2.0.0 +myst-parser==3.0.1