From 608ddd38dede76e81be34791b945ba6cca7bd2fe Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Wed, 25 Oct 2023 20:20:02 -0700 Subject: [PATCH 01/55] more tests in experimental conformance profile report (#2056) Signed-off-by: Arko Dasgupta --- test/conformance/experimental_conformance_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index 5415f150ca7..2abc238823d 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -95,6 +95,7 @@ func experimentalConformance(t *testing.T) { GatewayClassName: *flags.GatewayClassName, Debug: *flags.ShowDebug, CleanupBaseResources: *flags.CleanupBaseResources, + SupportedFeatures: suite.AllFeatures, SkipTests: []string{ tests.GatewaySecretInvalidReferenceGrant.ShortName, tests.HTTPRouteRewritePath.ShortName, @@ -102,7 +103,7 @@ func experimentalConformance(t *testing.T) { tests.GatewayWithAttachedRoutes.ShortName, tests.HTTPRouteBackendProtocolH2C.ShortName, }, - SupportedFeatures: sets.Set[suite.SupportedFeature]{}.Insert(suite.HTTPRouteExtendedFeatures.UnsortedList()...), + ExemptFeatures: suite.MeshCoreFeatures, }, Implementation: *implementation, ConformanceProfiles: conformanceProfiles, From a6e62d5987995f35d1d1d304f50f64f22727a455 Mon Sep 17 00:00:00 2001 From: zirain Date: Wed, 25 Oct 2023 23:57:15 -0500 Subject: [PATCH 02/55] chore: correct comment and rename function (#2074) correct comment and rename function Signed-off-by: zirain --- api/v1alpha1/envoygateway_helpers.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v1alpha1/envoygateway_helpers.go b/api/v1alpha1/envoygateway_helpers.go index e9e369f4e74..e0352ba6969 100644 --- a/api/v1alpha1/envoygateway_helpers.go +++ b/api/v1alpha1/envoygateway_helpers.go @@ -92,7 +92,7 @@ func DefaultEnvoyGatewayLogging() *EnvoyGatewayLogging { } } -// GetEnvoyGatewayAdmin returns the EnvoyGatewayAdmin of EnvoyGateway or a default EnvoyGatewayAdmin if unspecified. +// GetEnvoyGatewayTelemetry returns the EnvoyGatewayTelemetry of EnvoyGateway or a default EnvoyGatewayTelemetry if unspecified. func (e *EnvoyGateway) GetEnvoyGatewayTelemetry() *EnvoyGatewayTelemetry { if e.Telemetry != nil { if e.Telemetry.Metrics.Prometheus == nil { @@ -109,8 +109,8 @@ func (e *EnvoyGateway) GetEnvoyGatewayTelemetry() *EnvoyGatewayTelemetry { return e.Telemetry } -// IfDisablePrometheus returns if disable prometheus. -func (e *EnvoyGateway) IfDisablePrometheus() bool { +// DisablePrometheus returns if disable prometheus. +func (e *EnvoyGateway) DisablePrometheus() bool { return e.GetEnvoyGatewayTelemetry().Metrics.Prometheus.Disable } From bec3f2963bc06f80ab4ffea7342147d7585ecf08 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Thu, 26 Oct 2023 12:58:04 +0800 Subject: [PATCH 03/55] team: add new reviewers of eg (#2064) * team: add new reviewers of eg Signed-off-by: bitliu * update Signed-off-by: bitliu --------- Signed-off-by: bitliu --- OWNERS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OWNERS b/OWNERS index c079d03b882..2895f975ebf 100644 --- a/OWNERS +++ b/OWNERS @@ -20,5 +20,8 @@ reviewers: - chauhanshubham - kflynn - LanceEa -- qicz - zhaohuabing +- tmsnan +- tanujd11 +- cnvergence +- shawnh2 From 70a31b203886bd5edf05fc6fbd57167aea0a481d Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Wed, 25 Oct 2023 22:45:13 -0700 Subject: [PATCH 04/55] Enable GatewaySecretInvalidReferenceGrant test (#2078) Relates to https://github.com/kubernetes-sigs/gateway-api/pull/2494 Fixes https://github.com/envoyproxy/gateway/issues/2002 Signed-off-by: Arko Dasgupta Signed-off-by: zirain Co-authored-by: zirain --- test/conformance/conformance_test.go | 1 - test/conformance/experimental_conformance_test.go | 1 - 2 files changed, 2 deletions(-) diff --git a/test/conformance/conformance_test.go b/test/conformance/conformance_test.go index ad81e21cd26..eeb8898ffc7 100644 --- a/test/conformance/conformance_test.go +++ b/test/conformance/conformance_test.go @@ -48,7 +48,6 @@ func TestGatewayAPIConformance(t *testing.T) { CleanupBaseResources: *flags.CleanupBaseResources, SupportedFeatures: suite.AllFeatures, SkipTests: []string{ - tests.GatewaySecretInvalidReferenceGrant.ShortName, tests.HTTPRouteRewritePath.ShortName, tests.GatewayStaticAddresses.ShortName, tests.GatewayWithAttachedRoutes.ShortName, diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index 2abc238823d..fd4a5620973 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -97,7 +97,6 @@ func experimentalConformance(t *testing.T) { CleanupBaseResources: *flags.CleanupBaseResources, SupportedFeatures: suite.AllFeatures, SkipTests: []string{ - tests.GatewaySecretInvalidReferenceGrant.ShortName, tests.HTTPRouteRewritePath.ShortName, tests.GatewayStaticAddresses.ShortName, tests.GatewayWithAttachedRoutes.ShortName, From 6b8794e2e82cdc40fedc955c45a204bc05e7f2fe Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Thu, 26 Oct 2023 14:08:47 +0800 Subject: [PATCH 05/55] feat: add control plane metrics library (#1982) * feat: add control plane metrics library Signed-off-by: bitliu * update Signed-off-by: bitliu * update Signed-off-by: bitliu * rebase Signed-off-by: bitliu * update Signed-off-by: bitliu --------- Signed-off-by: bitliu --- api/v1alpha1/envoygateway_helpers.go | 1 - api/v1alpha1/shared_types.go | 4 + .../validation/envoygateway_validate_test.go | 229 ++++++++++++++++++ .../validation/envoyproxy_validate_test.go | 175 ------------- go.mod | 14 +- go.sum | 26 ++ internal/admin/server.go | 8 +- internal/cmd/server.go | 6 + internal/metrics/metadata.go | 102 ++++++++ internal/metrics/options.go | 31 +++ internal/metrics/otel_label.go | 48 ++++ internal/metrics/otel_metric_counter.go | 48 ++++ internal/metrics/otel_metric_gauge.go | 57 +++++ internal/metrics/otel_metric_histogram.go | 41 ++++ internal/metrics/otel_metric_sink.go | 100 ++++++++ internal/metrics/register.go | 207 ++++++++++++++++ internal/metrics/sample_counter_test.go | 23 ++ internal/metrics/sample_gauge_test.go | 27 +++ internal/metrics/sample_histogram_test.go | 23 ++ internal/metrics/units.go | 18 ++ site/content/en/latest/design/eg-metrics.md | 2 +- 21 files changed, 1008 insertions(+), 182 deletions(-) create mode 100644 internal/metrics/metadata.go create mode 100644 internal/metrics/options.go create mode 100644 internal/metrics/otel_label.go create mode 100644 internal/metrics/otel_metric_counter.go create mode 100644 internal/metrics/otel_metric_gauge.go create mode 100644 internal/metrics/otel_metric_histogram.go create mode 100644 internal/metrics/otel_metric_sink.go create mode 100644 internal/metrics/register.go create mode 100644 internal/metrics/sample_counter_test.go create mode 100644 internal/metrics/sample_gauge_test.go create mode 100644 internal/metrics/sample_histogram_test.go create mode 100644 internal/metrics/units.go diff --git a/api/v1alpha1/envoygateway_helpers.go b/api/v1alpha1/envoygateway_helpers.go index e0352ba6969..ef9ab69706b 100644 --- a/api/v1alpha1/envoygateway_helpers.go +++ b/api/v1alpha1/envoygateway_helpers.go @@ -98,7 +98,6 @@ func (e *EnvoyGateway) GetEnvoyGatewayTelemetry() *EnvoyGatewayTelemetry { if e.Telemetry.Metrics.Prometheus == nil { e.Telemetry.Metrics.Prometheus = DefaultEnvoyGatewayPrometheus() } - if e.Telemetry.Metrics == nil { e.Telemetry.Metrics = DefaultEnvoyGatewayMetrics() } diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index 588eefebb47..bbda8a16ec3 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -21,6 +21,10 @@ const ( DefaultEnvoyProxyImage = "envoyproxy/envoy-dev:latest" // DefaultRateLimitImage is the default image used by ratelimit. DefaultRateLimitImage = "envoyproxy/ratelimit:master" + // HTTPProtocol is the common-used http protocol. + HTTPProtocol = "http" + // GRPCProtocol is the common-used grpc protocol. + GRPCProtocol = "grpc" ) // GroupVersionKind unambiguously identifies a Kind. diff --git a/api/v1alpha1/validation/envoygateway_validate_test.go b/api/v1alpha1/validation/envoygateway_validate_test.go index 06a3043be12..1728cb8a058 100644 --- a/api/v1alpha1/validation/envoygateway_validate_test.go +++ b/api/v1alpha1/validation/envoygateway_validate_test.go @@ -8,7 +8,9 @@ package validation import ( "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "sigs.k8s.io/gateway-api/apis/v1" "github.com/envoyproxy/gateway/api/v1alpha1" @@ -469,3 +471,230 @@ func TestValidateEnvoyGateway(t *testing.T) { }) } } + +func TestEnvoyGateway(t *testing.T) { + envoyGateway := v1alpha1.DefaultEnvoyGateway() + assert.True(t, envoyGateway.Provider != nil) + assert.True(t, envoyGateway.Gateway != nil) + assert.True(t, envoyGateway.Logging != nil) + envoyGateway.SetEnvoyGatewayDefaults() + assert.Equal(t, envoyGateway.Logging, v1alpha1.DefaultEnvoyGatewayLogging()) + + logging := v1alpha1.DefaultEnvoyGatewayLogging() + assert.True(t, logging != nil) + assert.True(t, logging.Level[v1alpha1.LogComponentGatewayDefault] == v1alpha1.LogLevelInfo) + + gatewayLogging := &v1alpha1.EnvoyGatewayLogging{ + Level: logging.Level, + } + gatewayLogging.SetEnvoyGatewayLoggingDefaults() + assert.True(t, gatewayLogging != nil) + assert.True(t, gatewayLogging.Level[v1alpha1.LogComponentGatewayDefault] == v1alpha1.LogLevelInfo) +} + +func TestDefaultEnvoyGatewayLoggingLevel(t *testing.T) { + type args struct { + component string + level v1alpha1.LogLevel + } + tests := []struct { + name string + args args + want v1alpha1.LogLevel + }{ + { + name: "test default info level for empty level", + args: args{component: "", level: ""}, + want: v1alpha1.LogLevelInfo, + }, + { + name: "test default info level for empty level", + args: args{component: string(v1alpha1.LogComponentGatewayDefault), level: ""}, + want: v1alpha1.LogLevelInfo, + }, + { + name: "test default info level for info level", + args: args{component: string(v1alpha1.LogComponentGatewayDefault), level: v1alpha1.LogLevelInfo}, + want: v1alpha1.LogLevelInfo, + }, + { + name: "test default error level for error level", + args: args{component: string(v1alpha1.LogComponentGatewayDefault), level: v1alpha1.LogLevelError}, + want: v1alpha1.LogLevelError, + }, + { + name: "test gateway-api error level for error level", + args: args{component: string(v1alpha1.LogComponentGatewayAPIRunner), level: v1alpha1.LogLevelError}, + want: v1alpha1.LogLevelError, + }, + { + name: "test gateway-api info level for info level", + args: args{component: string(v1alpha1.LogComponentGatewayAPIRunner), level: v1alpha1.LogLevelInfo}, + want: v1alpha1.LogLevelInfo, + }, + { + name: "test default gateway-api warn level for info level", + args: args{component: string(v1alpha1.LogComponentGatewayAPIRunner), level: ""}, + want: v1alpha1.LogLevelInfo, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + logging := &v1alpha1.EnvoyGatewayLogging{} + if got := logging.DefaultEnvoyGatewayLoggingLevel(tt.args.level); got != tt.want { + t.Errorf("defaultLevel() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestEnvoyGatewayProvider(t *testing.T) { + envoyGateway := &v1alpha1.EnvoyGateway{ + TypeMeta: metav1.TypeMeta{}, + EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{Provider: v1alpha1.DefaultEnvoyGatewayProvider()}, + } + assert.True(t, envoyGateway.Provider != nil) + + envoyGatewayProvider := envoyGateway.GetEnvoyGatewayProvider() + assert.True(t, envoyGatewayProvider.Kubernetes == nil) + assert.Equal(t, envoyGateway.Provider, envoyGatewayProvider) + + envoyGatewayProvider.Kubernetes = v1alpha1.DefaultEnvoyGatewayKubeProvider() + assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment, v1alpha1.DefaultKubernetesDeployment(v1alpha1.DefaultRateLimitImage)) + + envoyGatewayProvider.Kubernetes = &v1alpha1.EnvoyGatewayKubernetesProvider{} + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment == nil) + + envoyGatewayProvider.Kubernetes = &v1alpha1.EnvoyGatewayKubernetesProvider{ + RateLimitDeployment: &v1alpha1.KubernetesDeploymentSpec{ + Replicas: nil, + Pod: nil, + Container: nil, + }} + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas == nil) + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod == nil) + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container == nil) + envoyGatewayKubeProvider := envoyGatewayProvider.GetEnvoyGatewayKubeProvider() + + envoyGatewayProvider.Kubernetes = &v1alpha1.EnvoyGatewayKubernetesProvider{ + RateLimitDeployment: &v1alpha1.KubernetesDeploymentSpec{ + Replicas: nil, + Pod: nil, + Container: &v1alpha1.KubernetesContainerSpec{ + Resources: nil, + SecurityContext: nil, + Image: nil, + }, + }} + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources == nil) + envoyGatewayProvider.GetEnvoyGatewayKubeProvider() + + assert.True(t, envoyGatewayProvider.Kubernetes != nil) + assert.Equal(t, envoyGatewayProvider.Kubernetes, envoyGatewayKubeProvider) + + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment != nil) + assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment, v1alpha1.DefaultKubernetesDeployment(v1alpha1.DefaultRateLimitImage)) + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas != nil) + assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas, v1alpha1.DefaultKubernetesDeploymentReplicas()) + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod != nil) + assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod, v1alpha1.DefaultKubernetesPod()) + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container != nil) + assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container, v1alpha1.DefaultKubernetesContainer(v1alpha1.DefaultRateLimitImage)) + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources != nil) + assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources, v1alpha1.DefaultResourceRequirements()) + assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Image != nil) + assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Image, v1alpha1.DefaultKubernetesContainerImage(v1alpha1.DefaultRateLimitImage)) +} + +func TestEnvoyGatewayAdmin(t *testing.T) { + // default envoygateway config admin should not be nil + eg := v1alpha1.DefaultEnvoyGateway() + assert.True(t, eg.Admin != nil) + + // get default admin config from envoygateway + // values should be set in default + egAdmin := eg.GetEnvoyGatewayAdmin() + assert.True(t, egAdmin != nil) + assert.True(t, egAdmin.Address.Port == v1alpha1.GatewayAdminPort) + assert.True(t, egAdmin.Address.Host == v1alpha1.GatewayAdminHost) + assert.True(t, egAdmin.EnableDumpConfig == false) + assert.True(t, egAdmin.EnablePprof == false) + + // override the admin config + // values should be updated + eg.Admin = &v1alpha1.EnvoyGatewayAdmin{ + Address: &v1alpha1.EnvoyGatewayAdminAddress{ + Host: "0.0.0.0", + Port: 19010, + }, + EnableDumpConfig: true, + EnablePprof: true, + } + + assert.True(t, eg.GetEnvoyGatewayAdmin().Address.Port == 19010) + assert.True(t, eg.GetEnvoyGatewayAdmin().Address.Host == "0.0.0.0") + assert.True(t, eg.GetEnvoyGatewayAdmin().EnableDumpConfig == true) + assert.True(t, eg.GetEnvoyGatewayAdmin().EnablePprof == true) + + // set eg defaults when admin is nil + // the admin should not be nil + eg.Admin = nil + eg.SetEnvoyGatewayDefaults() + assert.True(t, eg.Admin != nil) + assert.True(t, eg.Admin.Address.Port == v1alpha1.GatewayAdminPort) + assert.True(t, eg.Admin.Address.Host == v1alpha1.GatewayAdminHost) + assert.True(t, eg.Admin.EnableDumpConfig == false) + assert.True(t, eg.Admin.EnablePprof == false) +} + +func TestEnvoyGatewayTelemetry(t *testing.T) { + // default envoygateway config telemetry should not be nil + eg := v1alpha1.DefaultEnvoyGateway() + assert.True(t, eg.Telemetry != nil) + + // get default telemetry config from envoygateway + // values should be set in default + egTelemetry := eg.GetEnvoyGatewayTelemetry() + assert.True(t, egTelemetry != nil) + assert.True(t, egTelemetry.Metrics != nil) + assert.True(t, egTelemetry.Metrics.Prometheus.Disable == false) + assert.True(t, egTelemetry.Metrics.Sinks == nil) + + // override the telemetry config + // values should be updated + eg.Telemetry.Metrics = &v1alpha1.EnvoyGatewayMetrics{ + Prometheus: &v1alpha1.EnvoyGatewayPrometheusProvider{ + Disable: true, + }, + Sinks: []v1alpha1.EnvoyGatewayMetricSink{ + { + Type: v1alpha1.MetricSinkTypeOpenTelemetry, + OpenTelemetry: &v1alpha1.EnvoyGatewayOpenTelemetrySink{ + Host: "otel-collector.monitoring.svc.cluster.local", + Protocol: "grpc", + Port: 4317, + }, + }, { + Type: v1alpha1.MetricSinkTypeOpenTelemetry, + OpenTelemetry: &v1alpha1.EnvoyGatewayOpenTelemetrySink{ + Host: "otel-collector.monitoring.svc.cluster.local", + Protocol: "http", + Port: 4318, + }, + }, + }, + } + + assert.True(t, eg.GetEnvoyGatewayTelemetry().Metrics.Prometheus.Disable == true) + assert.True(t, len(eg.GetEnvoyGatewayTelemetry().Metrics.Sinks) == 2) + assert.True(t, eg.GetEnvoyGatewayTelemetry().Metrics.Sinks[0].Type == v1alpha1.MetricSinkTypeOpenTelemetry) + + // set eg defaults when telemetry is nil + // the telemetry should not be nil + eg.Telemetry = nil + eg.SetEnvoyGatewayDefaults() + assert.True(t, eg.Telemetry != nil) + assert.True(t, eg.Telemetry.Metrics != nil) + assert.True(t, eg.Telemetry.Metrics.Prometheus.Disable == false) + assert.True(t, eg.Telemetry.Metrics.Sinks == nil) +} diff --git a/api/v1alpha1/validation/envoyproxy_validate_test.go b/api/v1alpha1/validation/envoyproxy_validate_test.go index 0f60a6fa593..0bfc5558e1b 100644 --- a/api/v1alpha1/validation/envoyproxy_validate_test.go +++ b/api/v1alpha1/validation/envoyproxy_validate_test.go @@ -464,140 +464,6 @@ func TestValidateEnvoyProxy(t *testing.T) { } } -func TestEnvoyGateway(t *testing.T) { - envoyGateway := egv1a1.DefaultEnvoyGateway() - assert.True(t, envoyGateway.Provider != nil) - assert.True(t, envoyGateway.Gateway != nil) - assert.True(t, envoyGateway.Logging != nil) - envoyGateway.SetEnvoyGatewayDefaults() - assert.Equal(t, envoyGateway.Logging, egv1a1.DefaultEnvoyGatewayLogging()) - - logging := egv1a1.DefaultEnvoyGatewayLogging() - assert.True(t, logging != nil) - assert.True(t, logging.Level[egv1a1.LogComponentGatewayDefault] == egv1a1.LogLevelInfo) - - gatewayLogging := &egv1a1.EnvoyGatewayLogging{ - Level: logging.Level, - } - gatewayLogging.SetEnvoyGatewayLoggingDefaults() - assert.True(t, gatewayLogging != nil) - assert.True(t, gatewayLogging.Level[egv1a1.LogComponentGatewayDefault] == egv1a1.LogLevelInfo) -} - -func TestDefaultEnvoyGatewayLoggingLevel(t *testing.T) { - type args struct { - component string - level egv1a1.LogLevel - } - tests := []struct { - name string - args args - want egv1a1.LogLevel - }{ - { - name: "test default info level for empty level", - args: args{component: "", level: ""}, - want: egv1a1.LogLevelInfo, - }, - { - name: "test default info level for empty level", - args: args{component: string(egv1a1.LogComponentGatewayDefault), level: ""}, - want: egv1a1.LogLevelInfo, - }, - { - name: "test default info level for info level", - args: args{component: string(egv1a1.LogComponentGatewayDefault), level: egv1a1.LogLevelInfo}, - want: egv1a1.LogLevelInfo, - }, - { - name: "test default error level for error level", - args: args{component: string(egv1a1.LogComponentGatewayDefault), level: egv1a1.LogLevelError}, - want: egv1a1.LogLevelError, - }, - { - name: "test gateway-api error level for error level", - args: args{component: string(egv1a1.LogComponentGatewayAPIRunner), level: egv1a1.LogLevelError}, - want: egv1a1.LogLevelError, - }, - { - name: "test gateway-api info level for info level", - args: args{component: string(egv1a1.LogComponentGatewayAPIRunner), level: egv1a1.LogLevelInfo}, - want: egv1a1.LogLevelInfo, - }, - { - name: "test default gateway-api warn level for info level", - args: args{component: string(egv1a1.LogComponentGatewayAPIRunner), level: ""}, - want: egv1a1.LogLevelInfo, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - logging := &egv1a1.EnvoyGatewayLogging{} - if got := logging.DefaultEnvoyGatewayLoggingLevel(tt.args.level); got != tt.want { - t.Errorf("defaultLevel() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestEnvoyGatewayProvider(t *testing.T) { - envoyGateway := &egv1a1.EnvoyGateway{ - TypeMeta: metav1.TypeMeta{}, - EnvoyGatewaySpec: egv1a1.EnvoyGatewaySpec{Provider: egv1a1.DefaultEnvoyGatewayProvider()}, - } - assert.True(t, envoyGateway.Provider != nil) - - envoyGatewayProvider := envoyGateway.GetEnvoyGatewayProvider() - assert.True(t, envoyGatewayProvider.Kubernetes == nil) - assert.Equal(t, envoyGateway.Provider, envoyGatewayProvider) - - envoyGatewayProvider.Kubernetes = egv1a1.DefaultEnvoyGatewayKubeProvider() - assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment, egv1a1.DefaultKubernetesDeployment(egv1a1.DefaultRateLimitImage)) - - envoyGatewayProvider.Kubernetes = &egv1a1.EnvoyGatewayKubernetesProvider{} - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment == nil) - - envoyGatewayProvider.Kubernetes = &egv1a1.EnvoyGatewayKubernetesProvider{ - RateLimitDeployment: &egv1a1.KubernetesDeploymentSpec{ - Replicas: nil, - Pod: nil, - Container: nil, - }} - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas == nil) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod == nil) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container == nil) - envoyGatewayKubeProvider := envoyGatewayProvider.GetEnvoyGatewayKubeProvider() - - envoyGatewayProvider.Kubernetes = &egv1a1.EnvoyGatewayKubernetesProvider{ - RateLimitDeployment: &egv1a1.KubernetesDeploymentSpec{ - Replicas: nil, - Pod: nil, - Container: &egv1a1.KubernetesContainerSpec{ - Resources: nil, - SecurityContext: nil, - Image: nil, - }, - }} - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources == nil) - envoyGatewayProvider.GetEnvoyGatewayKubeProvider() - - assert.True(t, envoyGatewayProvider.Kubernetes != nil) - assert.Equal(t, envoyGatewayProvider.Kubernetes, envoyGatewayKubeProvider) - - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment != nil) - assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment, egv1a1.DefaultKubernetesDeployment(egv1a1.DefaultRateLimitImage)) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas != nil) - assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas, egv1a1.DefaultKubernetesDeploymentReplicas()) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod != nil) - assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod, egv1a1.DefaultKubernetesPod()) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container != nil) - assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container, egv1a1.DefaultKubernetesContainer(egv1a1.DefaultRateLimitImage)) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources != nil) - assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources, egv1a1.DefaultResourceRequirements()) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Image != nil) - assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Image, egv1a1.DefaultKubernetesContainerImage(egv1a1.DefaultRateLimitImage)) -} - func TestEnvoyProxyProvider(t *testing.T) { envoyProxy := &egv1a1.EnvoyProxy{ Spec: egv1a1.EnvoyProxySpec{ @@ -634,47 +500,6 @@ func TestEnvoyProxyProvider(t *testing.T) { assert.True(t, reflect.DeepEqual(envoyProxyProvider.Kubernetes.EnvoyService.Type, egv1a1.GetKubernetesServiceType(egv1a1.ServiceTypeLoadBalancer))) } -func TestEnvoyGatewayAdmin(t *testing.T) { - // default envoygateway config admin should not be nil - eg := egv1a1.DefaultEnvoyGateway() - assert.True(t, eg.Admin != nil) - - // get default admin config from envoygateway - // values should be set in default - egAdmin := eg.GetEnvoyGatewayAdmin() - assert.True(t, egAdmin != nil) - assert.True(t, egAdmin.Address.Port == egv1a1.GatewayAdminPort) - assert.True(t, egAdmin.Address.Host == egv1a1.GatewayAdminHost) - assert.True(t, egAdmin.EnableDumpConfig == false) - assert.True(t, egAdmin.EnablePprof == false) - - // override the admin config - // values should be updated - eg.Admin = &egv1a1.EnvoyGatewayAdmin{ - Address: &egv1a1.EnvoyGatewayAdminAddress{ - Host: "0.0.0.0", - Port: 19010, - }, - EnableDumpConfig: true, - EnablePprof: true, - } - - assert.True(t, eg.GetEnvoyGatewayAdmin().Address.Port == 19010) - assert.True(t, eg.GetEnvoyGatewayAdmin().Address.Host == "0.0.0.0") - assert.True(t, eg.GetEnvoyGatewayAdmin().EnableDumpConfig == true) - assert.True(t, eg.GetEnvoyGatewayAdmin().EnablePprof == true) - - // set eg defaults when admin is nil - // the admin should not be nil - eg.Admin = nil - eg.SetEnvoyGatewayDefaults() - assert.True(t, eg.Admin != nil) - assert.True(t, eg.Admin.Address.Port == egv1a1.GatewayAdminPort) - assert.True(t, eg.Admin.Address.Host == egv1a1.GatewayAdminHost) - assert.True(t, eg.Admin.EnableDumpConfig == false) - assert.True(t, eg.Admin.EnablePprof == false) -} - func TestGetEnvoyProxyDefaultComponentLevel(t *testing.T) { cases := []struct { logging egv1a1.ProxyLogging diff --git a/go.mod b/go.mod index f75200ffe34..061b2188694 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,12 @@ require ( github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7 github.com/tetratelabs/multierror v1.1.1 github.com/tsaarni/certyaml v0.9.2 + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 + go.opentelemetry.io/otel/metric v1.19.0 + go.opentelemetry.io/otel/sdk/metric v1.19.0 go.opentelemetry.io/proto/otlp v1.0.0 go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e @@ -42,7 +48,13 @@ require ( ) require ( + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/sdk v1.19.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect golang.org/x/sync v0.3.0 // indirect ) @@ -88,7 +100,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_golang v1.17.0 github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 601027d0fe0..9c0770ae263 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= @@ -125,8 +127,11 @@ 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.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= @@ -188,6 +193,7 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -253,6 +259,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -466,6 +474,24 @@ go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qL go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= diff --git a/internal/admin/server.go b/internal/admin/server.go index be25bec5be3..9c035b43816 100644 --- a/internal/admin/server.go +++ b/internal/admin/server.go @@ -18,7 +18,7 @@ import ( ) var ( - debugLogger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("admin") + adminLogger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("admin") ) func Init(cfg *config.Server) error { @@ -36,7 +36,7 @@ func start(cfg *config.Server) error { address := cfg.EnvoyGateway.GetEnvoyGatewayAdminAddress() enablePprof := cfg.EnvoyGateway.GetEnvoyGatewayAdmin().EnablePprof - debugLogger.Info("starting admin server", "address", address, "enablePprof", enablePprof) + adminLogger.Info("starting admin server", "address", address, "enablePprof", enablePprof) if enablePprof { // Serve pprof endpoints to aid in live debugging. @@ -47,7 +47,7 @@ func start(cfg *config.Server) error { handlers.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) } - debugServer := &http.Server{ + adminServer := &http.Server{ Handler: handlers, Addr: address, ReadTimeout: 5 * time.Second, @@ -58,7 +58,7 @@ func start(cfg *config.Server) error { // Listen And Serve Admin Server. go func() { - if err := debugServer.ListenAndServe(); err != nil { + if err := adminServer.ListenAndServe(); err != nil { cfg.Logger.Error(err, "start admin server failed") } }() diff --git a/internal/cmd/server.go b/internal/cmd/server.go index 017ca9a6c42..6dc25a19946 100644 --- a/internal/cmd/server.go +++ b/internal/cmd/server.go @@ -17,6 +17,7 @@ import ( infrarunner "github.com/envoyproxy/gateway/internal/infrastructure/runner" "github.com/envoyproxy/gateway/internal/logging" "github.com/envoyproxy/gateway/internal/message" + "github.com/envoyproxy/gateway/internal/metrics" providerrunner "github.com/envoyproxy/gateway/internal/provider/runner" xdsserverrunner "github.com/envoyproxy/gateway/internal/xds/server/runner" xdstranslatorrunner "github.com/envoyproxy/gateway/internal/xds/translator/runner" @@ -54,6 +55,11 @@ func server() error { if err := admin.Init(cfg); err != nil { return err } + // Init eg metrics servers. + if err := metrics.Init(cfg); err != nil { + return err + } + // init eg runners. if err := setupRunners(cfg); err != nil { return err diff --git a/internal/metrics/metadata.go b/internal/metrics/metadata.go new file mode 100644 index 00000000000..f2ab8498407 --- /dev/null +++ b/internal/metrics/metadata.go @@ -0,0 +1,102 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +import ( + "errors" + "sync" + + "go.opentelemetry.io/otel" + api "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/sdk/metric" + + "github.com/envoyproxy/gateway/api/v1alpha1" + log "github.com/envoyproxy/gateway/internal/logging" +) + +var ( + meter = func() api.Meter { + return otel.GetMeterProvider().Meter("envoy-gateway") + } + + metricsLogger = log.DefaultLogger(v1alpha1.LogLevelInfo).WithName("metrics") +) + +func init() { + otel.SetLogger(metricsLogger.Logger) +} + +// MetricType is the type of a metric. +type MetricType string + +// Metric type supports: +// * Counter: A Counter is a simple metric that only goes up (increments). +// +// * Gauge: A Gauge is a metric that represent +// a single numerical value that can arbitrarily go up and down. +// +// * Histogram: A Histogram samples observations and counts them in configurable buckets. +// It also provides a sum of all observed values. +// It's used to visualize the statistical distribution of these observations. + +const ( + CounterType MetricType = "Counter" + GaugeType MetricType = "Gauge" + HistogramType MetricType = "Histogram" +) + +// Metadata records a metric's metadata. +type Metadata struct { + Name string + Type MetricType + Description string + Bounds []float64 +} + +// metrics stores stores metrics +type store struct { + started bool + mu sync.Mutex + stores map[string]Metadata +} + +// stores is a global that stores all registered metrics +var stores = store{ + stores: map[string]Metadata{}, +} + +// register records a newly defined metric. Only valid before an exporter is set. +func (d *store) register(store Metadata) { + d.mu.Lock() + defer d.mu.Unlock() + if d.started { + metricsLogger.Error(errors.New("cannot initialize metric after metric has started"), "metric", store.Name) + } + d.stores[store.Name] = store +} + +// preAddOptions runs pre-run steps before adding to meter provider. +func (d *store) preAddOptions() []metric.Option { + d.mu.Lock() + defer d.mu.Unlock() + d.started = true + opts := []metric.Option{} + for name, store := range d.stores { + if store.Bounds == nil { + continue + } + // for each histogram metric (i.e. those with bounds), set up a view explicitly defining those buckets. + v := metric.WithView(metric.NewView( + metric.Instrument{Name: name}, + metric.Stream{ + Aggregation: metric.AggregationExplicitBucketHistogram{ + Boundaries: store.Bounds, + }}, + )) + opts = append(opts, v) + } + return opts +} diff --git a/internal/metrics/options.go b/internal/metrics/options.go new file mode 100644 index 00000000000..f274582f459 --- /dev/null +++ b/internal/metrics/options.go @@ -0,0 +1,31 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +// Options encode changes to the options passed to a Metric at creation time. +type MetricOption func(*MetricOptions) + +type MetricOptions struct { + Unit Unit + Name string + Description string +} + +// WithUnit provides configuration options for a new Metric, providing unit of measure +// information for a new Metric. +func WithUnit(unit Unit) MetricOption { + return func(opts *MetricOptions) { + opts.Unit = unit + } +} + +func metricOptions(name, description string, opts ...MetricOption) MetricOptions { + o := MetricOptions{Unit: None, Name: name, Description: description} + for _, opt := range opts { + opt(&o) + } + return o +} diff --git a/internal/metrics/otel_label.go b/internal/metrics/otel_label.go new file mode 100644 index 00000000000..45d04ff4bb0 --- /dev/null +++ b/internal/metrics/otel_label.go @@ -0,0 +1,48 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +import "go.opentelemetry.io/otel/attribute" + +// A Label provides a named dimension for a Metric. +type Label struct { + key attribute.Key +} + +// NewLabel will attempt to create a new Label. +func NewLabel(key string) Label { + return Label{attribute.Key(key)} +} + +// Value creates a new LabelValue for the Label. +func (l Label) Value(value string) LabelValue { + return LabelValue{l.key.String(value)} +} + +// A LabelValue represents a Label with a specific value. It is used to record +// values for a Metric. +type LabelValue struct { + keyValue attribute.KeyValue +} + +func (l LabelValue) Key() Label { + return Label{l.keyValue.Key} +} + +func (l LabelValue) Value() string { + return l.keyValue.Value.AsString() +} + +func mergeLabelValues(attrs []attribute.KeyValue, labelValues []LabelValue) ([]attribute.KeyValue, attribute.Set) { + mergedAttrs := make([]attribute.KeyValue, 0, len(attrs)+len(labelValues)) + mergedAttrs = append(mergedAttrs, attrs...) + for _, v := range labelValues { + kv := v + mergedAttrs = append(mergedAttrs, kv.keyValue) + } + + return mergedAttrs, attribute.NewSet(mergedAttrs...) +} diff --git a/internal/metrics/otel_metric_counter.go b/internal/metrics/otel_metric_counter.go new file mode 100644 index 00000000000..93dcaa13650 --- /dev/null +++ b/internal/metrics/otel_metric_counter.go @@ -0,0 +1,48 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + api "go.opentelemetry.io/otel/metric" +) + +type Counter struct { + name string + attrs []attribute.KeyValue + c api.Float64Counter + preRecordOptions []api.AddOption +} + +func (f *Counter) Add(value float64) { + if f.preRecordOptions != nil { + f.c.Add(context.Background(), value, f.preRecordOptions...) + } else { + f.c.Add(context.Background(), value) + } +} + +func (f *Counter) Increment() { + f.Add(1) +} + +func (f *Counter) Decrement() { + f.Add(-1) +} + +func (f *Counter) With(labelValues ...LabelValue) *Counter { + attrs, set := mergeLabelValues(f.attrs, labelValues) + m := &Counter{ + c: f.c, + preRecordOptions: []api.AddOption{api.WithAttributeSet(set)}, + name: f.name, + attrs: attrs, + } + + return m +} diff --git a/internal/metrics/otel_metric_gauge.go b/internal/metrics/otel_metric_gauge.go new file mode 100644 index 00000000000..49e02395b67 --- /dev/null +++ b/internal/metrics/otel_metric_gauge.go @@ -0,0 +1,57 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +import ( + "sync" + + "go.opentelemetry.io/otel/attribute" + api "go.opentelemetry.io/otel/metric" +) + +type Gauge struct { + name string + attrs []attribute.KeyValue + + g api.Float64ObservableGauge + mutex *sync.RWMutex + stores map[attribute.Set]*GaugeValues + current *GaugeValues +} + +type GaugeValues struct { + val float64 + opt []api.ObserveOption +} + +func (f *Gauge) Record(value float64) { + f.mutex.Lock() + if f.current == nil { + f.current = &GaugeValues{} + f.stores[attribute.NewSet()] = f.current + } + f.current.val = value + f.mutex.Unlock() +} + +func (f *Gauge) With(labelValues ...LabelValue) *Gauge { + attrs, set := mergeLabelValues(f.attrs, labelValues) + m := &Gauge{ + g: f.g, + mutex: f.mutex, + stores: f.stores, + name: f.name, + attrs: attrs, + } + if _, f := m.stores[set]; !f { + m.stores[set] = &GaugeValues{ + opt: []api.ObserveOption{api.WithAttributeSet(set)}, + } + } + m.current = m.stores[set] + + return m +} diff --git a/internal/metrics/otel_metric_histogram.go b/internal/metrics/otel_metric_histogram.go new file mode 100644 index 00000000000..b1837b7a8d2 --- /dev/null +++ b/internal/metrics/otel_metric_histogram.go @@ -0,0 +1,41 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + api "go.opentelemetry.io/otel/metric" +) + +type Histogram struct { + name string + attrs []attribute.KeyValue + + d api.Float64Histogram + preRecordOptions []api.RecordOption +} + +func (f *Histogram) Record(value float64) { + if f.preRecordOptions != nil { + f.d.Record(context.Background(), value, f.preRecordOptions...) + } else { + f.d.Record(context.Background(), value) + } +} + +func (f *Histogram) With(labelValues ...LabelValue) *Histogram { + attrs, set := mergeLabelValues(f.attrs, labelValues) + m := &Histogram{ + name: f.name, + attrs: attrs, + d: f.d, + preRecordOptions: []api.RecordOption{api.WithAttributeSet(set)}, + } + + return m +} diff --git a/internal/metrics/otel_metric_sink.go b/internal/metrics/otel_metric_sink.go new file mode 100644 index 00000000000..442f0c0d3c0 --- /dev/null +++ b/internal/metrics/otel_metric_sink.go @@ -0,0 +1,100 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +import ( + "context" + "sync" + + "go.opentelemetry.io/otel/attribute" + api "go.opentelemetry.io/otel/metric" +) + +// NewCounter creates a new Counter Metric (the values will be cumulative). +// That means that data collected by the new Metric will be summed before export. +func NewCounter(name, description string, opts ...MetricOption) *Counter { + stores.register(Metadata{ + Name: name, + Type: CounterType, + Description: description, + }) + o := metricOptions(name, description, opts...) + + return newCounter(o) +} + +// NewGauge creates a new Gauge Metric. That means that data collected by the new +// Metric will export only the last recorded value. +func NewGauge(name, description string, opts ...MetricOption) *Gauge { + stores.register(Metadata{ + Name: name, + Type: GaugeType, + Description: description, + }) + o := metricOptions(name, description, opts...) + + return newGauge(o) +} + +// NewHistogram creates a new Metric with an aggregation type of Histogram. +// This means that the data collected by the Metric will be collected and exported as a histogram, with the specified bounds. +func NewHistogram(name, description string, bounds []float64, opts ...MetricOption) *Histogram { + stores.register(Metadata{ + Name: name, + Type: HistogramType, + Description: description, + Bounds: bounds, + }) + o := metricOptions(name, description, opts...) + + return newHistogram(o) +} + +func newCounter(o MetricOptions) *Counter { + c, err := meter().Float64Counter(o.Name, + api.WithDescription(o.Description), + api.WithUnit(string(o.Unit))) + if err != nil { + metricsLogger.Error(err, "failed to create otel Counter") + } + m := &Counter{c: c, name: o.Name} + + return m +} + +func newGauge(o MetricOptions) *Gauge { + r := &Gauge{mutex: &sync.RWMutex{}, name: o.Name} + r.stores = map[attribute.Set]*GaugeValues{} + g, err := meter().Float64ObservableGauge(o.Name, + api.WithFloat64Callback(func(ctx context.Context, observer api.Float64Observer) error { + r.mutex.Lock() + defer r.mutex.Unlock() + for _, gv := range r.stores { + observer.Observe(gv.val, gv.opt...) + } + return nil + }), + api.WithDescription(o.Description), + api.WithUnit(string(o.Unit))) + if err != nil { + metricsLogger.Error(err, "failed to create otel Gauge") + } + r.g = g + + return r +} + +func newHistogram(o MetricOptions) *Histogram { + d, err := meter().Float64Histogram(o.Name, + api.WithDescription(o.Description), + api.WithUnit(string(o.Unit))) + if err != nil { + metricsLogger.Error(err, "failed to create otel Histogram") + } + m := &Histogram{d: d, name: o.Name} + + return m +} diff --git a/internal/metrics/register.go b/internal/metrics/register.go new file mode 100644 index 00000000000..9c8abdf479d --- /dev/null +++ b/internal/metrics/register.go @@ -0,0 +1,207 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +import ( + "context" + "fmt" + "net" + "net/http" + "time" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" + otelprom "go.opentelemetry.io/otel/exporters/prometheus" + "go.opentelemetry.io/otel/sdk/metric" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/envoygateway/config" +) + +const ( + defaultEndpoint = "/metrics" +) + +// Init initializes and registers the global metrics server. +func Init(cfg *config.Server) error { + options := newOptions(cfg) + handler, err := registerForHandler(options) + if err != nil { + return err + } + + if !options.pullOptions.disable { + return start(options.address, handler) + } + + return nil +} + +func start(address string, handler http.Handler) error { + handlers := http.NewServeMux() + + metricsLogger.Info("starting metrics server", "address", address) + if handler != nil { + handlers.Handle(defaultEndpoint, handler) + } + + metricsServer := &http.Server{ + Handler: handlers, + Addr: address, + ReadTimeout: 5 * time.Second, + ReadHeaderTimeout: 5 * time.Second, + WriteTimeout: 10 * time.Second, + IdleTimeout: 15 * time.Second, + } + + // Listen And Serve Metrics Server. + go func() { + if err := metricsServer.ListenAndServe(); err != nil { + metricsLogger.Error(err, "start metrics server failed") + } + }() + + return nil +} + +func newOptions(svr *config.Server) registerOptions { + newOpts := registerOptions{} + newOpts.address = net.JoinHostPort(v1alpha1.GatewayMetricsHost, fmt.Sprint(v1alpha1.GatewayMetricsPort)) + + if svr.EnvoyGateway.DisablePrometheus() { + newOpts.pullOptions.disable = true + } else { + newOpts.pullOptions.disable = false + newOpts.pullOptions.registry = metricsserver.Registry + newOpts.pullOptions.gatherer = metricsserver.Registry + } + + for _, config := range svr.EnvoyGateway.GetEnvoyGatewayTelemetry().Metrics.Sinks { + newOpts.pushOptions.sinks = append(newOpts.pushOptions.sinks, metricsSink{ + host: config.OpenTelemetry.Host, + port: config.OpenTelemetry.Port, + protocol: config.OpenTelemetry.Protocol, + }) + } + + return newOpts +} + +// registerForHandler sets the global metrics registry to the provided Prometheus registerer. +// if enables prometheus, it will return a prom http handler. +func registerForHandler(opts registerOptions) (http.Handler, error) { + otelOpts := []metric.Option{} + + if err := registerOTELPromExporter(&otelOpts, opts); err != nil { + return nil, err + } + if err := registerOTELHTTPexporter(&otelOpts, opts); err != nil { + return nil, err + } + if err := registerOTELgRPCexporter(&otelOpts, opts); err != nil { + return nil, err + } + otelOpts = append(otelOpts, stores.preAddOptions()...) + + mp := metric.NewMeterProvider(otelOpts...) + otel.SetMeterProvider(mp) + + if !opts.pullOptions.disable { + return promhttp.HandlerFor(opts.pullOptions.gatherer, promhttp.HandlerOpts{}), nil + } + return nil, nil +} + +// registerOTELPromExporter registers OTEL prometheus exporter (PULL mode). +func registerOTELPromExporter(otelOpts *[]metric.Option, opts registerOptions) error { + if !opts.pullOptions.disable { + promOpts := []otelprom.Option{ + otelprom.WithoutScopeInfo(), + otelprom.WithoutTargetInfo(), + otelprom.WithoutUnits(), + otelprom.WithRegisterer(opts.pullOptions.registry), + otelprom.WithoutCounterSuffixes(), + } + promreader, err := otelprom.New(promOpts...) + if err != nil { + return err + } + + *otelOpts = append(*otelOpts, metric.WithReader(promreader)) + metricsLogger.Info("initialized metrics pull endpoint", "address", opts.address, "endpoint", defaultEndpoint) + } + + return nil +} + +// registerOTELHTTPexporter registers OTEL HTTP metrics exporter (PUSH mode). +func registerOTELHTTPexporter(otelOpts *[]metric.Option, opts registerOptions) error { + for _, sink := range opts.pushOptions.sinks { + if sink.protocol == v1alpha1.HTTPProtocol { + address := net.JoinHostPort(sink.host, fmt.Sprint(sink.port)) + httpexporter, err := otlpmetrichttp.New( + context.Background(), + otlpmetrichttp.WithEndpoint(address), + otlpmetrichttp.WithInsecure(), + ) + if err != nil { + return err + } + + otelreader := metric.NewPeriodicReader(httpexporter) + *otelOpts = append(*otelOpts, metric.WithReader(otelreader)) + metricsLogger.Info("initialized otel http metrics push endpoint", "address", address) + } + } + + return nil +} + +// registerOTELgRPCexporter registers OTEL gRPC metrics exporter (PUSH mode). +func registerOTELgRPCexporter(otelOpts *[]metric.Option, opts registerOptions) error { + for _, sink := range opts.pushOptions.sinks { + if sink.protocol == v1alpha1.GRPCProtocol { + address := net.JoinHostPort(sink.host, fmt.Sprint(sink.port)) + httpexporter, err := otlpmetricgrpc.New( + context.Background(), + otlpmetricgrpc.WithEndpoint(address), + otlpmetricgrpc.WithInsecure(), + ) + if err != nil { + return err + } + + otelreader := metric.NewPeriodicReader(httpexporter) + *otelOpts = append(*otelOpts, metric.WithReader(otelreader)) + metricsLogger.Info("initialized otel grpc metrics push endpoint", "address", address) + } + } + + return nil +} + +type registerOptions struct { + address string + pullOptions struct { + registry prometheus.Registerer + gatherer prometheus.Gatherer + disable bool + } + pushOptions struct { + sinks []metricsSink + } +} + +type metricsSink struct { + protocol string + host string + port int32 +} diff --git a/internal/metrics/sample_counter_test.go b/internal/metrics/sample_counter_test.go new file mode 100644 index 00000000000..ffd3a18aac3 --- /dev/null +++ b/internal/metrics/sample_counter_test.go @@ -0,0 +1,23 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics_test + +import "github.com/envoyproxy/gateway/internal/metrics" + +var ( + irUpdates = metrics.NewCounter( + "ir_updates_total", + "Number of IR updates, by ir type", + ) +) + +func NewCounter() { + // increment on every xds ir update + irUpdates.With(irType.Value("xds")).Increment() + + // xds ir updates double + irUpdates.With(irType.Value("xds")).Add(2) +} diff --git a/internal/metrics/sample_gauge_test.go b/internal/metrics/sample_gauge_test.go new file mode 100644 index 00000000000..6b287ed9ca1 --- /dev/null +++ b/internal/metrics/sample_gauge_test.go @@ -0,0 +1,27 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics_test + +import "github.com/envoyproxy/gateway/internal/metrics" + +var ( + irType = metrics.NewLabel("ir-type") + currentIRsNum = metrics.NewGauge( + "current_irs_queue_num", + "current number of ir in queue, by ir type", + ) +) + +func NewGauge() { + // only the last recorded value (2) will be exported for this gauge + currentIRsNum.With(irType.Value("xds")).Record(1) + currentIRsNum.With(irType.Value("xds")).Record(3) + currentIRsNum.With(irType.Value("xds")).Record(2) + + currentIRsNum.With(irType.Value("infra")).Record(1) + currentIRsNum.With(irType.Value("infra")).Record(3) + currentIRsNum.With(irType.Value("infra")).Record(2) +} diff --git a/internal/metrics/sample_histogram_test.go b/internal/metrics/sample_histogram_test.go new file mode 100644 index 00000000000..b34658fcbe5 --- /dev/null +++ b/internal/metrics/sample_histogram_test.go @@ -0,0 +1,23 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics_test + +import "github.com/envoyproxy/gateway/internal/metrics" + +var ( + method = metrics.NewLabel("method") + + sentBytes = metrics.NewHistogram( + "sent_bytes_total", + "Histogram of sent bytes by method", + []float64{10, 50, 100, 1000, 10000}, + metrics.WithUnit(metrics.Bytes), + ) +) + +func NewHistogram() { + sentBytes.With(method.Value("/request/path/1")).Record(458) +} diff --git a/internal/metrics/units.go b/internal/metrics/units.go new file mode 100644 index 00000000000..1c7b5ff13c2 --- /dev/null +++ b/internal/metrics/units.go @@ -0,0 +1,18 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package metrics + +// Unit encodes the standard name for describing the quantity +// measured by a Metric (if applicable). +type Unit string + +// Predefined units for use with the metrics package. +const ( + None Unit = "1" + Bytes Unit = "By" + Seconds Unit = "s" + Milliseconds Unit = "ms" +) diff --git a/site/content/en/latest/design/eg-metrics.md b/site/content/en/latest/design/eg-metrics.md index f43af77be12..60b93840852 100644 --- a/site/content/en/latest/design/eg-metrics.md +++ b/site/content/en/latest/design/eg-metrics.md @@ -6,7 +6,7 @@ title: "Control Plane Observability: Metrics" This document aims to cover all aspects of envoy gateway control plane metrics observability. {{% alert title="Note" color="secondary" %}} -**Data plane** observability (while important) is outside of scope for this document. For dataplane observability, refer to [here](./metrics). +**Data plane** observability (while important) is outside of scope for this document. For dataplane observability, refer to [here](../metrics). {{% /alert %}} ## Current State From c3ee9605f682e58369aa5bb576f06d2b2b059d34 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Fri, 27 Oct 2023 07:33:35 +0800 Subject: [PATCH 06/55] feat: add jwt authn to SecurityPolicy (#2079) * add jwt authn to SecurityPolicy Signed-off-by: huabing zhao * rename JWTAuthentication to JWT Signed-off-by: huabing zhao * fix test Signed-off-by: huabing zhao --------- Signed-off-by: huabing zhao --- api/v1alpha1/securitypolicy_types.go | 63 ++- .../validation/authenticationfilter.go | 1 + .../validation/authenticationfilter_test.go | 1 + .../validation/securitypolicy_validate.go | 117 +++++ .../securitypolicy_validate_test.go | 479 ++++++++++++++++++ api/v1alpha1/zz_generated.deepcopy.go | 53 ++ ...ateway.envoyproxy.io_securitypolicies.yaml | 86 ++++ internal/gatewayapi/securitypolicy.go | 34 +- .../testdata/securitypolicy-with-jwt.in.yaml | 118 +++++ .../testdata/securitypolicy-with-jwt.out.yaml | 337 ++++++++++++ internal/ir/xds.go | 30 +- internal/ir/xds_test.go | 26 +- internal/ir/zz_generated.deepcopy.go | 27 + internal/xds/translator/authentication.go | 53 +- internal/xds/translator/httpfilters.go | 16 +- internal/xds/translator/httpfilters_test.go | 4 +- internal/xds/translator/jwt_authn.go | 359 +++++++++++++ .../jwt-authn-multi-route-multi-provider.yaml | 68 +++ ...jwt-authn-multi-route-single-provider.yaml | 49 ++ .../in/xds-ir/jwt-authn-ratelimit.yaml | 69 +++ .../jwt-authn-single-route-single-match.yaml | 25 + ...n-multi-route-multi-provider.clusters.yaml | 81 +++ ...-multi-route-multi-provider.endpoints.yaml | 33 ++ ...-multi-route-multi-provider.listeners.yaml | 113 +++++ ...thn-multi-route-multi-provider.routes.yaml | 25 + ...-multi-route-single-provider.clusters.yaml | 59 +++ ...multi-route-single-provider.endpoints.yaml | 22 + ...multi-route-single-provider.listeners.yaml | 93 ++++ ...hn-multi-route-single-provider.routes.yaml | 25 + .../xds-ir/jwt-authn-ratelimit.clusters.yaml | 105 ++++ .../xds-ir/jwt-authn-ratelimit.endpoints.yaml | 44 ++ .../xds-ir/jwt-authn-ratelimit.listeners.yaml | 63 +++ .../xds-ir/jwt-authn-ratelimit.routes.yaml | 46 ++ ...hn-single-route-single-match.clusters.yaml | 45 ++ ...n-single-route-single-match.endpoints.yaml | 11 + ...n-single-route-single-match.listeners.yaml | 53 ++ ...uthn-single-route-single-match.routes.yaml | 16 + internal/xds/translator/translator.go | 8 +- internal/xds/translator/translator_test.go | 12 + site/content/en/latest/api/extension_types.md | 36 ++ 40 files changed, 2832 insertions(+), 73 deletions(-) create mode 100644 api/v1alpha1/validation/securitypolicy_validate.go create mode 100644 api/v1alpha1/validation/securitypolicy_validate_test.go create mode 100644 internal/gatewayapi/testdata/securitypolicy-with-jwt.in.yaml create mode 100755 internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml create mode 100644 internal/xds/translator/jwt_authn.go create mode 100644 internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-multi-provider.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-single-provider.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/jwt-authn-ratelimit.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/jwt-authn-single-route-single-match.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.clusters.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.endpoints.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.listeners.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.routes.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.routes.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.routes.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.routes.yaml diff --git a/api/v1alpha1/securitypolicy_types.go b/api/v1alpha1/securitypolicy_types.go index 05117a77278..c9d346f100f 100644 --- a/api/v1alpha1/securitypolicy_types.go +++ b/api/v1alpha1/securitypolicy_types.go @@ -43,17 +43,24 @@ type SecurityPolicySpec struct { TargetRef gwapiv1a2.PolicyTargetReferenceWithSectionName `json:"targetRef"` // CORS defines the configuration for Cross-Origin Resource Sharing (CORS). + // + // +optional CORS *CORS `json:"cors,omitempty"` + + // JWT defines the configuration for JSON Web Token (JWT) authentication. + // + // +optional + JWT *JWT `json:"jwt,omitempty"` } // CORS defines the configuration for Cross-Origin Resource Sharing (CORS). type CORS struct { // AllowOrigins defines the origins that are allowed to make requests. // +kubebuilder:validation:MinItems=1 - AllowOrigins []StringMatch `json:"allowOrigins,omitempty" yaml:"allowOrigins,omitempty"` + AllowOrigins []StringMatch `json:"allowOrigins,omitempty" yaml:"allowOrigins"` // AllowMethods defines the methods that are allowed to make requests. // +kubebuilder:validation:MinItems=1 - AllowMethods []string `json:"allowMethods,omitempty" yaml:"allowMethods,omitempty"` + AllowMethods []string `json:"allowMethods,omitempty" yaml:"allowMethods"` // AllowHeaders defines the headers that are allowed to be sent with requests. AllowHeaders []string `json:"allowHeaders,omitempty" yaml:"allowHeaders,omitempty"` // ExposeHeaders defines the headers that can be exposed in the responses. @@ -62,6 +69,58 @@ type CORS struct { MaxAge *metav1.Duration `json:"maxAge,omitempty" yaml:"maxAge,omitempty"` } +// JWT defines the configuration for JSON Web Token (JWT) authentication. +type JWT struct { + + // Providers defines the JSON Web Token (JWT) authentication provider type. + // + // When multiple JWT providers are specified, the JWT is considered valid if + // any of the providers successfully validate the JWT. For additional details, + // see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. + // + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=4 + Providers []JWTProvider `json:"providers"` +} + +// JWTProvider defines how a JSON Web Token (JWT) can be verified. +type JWTProvider struct { + // Name defines a unique name for the JWT provider. A name can have a variety of forms, + // including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name"` + + // Issuer is the principal that issued the JWT and takes the form of a URL or email address. + // For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 for + // URL format and https://rfc-editor.org/rfc/rfc5322.html for email format. If not provided, + // the JWT issuer is not checked. + // + // +kubebuilder:validation:MaxLength=253 + // +optional + Issuer string `json:"issuer,omitempty"` + + // Audiences is a list of JWT audiences allowed access. For additional details, see + // https://tools.ietf.org/html/rfc7519#section-4.1.3. If not provided, JWT audiences + // are not checked. + // + // +kubebuilder:validation:MaxItems=8 + // +optional + Audiences []string `json:"audiences,omitempty"` + + // RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote + // HTTP/HTTPS endpoint. + RemoteJWKS RemoteJWKS `json:"remoteJWKS"` + + // ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers + // For examples, following config: + // The claim must be of type; string, int, double, bool. Array type claims are not supported + // + ClaimToHeaders []ClaimToHeader `json:"claimToHeaders,omitempty"` + // TODO: Add TBD JWT fields based on defined use cases. +} + // StringMatch defines how to match any strings. // This is a general purpose match condition that can be used by other EG APIs // that need to match against a string. diff --git a/api/v1alpha1/validation/authenticationfilter.go b/api/v1alpha1/validation/authenticationfilter.go index 684d473f12e..378a63459fe 100644 --- a/api/v1alpha1/validation/authenticationfilter.go +++ b/api/v1alpha1/validation/authenticationfilter.go @@ -17,6 +17,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) +// TODO zhaohuabing remove this file after deprecating authentication filter // ValidateAuthenticationFilter validates the provided filter. The only supported // ValidateAuthenticationFilter type is "JWT". func ValidateAuthenticationFilter(filter *egv1a1.AuthenticationFilter) error { diff --git a/api/v1alpha1/validation/authenticationfilter_test.go b/api/v1alpha1/validation/authenticationfilter_test.go index 2ce3f272d0d..86470be158f 100644 --- a/api/v1alpha1/validation/authenticationfilter_test.go +++ b/api/v1alpha1/validation/authenticationfilter_test.go @@ -14,6 +14,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) +// TODO zhaohuabing remove this file after deprecating authentication filter func TestValidateAuthenticationFilter(t *testing.T) { testCases := []struct { name string diff --git a/api/v1alpha1/validation/securitypolicy_validate.go b/api/v1alpha1/validation/securitypolicy_validate.go new file mode 100644 index 00000000000..66bee6a8eb5 --- /dev/null +++ b/api/v1alpha1/validation/securitypolicy_validate.go @@ -0,0 +1,117 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package validation + +import ( + "errors" + "fmt" + "net/mail" + "net/url" + + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/validation" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +// ValidateSecurityPolicy validates the provided SecurityPolicy. +func ValidateSecurityPolicy(policy *egv1a1.SecurityPolicy) error { + var errs []error + if policy == nil { + return errors.New("policy is nil") + } + if err := validateSecurityPolicySpec(&policy.Spec); err != nil { + errs = append(errs, errors.New("policy is nil")) + } + + return utilerrors.NewAggregate(errs) +} + +// validateSecurityPolicySpec validates the provided spec. +func validateSecurityPolicySpec(spec *egv1a1.SecurityPolicySpec) error { + var errs []error + + sum := 0 + switch { + case spec == nil: + errs = append(errs, errors.New("spec is nil")) + case spec.CORS != nil: + sum++ + case spec.JWT != nil: + sum++ + } + if sum == 0 { + errs = append(errs, errors.New("no security policy is specified")) + } + + // Return early if any errors exist. + if len(errs) != 0 { + return utilerrors.NewAggregate(errs) + } + + if err := ValidateJWTProvider(spec.JWT.Providers); err != nil { + errs = append(errs, err) + } + + return utilerrors.NewAggregate(errs) +} + +// ValidateJWTProvider validates the provided JWT authentication configuration. +func ValidateJWTProvider(providers []egv1a1.JWTProvider) error { + var errs []error + + var names []string + for _, provider := range providers { + switch { + case len(provider.Name) == 0: + errs = append(errs, errors.New("jwt provider cannot be an empty string")) + case len(provider.Issuer) != 0: + // Issuer can take the format of a URL or an email address. + if _, err := url.ParseRequestURI(provider.Issuer); err != nil { + _, err := mail.ParseAddress(provider.Issuer) + if err != nil { + errs = append(errs, fmt.Errorf("invalid issuer; must be a URL or email address: %v", err)) + } + } + case len(provider.RemoteJWKS.URI) == 0: + errs = append(errs, fmt.Errorf("uri must be set for remote JWKS provider: %s", provider.Name)) + } + if _, err := url.ParseRequestURI(provider.RemoteJWKS.URI); err != nil { + errs = append(errs, fmt.Errorf("invalid remote JWKS URI: %v", err)) + } + + if len(errs) == 0 { + if strErrs := validation.IsQualifiedName(provider.Name); len(strErrs) != 0 { + for _, strErr := range strErrs { + errs = append(errs, errors.New(strErr)) + } + } + // Ensure uniqueness among provider names. + if names == nil { + names = append(names, provider.Name) + } else { + for _, name := range names { + if name == provider.Name { + errs = append(errs, fmt.Errorf("provider name %s must be unique", provider.Name)) + } else { + names = append(names, provider.Name) + } + } + } + } + + for _, claimToHeader := range provider.ClaimToHeaders { + switch { + case len(claimToHeader.Header) == 0: + errs = append(errs, fmt.Errorf("header must be set for claimToHeader provider: %s", claimToHeader.Header)) + case len(claimToHeader.Claim) == 0: + errs = append(errs, fmt.Errorf("claim must be set for claimToHeader provider: %s", claimToHeader.Claim)) + } + } + } + + return utilerrors.NewAggregate(errs) +} diff --git a/api/v1alpha1/validation/securitypolicy_validate_test.go b/api/v1alpha1/validation/securitypolicy_validate_test.go new file mode 100644 index 00000000000..489c7644f8b --- /dev/null +++ b/api/v1alpha1/validation/securitypolicy_validate_test.go @@ -0,0 +1,479 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package validation + +import ( + "testing" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +func TestValidateSecurityPolicy(t *testing.T) { + testCases := []struct { + name string + policy *egv1a1.SecurityPolicy + expected bool + }{ + { + name: "nil security policy", + policy: nil, + expected: false, + }, + { + name: "empty security policy", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{}, + }, + expected: false, + }, + { + name: "valid security policy with url", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "https://www.test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + }, + }, + }, + }, + expected: true, + }, + { + name: "valid security policy with email", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "test@test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + }, + }, + }, + }, + expected: true, + }, + { + name: "valid security policy with jwtClaimToHeader", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "test@test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + ClaimToHeaders: []egv1a1.ClaimToHeader{ + { + Header: "test", + Claim: "test", + }, + }, + }, + }, + }, + }, + }, + expected: true, + }, + { + name: "unqualified authentication provider name", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "unqualified_...", + Issuer: "https://www.test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "unspecified provider name", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "", + Issuer: "https://www.test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "non unique provider names", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "unique", + Issuer: "https://www.test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + { + Name: "non-unique", + Issuer: "https://www.test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + { + Name: "non-unique", + Issuer: "https://www.test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "invalid issuer uri", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "http://invalid url.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "http://www.test.local", + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "inivalid issuer email", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "test@!123...", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "invalid remote jwks uri", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "http://www.test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "invalid/local", + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "unspecified remote jwks uri", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "", + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "unspecified jwtClaimToHeader headerName", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "test@test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + ClaimToHeaders: []egv1a1.ClaimToHeader{ + { + Header: "", + Claim: "test", + }, + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "unspecified jwtClaimToHeader claimName", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "test@test.local", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + ClaimToHeaders: []egv1a1.ClaimToHeader{ + { + Header: "test", + Claim: "", + }, + }, + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "unspecified issuer", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Audiences: []string{"test.local"}, + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + }, + }, + }, + }, + expected: true, + }, + { + name: "unspecified audiences", + policy: &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.SecurityPolicySpec{ + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test", + Issuer: "https://www.test.local", + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test.local/jwt/public-key/jwks.json", + }, + }, + }, + }, + }, + }, + expected: true, + }, + } + + for i := range testCases { + tc := testCases[i] + t.Run(tc.name, func(t *testing.T) { + err := ValidateSecurityPolicy(tc.policy) + if tc.expected { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 0854f1f8fe5..be47b98c57d 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1298,6 +1298,54 @@ func (in *JSONPatchOperation) DeepCopy() *JSONPatchOperation { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JWT) DeepCopyInto(out *JWT) { + *out = *in + if in.Providers != nil { + in, out := &in.Providers, &out.Providers + *out = make([]JWTProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWT. +func (in *JWT) DeepCopy() *JWT { + if in == nil { + return nil + } + out := new(JWT) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JWTProvider) DeepCopyInto(out *JWTProvider) { + *out = *in + if in.Audiences != nil { + in, out := &in.Audiences, &out.Audiences + *out = make([]string, len(*in)) + copy(*out, *in) + } + out.RemoteJWKS = in.RemoteJWKS + if in.ClaimToHeaders != nil { + in, out := &in.ClaimToHeaders, &out.ClaimToHeaders + *out = make([]ClaimToHeader, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWTProvider. +func (in *JWTProvider) DeepCopy() *JWTProvider { + if in == nil { + return nil + } + out := new(JWTProvider) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JwtAuthenticationFilterProvider) DeepCopyInto(out *JwtAuthenticationFilterProvider) { *out = *in @@ -2223,6 +2271,11 @@ func (in *SecurityPolicySpec) DeepCopyInto(out *SecurityPolicySpec) { *out = new(CORS) (*in).DeepCopyInto(*out) } + if in.JWT != nil { + in, out := &in.JWT, &out.JWT + *out = new(JWT) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityPolicySpec. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index e3bf0d73926..d371e6b02ca 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -98,6 +98,92 @@ spec: request can be cached. type: string type: object + jwt: + description: JWT defines the configuration for JSON Web Token (JWT) + authentication. + properties: + providers: + description: "Providers defines the JSON Web Token (JWT) authentication + provider type. \n When multiple JWT providers are specified, + the JWT is considered valid if any of the providers successfully + validate the JWT. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html." + items: + description: JWTProvider defines how a JSON Web Token (JWT) + can be verified. + properties: + audiences: + description: Audiences is a list of JWT audiences allowed + access. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.3. + If not provided, JWT audiences are not checked. + items: + type: string + maxItems: 8 + type: array + claimToHeaders: + description: 'ClaimToHeaders is a list of JWT claims that + must be extracted into HTTP request headers For examples, + following config: The claim must be of type; string, int, + double, bool. Array type claims are not supported' + items: + description: ClaimToHeader defines a configuration to + convert JWT claims into HTTP headers + properties: + claim: + description: 'Claim is the JWT Claim that should be + saved into the header : it can be a nested claim + of type (eg. "claim.nested.key", "sub"). The nested + claim name must use dot "." to separate the JSON + name path.' + type: string + header: + description: Header defines the name of the HTTP request + header that the JWT Claim will be saved into. + type: string + required: + - claim + - header + type: object + type: array + issuer: + description: Issuer is the principal that issued the JWT + and takes the form of a URL or email address. For additional + details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 + for URL format and https://rfc-editor.org/rfc/rfc5322.html + for email format. If not provided, the JWT issuer is not + checked. + maxLength: 253 + type: string + name: + description: Name defines a unique name for the JWT provider. + A name can have a variety of forms, including RFC1123 + subdomains, RFC 1123 labels, or RFC 1035 labels. + maxLength: 253 + minLength: 1 + type: string + remoteJWKS: + description: RemoteJWKS defines how to fetch and cache JSON + Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. + properties: + uri: + description: URI is the HTTPS URI to fetch the JWKS. + Envoy's system trust bundle is used to validate the + server certificate. + maxLength: 253 + minLength: 1 + type: string + required: + - uri + type: object + required: + - name + - remoteJWKS + type: object + maxItems: 4 + minItems: 1 + type: array + required: + - providers + type: object targetRef: description: TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 57df03abee4..1b52af2bbf9 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -222,19 +222,30 @@ func resolveSecurityPolicyRouteTargetRef(policy *egv1a1.SecurityPolicy, routes m func (t *Translator) translateSecurityPolicyForRoute(policy *egv1a1.SecurityPolicy, route RouteContext, xdsIR XdsIRMap) { // Build IR - var cors *ir.CORS + var ( + cors *ir.CORS + jwt *ir.JWT + ) + if policy.Spec.CORS != nil { cors = t.buildCORS(policy) } + if policy.Spec.JWT != nil { + jwt = t.buildJWT(policy) + } + // Apply IR to all relevant routes prefix := irRoutePrefix(route) for _, ir := range xdsIR { for _, http := range ir.HTTP { for _, r := range http.Routes { // Apply if there is a match + // TODO zhaohuabing: extract a utils function to check if an HTTP + // route is associated with a Gateway API xRoute if strings.HasPrefix(r.Name, prefix) { r.CORS = cors + r.JWT = jwt } } } @@ -244,13 +255,21 @@ func (t *Translator) translateSecurityPolicyForRoute(policy *egv1a1.SecurityPoli func (t *Translator) translateSecurityPolicyForGateway(policy *egv1a1.SecurityPolicy, gateway *GatewayContext, xdsIR XdsIRMap) { // Build IR - var cors *ir.CORS + var ( + cors *ir.CORS + jwt *ir.JWT + ) + if policy.Spec.CORS != nil { cors = t.buildCORS(policy) } + if policy.Spec.JWT != nil { + jwt = t.buildJWT(policy) + } + // Apply IR to all the routes within the specific Gateway - // If the feature is already set, then skip it, since it must be have + // If the feature is already set, then skip it, since it must have be // set by a policy attaching to the route irKey := t.getIRKey(gateway.Gateway) // Should exist since we've validated this @@ -262,6 +281,9 @@ func (t *Translator) translateSecurityPolicyForGateway(policy *egv1a1.SecurityPo if r.CORS == nil { r.CORS = cors } + if r.JWT == nil { + r.JWT = jwt + } } } @@ -308,3 +330,9 @@ func (t *Translator) buildCORS(policy *egv1a1.SecurityPolicy) *ir.CORS { MaxAge: policy.Spec.CORS.MaxAge, } } + +func (t *Translator) buildJWT(policy *egv1a1.SecurityPolicy) *ir.JWT { + return &ir.JWT{ + Providers: policy.Spec.JWT.Providers, + } +} diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt.in.yaml new file mode 100644 index 00000000000..b7eec111123 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt.in.yaml @@ -0,0 +1,118 @@ +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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 +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-2 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: envoy-gateway + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + jwt: + providers: + - name: example1 + issuer: https://one.example.com + audiences: + - one.foo.com + remoteJWKS: + uri: https://one.example.com/jwt/public-key/jwks.json + claimToHeaders: + - header: one-route-example-key + claim: claim1 + - name: example2 + issuer: https://two.example.com + audiences: + - two.foo.com + remoteJWKS: + uri: https://two.example.com/jwt/public-key/jwks.json + claimToHeaders: + - header: two-route-example-key + claim: claim2 +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + jwt: + providers: + - name: example3 + issuer: https://three.example.com + audiences: + - three.foo.com + remoteJWKS: + uri: https://three.example.com/jwt/public-key/jwks.json + claimToHeaders: + - header: three-route-example-key + claim: claim3 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml new file mode 100755 index 00000000000..8acf1b66a51 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml @@ -0,0 +1,337 @@ +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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + 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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + creationTimestamp: null + name: grpcroute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + 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 +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-2 + 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-2 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: "" + ports: + - containerPort: 10080 + name: http + 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 + envoy-gateway/gateway-2: + proxy: + listeners: + - address: "" + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-2 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-2 +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-route + namespace: default + spec: + jwt: + providers: + - audiences: + - three.foo.com + claimToHeaders: + - claim: claim3 + header: three-route-example-key + issuer: https://three.example.com + name: example3 + remoteJWKS: + uri: https://three.example.com/jwt/public-key/jwks.json + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: SecurityPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: envoy-gateway + spec: + jwt: + providers: + - audiences: + - one.foo.com + claimToHeaders: + - claim: claim1 + header: one-route-example-key + issuer: https://one.example.com + name: example1 + remoteJWKS: + uri: https://one.example.com/jwt/public-key/jwks.json + - audiences: + - two.foo.com + claimToHeaders: + - claim: claim2 + header: two-route-example-key + issuer: https://two.example.com + name: example2 + remoteJWKS: + uri: https://two.example.com/jwt/public-key/jwks.json + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + status: + conditions: + - lastTransitionTime: null + message: SecurityPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: true + name: envoy-gateway/gateway-1/http + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: grpcroute/default/grpcroute-1/rule/0 + settings: + - endpoints: + - host: 7.7.7.7 + port: 8080 + weight: 1 + hostname: '*' + jwt: + providers: + - audiences: + - one.foo.com + claimToHeaders: + - claim: claim1 + header: one-route-example-key + issuer: https://one.example.com + name: example1 + remoteJWKS: + uri: https://one.example.com/jwt/public-key/jwks.json + - audiences: + - two.foo.com + claimToHeaders: + - claim: claim2 + header: two-route-example-key + issuer: https://two.example.com + name: example2 + remoteJWKS: + uri: https://two.example.com/jwt/public-key/jwks.json + name: grpcroute/default/grpcroute-1/rule/0/match/-1/* + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - endpoints: + - host: 7.7.7.7 + port: 8080 + weight: 1 + hostname: gateway.envoyproxy.io + jwt: + providers: + - audiences: + - three.foo.com + claimToHeaders: + - claim: claim3 + header: three-route-example-key + issuer: https://three.example.com + name: example3 + remoteJWKS: + uri: https://three.example.com/jwt/public-key/jwks.json + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / diff --git a/internal/ir/xds.go b/internal/ir/xds.go index e7bf0415621..6a7a0041918 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -273,7 +273,7 @@ type HTTPRoute struct { // RateLimit defines the more specific match conditions as well as limits for ratelimiting // the requests on this route. RateLimit *RateLimit `json:"rateLimit,omitempty" yaml:"rateLimit,omitempty"` - // RequestAuthentication defines the schema for authenticating HTTP requests. + // RequestAuthentication defines the schema for authenticating HTTP requests. //TODO zhaohuabing remove this field RequestAuthentication *RequestAuthentication `json:"requestAuthentication,omitempty" yaml:"requestAuthentication,omitempty"` // Timeout is the time until which entire response is received from the upstream. Timeout *metav1.Duration `json:"timeout,omitempty" yaml:"timeout,omitempty"` @@ -281,6 +281,8 @@ type HTTPRoute struct { LoadBalancer *LoadBalancer `json:"loadBalancer,omitempty" yaml:"loadBalancer,omitempty"` // CORS policy for the route. CORS *CORS `json:"cors,omitempty" yaml:"cors,omitempty"` + // JWT defines the schema for authenticating HTTP requests using JSON Web Tokens (JWT). + JWT *JWT `json:"jwt,omitempty" yaml:"jwt,omitempty"` // ExtensionRefs holds unstructured resources that were introduced by an extension and used on the HTTPRoute as extensionRef filters ExtensionRefs []*UnstructuredRef `json:"extensionRefs,omitempty" yaml:"extensionRefs,omitempty"` } @@ -300,6 +302,7 @@ type UnstructuredRef struct { // TODO: Add support for additional request authentication providers, i.e. OIDC. // // +k8s:deepcopy-gen=true +// TODO zhaohuabing remove this type type RequestAuthentication struct { // JWT defines the schema for authenticating HTTP requests using JSON Web Tokens (JWT). JWT *JwtRequestAuthentication `json:"jwt,omitempty" yaml:"jwt,omitempty"` @@ -309,6 +312,7 @@ type RequestAuthentication struct { // JSON Web Tokens (JWT). // // +k8s:deepcopy-gen=true +// TODO zhaohuabing remove this type type JwtRequestAuthentication struct { // Providers defines a list of JSON Web Token (JWT) authentication providers. Providers []egv1a1.JwtAuthenticationFilterProvider `json:"providers,omitempty" yaml:"providers,omitempty"` @@ -330,6 +334,15 @@ type CORS struct { MaxAge *metav1.Duration `json:"maxAge,omitempty" yaml:"maxAge,omitempty"` } +// JWT defines the schema for authenticating HTTP requests using +// JSON Web Tokens (JWT). +// +// +k8s:deepcopy-gen=true +type JWT struct { + // Providers defines a list of JSON Web Token (JWT) authentication providers. + Providers []egv1a1.JWTProvider `json:"providers,omitempty" yaml:"providers,omitempty"` +} + // Validate the fields within the HTTPRoute structure func (h HTTPRoute) Validate() error { var errs error @@ -446,6 +459,11 @@ func (h HTTPRoute) Validate() error { errs = multierror.Append(errs, err) } } + if h.JWT != nil { + if err := h.JWT.validate(); err != nil { + errs = multierror.Append(errs, err) + } + } return errs } @@ -460,6 +478,16 @@ func (j *JwtRequestAuthentication) Validate() error { return errs } +func (j *JWT) validate() error { + var errs error + + if err := validation.ValidateJWTProvider(j.Providers); err != nil { + errs = multierror.Append(errs, err) + } + + return errs +} + // RouteDestination holds the destination details associated with the route // +kubebuilder:object:generate=true type RouteDestination struct { diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index 5d5344b8e02..17ca9878751 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -426,14 +426,12 @@ var ( PathMatch: &StringMatch{ Exact: ptrTo("jwtauthen"), }, - RequestAuthentication: &RequestAuthentication{ - JWT: &JwtRequestAuthentication{ - Providers: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test1", - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test1.local", - }, + JWT: &JWT{ + Providers: []egv1a1.JWTProvider{ + { + Name: "test1", + RemoteJWKS: egv1a1.RemoteJWKS{ + URI: "https://test1.local", }, }, }, @@ -1072,20 +1070,20 @@ func TestValidateStringMatch(t *testing.T) { func TestValidateJwtRequestAuthentication(t *testing.T) { tests := []struct { name string - input JwtRequestAuthentication + input JWT want error }{ { name: "nil rules", - input: JwtRequestAuthentication{ + input: JWT{ Providers: nil, }, want: nil, }, { name: "provider with remote jwks uri", - input: JwtRequestAuthentication{ - Providers: []egv1a1.JwtAuthenticationFilterProvider{ + input: JWT{ + Providers: []egv1a1.JWTProvider{ { Name: "test", Issuer: "https://test.local", @@ -1103,9 +1101,9 @@ func TestValidateJwtRequestAuthentication(t *testing.T) { test := tests[i] t.Run(test.name, func(t *testing.T) { if test.want == nil { - require.NoError(t, test.input.Validate()) + require.NoError(t, test.input.validate()) } else { - require.EqualError(t, test.input.Validate(), test.want.Error()) + require.EqualError(t, test.input.validate(), test.want.Error()) } }) } diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 02173a1ae7f..8044ec291a5 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -461,6 +461,11 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = new(CORS) (*in).DeepCopyInto(*out) } + if in.JWT != nil { + in, out := &in.JWT, &out.JWT + *out = new(JWT) + (*in).DeepCopyInto(*out) + } if in.ExtensionRefs != nil { in, out := &in.ExtensionRefs, &out.ExtensionRefs *out = make([]*UnstructuredRef, len(*in)) @@ -580,6 +585,28 @@ func (in *JSONPatchOperation) DeepCopy() *JSONPatchOperation { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JWT) DeepCopyInto(out *JWT) { + *out = *in + if in.Providers != nil { + in, out := &in.Providers, &out.Providers + *out = make([]v1alpha1.JWTProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWT. +func (in *JWT) DeepCopy() *JWT { + if in == nil { + return nil + } + out := new(JWT) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JwtRequestAuthentication) DeepCopyInto(out *JwtRequestAuthentication) { *out = *in diff --git a/internal/xds/translator/authentication.go b/internal/xds/translator/authentication.go index 80426d4f320..17fd874edd4 100644 --- a/internal/xds/translator/authentication.go +++ b/internal/xds/translator/authentication.go @@ -17,9 +17,7 @@ import ( routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" jwtauthnv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/jwt_authn/v3" 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" "github.com/envoyproxy/go-control-plane/pkg/resource/v3" - "github.com/envoyproxy/go-control-plane/pkg/wellknown" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" @@ -29,11 +27,7 @@ import ( "github.com/envoyproxy/gateway/internal/xds/types" ) -const ( - jwtAuthenFilter = "envoy.filters.http.jwt_authn" - envoyTrustBundle = "/etc/ssl/certs/ca-certificates.crt" -) - +// TODO zhaohuabing remove this file after deprecating authentication filter // patchHCMWithJwtAuthnFilter builds and appends the Jwt Filter to the HTTP // Connection Manager if applicable, and it does not already exist. func patchHCMWithJwtAuthnFilter(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error { @@ -51,7 +45,7 @@ func patchHCMWithJwtAuthnFilter(mgr *hcmv3.HttpConnectionManager, irListener *ir // Return early if filter already exists. for _, httpFilter := range mgr.HttpFilters { - if httpFilter.Name == jwtAuthenFilter { + if httpFilter.Name == jwtAuthnFilter { return nil } } @@ -84,7 +78,7 @@ func buildHCMJwtFilter(irListener *ir.HTTPListener) (*hcmv3.HttpFilter, error) { } return &hcmv3.HttpFilter{ - Name: jwtAuthenFilter, + Name: jwtAuthnFilter, ConfigType: &hcmv3.HttpFilter_TypedConfig{ TypedConfig: jwtAuthnAny, }, @@ -164,36 +158,6 @@ func buildJwtAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, }, nil } -// buildXdsUpstreamTLSSocket returns an xDS TransportSocket that uses envoyTrustBundle -// as the CA to authenticate server certificates. -func buildXdsUpstreamTLSSocket() (*corev3.TransportSocket, error) { - tlsCtxProto := &tlsv3.UpstreamTlsContext{ - CommonTlsContext: &tlsv3.CommonTlsContext{ - ValidationContextType: &tlsv3.CommonTlsContext_ValidationContext{ - ValidationContext: &tlsv3.CertificateValidationContext{ - TrustedCa: &corev3.DataSource{ - Specifier: &corev3.DataSource_Filename{ - Filename: envoyTrustBundle, - }, - }, - }, - }, - }, - } - - tlsCtxAny, err := anypb.New(tlsCtxProto) - if err != nil { - return nil, err - } - - return &corev3.TransportSocket{ - Name: wellknown.TransportSocketTls, - ConfigType: &corev3.TransportSocket_TypedConfig{ - TypedConfig: tlsCtxAny, - }, - }, nil -} - // patchRouteWithJwtConfig patches the provided route with a JWT PerRouteConfig, if the // route doesn't contain it. func patchRouteWithJwtConfig(route *routev3.Route, irRoute *ir.HTTPRoute) error { @@ -205,7 +169,7 @@ func patchRouteWithJwtConfig(route *routev3.Route, irRoute *ir.HTTPRoute) error } filterCfg := route.GetTypedPerFilterConfig() - if _, ok := filterCfg[jwtAuthenFilter]; !ok { + if _, ok := filterCfg[jwtAuthnFilter]; !ok { if !routeContainsJwtAuthn(irRoute) { return nil } @@ -222,19 +186,12 @@ func patchRouteWithJwtConfig(route *routev3.Route, irRoute *ir.HTTPRoute) error route.TypedPerFilterConfig = make(map[string]*anypb.Any) } - route.TypedPerFilterConfig[jwtAuthenFilter] = routeCfgAny + route.TypedPerFilterConfig[jwtAuthnFilter] = routeCfgAny } return nil } -type jwksCluster struct { - name string - hostname string - port uint32 - isStatic bool -} - // createJwksClusters creates JWKS clusters from the provided routes, if needed. func createJwksClusters(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRoute) error { if tCtx == nil || diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index cef974cec33..4aba259b1e5 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -40,7 +40,7 @@ func newOrderedHTTPFilter(filter *hcmv3.HttpFilter) *OrderedHTTPFilter { switch filter.Name { case wellknown.CORS: order = 1 - case jwtAuthenFilter: + case jwtAuthnFilter: order = 2 case wellknown.HTTPRateLimit: order = 3 @@ -101,6 +101,7 @@ func (t *Translator) patchHCMWithFilters( t.patchHCMWithRateLimit(mgr, irListener) // Add the jwt authn filter, if needed. + // TODO zhaohuabing remove this after deprecating authentication filter if err := patchHCMWithJwtAuthnFilter(mgr, irListener); err != nil { return err } @@ -110,6 +111,11 @@ func (t *Translator) patchHCMWithFilters( return err } + // Add the jwt authn filter, if needed. + if err := patchHCMWithJWTAuthnFilter(mgr, irListener); err != nil { + return err + } + // Add the router filter mgr.HttpFilters = append(mgr.HttpFilters, xdsfilters.HTTPRouter) @@ -129,7 +135,7 @@ func patchRouteWithFilters( return nil } - // Add the jwt per route config to the route, if needed. + // Add the jwt per route config to the route, if needed. // TODO zhaohuabing remove this after deprecating authentication filter if err := patchRouteWithJwtConfig(route, irRoute); err != nil { return nil } @@ -138,5 +144,11 @@ func patchRouteWithFilters( if err := patchRouteWithCORSConfig(route, irRoute); err != nil { return err } + + // Add the jwt per route config to the route, if needed. + if err := patchRouteWithJWTConfig(route, irRoute); err != nil { + return nil + } + return nil } diff --git a/internal/xds/translator/httpfilters_test.go b/internal/xds/translator/httpfilters_test.go index 928afb183c4..ae4f0452014 100644 --- a/internal/xds/translator/httpfilters_test.go +++ b/internal/xds/translator/httpfilters_test.go @@ -24,12 +24,12 @@ func Test_sortHTTPFilters(t *testing.T) { filters: []*hcmv3.HttpFilter{ httpFilterForTest(wellknown.Router), httpFilterForTest(wellknown.CORS), - httpFilterForTest(jwtAuthenFilter), + httpFilterForTest(jwtAuthnFilter), httpFilterForTest(wellknown.HTTPRateLimit), }, want: []*hcmv3.HttpFilter{ httpFilterForTest(wellknown.CORS), - httpFilterForTest(jwtAuthenFilter), + httpFilterForTest(jwtAuthnFilter), httpFilterForTest(wellknown.HTTPRateLimit), httpFilterForTest(wellknown.Router), }, diff --git a/internal/xds/translator/jwt_authn.go b/internal/xds/translator/jwt_authn.go new file mode 100644 index 00000000000..7003bcac3fb --- /dev/null +++ b/internal/xds/translator/jwt_authn.go @@ -0,0 +1,359 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package translator + +import ( + "errors" + "fmt" + "net" + "net/url" + "strconv" + "strings" + + corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + jwtauthnv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/jwt_authn/v3" + 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" + "github.com/envoyproxy/go-control-plane/pkg/resource/v3" + "github.com/envoyproxy/go-control-plane/pkg/wellknown" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/ir" + "github.com/envoyproxy/gateway/internal/utils/ptr" + "github.com/envoyproxy/gateway/internal/xds/types" +) + +const ( + jwtAuthnFilter = "envoy.filters.http.jwt_authn" + envoyTrustBundle = "/etc/ssl/certs/ca-certificates.crt" +) + +// patchHCMWithJWTAuthnFilter builds and appends the Jwt Filter to the HTTP +// Connection Manager if applicable, and it does not already exist. +func patchHCMWithJWTAuthnFilter(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error { + if mgr == nil { + return errors.New("hcm is nil") + } + + if irListener == nil { + return errors.New("ir listener is nil") + } + + if !listenerContainsJWTAuthn(irListener) { + return nil + } + + // Return early if filter already exists. + for _, httpFilter := range mgr.HttpFilters { + if httpFilter.Name == jwtAuthnFilter { + return nil + } + } + + jwtFilter, err := buildHCMJWTFilter(irListener) + if err != nil { + return err + } + + // Ensure the authn filter is the first and the terminal filter is the last in the chain. + mgr.HttpFilters = append([]*hcmv3.HttpFilter{jwtFilter}, mgr.HttpFilters...) + + return nil +} + +// buildHCMJWTFilter returns a JWT authn HTTP filter from the provided IR listener. +func buildHCMJWTFilter(irListener *ir.HTTPListener) (*hcmv3.HttpFilter, error) { + jwtAuthnProto, err := buildJWTAuthn(irListener) + if err != nil { + return nil, err + } + + if err := jwtAuthnProto.ValidateAll(); err != nil { + return nil, err + } + + jwtAuthnAny, err := anypb.New(jwtAuthnProto) + if err != nil { + return nil, err + } + + return &hcmv3.HttpFilter{ + Name: jwtAuthnFilter, + ConfigType: &hcmv3.HttpFilter_TypedConfig{ + TypedConfig: jwtAuthnAny, + }, + }, nil +} + +// buildJWTAuthn returns a JwtAuthentication based on the provided IR HTTPListener. +func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, error) { + jwtProviders := make(map[string]*jwtauthnv3.JwtProvider) + reqMap := make(map[string]*jwtauthnv3.JwtRequirement) + + for _, route := range irListener.Routes { + if route != nil && routeContainsJWTAuthn(route) { + var reqs []*jwtauthnv3.JwtRequirement + for i := range route.JWT.Providers { + irProvider := route.JWT.Providers[i] + // Create the cluster for the remote jwks, if it doesn't exist. + jwksCluster, err := newJWKSCluster(&irProvider) + if err != nil { + return nil, err + } + + remote := &jwtauthnv3.JwtProvider_RemoteJwks{ + RemoteJwks: &jwtauthnv3.RemoteJwks{ + HttpUri: &corev3.HttpUri{ + Uri: irProvider.RemoteJWKS.URI, + HttpUpstreamType: &corev3.HttpUri_Cluster{ + Cluster: jwksCluster.name, + }, + Timeout: &durationpb.Duration{Seconds: 5}, + }, + CacheDuration: &durationpb.Duration{Seconds: 5 * 60}, + AsyncFetch: &jwtauthnv3.JwksAsyncFetch{}, + RetryPolicy: &corev3.RetryPolicy{}, + }, + } + + claimToHeaders := []*jwtauthnv3.JwtClaimToHeader{} + for _, claimToHeader := range irProvider.ClaimToHeaders { + claimToHeader := &jwtauthnv3.JwtClaimToHeader{HeaderName: claimToHeader.Header, ClaimName: claimToHeader.Claim} + claimToHeaders = append(claimToHeaders, claimToHeader) + } + jwtProvider := &jwtauthnv3.JwtProvider{ + Issuer: irProvider.Issuer, + Audiences: irProvider.Audiences, + JwksSourceSpecifier: remote, + PayloadInMetadata: irProvider.Issuer, + ClaimToHeaders: claimToHeaders, + } + + providerKey := fmt.Sprintf("%s/%s", route.Name, irProvider.Name) + jwtProviders[providerKey] = jwtProvider + reqs = append(reqs, &jwtauthnv3.JwtRequirement{ + RequiresType: &jwtauthnv3.JwtRequirement_ProviderName{ + ProviderName: providerKey, + }, + }) + } + if len(reqs) == 1 { + reqMap[route.Name] = reqs[0] + } else { + orListReqs := &jwtauthnv3.JwtRequirement{ + RequiresType: &jwtauthnv3.JwtRequirement_RequiresAny{ + RequiresAny: &jwtauthnv3.JwtRequirementOrList{ + Requirements: reqs, + }, + }, + } + reqMap[route.Name] = orListReqs + } + } + } + + return &jwtauthnv3.JwtAuthentication{ + RequirementMap: reqMap, + Providers: jwtProviders, + }, nil +} + +// buildXdsUpstreamTLSSocket returns an xDS TransportSocket that uses envoyTrustBundle +// as the CA to authenticate server certificates. +func buildXdsUpstreamTLSSocket() (*corev3.TransportSocket, error) { + tlsCtxProto := &tlsv3.UpstreamTlsContext{ + CommonTlsContext: &tlsv3.CommonTlsContext{ + ValidationContextType: &tlsv3.CommonTlsContext_ValidationContext{ + ValidationContext: &tlsv3.CertificateValidationContext{ + TrustedCa: &corev3.DataSource{ + Specifier: &corev3.DataSource_Filename{ + Filename: envoyTrustBundle, + }, + }, + }, + }, + }, + } + + tlsCtxAny, err := anypb.New(tlsCtxProto) + if err != nil { + return nil, err + } + + return &corev3.TransportSocket{ + Name: wellknown.TransportSocketTls, + ConfigType: &corev3.TransportSocket_TypedConfig{ + TypedConfig: tlsCtxAny, + }, + }, nil +} + +// patchRouteWithJWTConfig patches the provided route with a JWT PerRouteConfig, if the +// route doesn't contain it. +func patchRouteWithJWTConfig(route *routev3.Route, irRoute *ir.HTTPRoute) error { + if route == nil { + return errors.New("xds route is nil") + } + if irRoute == nil { + return errors.New("ir route is nil") + } + + filterCfg := route.GetTypedPerFilterConfig() + if _, ok := filterCfg[jwtAuthnFilter]; !ok { + if !routeContainsJWTAuthn(irRoute) { + return nil + } + + routeCfgProto := &jwtauthnv3.PerRouteConfig{ + RequirementSpecifier: &jwtauthnv3.PerRouteConfig_RequirementName{RequirementName: irRoute.Name}} + + routeCfgAny, err := anypb.New(routeCfgProto) + if err != nil { + return err + } + + if filterCfg == nil { + route.TypedPerFilterConfig = make(map[string]*anypb.Any) + } + + route.TypedPerFilterConfig[jwtAuthnFilter] = routeCfgAny + } + + return nil +} + +type jwksCluster struct { + name string + hostname string + port uint32 + isStatic bool +} + +// createJWKSClusters creates JWKS clusters from the provided routes, if needed. +func createJWKSClusters(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRoute) error { + if tCtx == nil || + tCtx.XdsResources == nil || + tCtx.XdsResources[resource.ClusterType] == nil || + len(routes) == 0 { + return nil + } + + for _, route := range routes { + if routeContainsJWTAuthn(route) { + for i := range route.JWT.Providers { + provider := route.JWT.Providers[i] + jwks, err := newJWKSCluster(&provider) + epType := DefaultEndpointType + if jwks.isStatic { + epType = Static + } + if err != nil { + return err + } + ds := &ir.DestinationSetting{ + Weight: ptr.To(uint32(1)), + Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(jwks.hostname, jwks.port)}, + } + tSocket, err := buildXdsUpstreamTLSSocket() + if err != nil { + return err + } + if err := addXdsCluster(tCtx, &xdsClusterArgs{ + name: jwks.name, + settings: []*ir.DestinationSetting{ds}, + tSocket: tSocket, + protocol: DefaultProtocol, + endpointType: epType, + }); err != nil && !errors.Is(err, ErrXdsClusterExists) { + return err + } + } + } + } + + return nil +} + +// newJWKSCluster returns a jwksCluster from the provided provider. +func newJWKSCluster(provider *v1alpha1.JWTProvider) (*jwksCluster, error) { + static := false + if provider == nil { + return nil, errors.New("nil provider") + } + + u, err := url.Parse(provider.RemoteJWKS.URI) + if err != nil { + return nil, err + } + + var strPort string + switch u.Scheme { + case "https": + strPort = "443" + default: + return nil, fmt.Errorf("unsupported JWKS URI scheme %s", u.Scheme) + } + + if u.Port() != "" { + strPort = u.Port() + } + + name := fmt.Sprintf("%s_%s", strings.ReplaceAll(u.Hostname(), ".", "_"), strPort) + + port, err := strconv.Atoi(strPort) + if err != nil { + return nil, err + } + + if ip := net.ParseIP(u.Hostname()); ip != nil { + if v4 := ip.To4(); v4 != nil { + static = true + } + } + + return &jwksCluster{ + name: name, + hostname: u.Hostname(), + port: uint32(port), + isStatic: static, + }, nil +} + +// listenerContainsJWTAuthn returns true if JWT authentication exists for the +// provided listener. +func listenerContainsJWTAuthn(irListener *ir.HTTPListener) bool { + if irListener == nil { + return false + } + + for _, route := range irListener.Routes { + if routeContainsJWTAuthn(route) { + return true + } + } + + return false +} + +// routeContainsJWTAuthn returns true if JWT authentication exists for the +// provided route. +func routeContainsJWTAuthn(irRoute *ir.HTTPRoute) bool { + if irRoute == nil { + return false + } + + if irRoute != nil && + irRoute.JWT != nil && + irRoute.JWT.Providers != nil && + len(irRoute.JWT.Providers) > 0 { + return true + } + + return false +} diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-multi-provider.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-multi-provider.yaml new file mode 100644 index 00000000000..6abee5f0575 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-multi-provider.yaml @@ -0,0 +1,68 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + routes: + - name: "first-route-www.test.com" + hostname: "*" + pathMatch: + exact: "foo/bar" + jwt: + providers: + - name: example + issuer: https://www.example.com + audiences: + - foo.com + remoteJWKS: + uri: https://localhost/jwt/public-key/jwks.json + claimToHeaders: + - header: one-route-example-key1 + claim: claim.neteased.key + - name: example2 + issuer: https://www.two.example.com + audiences: + - one.foo.com + - two.foo.com + remoteJWKS: + uri: https://192.168.1.250:8080/jwt/public-key/jwks.json + claimToHeaders: + - header: one-route-example2-key1 + claim: claim.neteased.key + - header: one-route-example2-key2 + claim: name + destination: + name: "first-route-www.test.com-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - name: "second-route-www.test.com" + hostname: "*" + pathMatch: + exact: "foo/baz" + jwt: + providers: + - name: example + issuer: https://www.example.com + audiences: + - foo.com + remoteJWKS: + uri: https://localhost/jwt/public-key/jwks.json + claimToHeaders: + - header: second-route-example-key1 + claim: claim.neteased.key + - name: example2 + issuer: https://www.two.example.com + audiences: + - one.foo.com + - two.foo.com + remoteJWKS: + uri: https://192.168.1.250:8080/jwt/public-key/jwks.json + destination: + name: "second-route-www.test.com-dest" + settings: + - endpoints: + - host: "5.6.7.8" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-single-provider.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-single-provider.yaml new file mode 100644 index 00000000000..d9699c052f9 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-single-provider.yaml @@ -0,0 +1,49 @@ +accesslog: + text: + - path: "/dev/stdout" +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + routes: + - name: "first-route" + hostname: "*" + pathMatch: + exact: "foo/bar" + jwt: + providers: + - name: example + issuer: https://www.example.com + audiences: + - foo.com + remoteJWKS: + uri: https://localhost/jwt/public-key/jwks.json + claimToHeaders: + - header: first-route-key + claim: claim.neteased.key + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - name: "second-route" + hostname: "*" + pathMatch: + exact: "foo/baz" + jwt: + providers: + - name: example + issuer: https://www.example.com + audiences: + - foo.com + remoteJWKS: + uri: https://localhost/jwt/public-key/jwks.json + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "5.6.7.8" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-authn-ratelimit.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-authn-ratelimit.yaml new file mode 100644 index 00000000000..f4b24fe3525 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/jwt-authn-ratelimit.yaml @@ -0,0 +1,69 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + routes: + - name: "first-route" + hostname: "*" + rateLimit: + global: + rules: + - headerMatches: + - name: "x-user-id" + exact: "one" + limit: + requests: 5 + unit: second + pathMatch: + exact: "foo/bar" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + jwt: + providers: + - name: example + issuer: https://www.example.com + audiences: + - foo.com + remoteJWKS: + uri: https://192.168.1.250/jwt/public-key/jwks.json + - name: "second-route" + hostname: "*" + rateLimit: + global: + rules: + - headerMatches: + - name: "x-user-id" + distinct: true + limit: + requests: 5 + unit: second + pathMatch: + exact: "example" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - name: "third-route" + hostname: "*" + rateLimit: + global: + rules: + - limit: + requests: 5 + unit: second + pathMatch: + exact: "test" + destination: + name: "third-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-authn-single-route-single-match.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-authn-single-route-single-match.yaml new file mode 100644 index 00000000000..cb7b0a20946 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/jwt-authn-single-route-single-match.yaml @@ -0,0 +1,25 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + routes: + - name: "first-route" + hostname: "*" + pathMatch: + exact: "foo/bar" + jwt: + providers: + - name: example + issuer: https://www.example.com + audiences: + - foo.com + remoteJWKS: + uri: https://localhost/jwt/public-key/jwks.json + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.clusters.yaml new file mode 100755 index 00000000000..bf7f010954b --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.clusters.yaml @@ -0,0 +1,81 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-www.test.com-dest + lbPolicy: LEAST_REQUEST + name: first-route-www.test.com-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-www.test.com-dest + lbPolicy: LEAST_REQUEST + name: second-route-www.test.com-dest + 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 +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: "192_168_1_250_8080" + lbPolicy: LEAST_REQUEST + name: "192_168_1_250_8080" + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + 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: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.endpoints.yaml new file mode 100755 index 00000000000..7d394e5f496 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.endpoints.yaml @@ -0,0 +1,33 @@ +- clusterName: first-route-www.test.com-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} +- clusterName: second-route-www.test.com-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 5.6.7.8 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} +- clusterName: "192_168_1_250_8080" + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 192.168.1.250 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.listeners.yaml new file mode 100755 index 00000000000..1eec8005ef8 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.listeners.yaml @@ -0,0 +1,113 @@ +- 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.jwt_authn + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication + providers: + first-route-www.test.com/example: + audiences: + - foo.com + claimToHeaders: + - claimName: claim.neteased.key + headerName: one-route-example-key1 + 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: {} + first-route-www.test.com/example2: + audiences: + - one.foo.com + - two.foo.com + claimToHeaders: + - claimName: claim.neteased.key + headerName: one-route-example2-key1 + - claimName: name + headerName: one-route-example2-key2 + issuer: https://www.two.example.com + payloadInMetadata: https://www.two.example.com + remoteJwks: + asyncFetch: {} + cacheDuration: 300s + httpUri: + cluster: "192_168_1_250_8080" + timeout: 5s + uri: https://192.168.1.250:8080/jwt/public-key/jwks.json + retryPolicy: {} + second-route-www.test.com/example: + audiences: + - foo.com + claimToHeaders: + - claimName: claim.neteased.key + headerName: second-route-example-key1 + 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: {} + second-route-www.test.com/example2: + audiences: + - one.foo.com + - two.foo.com + issuer: https://www.two.example.com + payloadInMetadata: https://www.two.example.com + remoteJwks: + asyncFetch: {} + cacheDuration: 300s + httpUri: + cluster: "192_168_1_250_8080" + timeout: 5s + uri: https://192.168.1.250:8080/jwt/public-key/jwks.json + retryPolicy: {} + requirementMap: + first-route-www.test.com: + requiresAny: + requirements: + - providerName: first-route-www.test.com/example + - providerName: first-route-www.test.com/example2 + second-route-www.test.com: + requiresAny: + requirements: + - providerName: second-route-www.test.com/example + - providerName: second-route-www.test.com/example2 + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.routes.yaml new file mode 100755 index 00000000000..630157c4b40 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.routes.yaml @@ -0,0 +1,25 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + path: foo/bar + name: first-route-www.test.com + route: + cluster: first-route-www.test.com-dest + typedPerFilterConfig: + envoy.filters.http.jwt_authn: + '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig + requirementName: first-route-www.test.com + - match: + path: foo/baz + name: second-route-www.test.com + route: + cluster: second-route-www.test.com-dest + typedPerFilterConfig: + envoy.filters.http.jwt_authn: + '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig + requirementName: second-route-www.test.com diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.clusters.yaml new file mode 100644 index 00000000000..35bc85eaf5b --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.clusters.yaml @@ -0,0 +1,59 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + 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/jwt-authn-multi-route-single-provider.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.endpoints.yaml new file mode 100644 index 00000000000..b321ca1f8e7 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.endpoints.yaml @@ -0,0 +1,22 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 5.6.7.8 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.listeners.yaml new file mode 100644 index 00000000000..133530ef79f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.listeners.yaml @@ -0,0 +1,93 @@ +- accessLog: + - filter: + responseFlagFilter: + flags: + - NR + name: envoy.access_loggers.file + typedConfig: + '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + logFormat: + textFormatSource: + inlineString: | + {"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"} + path: /dev/stdout + 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 + accessLog: + - name: envoy.access_loggers.file + typedConfig: + '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + logFormat: + textFormatSource: + inlineString: | + {"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"} + path: /dev/stdout + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + 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 + claimToHeaders: + - claimName: claim.neteased.key + headerName: first-route-key + 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: {} + second-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 + second-route: + providerName: second-route/example + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.routes.yaml new file mode 100644 index 00000000000..2078809a694 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.routes.yaml @@ -0,0 +1,25 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + path: foo/bar + 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 + - match: + path: foo/baz + name: second-route + route: + cluster: second-route-dest + typedPerFilterConfig: + envoy.filters.http.jwt_authn: + '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig + requirementName: second-route diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.clusters.yaml new file mode 100644 index 00000000000..868cdb1b6c2 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.clusters.yaml @@ -0,0 +1,105 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: third-route-dest + lbPolicy: LEAST_REQUEST + name: third-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + dnsRefreshRate: 30s + lbPolicy: LEAST_REQUEST + loadAssignment: + clusterName: ratelimit_cluster + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: envoy-ratelimit.envoy-gateway-system.svc.cluster.local + portValue: 8081 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} + name: ratelimit_cluster + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + respectDnsTtl: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + commonTlsContext: + tlsCertificates: + - certificateChain: + filename: /certs/tls.crt + privateKey: + filename: /certs/tls.key + validationContext: + trustedCa: + filename: /certs/ca.crt + type: STRICT_DNS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: "192_168_1_250_443" + lbPolicy: LEAST_REQUEST + name: "192_168_1_250_443" + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + 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: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.endpoints.yaml new file mode 100644 index 00000000000..d8d04b17185 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.endpoints.yaml @@ -0,0 +1,44 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} +- clusterName: third-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} +- clusterName: "192_168_1_250_443" + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 192.168.1.250 + portValue: 443 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.listeners.yaml new file mode 100644 index 00000000000..8ff2832d64b --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.listeners.yaml @@ -0,0 +1,63 @@ +- 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.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: "192_168_1_250_443" + timeout: 5s + uri: https://192.168.1.250/jwt/public-key/jwks.json + retryPolicy: {} + requirementMap: + first-route: + providerName: first-route/example + - name: envoy.filters.http.ratelimit + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit + domain: first-listener + enableXRatelimitHeaders: DRAFT_VERSION_03 + rateLimitService: + grpcService: + envoyGrpc: + clusterName: ratelimit_cluster + transportApiVersion: V3 + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.routes.yaml new file mode 100644 index 00000000000..0223e989d39 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.routes.yaml @@ -0,0 +1,46 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + path: foo/bar + name: first-route + route: + cluster: first-route-dest + rateLimits: + - actions: + - headerValueMatch: + descriptorKey: first-route-key-rule-0-match-0 + descriptorValue: first-route-value-rule-0-match-0 + expectMatch: true + headers: + - name: x-user-id + stringMatch: + exact: one + typedPerFilterConfig: + envoy.filters.http.jwt_authn: + '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig + requirementName: first-route + - match: + path: example + name: second-route + route: + cluster: second-route-dest + rateLimits: + - actions: + - requestHeaders: + descriptorKey: second-route-key-rule-0-match-0 + headerName: x-user-id + - match: + path: test + name: third-route + route: + cluster: third-route-dest + rateLimits: + - actions: + - genericKey: + descriptorKey: third-route-key-rule-0-match--1 + descriptorValue: third-route-value-rule-0-match--1 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.clusters.yaml new file mode 100644 index 00000000000..7a0c933174e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.clusters.yaml @@ -0,0 +1,45 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- 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/jwt-authn-single-route-single-match.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.endpoints.yaml new file mode 100644 index 00000000000..0d68b430c20 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.endpoints.yaml @@ -0,0 +1,11 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.listeners.yaml new file mode 100644 index 00000000000..9a095ee2e29 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.listeners.yaml @@ -0,0 +1,53 @@ +- 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.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 + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.routes.yaml new file mode 100644 index 00000000000..c73bec09093 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.routes.yaml @@ -0,0 +1,16 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + path: foo/bar + 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 diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index a72b493e986..e13f8f4cc93 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -254,10 +254,16 @@ func (t *Translator) processHTTPListenerXdsTranslation(tCtx *types.ResourceVersi return err } - // Create authn jwks clusters, if needed. + // Create authn jwks clusters, if needed. // TODO zhaohuabing remove this after deprecating authentication filter if err := createJwksClusters(tCtx, httpListener.Routes); err != nil { return err } + + // Create authn jwks clusters, if needed. + if err := createJWKSClusters(tCtx, httpListener.Routes); err != nil { + return err + } + // Check if an extension want to modify the listener that was just configured/created // If no extension exists (or it doesn't subscribe to this hook) then this is a quick no-op if err := processExtensionPostListenerHook(tCtx, xdsListener, t.ExtensionManager); err != nil { diff --git a/internal/xds/translator/translator_test.go b/internal/xds/translator/translator_test.go index 2ca793722f1..6c6fd275397 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -193,6 +193,18 @@ func TestTranslateXds(t *testing.T) { { name: "cors", }, + { + name: "jwt-authn-multi-route-multi-provider", + }, + { + name: "jwt-authn-multi-route-single-provider", + }, + { + name: "jwt-authn-ratelimit", + }, + { + name: "jwt-authn-single-route-single-match", + }, } for _, tc := range testCases { diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 5e680fc52ba..b79f1dc2b94 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -158,6 +158,7 @@ _Appears in:_ ClaimToHeader defines a configuration to convert JWT claims into HTTP headers _Appears in:_ +- [JWTProvider](#jwtprovider) - [JwtAuthenticationFilterProvider](#jwtauthenticationfilterprovider) | Field | Description | @@ -906,6 +907,39 @@ _Appears in:_ +#### JWT + + + +JWT defines the configuration for JSON Web Token (JWT) authentication. + +_Appears in:_ +- [SecurityPolicySpec](#securitypolicyspec) + +| Field | Description | +| --- | --- | +| `providers` _[JWTProvider](#jwtprovider) array_ | Providers defines the JSON Web Token (JWT) authentication provider type. + When multiple JWT providers are specified, the JWT is considered valid if any of the providers successfully validate the JWT. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. | + + +#### JWTProvider + + + +JWTProvider defines how a JSON Web Token (JWT) can be verified. + +_Appears in:_ +- [JWT](#jwt) + +| Field | Description | +| --- | --- | +| `name` _string_ | Name defines a unique name for the JWT provider. A name can have a variety of forms, including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. | +| `issuer` _string_ | Issuer is the principal that issued the JWT and takes the form of a URL or email address. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 for URL format and https://rfc-editor.org/rfc/rfc5322.html for email format. If not provided, the JWT issuer is not checked. | +| `audiences` _string array_ | Audiences is a list of JWT audiences allowed access. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.3. If not provided, JWT audiences are not checked. | +| `remoteJWKS` _[RemoteJWKS](#remotejwks)_ | RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. | +| `claimToHeaders` _[ClaimToHeader](#claimtoheader) array_ | ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers For examples, following config: The claim must be of type; string, int, double, bool. Array type claims are not supported | + + #### JwtAuthenticationFilterProvider @@ -1560,6 +1594,7 @@ _Appears in:_ RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. _Appears in:_ +- [JWTProvider](#jwtprovider) - [JwtAuthenticationFilterProvider](#jwtauthenticationfilterprovider) | Field | Description | @@ -1639,6 +1674,7 @@ _Appears in:_ | --- | --- | | `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. TargetRef | | `cors` _[CORS](#cors)_ | CORS defines the configuration for Cross-Origin Resource Sharing (CORS). | +| `jwt` _[JWT](#jwt)_ | JWT defines the configuration for JSON Web Token (JWT) authentication. | From 54803c1abaa1da282e01a7e07cfcac71c64a15f9 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Thu, 26 Oct 2023 17:16:00 -0700 Subject: [PATCH 07/55] remove RateLimitFilter in favor of BackendTrafficPolicy (#2083) * remove RateLimitFilter in favor of BackendTrafficPolicy Relates to https://github.com/envoyproxy/gateway/issues/2006 Signed-off-by: Arko Dasgupta * fix tests Signed-off-by: Arko Dasgupta * fix e2e Signed-off-by: Arko Dasgupta * fix docs Signed-off-by: Arko Dasgupta * lint Signed-off-by: Arko Dasgupta --------- Signed-off-by: Arko Dasgupta --- api/v1alpha1/backendtrafficpolicy_types.go | 2 +- ...imitfilter_types.go => ratelimit_types.go} | 39 +- api/v1alpha1/zz_generated.deepcopy.go | 100 +--- ...ateway.envoyproxy.io_ratelimitfilters.yaml | 180 ------ ...lter-single-route-single-match-to-xds.yaml | 113 ---- ...-single-route-single-match-to-xds.all.json | 512 ------------------ ...-single-route-single-match-to-xds.all.yaml | 292 ---------- ...e-route-single-match-to-xds.bootstrap.yaml | 119 ---- ...gle-route-single-match-to-xds.cluster.yaml | 63 --- ...le-route-single-match-to-xds.endpoint.yaml | 17 - ...le-route-single-match-to-xds.listener.yaml | 72 --- ...ingle-route-single-match-to-xds.route.yaml | 28 - internal/cmd/egctl/translate.go | 14 - internal/cmd/egctl/translate_test.go | 77 --- internal/gatewayapi/filters.go | 98 ---- internal/gatewayapi/helpers.go | 22 - internal/gatewayapi/helpers_test.go | 48 -- internal/gatewayapi/resource.go | 2 - internal/gatewayapi/route.go | 3 - ...pcroute-with-valid-ratelimitfilter.in.yaml | 55 -- ...croute-with-valid-ratelimitfilter.out.yaml | 133 ----- ...with-distinct-sourcecidr-ratelimit.in.yaml | 59 -- ...ith-distinct-sourcecidr-ratelimit.out.yaml | 143 ----- ...route-with-invalid-ratelimitfilter.in.yaml | 60 -- ...oute-with-invalid-ratelimitfilter.out.yaml | 116 ---- ...ttproute-with-sourcecidr-ratelimit.in.yaml | 58 -- ...tproute-with-sourcecidr-ratelimit.out.yaml | 143 ----- ...tproute-with-valid-ratelimitfilter.in.yaml | 61 --- ...proute-with-valid-ratelimitfilter.out.yaml | 143 ----- internal/gatewayapi/zz_generated.deepcopy.go | 11 - internal/provider/kubernetes/controller.go | 71 +-- internal/provider/kubernetes/filters.go | 28 - .../provider/kubernetes/kubernetes_test.go | 211 -------- internal/provider/kubernetes/predicates.go | 24 - internal/provider/kubernetes/routes.go | 46 +- internal/provider/kubernetes/routes_test.go | 317 ----------- internal/provider/kubernetes/test/utils.go | 42 -- site/content/en/latest/api/extension_types.md | 54 +- site/content/en/latest/user/rate-limit.md | 429 +++------------ .../testdata/ratelimit-based-jwt-claims.yaml | 33 +- .../e2e/testdata/ratelimit-block-all-ips.yaml | 34 +- tools/crd-ref-docs/config.yaml | 2 +- 42 files changed, 170 insertions(+), 3904 deletions(-) rename api/v1alpha1/{ratelimitfilter_types.go => ratelimit_types.go} (84%) delete mode 100644 charts/gateway-helm/crds/generated/gateway.envoyproxy.io_ratelimitfilters.yaml delete mode 100644 internal/cmd/egctl/testdata/translate/in/rate-limit-filter-single-route-single-match-to-xds.yaml delete mode 100644 internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.all.json delete mode 100644 internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.all.yaml delete mode 100644 internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.bootstrap.yaml delete mode 100644 internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.cluster.yaml delete mode 100644 internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.endpoint.yaml delete mode 100644 internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.listener.yaml delete mode 100644 internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.route.yaml delete mode 100644 internal/gatewayapi/testdata/grpcroute-with-valid-ratelimitfilter.in.yaml delete mode 100644 internal/gatewayapi/testdata/grpcroute-with-valid-ratelimitfilter.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-distinct-sourcecidr-ratelimit.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-distinct-sourcecidr-ratelimit.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-invalid-ratelimitfilter.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-invalid-ratelimitfilter.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-sourcecidr-ratelimit.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-sourcecidr-ratelimit.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-valid-ratelimitfilter.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-valid-ratelimitfilter.out.yaml diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go index f01bb401d02..1d092a31dc5 100644 --- a/api/v1alpha1/backendtrafficpolicy_types.go +++ b/api/v1alpha1/backendtrafficpolicy_types.go @@ -49,7 +49,7 @@ type BackendTrafficPolicySpec struct { // RateLimit allows the user to limit the number of incoming requests // to a predefined value based on attributes within the traffic flow. // +optional - RateLimit *RateLimitFilterSpec `json:"rateLimit,omitempty"` + RateLimit *RateLimitSpec `json:"rateLimit,omitempty"` // LoadBalancer policy to apply when routing traffic from the gateway to // the backend endpoints diff --git a/api/v1alpha1/ratelimitfilter_types.go b/api/v1alpha1/ratelimit_types.go similarity index 84% rename from api/v1alpha1/ratelimitfilter_types.go rename to api/v1alpha1/ratelimit_types.go index 5ee825d3b3c..e013579efdf 100644 --- a/api/v1alpha1/ratelimitfilter_types.go +++ b/api/v1alpha1/ratelimit_types.go @@ -5,31 +5,9 @@ package v1alpha1 -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - // KindRateLimitFilter is the name of the RateLimitFilter kind. - KindRateLimitFilter = "RateLimitFilter" -) - -// +kubebuilder:object:root=true -// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` - -// RateLimitFilter allows the user to limit the number of incoming requests -// to a predefined value based on attributes within the traffic flow. -type RateLimitFilter struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - // Spec defines the desired state of RateLimitFilter. - Spec RateLimitFilterSpec `json:"spec"` -} - -// RateLimitFilterSpec defines the desired state of RateLimitFilter. +// RateLimitSpec defines the desired state of RateLimitSpec. // +union -type RateLimitFilterSpec struct { +type RateLimitSpec struct { // Type decides the scope for the RateLimits. // Valid RateLimitType values are "Global". // @@ -184,16 +162,3 @@ type RateLimitValue struct { // // +kubebuilder:validation:Enum=Second;Minute;Hour;Day type RateLimitUnit string - -//+kubebuilder:object:root=true - -// RateLimitFilterList contains a list of RateLimitFilter resources. -type RateLimitFilterList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []RateLimitFilter `json:"items"` -} - -func init() { - SchemeBuilder.Register(&RateLimitFilter{}, &RateLimitFilterList{}) -} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index be47b98c57d..603df02472e 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -162,7 +162,7 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) in.TargetRef.DeepCopyInto(&out.TargetRef) if in.RateLimit != nil { in, out := &in.RateLimit, &out.RateLimit - *out = new(RateLimitFilterSpec) + *out = new(RateLimitSpec) (*in).DeepCopyInto(*out) } if in.LoadBalancer != nil { @@ -1985,84 +1985,6 @@ func (in *RateLimitDatabaseBackend) DeepCopy() *RateLimitDatabaseBackend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RateLimitFilter) DeepCopyInto(out *RateLimitFilter) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitFilter. -func (in *RateLimitFilter) DeepCopy() *RateLimitFilter { - if in == nil { - return nil - } - out := new(RateLimitFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *RateLimitFilter) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RateLimitFilterList) DeepCopyInto(out *RateLimitFilterList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]RateLimitFilter, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitFilterList. -func (in *RateLimitFilterList) DeepCopy() *RateLimitFilterList { - if in == nil { - return nil - } - out := new(RateLimitFilterList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *RateLimitFilterList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RateLimitFilterSpec) DeepCopyInto(out *RateLimitFilterSpec) { - *out = *in - if in.Global != nil { - in, out := &in.Global, &out.Global - *out = new(GlobalRateLimit) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitFilterSpec. -func (in *RateLimitFilterSpec) DeepCopy() *RateLimitFilterSpec { - if in == nil { - return nil - } - out := new(RateLimitFilterSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RateLimitRedisSettings) DeepCopyInto(out *RateLimitRedisSettings) { *out = *in @@ -2133,6 +2055,26 @@ func (in *RateLimitSelectCondition) DeepCopy() *RateLimitSelectCondition { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RateLimitSpec) DeepCopyInto(out *RateLimitSpec) { + *out = *in + if in.Global != nil { + in, out := &in.Global, &out.Global + *out = new(GlobalRateLimit) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitSpec. +func (in *RateLimitSpec) DeepCopy() *RateLimitSpec { + if in == nil { + return nil + } + out := new(RateLimitSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RateLimitValue) DeepCopyInto(out *RateLimitValue) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_ratelimitfilters.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_ratelimitfilters.yaml deleted file mode 100644 index 1c403566111..00000000000 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_ratelimitfilters.yaml +++ /dev/null @@ -1,180 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.13.0 - name: ratelimitfilters.gateway.envoyproxy.io -spec: - group: gateway.envoyproxy.io - names: - kind: RateLimitFilter - listKind: RateLimitFilterList - plural: ratelimitfilters - singular: ratelimitfilter - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: RateLimitFilter allows the user to limit the number of incoming - requests to a predefined value based on attributes within the traffic flow. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of RateLimitFilter. - properties: - global: - description: Global defines global rate limit configuration. - properties: - rules: - description: Rules are a list of RateLimit selectors and limits. - Each rule and its associated limit is applied in a mutually - exclusive way i.e. if multiple rules get selected, each of their - associated limits get applied, so a single traffic request might - increase the rate limit counters for multiple rules if selected. - items: - description: RateLimitRule defines the semantics for matching - attributes from the incoming requests, and setting limits - for them. - properties: - clientSelectors: - description: ClientSelectors holds the list of select conditions - to select specific clients using attributes from the traffic - flow. All individual select conditions must hold True - for this rule and its limit to be applied. If this field - is empty, it is equivalent to True, and the limit is applied. - items: - description: RateLimitSelectCondition specifies the attributes - within the traffic flow that can be used to select a - subset of clients to be ratelimited. All the individual - conditions must hold True for the overall condition - to hold True. - properties: - headers: - description: Headers is a list of request headers - to match. Multiple header values are ANDed together, - meaning, a request MUST match all the specified - headers. - items: - description: HeaderMatch defines the match attributes - within the HTTP Headers of the request. - properties: - name: - description: Name of the HTTP header. - maxLength: 256 - minLength: 1 - type: string - type: - default: Exact - description: Type specifies how to match against - the value of the header. - enum: - - Exact - - RegularExpression - - Distinct - type: string - value: - description: Value within the HTTP header. Due - to the case-insensitivity of header names, - "foo" and "Foo" are considered equivalent. - Do not set this field when Type="Distinct", - implying matching on any/all unique values - within the header. - maxLength: 1024 - type: string - required: - - name - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - sourceCIDR: - description: SourceCIDR is the client IP Address range - to match on. - properties: - type: - default: Exact - type: string - value: - description: Value is the IP CIDR that represents - the range of Source IP Addresses of the client. - These could also be the intermediate addresses - through which the request has flown through - and is part of the `X-Forwarded-For` header. - For example, `192.168.0.1/32`, `192.168.0.0/24`, - `001:db8::/64`. - maxLength: 256 - minLength: 1 - type: string - required: - - value - type: object - type: object - maxItems: 8 - type: array - limit: - description: Limit holds the rate limit values. This limit - is applied for traffic flows when the selectors compute - to True, causing the request to be counted towards the - limit. The limit is enforced and the request is ratelimited, - i.e. a response with 429 HTTP status code is sent back - to the client when the selected requests have reached - the limit. - properties: - requests: - type: integer - unit: - description: RateLimitUnit specifies the intervals for - setting rate limits. Valid RateLimitUnit values are - "Second", "Minute", "Hour", and "Day". - enum: - - Second - - Minute - - Hour - - Day - type: string - required: - - requests - - unit - type: object - required: - - limit - type: object - maxItems: 16 - type: array - required: - - rules - type: object - type: - description: Type decides the scope for the RateLimits. Valid RateLimitType - values are "Global". - enum: - - Global - type: string - required: - - type - type: object - required: - - spec - type: object - served: true - storage: true - subresources: {} diff --git a/internal/cmd/egctl/testdata/translate/in/rate-limit-filter-single-route-single-match-to-xds.yaml b/internal/cmd/egctl/testdata/translate/in/rate-limit-filter-single-route-single-match-to-xds.yaml deleted file mode 100644 index af4c794e82a..00000000000 --- a/internal/cmd/egctl/testdata/translate/in/rate-limit-filter-single-route-single-match-to-xds.yaml +++ /dev/null @@ -1,113 +0,0 @@ -apiVersion: gateway.networking.k8s.io/v1 -kind: GatewayClass -metadata: - name: eg -spec: - controllerName: gateway.envoyproxy.io/gatewayclass-controller ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: Gateway -metadata: - name: eg -spec: - gatewayClassName: eg - listeners: - - name: http - protocol: HTTP - port: 80 ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: backend ---- -apiVersion: v1 -kind: Service -metadata: - name: backend - labels: - app: backend - service: backend -spec: - clusterIP: 7.7.7.7 - ports: - - name: http - port: 3000 - targetPort: 3000 - selector: - app: backend ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: backend -spec: - replicas: 1 - selector: - matchLabels: - app: backend - version: v1 - template: - metadata: - labels: - app: backend - version: v1 - spec: - serviceAccountName: backend - containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e - imagePullPolicy: IfNotPresent - name: backend - ports: - - containerPort: 3000 - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace ---- -apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: RateLimitFilter -metadata: - name: ratelimit-specific-user -spec: - type: Global - global: - rules: - - clientSelectors: - - headers: - - name: x-user-id - value: one - limit: - requests: 3 - unit: Hour ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: http-ratelimit -spec: - parentRefs: - - name: eg - hostnames: - - "ratelimit.example" - rules: - - matches: - - path: - type: PathPrefix - value: / - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: ratelimit-specific-user - backendRefs: - - group: "" - kind: Service - name: backend - port: 3000 diff --git a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.all.json deleted file mode 100644 index 144c585d40f..00000000000 --- a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.all.json +++ /dev/null @@ -1,512 +0,0 @@ -{ - "xds": { - "envoy-gateway-system/eg": { - "configs": [ - { - "@type": "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump", - "bootstrap": { - "admin": { - "accessLog": [ - { - "name": "envoy.access_loggers.file", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", - "path": "/dev/null" - } - } - ], - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 19000 - } - } - }, - "dynamicResources": { - "adsConfig": { - "apiType": "DELTA_GRPC", - "grpcServices": [ - { - "envoyGrpc": { - "clusterName": "xds_cluster" - } - } - ], - "setNodeOnFirstMessageOnly": true, - "transportApiVersion": "V3" - }, - "cdsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "ldsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "staticResources": { - "clusters": [ - { - "connectTimeout": "0.250s", - "loadAssignment": { - "clusterName": "prometheus_stats", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 19000 - } - } - } - } - ] - } - ] - }, - "name": "prometheus_stats", - "type": "STATIC" - }, - { - "connectTimeout": "10s", - "http2ProtocolOptions": { - "connectionKeepalive": { - "interval": "30s", - "timeout": "5s" - } - }, - "loadAssignment": { - "clusterName": "xds_cluster", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "envoy-gateway", - "portValue": 18000 - } - } - }, - "loadBalancingWeight": 1 - } - ], - "loadBalancingWeight": 1 - } - ] - }, - "name": "xds_cluster", - "transportSocket": { - "name": "envoy.transport_sockets.tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsCertificateSdsSecretConfigs": [ - { - "name": "xds_certificate", - "sdsConfig": { - "pathConfigSource": { - "path": "/sds/xds-certificate.json" - }, - "resourceApiVersion": "V3" - } - } - ], - "tlsParams": { - "tlsMaximumProtocolVersion": "TLSv1_3" - }, - "validationContextSdsSecretConfig": { - "name": "xds_trusted_ca", - "sdsConfig": { - "pathConfigSource": { - "path": "/sds/xds-trusted-ca.json" - }, - "resourceApiVersion": "V3" - } - } - } - } - }, - "type": "STRICT_DNS", - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - } - ], - "listeners": [ - { - "address": { - "socketAddress": { - "address": "0.0.0.0", - "portValue": 19001 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "httpFilters": [ - { - "name": "envoy.filters.http.health_check", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck", - "headers": [ - { - "name": ":path", - "stringMatch": { - "exact": "/ready" - } - } - ], - "passThroughMode": false - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "routeConfig": { - "name": "local_route", - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "prometheus_stats", - "routes": [ - { - "match": { - "prefix": "/stats/prometheus" - }, - "route": { - "cluster": "prometheus_stats" - } - } - ] - } - ] - }, - "statPrefix": "eg-ready-http" - } - } - ] - } - ], - "name": "envoy-gateway-proxy-ready-0.0.0.0-19001" - } - ] - } - } - }, - { - "@type": "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump", - "dynamicEndpointConfigs": [ - { - "endpointConfig": { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "httproute/envoy-gateway-system/http-ratelimit/rule/0", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "7.7.7.7", - "portValue": 3000 - } - } - }, - "loadBalancingWeight": 1 - } - ], - "loadBalancingWeight": 1, - "locality": {} - } - ] - } - } - ] - }, - { - "@type": "type.googleapis.com/envoy.admin.v3.ClustersConfigDump", - "dynamicActiveClusters": [ - { - "cluster": { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "commonLbConfig": { - "localityWeightedLbConfig": {} - }, - "connectTimeout": "10s", - "dnsLookupFamily": "V4_ONLY", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "serviceName": "httproute/envoy-gateway-system/http-ratelimit/rule/0" - }, - "lbPolicy": "LEAST_REQUEST", - "name": "httproute/envoy-gateway-system/http-ratelimit/rule/0", - "outlierDetection": {}, - "perConnectionBufferLimitBytes": 32768, - "type": "EDS" - } - }, - { - "cluster": { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "commonLbConfig": { - "localityWeightedLbConfig": {} - }, - "connectTimeout": "10s", - "dnsLookupFamily": "V4_ONLY", - "dnsRefreshRate": "30s", - "lbPolicy": "LEAST_REQUEST", - "loadAssignment": { - "clusterName": "ratelimit_cluster", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "envoy-ratelimit.envoy-gateway.svc.cluster.local", - "portValue": 8081 - } - } - }, - "loadBalancingWeight": 1 - } - ], - "loadBalancingWeight": 1, - "locality": {} - } - ] - }, - "name": "ratelimit_cluster", - "outlierDetection": {}, - "perConnectionBufferLimitBytes": 32768, - "respectDnsTtl": true, - "transportSocket": { - "name": "envoy.transport_sockets.tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsCertificates": [ - { - "certificateChain": { - "filename": "/certs/tls.crt" - }, - "privateKey": { - "filename": "/certs/tls.key" - } - } - ], - "validationContext": { - "trustedCa": { - "filename": "/certs/ca.crt" - } - } - } - } - }, - "type": "STRICT_DNS", - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - } - } - ] - }, - { - "@type": "type.googleapis.com/envoy.admin.v3.ListenersConfigDump", - "dynamicListeners": [ - { - "activeState": { - "listener": { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "accessLog": [ - { - "filter": { - "responseFlagFilter": { - "flags": [ - "NR" - ] - } - }, - "name": "envoy.access_loggers.file", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", - "logFormat": { - "textFormatSource": { - "inlineString": "{\"start_time\":\"%START_TIME%\",\"method\":\"%REQ(:METHOD)%\",\"x-envoy-origin-path\":\"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%\",\"protocol\":\"%PROTOCOL%\",\"response_code\":\"%RESPONSE_CODE%\",\"response_flags\":\"%RESPONSE_FLAGS%\",\"response_code_details\":\"%RESPONSE_CODE_DETAILS%\",\"connection_termination_details\":\"%CONNECTION_TERMINATION_DETAILS%\",\"upstream_transport_failure_reason\":\"%UPSTREAM_TRANSPORT_FAILURE_REASON%\",\"bytes_received\":\"%BYTES_RECEIVED%\",\"bytes_sent\":\"%BYTES_SENT%\",\"duration\":\"%DURATION%\",\"x-envoy-upstream-service-time\":\"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%\",\"x-forwarded-for\":\"%REQ(X-FORWARDED-FOR)%\",\"user-agent\":\"%REQ(USER-AGENT)%\",\"x-request-id\":\"%REQ(X-REQUEST-ID)%\",\":authority\":\"%REQ(:AUTHORITY)%\",\"upstream_host\":\"%UPSTREAM_HOST%\",\"upstream_cluster\":\"%UPSTREAM_CLUSTER%\",\"upstream_local_address\":\"%UPSTREAM_LOCAL_ADDRESS%\",\"downstream_local_address\":\"%DOWNSTREAM_LOCAL_ADDRESS%\",\"downstream_remote_address\":\"%DOWNSTREAM_REMOTE_ADDRESS%\",\"requested_server_name\":\"%REQUESTED_SERVER_NAME%\",\"route_name\":\"%ROUTE_NAME%\"}\n" - } - }, - "path": "/dev/stdout" - } - } - ], - "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", - "accessLog": [ - { - "name": "envoy.access_loggers.file", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", - "logFormat": { - "textFormatSource": { - "inlineString": "{\"start_time\":\"%START_TIME%\",\"method\":\"%REQ(:METHOD)%\",\"x-envoy-origin-path\":\"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%\",\"protocol\":\"%PROTOCOL%\",\"response_code\":\"%RESPONSE_CODE%\",\"response_flags\":\"%RESPONSE_FLAGS%\",\"response_code_details\":\"%RESPONSE_CODE_DETAILS%\",\"connection_termination_details\":\"%CONNECTION_TERMINATION_DETAILS%\",\"upstream_transport_failure_reason\":\"%UPSTREAM_TRANSPORT_FAILURE_REASON%\",\"bytes_received\":\"%BYTES_RECEIVED%\",\"bytes_sent\":\"%BYTES_SENT%\",\"duration\":\"%DURATION%\",\"x-envoy-upstream-service-time\":\"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%\",\"x-forwarded-for\":\"%REQ(X-FORWARDED-FOR)%\",\"user-agent\":\"%REQ(USER-AGENT)%\",\"x-request-id\":\"%REQ(X-REQUEST-ID)%\",\":authority\":\"%REQ(:AUTHORITY)%\",\"upstream_host\":\"%UPSTREAM_HOST%\",\"upstream_cluster\":\"%UPSTREAM_CLUSTER%\",\"upstream_local_address\":\"%UPSTREAM_LOCAL_ADDRESS%\",\"downstream_local_address\":\"%DOWNSTREAM_LOCAL_ADDRESS%\",\"downstream_remote_address\":\"%DOWNSTREAM_REMOTE_ADDRESS%\",\"requested_server_name\":\"%REQUESTED_SERVER_NAME%\",\"route_name\":\"%ROUTE_NAME%\"}\n" - } - }, - "path": "/dev/stdout" - } - } - ], - "commonHttpProtocolOptions": { - "headersWithUnderscoresAction": "REJECT_REQUEST" - }, - "http2ProtocolOptions": { - "initialConnectionWindowSize": 1048576, - "initialStreamWindowSize": 65536, - "maxConcurrentStreams": 100 - }, - "httpFilters": [ - { - "name": "envoy.filters.http.ratelimit", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit", - "domain": "envoy-gateway-system/eg/http", - "enableXRatelimitHeaders": "DRAFT_VERSION_03", - "rateLimitService": { - "grpcService": { - "envoyGrpc": { - "clusterName": "ratelimit_cluster" - } - }, - "transportApiVersion": "V3" - } - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "mergeSlashes": true, - "normalizePath": true, - "pathWithEscapedSlashesAction": "UNESCAPE_AND_REDIRECT", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "envoy-gateway-system/eg/http" - }, - "statPrefix": "http", - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ], - "useRemoteAddress": true - } - } - ] - }, - "name": "envoy-gateway-system/eg/http", - "perConnectionBufferLimitBytes": 32768 - } - } - } - ] - }, - { - "@type": "type.googleapis.com/envoy.admin.v3.RoutesConfigDump", - "dynamicRouteConfigs": [ - { - "routeConfig": { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "ignorePortInHostMatching": true, - "name": "envoy-gateway-system/eg/http", - "virtualHosts": [ - { - "domains": [ - "ratelimit.example" - ], - "name": "envoy-gateway-system/eg/http/ratelimit_example", - "routes": [ - { - "match": { - "prefix": "/" - }, - "name": "httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example", - "route": { - "cluster": "httproute/envoy-gateway-system/http-ratelimit/rule/0", - "rateLimits": [ - { - "actions": [ - { - "headerValueMatch": { - "descriptorKey": "httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example-key-rule-0-match-0", - "descriptorValue": "httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example-value-rule-0-match-0", - "expectMatch": true, - "headers": [ - { - "name": "x-user-id", - "stringMatch": { - "exact": "one" - } - } - ] - } - } - ] - } - ] - } - } - ] - } - ] - } - } - ] - } - ] - } - } -} \ No newline at end of file diff --git a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.all.yaml deleted file mode 100644 index 8168cf49122..00000000000 --- a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.all.yaml +++ /dev/null @@ -1,292 +0,0 @@ -xds: - envoy-gateway-system/eg: - configs: - - '@type': type.googleapis.com/envoy.admin.v3.BootstrapConfigDump - bootstrap: - admin: - accessLog: - - name: envoy.access_loggers.file - typedConfig: - '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - path: /dev/null - address: - socketAddress: - address: 127.0.0.1 - portValue: 19000 - dynamicResources: - adsConfig: - apiType: DELTA_GRPC - grpcServices: - - envoyGrpc: - clusterName: xds_cluster - setNodeOnFirstMessageOnly: true - transportApiVersion: V3 - cdsConfig: - ads: {} - resourceApiVersion: V3 - ldsConfig: - ads: {} - resourceApiVersion: V3 - staticResources: - clusters: - - connectTimeout: 0.250s - loadAssignment: - clusterName: prometheus_stats - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 127.0.0.1 - portValue: 19000 - name: prometheus_stats - type: STATIC - - connectTimeout: 10s - http2ProtocolOptions: - connectionKeepalive: - interval: 30s - timeout: 5s - loadAssignment: - clusterName: xds_cluster - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: envoy-gateway - portValue: 18000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - name: xds_cluster - transportSocket: - name: envoy.transport_sockets.tls - typedConfig: - '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - commonTlsContext: - tlsCertificateSdsSecretConfigs: - - name: xds_certificate - sdsConfig: - pathConfigSource: - path: /sds/xds-certificate.json - resourceApiVersion: V3 - tlsParams: - tlsMaximumProtocolVersion: TLSv1_3 - validationContextSdsSecretConfig: - name: xds_trusted_ca - sdsConfig: - pathConfigSource: - path: /sds/xds-trusted-ca.json - resourceApiVersion: V3 - type: STRICT_DNS - typedExtensionProtocolOptions: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicitHttpConfig: - http2ProtocolOptions: {} - listeners: - - address: - socketAddress: - address: 0.0.0.0 - portValue: 19001 - filterChains: - - filters: - - name: envoy.filters.network.http_connection_manager - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - httpFilters: - - name: envoy.filters.http.health_check - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck - headers: - - name: :path - stringMatch: - exact: /ready - passThroughMode: false - - name: envoy.filters.http.router - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - routeConfig: - name: local_route - virtualHosts: - - domains: - - '*' - name: prometheus_stats - routes: - - match: - prefix: /stats/prometheus - route: - cluster: prometheus_stats - statPrefix: eg-ready-http - name: envoy-gateway-proxy-ready-0.0.0.0-19001 - - '@type': type.googleapis.com/envoy.admin.v3.EndpointsConfigDump - dynamicEndpointConfigs: - - endpointConfig: - '@type': type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment - clusterName: httproute/envoy-gateway-system/http-ratelimit/rule/0 - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 7.7.7.7 - portValue: 3000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} - - '@type': type.googleapis.com/envoy.admin.v3.ClustersConfigDump - dynamicActiveClusters: - - cluster: - '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster - commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: httproute/envoy-gateway-system/http-ratelimit/rule/0 - lbPolicy: LEAST_REQUEST - name: httproute/envoy-gateway-system/http-ratelimit/rule/0 - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - type: EDS - - cluster: - '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster - commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - dnsRefreshRate: 30s - lbPolicy: LEAST_REQUEST - loadAssignment: - clusterName: ratelimit_cluster - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: envoy-ratelimit.envoy-gateway.svc.cluster.local - portValue: 8081 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} - name: ratelimit_cluster - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - respectDnsTtl: true - transportSocket: - name: envoy.transport_sockets.tls - typedConfig: - '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - commonTlsContext: - tlsCertificates: - - certificateChain: - filename: /certs/tls.crt - privateKey: - filename: /certs/tls.key - validationContext: - trustedCa: - filename: /certs/ca.crt - type: STRICT_DNS - typedExtensionProtocolOptions: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicitHttpConfig: - http2ProtocolOptions: {} - - '@type': type.googleapis.com/envoy.admin.v3.ListenersConfigDump - dynamicListeners: - - activeState: - listener: - '@type': type.googleapis.com/envoy.config.listener.v3.Listener - accessLog: - - filter: - responseFlagFilter: - flags: - - NR - name: envoy.access_loggers.file - typedConfig: - '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - logFormat: - textFormatSource: - inlineString: | - {"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"} - path: /dev/stdout - 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 - accessLog: - - name: envoy.access_loggers.file - typedConfig: - '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - logFormat: - textFormatSource: - inlineString: | - {"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"} - path: /dev/stdout - commonHttpProtocolOptions: - headersWithUnderscoresAction: REJECT_REQUEST - http2ProtocolOptions: - initialConnectionWindowSize: 1048576 - initialStreamWindowSize: 65536 - maxConcurrentStreams: 100 - httpFilters: - - name: envoy.filters.http.ratelimit - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit - domain: envoy-gateway-system/eg/http - enableXRatelimitHeaders: DRAFT_VERSION_03 - rateLimitService: - grpcService: - envoyGrpc: - clusterName: ratelimit_cluster - transportApiVersion: V3 - - name: envoy.filters.http.router - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - mergeSlashes: true - normalizePath: true - pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT - rds: - configSource: - ads: {} - resourceApiVersion: V3 - routeConfigName: envoy-gateway-system/eg/http - statPrefix: http - upgradeConfigs: - - upgradeType: websocket - useRemoteAddress: true - name: envoy-gateway-system/eg/http - perConnectionBufferLimitBytes: 32768 - - '@type': type.googleapis.com/envoy.admin.v3.RoutesConfigDump - dynamicRouteConfigs: - - routeConfig: - '@type': type.googleapis.com/envoy.config.route.v3.RouteConfiguration - ignorePortInHostMatching: true - name: envoy-gateway-system/eg/http - virtualHosts: - - domains: - - ratelimit.example - name: envoy-gateway-system/eg/http/ratelimit_example - routes: - - match: - prefix: / - name: httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example - route: - cluster: httproute/envoy-gateway-system/http-ratelimit/rule/0 - rateLimits: - - actions: - - headerValueMatch: - descriptorKey: httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example-key-rule-0-match-0 - descriptorValue: httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example-value-rule-0-match-0 - expectMatch: true - headers: - - name: x-user-id - stringMatch: - exact: one diff --git a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.bootstrap.yaml b/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.bootstrap.yaml deleted file mode 100644 index 169f3f954c6..00000000000 --- a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.bootstrap.yaml +++ /dev/null @@ -1,119 +0,0 @@ -xds: - envoy-gateway-system/eg: - '@type': type.googleapis.com/envoy.admin.v3.BootstrapConfigDump - bootstrap: - admin: - accessLog: - - name: envoy.access_loggers.file - typedConfig: - '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - path: /dev/null - address: - socketAddress: - address: 127.0.0.1 - portValue: 19000 - dynamicResources: - adsConfig: - apiType: DELTA_GRPC - grpcServices: - - envoyGrpc: - clusterName: xds_cluster - setNodeOnFirstMessageOnly: true - transportApiVersion: V3 - cdsConfig: - ads: {} - resourceApiVersion: V3 - ldsConfig: - ads: {} - resourceApiVersion: V3 - staticResources: - clusters: - - connectTimeout: 0.250s - loadAssignment: - clusterName: prometheus_stats - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 127.0.0.1 - portValue: 19000 - name: prometheus_stats - type: STATIC - - connectTimeout: 10s - http2ProtocolOptions: - connectionKeepalive: - interval: 30s - timeout: 5s - loadAssignment: - clusterName: xds_cluster - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: envoy-gateway - portValue: 18000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - name: xds_cluster - transportSocket: - name: envoy.transport_sockets.tls - typedConfig: - '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - commonTlsContext: - tlsCertificateSdsSecretConfigs: - - name: xds_certificate - sdsConfig: - pathConfigSource: - path: /sds/xds-certificate.json - resourceApiVersion: V3 - tlsParams: - tlsMaximumProtocolVersion: TLSv1_3 - validationContextSdsSecretConfig: - name: xds_trusted_ca - sdsConfig: - pathConfigSource: - path: /sds/xds-trusted-ca.json - resourceApiVersion: V3 - type: STRICT_DNS - typedExtensionProtocolOptions: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicitHttpConfig: - http2ProtocolOptions: {} - listeners: - - address: - socketAddress: - address: 0.0.0.0 - portValue: 19001 - filterChains: - - filters: - - name: envoy.filters.network.http_connection_manager - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - httpFilters: - - name: envoy.filters.http.health_check - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck - headers: - - name: :path - stringMatch: - exact: /ready - passThroughMode: false - - name: envoy.filters.http.router - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - routeConfig: - name: local_route - virtualHosts: - - domains: - - '*' - name: prometheus_stats - routes: - - match: - prefix: /stats/prometheus - route: - cluster: prometheus_stats - statPrefix: eg-ready-http - name: envoy-gateway-proxy-ready-0.0.0.0-19001 diff --git a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.cluster.yaml b/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.cluster.yaml deleted file mode 100644 index 2bcdcb87388..00000000000 --- a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.cluster.yaml +++ /dev/null @@ -1,63 +0,0 @@ -xds: - envoy-gateway-system/eg: - '@type': type.googleapis.com/envoy.admin.v3.ClustersConfigDump - dynamicActiveClusters: - - cluster: - '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster - commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: httproute/envoy-gateway-system/http-ratelimit/rule/0 - lbPolicy: LEAST_REQUEST - name: httproute/envoy-gateway-system/http-ratelimit/rule/0 - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - type: EDS - - cluster: - '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster - commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - dnsRefreshRate: 30s - lbPolicy: LEAST_REQUEST - loadAssignment: - clusterName: ratelimit_cluster - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: envoy-ratelimit.envoy-gateway.svc.cluster.local - portValue: 8081 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} - name: ratelimit_cluster - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - respectDnsTtl: true - transportSocket: - name: envoy.transport_sockets.tls - typedConfig: - '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - commonTlsContext: - tlsCertificates: - - certificateChain: - filename: /certs/tls.crt - privateKey: - filename: /certs/tls.key - validationContext: - trustedCa: - filename: /certs/ca.crt - type: STRICT_DNS - typedExtensionProtocolOptions: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicitHttpConfig: - http2ProtocolOptions: {} diff --git a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.endpoint.yaml b/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.endpoint.yaml deleted file mode 100644 index d30d56266be..00000000000 --- a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.endpoint.yaml +++ /dev/null @@ -1,17 +0,0 @@ -xds: - envoy-gateway-system/eg: - '@type': type.googleapis.com/envoy.admin.v3.EndpointsConfigDump - dynamicEndpointConfigs: - - endpointConfig: - '@type': type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment - clusterName: httproute/envoy-gateway-system/http-ratelimit/rule/0 - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 7.7.7.7 - portValue: 3000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} diff --git a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.listener.yaml b/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.listener.yaml deleted file mode 100644 index 112a3fd288f..00000000000 --- a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.listener.yaml +++ /dev/null @@ -1,72 +0,0 @@ -xds: - envoy-gateway-system/eg: - '@type': type.googleapis.com/envoy.admin.v3.ListenersConfigDump - dynamicListeners: - - activeState: - listener: - '@type': type.googleapis.com/envoy.config.listener.v3.Listener - accessLog: - - filter: - responseFlagFilter: - flags: - - NR - name: envoy.access_loggers.file - typedConfig: - '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - logFormat: - textFormatSource: - inlineString: | - {"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"} - path: /dev/stdout - 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 - accessLog: - - name: envoy.access_loggers.file - typedConfig: - '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - logFormat: - textFormatSource: - inlineString: | - {"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"} - path: /dev/stdout - commonHttpProtocolOptions: - headersWithUnderscoresAction: REJECT_REQUEST - http2ProtocolOptions: - initialConnectionWindowSize: 1048576 - initialStreamWindowSize: 65536 - maxConcurrentStreams: 100 - httpFilters: - - name: envoy.filters.http.ratelimit - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit - domain: envoy-gateway-system/eg/http - enableXRatelimitHeaders: DRAFT_VERSION_03 - rateLimitService: - grpcService: - envoyGrpc: - clusterName: ratelimit_cluster - transportApiVersion: V3 - - name: envoy.filters.http.router - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - mergeSlashes: true - normalizePath: true - pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT - rds: - configSource: - ads: {} - resourceApiVersion: V3 - routeConfigName: envoy-gateway-system/eg/http - statPrefix: http - upgradeConfigs: - - upgradeType: websocket - useRemoteAddress: true - name: envoy-gateway-system/eg/http - perConnectionBufferLimitBytes: 32768 diff --git a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.route.yaml b/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.route.yaml deleted file mode 100644 index 91c3754dd2a..00000000000 --- a/internal/cmd/egctl/testdata/translate/out/rate-limit-filter-single-route-single-match-to-xds.route.yaml +++ /dev/null @@ -1,28 +0,0 @@ -xds: - envoy-gateway-system/eg: - '@type': type.googleapis.com/envoy.admin.v3.RoutesConfigDump - dynamicRouteConfigs: - - routeConfig: - '@type': type.googleapis.com/envoy.config.route.v3.RouteConfiguration - ignorePortInHostMatching: true - name: envoy-gateway-system/eg/http - virtualHosts: - - domains: - - ratelimit.example - name: envoy-gateway-system/eg/http/ratelimit_example - routes: - - match: - prefix: / - name: httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example - route: - cluster: httproute/envoy-gateway-system/http-ratelimit/rule/0 - rateLimits: - - actions: - - headerValueMatch: - descriptorKey: httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example-key-rule-0-match-0 - descriptorValue: httproute/envoy-gateway-system/http-ratelimit/rule/0/match/0/ratelimit_example-value-rule-0-match-0 - expectMatch: true - headers: - - name: x-user-id - stringMatch: - exact: one diff --git a/internal/cmd/egctl/translate.go b/internal/cmd/egctl/translate.go index c46be9a8495..5850f96a1fa 100644 --- a/internal/cmd/egctl/translate.go +++ b/internal/cmd/egctl/translate.go @@ -766,20 +766,6 @@ func kubernetesYAMLToResources(str string, addMissingResources bool) (*gatewayap Spec: typedSpec.(egv1a1.EnvoyPatchPolicySpec), } resources.EnvoyPatchPolicies = append(resources.EnvoyPatchPolicies, envoyPatchPolicy) - case egv1a1.KindRateLimitFilter: - typedSpec := spec.Interface() - rateLimitFilter := &egv1a1.RateLimitFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindRateLimitFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - }, - Spec: typedSpec.(egv1a1.RateLimitFilterSpec), - } - resources.RateLimitFilters = append(resources.RateLimitFilters, rateLimitFilter) } } diff --git a/internal/cmd/egctl/translate_test.go b/internal/cmd/egctl/translate_test.go index 4b13327b682..03ab44345a1 100644 --- a/internal/cmd/egctl/translate_test.go +++ b/internal/cmd/egctl/translate_test.go @@ -186,83 +186,6 @@ func TestTranslate(t *testing.T) { resourceType: string(AllEnvoyConfigType), expect: true, }, - { - - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: jsonOutput, - expect: true, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: yamlOutput, - expect: true, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - expect: true, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: yamlOutput, - resourceType: "unknown", - expect: false, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: yamlOutput, - resourceType: string(AllEnvoyConfigType), - expect: true, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: yamlOutput, - resourceType: string(BootstrapEnvoyConfigType), - expect: true, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: yamlOutput, - resourceType: string(ClusterEnvoyConfigType), - expect: true, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: yamlOutput, - resourceType: string(ListenerEnvoyConfigType), - expect: true, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: yamlOutput, - resourceType: string(RouteEnvoyConfigType), - expect: true, - }, - { - name: "rate-limit-filter-single-route-single-match-to-xds", - from: "gateway-api", - to: "xds", - output: yamlOutput, - resourceType: string(EndpointEnvoyConfigType), - expect: true, - }, { name: "default-resources", from: "gateway-api", diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go index a701b801080..961b2fd6ec4 100644 --- a/internal/gatewayapi/filters.go +++ b/internal/gatewayapi/filters.go @@ -7,7 +7,6 @@ package gatewayapi import ( "fmt" - "net" "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -59,7 +58,6 @@ type HTTPFilterIR struct { Mirrors []*ir.RouteDestination RequestAuthentication *ir.RequestAuthentication - RateLimit *ir.RateLimit ExtensionRefs []*ir.UnstructuredRef } @@ -679,102 +677,6 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec } } - // Set the filter context and return early if a matching RateLimitFilter is found. - if string(extFilter.Kind) == egv1a1.KindRateLimitFilter { - for _, rateLimitFilter := range resources.RateLimitFilters { - if rateLimitFilter.Namespace == filterNs && - rateLimitFilter.Name == string(extFilter.Name) { - if rateLimitFilter.Spec.Global == nil { - errMsg := fmt.Sprintf("Global configuration empty for RateLimitFilter: %s/%s", filterNs, - extFilter.Name) - t.processUnresolvedHTTPFilter(errMsg, filterContext) - return - } - if !t.GlobalRateLimitEnabled { - errMsg := fmt.Sprintf("Enable Ratelimit in the EnvoyGateway config to configure RateLimitFilter: %s/%s", - filterNs, extFilter.Name) - t.processUnresolvedHTTPFilter(errMsg, filterContext) - return - } - rateLimit := &ir.RateLimit{ - Global: &ir.GlobalRateLimit{ - Rules: make([]*ir.RateLimitRule, len(rateLimitFilter.Spec.Global.Rules)), - }, - } - rules := rateLimit.Global.Rules - for i, rule := range rateLimitFilter.Spec.Global.Rules { - rules[i] = &ir.RateLimitRule{ - Limit: &ir.RateLimitValue{ - Requests: rule.Limit.Requests, - Unit: ir.RateLimitUnit(rule.Limit.Unit), - }, - HeaderMatches: make([]*ir.StringMatch, 0), - } - for _, match := range rule.ClientSelectors { - for _, header := range match.Headers { - switch { - case header.Type == nil && header.Value != nil: - fallthrough - case *header.Type == egv1a1.HeaderMatchExact && header.Value != nil: - m := &ir.StringMatch{ - Name: header.Name, - Exact: header.Value, - } - rules[i].HeaderMatches = append(rules[i].HeaderMatches, m) - case *header.Type == egv1a1.HeaderMatchRegularExpression && header.Value != nil: - m := &ir.StringMatch{ - Name: header.Name, - SafeRegex: header.Value, - } - rules[i].HeaderMatches = append(rules[i].HeaderMatches, m) - case *header.Type == egv1a1.HeaderMatchDistinct && header.Value == nil: - m := &ir.StringMatch{ - Name: header.Name, - Distinct: true, - } - rules[i].HeaderMatches = append(rules[i].HeaderMatches, m) - default: - // set negative status condition. - errMsg := fmt.Sprintf("Unable to translate RateLimitFilter. Either the header.Type is not valid or the header is missing a value: %s/%s", filterNs, - extFilter.Name) - t.processUnresolvedHTTPFilter(errMsg, filterContext) - return - } - } - - if match.SourceCIDR != nil { - // distinct means that each IP Address within the specified Source IP CIDR is treated as a - // distinct client selector and uses a separate rate limit bucket/counter. - distinct := false - sourceCIDR := match.SourceCIDR.Value - if match.SourceCIDR.Type != nil && *match.SourceCIDR.Type == egv1a1.SourceMatchDistinct { - distinct = true - } - - ip, ipn, err := net.ParseCIDR(sourceCIDR) - if err != nil { - errMsg := fmt.Sprintf("Unable to translate RateLimitFilter: %s/%s", filterNs, - extFilter.Name) - t.processUnresolvedHTTPFilter(errMsg, filterContext) - return - } - - mask, _ := ipn.Mask.Size() - rules[i].CIDRMatch = &ir.CIDRMatch{ - CIDR: ipn.String(), - IPv6: ip.To4() == nil, - MaskLen: mask, - Distinct: distinct, - } - } - } - } - filterContext.HTTPFilterIR.RateLimit = rateLimit - return - } - } - } - // This list of resources will be empty unless an extension is loaded (and introduces resources) for _, res := range resources.ExtensionRefFilters { if res.GetKind() == string(extFilter.Kind) && res.GetName() == string(extFilter.Name) && res.GetNamespace() == filterNs { diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index f9a6732dbae..fc221085af3 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -192,9 +192,6 @@ func ValidateHTTPRouteFilter(filter *gwapiv1.HTTPRouteFilter, extGKs ...schema.G case string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && string(filter.ExtensionRef.Kind) == egv1a1.KindAuthenticationFilter: return nil - case string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - string(filter.ExtensionRef.Kind) == egv1a1.KindRateLimitFilter: - return nil default: for _, gk := range extGKs { if filter.ExtensionRef.Group == gwapiv1.Group(gk.Group) && @@ -217,14 +214,6 @@ func IsAuthnHTTPFilter(filter *gwapiv1.HTTPRouteFilter) bool { string(filter.ExtensionRef.Kind) == egv1a1.KindAuthenticationFilter } -// IsRateLimitHTTPFilter returns true if the provided filter is a RateLimitFilter. -func IsRateLimitHTTPFilter(filter *gwapiv1.HTTPRouteFilter) bool { - return filter.Type == gwapiv1.HTTPRouteFilterExtensionRef && - filter.ExtensionRef != nil && - string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - string(filter.ExtensionRef.Kind) == egv1a1.KindRateLimitFilter -} - // ValidateGRPCRouteFilter validates the provided filter within GRPCRoute. func ValidateGRPCRouteFilter(filter *v1alpha2.GRPCRouteFilter, extGKs ...schema.GroupKind) error { switch { @@ -241,9 +230,6 @@ func ValidateGRPCRouteFilter(filter *v1alpha2.GRPCRouteFilter, extGKs ...schema. case string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && string(filter.ExtensionRef.Kind) == egv1a1.KindAuthenticationFilter: return nil - case string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - string(filter.ExtensionRef.Kind) == egv1a1.KindRateLimitFilter: - return nil default: for _, gk := range extGKs { if filter.ExtensionRef.Group == gwapiv1.Group(gk.Group) && @@ -266,14 +252,6 @@ func IsAuthnGRPCFilter(filter *v1alpha2.GRPCRouteFilter) bool { string(filter.ExtensionRef.Kind) == egv1a1.KindAuthenticationFilter } -// IsRateLimitGRPCFilter returns true if the provided filter is an RateLimitFilter. -func IsRateLimitGRPCFilter(filter *v1alpha2.GRPCRouteFilter) bool { - return filter.Type == v1alpha2.GRPCRouteFilterExtensionRef && - filter.ExtensionRef != nil && - string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - string(filter.ExtensionRef.Kind) == egv1a1.KindRateLimitFilter -} - // GatewayOwnerLabels returns the Gateway Owner labels using // the provided namespace and name as the values. func GatewayOwnerLabels(namespace, name string) map[string]string { diff --git a/internal/gatewayapi/helpers_test.go b/internal/gatewayapi/helpers_test.go index 426845870b4..6ded00f8c72 100644 --- a/internal/gatewayapi/helpers_test.go +++ b/internal/gatewayapi/helpers_test.go @@ -128,42 +128,6 @@ func TestValidateGRPCFilterRef(t *testing.T) { }, expected: true, }, - { - name: "invalid ratelimitfilter group", - filter: &gwapiv1a2.GRPCRouteFilter{ - Type: gwapiv1a2.GRPCRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: "UnsupportedGroup", - Kind: egv1a1.KindRateLimitFilter, - Name: "test", - }, - }, - expected: false, - }, - { - name: "invalid ratelimitfilter kind", - filter: &gwapiv1a2.GRPCRouteFilter{ - Type: gwapiv1a2.GRPCRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: "UnsupportedKind", - Name: "test", - }, - }, - expected: false, - }, - { - name: "valid ratelimitfilter", - filter: &gwapiv1a2.GRPCRouteFilter{ - Type: gwapiv1a2.GRPCRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: egv1a1.KindRateLimitFilter, - Name: "test", - }, - }, - expected: true, - }, } for _, tc := range testCases { tc := tc @@ -267,18 +231,6 @@ func TestValidateHTTPFilterRef(t *testing.T) { }, expected: true, }, - { - name: "valid rateLimitfilter", - filter: &gwapiv1.HTTPRouteFilter{ - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: egv1a1.KindRateLimitFilter, - Name: "test", - }, - }, - expected: true, - }, { name: "valid extension resource", filter: &gwapiv1.HTTPRouteFilter{ diff --git a/internal/gatewayapi/resource.go b/internal/gatewayapi/resource.go index 318728afce7..6bd0fc4f696 100644 --- a/internal/gatewayapi/resource.go +++ b/internal/gatewayapi/resource.go @@ -41,7 +41,6 @@ type Resources struct { EndpointSlices []*discoveryv1.EndpointSlice `json:"endpointSlices,omitempty" yaml:"endpointSlices,omitempty"` Secrets []*v1.Secret `json:"secrets,omitempty" yaml:"secrets,omitempty"` AuthenticationFilters []*egv1a1.AuthenticationFilter `json:"authenticationFilters,omitempty" yaml:"authenticationFilters,omitempty"` - RateLimitFilters []*egv1a1.RateLimitFilter `json:"rateLimitFilters,omitempty" yaml:"rateLimitFilters,omitempty"` EnvoyProxy *egv1a1.EnvoyProxy `json:"envoyProxy,omitempty" yaml:"envoyProxy,omitempty"` ExtensionRefFilters []unstructured.Unstructured `json:"extensionRefFilters,omitempty" yaml:"extensionRefFilters,omitempty"` EnvoyPatchPolicies []*egv1a1.EnvoyPatchPolicy `json:"envoyPatchPolicies,omitempty" yaml:"envoyPatchPolicies,omitempty"` @@ -61,7 +60,6 @@ func NewResources() *Resources { Secrets: []*v1.Secret{}, ReferenceGrants: []*gwapiv1b1.ReferenceGrant{}, Namespaces: []*v1.Namespace{}, - RateLimitFilters: []*egv1a1.RateLimitFilter{}, AuthenticationFilters: []*egv1a1.AuthenticationFilter{}, ExtensionRefFilters: []unstructured.Unstructured{}, EnvoyPatchPolicies: []*egv1a1.EnvoyPatchPolicy{}, diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index fe0ec085def..fed00642f59 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -317,9 +317,6 @@ func applyHTTPFiltersContextToIRRoute(httpFiltersContext *HTTPFiltersContext, ir if httpFiltersContext.RequestAuthentication != nil { irRoute.RequestAuthentication = httpFiltersContext.RequestAuthentication } - if httpFiltersContext.RateLimit != nil { - irRoute.RateLimit = httpFiltersContext.RateLimit - } if len(httpFiltersContext.ExtensionRefs) > 0 { irRoute.ExtensionRefs = httpFiltersContext.ExtensionRefs diff --git a/internal/gatewayapi/testdata/grpcroute-with-valid-ratelimitfilter.in.yaml b/internal/gatewayapi/testdata/grpcroute-with-valid-ratelimitfilter.in.yaml deleted file mode 100644 index 29ddd013056..00000000000 --- a/internal/gatewayapi/testdata/grpcroute-with-valid-ratelimitfilter.in.yaml +++ /dev/null @@ -1,55 +0,0 @@ -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 -grpcRoutes: -- apiVersion: gateway.networking.k8s.io/v1alpha2 - kind: GRPCRoute - metadata: - namespace: default - name: grpcroute-1 - spec: - parentRefs: - - namespace: envoy-gateway - name: gateway-1 - sectionName: http - rules: - - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test - backendRefs: - - name: service-1 - port: 8080 -rateLimitFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: RateLimitFilter - metadata: - namespace: default - name: test - spec: - type: Global - global: - rules: - - clientSelectors: - - headers: - - name: x-user-id - value: one - - name: x-org-id - type: Distinct - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/testdata/grpcroute-with-valid-ratelimitfilter.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-valid-ratelimitfilter.out.yaml deleted file mode 100644 index 704f48edb10..00000000000 --- a/internal/gatewayapi/testdata/grpcroute-with-valid-ratelimitfilter.out.yaml +++ /dev/null @@ -1,133 +0,0 @@ -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 -grpcRoutes: -- apiVersion: gateway.networking.k8s.io/v1alpha2 - kind: GRPCRoute - metadata: - creationTimestamp: null - name: grpcroute-1 - namespace: default - spec: - parentRefs: - - name: gateway-1 - namespace: envoy-gateway - sectionName: http - rules: - - backendRefs: - - name: service-1 - port: 8080 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test - type: ExtensionRef - 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: "" - ports: - - containerPort: 10080 - name: http - 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: true - name: envoy-gateway/gateway-1/http - port: 10080 - routes: - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: grpcroute/default/grpcroute-1/rule/0 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: '*' - name: grpcroute/default/grpcroute-1/rule/0/match/-1/* - rateLimit: - global: - rules: - - headerMatches: - - distinct: false - exact: one - name: x-user-id - - distinct: true - name: x-org-id - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/testdata/httproute-with-distinct-sourcecidr-ratelimit.in.yaml b/internal/gatewayapi/testdata/httproute-with-distinct-sourcecidr-ratelimit.in.yaml deleted file mode 100644 index c956ebc3117..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-distinct-sourcecidr-ratelimit.in.yaml +++ /dev/null @@ -1,59 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test -rateLimitFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: RateLimitFilter - metadata: - name: test - namespace: default - spec: - type: Global - global: - rules: - - clientSelectors: - - sourceCIDR: - type: "Distinct" - value: 192.168.0.0/16 - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/testdata/httproute-with-distinct-sourcecidr-ratelimit.out.yaml b/internal/gatewayapi/testdata/httproute-with-distinct-sourcecidr-ratelimit.out.yaml deleted file mode 100644 index 556411900c9..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-distinct-sourcecidr-ratelimit.out.yaml +++ /dev/null @@ -1,143 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test - type: ExtensionRef - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 - routes: - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: httproute/default/httproute-1/rule/0 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: gateway.envoyproxy.io - name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io - pathMatch: - distinct: false - name: "" - prefix: / - rateLimit: - global: - rules: - - cidrMatch: - cidr: 192.168.0.0/16 - distinct: true - ipv6: false - maskLen: 16 - headerMatches: [] - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-ratelimitfilter.in.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-ratelimitfilter.in.yaml deleted file mode 100644 index 1c0a11c7526..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-invalid-ratelimitfilter.in.yaml +++ /dev/null @@ -1,60 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test -rateLimitFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: RateLimitFilter - metadata: - name: test - namespace: default - spec: - type: Global - global: - rules: - - clientSelectors: - - headers: - - type: Distinct - name: x-user-id - value: one - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-ratelimitfilter.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-ratelimitfilter.out.yaml deleted file mode 100644 index 4328150736a..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-invalid-ratelimitfilter.out.yaml +++ /dev/null @@ -1,116 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - name: http - port: 80 - protocol: HTTP - status: - listeners: - - attachedRoutes: 0 - conditions: - - lastTransitionTime: null - message: Sending translated listener configuration to the data plane - reason: Programmed - status: "True" - type: Programmed - - lastTransitionTime: null - message: Listener has been successfully translated - reason: Accepted - status: "True" - type: Accepted - - lastTransitionTime: null - message: Listener references have been resolved - reason: ResolvedRefs - status: "True" - type: ResolvedRefs - name: http - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test - type: ExtensionRef - matches: - - path: - value: / - status: - parents: - - conditions: - - lastTransitionTime: null - message: 'Unable to translate RateLimitFilter. Either the header.Type is not - valid or the header is missing a value: default/test' - reason: UnsupportedValue - status: "False" - type: Accepted - - lastTransitionTime: null - message: 'Unable to translate RateLimitFilter. Either the header.Type is not - valid or the header is missing a value: default/test' - reason: BackendNotFound - status: "False" - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 diff --git a/internal/gatewayapi/testdata/httproute-with-sourcecidr-ratelimit.in.yaml b/internal/gatewayapi/testdata/httproute-with-sourcecidr-ratelimit.in.yaml deleted file mode 100644 index 80512128a46..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-sourcecidr-ratelimit.in.yaml +++ /dev/null @@ -1,58 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test -rateLimitFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: RateLimitFilter - metadata: - name: test - namespace: default - spec: - type: Global - global: - rules: - - clientSelectors: - - sourceCIDR: - value: 192.168.0.0/16 - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/testdata/httproute-with-sourcecidr-ratelimit.out.yaml b/internal/gatewayapi/testdata/httproute-with-sourcecidr-ratelimit.out.yaml deleted file mode 100644 index 3f80798c10a..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-sourcecidr-ratelimit.out.yaml +++ /dev/null @@ -1,143 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test - type: ExtensionRef - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 - routes: - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: httproute/default/httproute-1/rule/0 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: gateway.envoyproxy.io - name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io - pathMatch: - distinct: false - name: "" - prefix: / - rateLimit: - global: - rules: - - cidrMatch: - cidr: 192.168.0.0/16 - distinct: false - ipv6: false - maskLen: 16 - headerMatches: [] - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/testdata/httproute-with-valid-ratelimitfilter.in.yaml b/internal/gatewayapi/testdata/httproute-with-valid-ratelimitfilter.in.yaml deleted file mode 100644 index 3d14a3e87a4..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-valid-ratelimitfilter.in.yaml +++ /dev/null @@ -1,61 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test -rateLimitFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: RateLimitFilter - metadata: - name: test - namespace: default - spec: - type: Global - global: - rules: - - clientSelectors: - - headers: - - name: x-user-id - value: one - - name: x-org-id - type: Distinct - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/testdata/httproute-with-valid-ratelimitfilter.out.yaml b/internal/gatewayapi/testdata/httproute-with-valid-ratelimitfilter.out.yaml deleted file mode 100644 index b278efea178..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-valid-ratelimitfilter.out.yaml +++ /dev/null @@ -1,143 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: RateLimitFilter - name: test - type: ExtensionRef - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 - routes: - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: httproute/default/httproute-1/rule/0 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: gateway.envoyproxy.io - name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io - pathMatch: - distinct: false - name: "" - prefix: / - rateLimit: - global: - rules: - - headerMatches: - - distinct: false - exact: one - name: x-user-id - - distinct: true - name: x-org-id - limit: - requests: 10 - unit: Hour diff --git a/internal/gatewayapi/zz_generated.deepcopy.go b/internal/gatewayapi/zz_generated.deepcopy.go index fb847507b0a..56969b4480a 100644 --- a/internal/gatewayapi/zz_generated.deepcopy.go +++ b/internal/gatewayapi/zz_generated.deepcopy.go @@ -171,17 +171,6 @@ func (in *Resources) DeepCopyInto(out *Resources) { } } } - if in.RateLimitFilters != nil { - in, out := &in.RateLimitFilters, &out.RateLimitFilters - *out = make([]*apiv1alpha1.RateLimitFilter, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(apiv1alpha1.RateLimitFilter) - (*in).DeepCopyInto(*out) - } - } - } if in.EnvoyProxy != nil { in, out := &in.EnvoyProxy, &out.EnvoyProxy *out = new(apiv1alpha1.EnvoyProxy) diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 663eb80a299..be6df0d1356 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -139,9 +139,6 @@ type resourceMappings struct { // authenFilters is a map of AuthenticationFilters, where the key is the // namespaced name of the AuthenticationFilter. authenFilters map[types.NamespacedName]*egv1a1.AuthenticationFilter - // rateLimitFilters is a map of RateLimitFilters, where the key is the - // namespaced name of the RateLimitFilter. - rateLimitFilters map[types.NamespacedName]*egv1a1.RateLimitFilter // extensionRefFilters is a map of filters managed by an extension. // The key is the namespaced name of the filter and the value is the // unstructured form of the resource. @@ -154,7 +151,6 @@ func newResourceMapping() *resourceMappings { allAssociatedBackendRefs: map[gwapiv1.BackendObjectReference]struct{}{}, allAssociatedRefGrants: map[types.NamespacedName]*gwapiv1b1.ReferenceGrant{}, authenFilters: map[types.NamespacedName]*egv1a1.AuthenticationFilter{}, - rateLimitFilters: map[types.NamespacedName]*egv1a1.RateLimitFilter{}, extensionRefFilters: map[types.NamespacedName]unstructured.Unstructured{}, } } @@ -657,7 +653,7 @@ func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error { // addHTTPRouteIndexers adds indexing on HTTPRoute. // - For Service, ServiceImports objects that are referenced in HTTPRoute objects via `.spec.rules.backendRefs`. // This helps in querying for HTTPRoutes that are affected by a particular Service CRUD. -// - For AuthenticationFilter and RateLimitFilter objects that are referenced in HTTPRoute objects via +// - For AuthenticationFilter objects that are referenced in HTTPRoute objects via // `.spec.rules[].filters`. This helps in querying for HTTPRoutes that are affected by a // particular AuthenticationFilter CRUD. func addHTTPRouteIndexers(ctx context.Context, mgr manager.Manager) error { @@ -673,9 +669,6 @@ func addHTTPRouteIndexers(ctx context.Context, mgr manager.Manager) error { return err } - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, rateLimitFilterHTTPRouteIndex, rateLimitFilterHTTPRouteIndexFunc); err != nil { - return err - } return nil } @@ -700,27 +693,6 @@ func authenFilterHTTPRouteIndexFunc(rawObj client.Object) []string { return filters } -func rateLimitFilterHTTPRouteIndexFunc(rawObj client.Object) []string { - httproute := rawObj.(*gwapiv1.HTTPRoute) - var filters []string - for _, rule := range httproute.Spec.Rules { - for i := range rule.Filters { - filter := rule.Filters[i] - if gatewayapi.IsRateLimitHTTPFilter(&filter) { - if err := gatewayapi.ValidateHTTPRouteFilter(&filter); err == nil { - filters = append(filters, - types.NamespacedName{ - Namespace: httproute.Namespace, - Name: string(filter.ExtensionRef.Name), - }.String(), - ) - } - } - } - } - return filters -} - func gatewayHTTPRouteIndexFunc(rawObj client.Object) []string { httproute := rawObj.(*gwapiv1.HTTPRoute) var gateways []string @@ -775,10 +747,6 @@ func addGRPCRouteIndexers(ctx context.Context, mgr manager.Manager) error { return err } - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.GRPCRoute{}, rateLimitFilterGRPCRouteIndex, rateLimitFilterGRPCRouteIndexFunc); err != nil { - return err - } - return nil } @@ -841,27 +809,6 @@ func authenFilterGRPCRouteIndexFunc(rawObj client.Object) []string { return filters } -func rateLimitFilterGRPCRouteIndexFunc(rawObj client.Object) []string { - grpcroute := rawObj.(*gwapiv1a2.GRPCRoute) - var filters []string - for _, rule := range grpcroute.Spec.Rules { - for i := range rule.Filters { - filter := rule.Filters[i] - if gatewayapi.IsRateLimitGRPCFilter(&filter) { - if err := gatewayapi.ValidateGRPCRouteFilter(&filter); err == nil { - filters = append(filters, - types.NamespacedName{ - Namespace: grpcroute.Namespace, - Name: string(filter.ExtensionRef.Name), - }.String(), - ) - } - } - } - } - return filters -} - // addTLSRouteIndexers adds indexing on TLSRoute, for Service objects that are // referenced in TLSRoute objects via `.spec.rules.backendRefs`. This helps in // querying for TLSRoutes that are affected by a particular Service CRUD. @@ -1578,22 +1525,6 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } - rfPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.httpRoutesForRateLimitFilter), - } - if len(r.namespaceLabels) != 0 { - rfPredicates = append(rfPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) - } - // Watch RateLimitFilter CRUDs and enqueue associated HTTPRoute objects. - if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.RateLimitFilter{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - rfPredicates..., - ); err != nil { - return err - } - // Watch EnvoyPatchPolicy if enabled in config eppPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} if len(r.namespaceLabels) != 0 { diff --git a/internal/provider/kubernetes/filters.go b/internal/provider/kubernetes/filters.go index c7d402a8593..bd3266a7040 100644 --- a/internal/provider/kubernetes/filters.go +++ b/internal/provider/kubernetes/filters.go @@ -42,34 +42,6 @@ func (r *gatewayAPIReconciler) getAuthenticationFilters(ctx context.Context) ([] return authens, nil } -func (r *gatewayAPIReconciler) getRateLimitFilters(ctx context.Context) ([]egv1a1.RateLimitFilter, error) { - rateLimitList := new(egv1a1.RateLimitFilterList) - if err := r.client.List(ctx, rateLimitList); err != nil { - return nil, fmt.Errorf("failed to list RateLimitFilters: %v", err) - } - - rateLimits := rateLimitList.Items - if len(r.namespaceLabels) != 0 { - var rls []egv1a1.RateLimitFilter - for _, rl := range rateLimits { - ns := rl.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return nil, fmt.Errorf("failed to check namespace labels for RateLimitFilter %s in namespace %s: %s", rl.GetName(), ns, err) - } - - if ok { - rls = append(rls, rl) - } - } - - rateLimits = rls - } - - return rateLimits, nil -} - func (r *gatewayAPIReconciler) getExtensionRefFilters(ctx context.Context) ([]unstructured.Unstructured, error) { var resourceItems []unstructured.Unstructured for _, gvk := range r.extGVKs { diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index f76d915b931..871874b5a90 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -73,7 +73,6 @@ func TestProvider(t *testing.T) { "gateway scheduled status": testGatewayScheduledStatus, "httproute": testHTTPRoute, "tlsroute": testTLSRoute, - "ratelimit filter": testRateLimitFilter, "authentication filter": testAuthenFilter, "stale service cleanup route deletion": testServiceCleanupForMultipleRoutes, } @@ -458,182 +457,6 @@ func testLongNameHashedResources(ctx context.Context, t *testing.T, provider *Pr assert.Equal(t, gw.Spec, res.Gateways[0].Spec) } -func testRateLimitFilter(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { - cli := provider.manager.GetClient() - - gc := test.GetGatewayClass("ratelimit-test", egv1a1.GatewayControllerName) - require.NoError(t, cli.Create(ctx, gc)) - - // Ensure the GatewayClass reports ready. - require.Eventually(t, func() bool { - if err := cli.Get(ctx, types.NamespacedName{Name: gc.Name}, gc); err != nil { - return false - } - - for _, cond := range gc.Status.Conditions { - if cond.Type == string(gwapiv1.GatewayClassConditionStatusAccepted) && cond.Status == metav1.ConditionTrue { - return true - } - } - - return false - }, defaultWait, defaultTick) - - defer func() { - require.NoError(t, cli.Delete(ctx, gc)) - }() - - // Create the namespace for the Gateway under test. - ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ratelimit-test"}} - require.NoError(t, cli.Create(ctx, ns)) - - gw := &gwapiv1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ratelimit-test", - Namespace: ns.Name, - }, - Spec: gwapiv1.GatewaySpec{ - GatewayClassName: gwapiv1.ObjectName(gc.Name), - Listeners: []gwapiv1.Listener{ - { - Name: "test", - Port: gwapiv1.PortNumber(int32(8080)), - Protocol: gwapiv1.HTTPProtocolType, - }, - }, - }, - } - require.NoError(t, cli.Create(ctx, gw)) - - defer func() { - require.NoError(t, cli.Delete(ctx, gw)) - }() - - svc := test.GetService(types.NamespacedName{Namespace: ns.Name, Name: "test"}, nil, map[string]int32{ - "http": 80, - "https": 443, - }) - - require.NoError(t, cli.Create(ctx, svc)) - - defer func() { - require.NoError(t, cli.Delete(ctx, svc)) - }() - - rateLimitFilter := test.GetRateLimitFilter("ratelimit-test", ns.Name) - - require.NoError(t, cli.Create(ctx, rateLimitFilter)) - - defer func() { - require.NoError(t, cli.Delete(ctx, rateLimitFilter)) - }() - - var testCases = []struct { - name string - route gwapiv1.HTTPRoute - }{ - { - name: "ratelimit-test-httproute", - route: gwapiv1.HTTPRoute{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ratelimit-test", - Namespace: ns.Name, - }, - Spec: gwapiv1.HTTPRouteSpec{ - CommonRouteSpec: gwapiv1.CommonRouteSpec{ - ParentRefs: []gwapiv1.ParentReference{ - { - Name: gwapiv1.ObjectName(gw.Name), - }, - }, - }, - Hostnames: []gwapiv1.Hostname{"test.hostname.local"}, - Rules: []gwapiv1.HTTPRouteRule{ - { - Matches: []gwapiv1.HTTPRouteMatch{ - { - Path: &gwapiv1.HTTPPathMatch{ - Type: ptr.To(gwapiv1.PathMatchPathPrefix), - Value: ptr.To("/ratelimitfilter/"), - }, - }, - }, - BackendRefs: []gwapiv1.HTTPBackendRef{ - { - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "test", - }, - }, - }, - }, - Filters: []gwapiv1.HTTPRouteFilter{ - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindRateLimitFilter), - Name: gwapiv1.ObjectName("ratelimit-test"), - }, - }, - }, - }, - }, - }, - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - require.NoError(t, cli.Create(ctx, &testCase.route)) - defer func() { - require.NoError(t, cli.Delete(ctx, &testCase.route)) - }() - - require.Eventually(t, func() bool { - return resources.GatewayAPIResources.Len() != 0 - }, defaultWait, defaultTick) - - // Ensure the test HTTPRoute in the HTTPRoute resources is as expected. - key := types.NamespacedName{ - Namespace: testCase.route.Namespace, - Name: testCase.route.Name, - } - require.Eventually(t, func() bool { - return cli.Get(ctx, key, &testCase.route) == nil - }, defaultWait, defaultTick) - - require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("ratelimit-test") - return ok && - len(res.HTTPRoutes) != 0 && - assert.Equal(t, testCase.route.Spec, res.HTTPRoutes[0].Spec) - }, defaultWait, defaultTick) - - // Ensure the RateLimitFilter is in the resource map. - require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("ratelimit-test") - return ok && - len(res.RateLimitFilters) != 0 && - assert.Equal(t, rateLimitFilter.Spec, res.RateLimitFilters[0].Spec) - }, defaultWait, defaultTick) - - // Update the rate limit filter. - rateLimitFilter.Spec.Global.Rules = append(rateLimitFilter.Spec.Global.Rules, test.GetRateLimitGlobalRule("two")) - require.NoError(t, cli.Update(ctx, rateLimitFilter)) - - // Ensure the RateLimitFilter in the resource map has been updated. - require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("ratelimit-test") - return ok && - len(res.RateLimitFilters) != 0 && - assert.Equal(t, 2, len(res.RateLimitFilters[0].Spec.Global.Rules)) - }, defaultWait, defaultTick) - }) - } -} - func testAuthenFilter(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { cli := provider.manager.GetClient() @@ -1820,20 +1643,6 @@ func TestNamespaceSelectorsProvider(t *testing.T) { require.NoError(t, cli.Delete(ctx, nonWatchedAuthenFilter)) }() - watchedRateLimitFilter := test.GetRateLimitFilter("watched-rate-limit-filter", watchedNS.Name) - require.NoError(t, cli.Create(ctx, watchedRateLimitFilter)) - - defer func() { - require.NoError(t, cli.Delete(ctx, watchedRateLimitFilter)) - }() - - nonWatchedRateLimitFilter := test.GetRateLimitFilter("non-watched-rate-limit-filter", nonWatchedNS.Name) - require.NoError(t, cli.Create(ctx, nonWatchedRateLimitFilter)) - - defer func() { - require.NoError(t, cli.Delete(ctx, nonWatchedRateLimitFilter)) - }() - watchedSvc := test.GetService(types.NamespacedName{Namespace: watchedNS.Name, Name: "watched-service"}, nil, map[string]int32{ "http": 80, "https": 443, @@ -1870,14 +1679,6 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: gwapiv1.ObjectName(watchedAuthenFilter.Name), }, }, - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindRateLimitFilter), - Name: gwapiv1.ObjectName(watchedRateLimitFilter.Name), - }, - }, } require.NoError(t, cli.Create(ctx, watchedHTTPRoute)) defer func() { @@ -1900,14 +1701,6 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: gwapiv1.ObjectName(nonWatchedAuthenFilter.Name), }, }, - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindRateLimitFilter), - Name: gwapiv1.ObjectName(nonWatchedRateLimitFilter.Name), - }, - }, } require.NoError(t, cli.Create(ctx, nonWatchedHTTPRoute)) defer func() { @@ -2046,8 +1839,4 @@ func TestNamespaceSelectorsProvider(t *testing.T) { return res != nil && len(res.AuthenticationFilters) == 1 }, defaultWait, defaultTick) - require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) - return res != nil && len(res.RateLimitFilters) == 1 - }, defaultWait, defaultTick) } diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index b24872447d4..343ef469d1b 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -349,30 +349,6 @@ func (r *gatewayAPIReconciler) httpRoutesForAuthenticationFilter(obj client.Obje return len(httpRoutes) != 0 } -// httpRoutesForRateLimitFilter tries finding HTTPRoute referents of the provided -// RateLimitFilter and returns true if any exist. -func (r *gatewayAPIReconciler) httpRoutesForRateLimitFilter(obj client.Object) bool { - ctx := context.Background() - filter, ok := obj.(*egv1a1.RateLimitFilter) - if !ok { - r.log.Info("unexpected object type, bypassing reconciliation", "object", obj) - return false - } - - // Check if the RateLimitFilter belongs to a managed HTTPRoute. - httpRouteList := &gwapiv1.HTTPRouteList{} - if err := r.client.List(ctx, httpRouteList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(rateLimitFilterHTTPRouteIndex, utils.NamespacedName(filter).String()), - }); err != nil { - r.log.Error(err, "unable to find associated HTTPRoutes") - return false - } - - httpRoutes := r.filterHTTPRoutesByNamespaceLabels(httpRouteList.Items) - - return len(httpRoutes) != 0 -} - func (r *gatewayAPIReconciler) filterHTTPRoutesByNamespaceLabels(httpRoutes []gwapiv1.HTTPRoute) []gwapiv1.HTTPRoute { if len(r.namespaceLabels) == 0 { return httpRoutes diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index d8447b9917b..c8876e28166 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -108,7 +108,7 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { grpcRouteList := &gwapiv1a2.GRPCRouteList{} - // An GRPCRoute may reference an AuthenticationFilter and RateLimitFilter, + // An GRPCRoute may reference an AuthenticationFilter, // so add them to the resource map first (if they exist). authenFilters, err := r.getAuthenticationFilters(ctx) if err != nil { @@ -119,15 +119,6 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam resourceMap.authenFilters[utils.NamespacedName(&filter)] = &filter } - rateLimitFilters, err := r.getRateLimitFilters(ctx) - if err != nil { - return err - } - for i := range rateLimitFilters { - filter := rateLimitFilters[i] - resourceMap.rateLimitFilters[utils.NamespacedName(&filter)] = &filter - } - if err := r.client.List(ctx, grpcRouteList, &client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayGRPCRouteIndex, gatewayNamespaceName), }); err != nil { @@ -224,18 +215,6 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam } resourceTree.AuthenticationFilters = append(resourceTree.AuthenticationFilters, authFilter) - case egv1a1.KindRateLimitFilter: - key := types.NamespacedName{ - Namespace: grpcRoute.Namespace, - Name: string(filter.ExtensionRef.Name), - } - rateLimitFilter, ok := resourceMap.rateLimitFilters[key] - if !ok { - r.log.Error(err, "RateLimitFilter not found; bypassing rule", "index", i) - continue - } - - resourceTree.RateLimitFilters = append(resourceTree.RateLimitFilters, rateLimitFilter) default: // If the Kind does not match any Envoy Gateway resources, check if it's a Kind // managed by an extension and add to resourceTree @@ -271,7 +250,7 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { httpRouteList := &gwapiv1.HTTPRouteList{} - // An HTTPRoute may reference an AuthenticationFilter, RateLimitFilter, or a filter managed + // An HTTPRoute may reference an AuthenticationFilter, or a filter managed // by an extension so add them to the resource map first (if they exist). authenFilters, err := r.getAuthenticationFilters(ctx) if err != nil { @@ -282,15 +261,6 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam resourceMap.authenFilters[utils.NamespacedName(&filter)] = &filter } - rateLimitFilters, err := r.getRateLimitFilters(ctx) - if err != nil { - return err - } - for i := range rateLimitFilters { - filter := rateLimitFilters[i] - resourceMap.rateLimitFilters[utils.NamespacedName(&filter)] = &filter - } - extensionRefFilters, err := r.getExtensionRefFilters(ctx) if err != nil { return err @@ -451,18 +421,6 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam } resourceTree.AuthenticationFilters = append(resourceTree.AuthenticationFilters, authFilter) - case egv1a1.KindRateLimitFilter: - key := types.NamespacedName{ - Namespace: httpRoute.Namespace, - Name: string(filter.ExtensionRef.Name), - } - rateLimitFilter, ok := resourceMap.rateLimitFilters[key] - if !ok { - r.log.Error(err, "RateLimitFilter not found; bypassing rule", "index", i) - continue - } - - resourceTree.RateLimitFilters = append(resourceTree.RateLimitFilters, rateLimitFilter) default: // If the Kind does not match any Envoy Gateway resources, check if it's a Kind // managed by an extension and add to resourceTree diff --git a/internal/provider/kubernetes/routes_test.go b/internal/provider/kubernetes/routes_test.go index a0a01346986..681af679a93 100644 --- a/internal/provider/kubernetes/routes_test.go +++ b/internal/provider/kubernetes/routes_test.go @@ -64,7 +64,6 @@ func TestProcessHTTPRoutes(t *testing.T) { name string routes []*gwapiv1.HTTPRoute authenFilters []*egv1a1.AuthenticationFilter - rateLimitFilters []*egv1a1.RateLimitFilter extensionFilters []*unstructured.Unstructured extensionAPIGroups []schema.GroupVersionKind expected bool @@ -192,209 +191,6 @@ func TestProcessHTTPRoutes(t *testing.T) { }, expected: true, }, - { - name: "httproute with one rateLimitfilter", - routes: []*gwapiv1.HTTPRoute{ - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: gwapiv1.HTTPRouteSpec{ - CommonRouteSpec: gwapiv1.CommonRouteSpec{ - ParentRefs: []gwapiv1.ParentReference{ - { - Name: "test", - }, - }, - }, - Rules: []gwapiv1.HTTPRouteRule{ - { - Matches: []gwapiv1.HTTPRouteMatch{ - { - Path: &gwapiv1.HTTPPathMatch{ - Type: ptr.To(gwapiv1.PathMatchPathPrefix), - Value: ptr.To("/"), - }, - }, - }, - Filters: []gwapiv1.HTTPRouteFilter{ - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindRateLimitFilter), - Name: gwapiv1.ObjectName("test"), - }, - }, - }, - BackendRefs: []gwapiv1.HTTPBackendRef{ - { - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Group: gatewayapi.GroupPtr(corev1.GroupName), - Kind: gatewayapi.KindPtr(gatewayapi.KindService), - Name: "test", - }, - }, - }, - }, - }, - }, - }, - }, - }, - rateLimitFilters: []*egv1a1.RateLimitFilter{ - { - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindRateLimitFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.RateLimitFilterSpec{ - Type: egv1a1.GlobalRateLimitType, - Global: &egv1a1.GlobalRateLimit{ - Rules: []egv1a1.RateLimitRule{ - { - ClientSelectors: []egv1a1.RateLimitSelectCondition{ - { - Headers: []egv1a1.HeaderMatch{ - { - Name: "x-user-id", - Value: ptr.To("one"), - }, - }, - }, - }, - Limit: egv1a1.RateLimitValue{ - Requests: 5, - Unit: "Second", - }, - }, - }, - }, - }, - }, - }, - expected: true, - }, - { - name: "httproute with one authenticationfilter and ratelimitfilter", - routes: []*gwapiv1.HTTPRoute{ - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: gwapiv1.HTTPRouteSpec{ - CommonRouteSpec: gwapiv1.CommonRouteSpec{ - ParentRefs: []gwapiv1.ParentReference{ - { - Name: "test", - }, - }, - }, - Rules: []gwapiv1.HTTPRouteRule{ - { - Matches: []gwapiv1.HTTPRouteMatch{ - { - Path: &gwapiv1.HTTPPathMatch{ - Type: ptr.To(gwapiv1.PathMatchPathPrefix), - Value: ptr.To("/"), - }, - }, - }, - Filters: []gwapiv1.HTTPRouteFilter{ - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindAuthenticationFilter), - Name: gwapiv1.ObjectName("test"), - }, - }, - }, - BackendRefs: []gwapiv1.HTTPBackendRef{ - { - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Group: gatewayapi.GroupPtr(corev1.GroupName), - Kind: gatewayapi.KindPtr(gatewayapi.KindService), - Name: "test", - }, - }, - }, - }, - }, - }, - }, - }, - }, - authenFilters: []*egv1a1.AuthenticationFilter{ - { - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - }, - rateLimitFilters: []*egv1a1.RateLimitFilter{ - { - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindRateLimitFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.RateLimitFilterSpec{ - Type: egv1a1.GlobalRateLimitType, - Global: &egv1a1.GlobalRateLimit{ - Rules: []egv1a1.RateLimitRule{ - { - ClientSelectors: []egv1a1.RateLimitSelectCondition{ - { - Headers: []egv1a1.HeaderMatch{ - { - Name: "x-user-id", - Value: ptr.To("one"), - }, - }, - }, - }, - Limit: egv1a1.RateLimitValue{ - Requests: 5, - Unit: "Second", - }, - }, - }, - }, - }, - }, - }, - expected: true, - }, { name: "httproute with one filter_from_extension", routes: []*gwapiv1.HTTPRoute{ @@ -494,9 +290,6 @@ func TestProcessHTTPRoutes(t *testing.T) { for _, filter := range tc.authenFilters { objs = append(objs, filter) } - for _, filter := range tc.rateLimitFilters { - objs = append(objs, filter) - } for _, filter := range tc.extensionFilters { objs = append(objs, filter) } @@ -527,15 +320,6 @@ func TestProcessHTTPRoutes(t *testing.T) { require.Equal(t, filter, resourceMap.authenFilters[key]) } } - if tc.rateLimitFilters != nil { - for i, filter := range tc.rateLimitFilters { - key := types.NamespacedName{ - Namespace: tc.routes[i].Namespace, - Name: filter.Name, - } - require.Equal(t, filter, resourceMap.rateLimitFilters[key]) - } - } if tc.extensionFilters != nil { for i, filter := range tc.extensionFilters { key := types.NamespacedName{ @@ -587,7 +371,6 @@ func TestProcessGRPCRoutes(t *testing.T) { name string routes []*gwapiv1a2.GRPCRoute authenFilters []*egv1a1.AuthenticationFilter - rateLimitFilters []*egv1a1.RateLimitFilter extensionAPIGroups []schema.GroupVersionKind expected bool }{ @@ -712,94 +495,6 @@ func TestProcessGRPCRoutes(t *testing.T) { }, expected: true, }, - { - name: "grpcroute with one ratelimitfilter", - routes: []*gwapiv1a2.GRPCRoute{ - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: gwapiv1a2.GRPCRouteSpec{ - CommonRouteSpec: gwapiv1.CommonRouteSpec{ - ParentRefs: []gwapiv1.ParentReference{ - { - Name: "test", - }, - }, - }, - Rules: []gwapiv1a2.GRPCRouteRule{ - { - Matches: []gwapiv1a2.GRPCRouteMatch{ - { - Method: &gwapiv1a2.GRPCMethodMatch{ - Method: ptr.To("Ping"), - }, - }, - }, - Filters: []gwapiv1a2.GRPCRouteFilter{ - { - Type: gwapiv1a2.GRPCRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindRateLimitFilter), - Name: gwapiv1.ObjectName("test"), - }, - }, - }, - BackendRefs: []gwapiv1a2.GRPCBackendRef{ - { - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Group: gatewayapi.GroupPtr(corev1.GroupName), - Kind: gatewayapi.KindPtr(gatewayapi.KindService), - Name: "test", - }, - }, - }, - }, - }, - }, - }, - }, - }, - rateLimitFilters: []*egv1a1.RateLimitFilter{ - { - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindRateLimitFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.RateLimitFilterSpec{ - Type: egv1a1.KindRateLimitFilter, - Global: &egv1a1.GlobalRateLimit{ - Rules: []egv1a1.RateLimitRule{ - { - ClientSelectors: []egv1a1.RateLimitSelectCondition{ - { - Headers: []egv1a1.HeaderMatch{ - { - Name: "x-user-id", - Value: ptr.To("one"), - }, - }, - }, - }, - Limit: egv1a1.RateLimitValue{ - Requests: 5, - Unit: "Second", - }, - }, - }, - }, - }, - }, - }, - expected: true, - }, } for i := range testCases { @@ -826,9 +521,6 @@ func TestProcessGRPCRoutes(t *testing.T) { for _, filter := range tc.authenFilters { objs = append(objs, filter) } - for _, filter := range tc.rateLimitFilters { - objs = append(objs, filter) - } if len(tc.extensionAPIGroups) > 0 { r.extGVKs = append(r.extGVKs, tc.extensionAPIGroups...) } @@ -856,15 +548,6 @@ func TestProcessGRPCRoutes(t *testing.T) { require.Equal(t, filter, resourceMap.authenFilters[key]) } } - if tc.rateLimitFilters != nil { - for i, filter := range tc.rateLimitFilters { - key := types.NamespacedName{ - Namespace: tc.routes[i].Namespace, - Name: filter.Name, - } - require.Equal(t, filter, resourceMap.rateLimitFilters[key]) - } - } } else { require.Error(t, err) } diff --git a/internal/provider/kubernetes/test/utils.go b/internal/provider/kubernetes/test/utils.go index 877e173bc29..f139d02f69a 100644 --- a/internal/provider/kubernetes/test/utils.go +++ b/internal/provider/kubernetes/test/utils.go @@ -343,48 +343,6 @@ func GetAuthenticationProvider(name string) egv1a1.JwtAuthenticationFilterProvid } } -// GetRateLimitFilter returns a pointer to an RateLimitFilter with dummy rules. -func GetRateLimitFilter(name, ns string) *egv1a1.RateLimitFilter { - rule := GetRateLimitGlobalRule("one") - return &egv1a1.RateLimitFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindRateLimitFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: ns, - Name: name, - }, - Spec: egv1a1.RateLimitFilterSpec{ - Type: egv1a1.GlobalRateLimitType, - Global: &egv1a1.GlobalRateLimit{ - Rules: []egv1a1.RateLimitRule{rule}, - }, - }, - } -} - -// GetRateLimitGlobalRule returns a RateLimitRule using the val as the ClientSelectors -// headers value. -func GetRateLimitGlobalRule(val string) egv1a1.RateLimitRule { - return egv1a1.RateLimitRule{ - ClientSelectors: []egv1a1.RateLimitSelectCondition{ - { - Headers: []egv1a1.HeaderMatch{ - { - Name: "x-user-id", - Value: ptr.To(val), - }, - }, - }, - }, - Limit: egv1a1.RateLimitValue{ - Requests: 5, - Unit: "Second", - }, - } -} - func ContainsAuthenFilter(hroute *gwapiv1.HTTPRoute) bool { if hroute == nil { return false diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index b79f1dc2b94..310aa30de47 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -23,7 +23,6 @@ API group. - [EnvoyPatchPolicy](#envoypatchpolicy) - [EnvoyPatchPolicyList](#envoypatchpolicylist) - [EnvoyProxy](#envoyproxy) -- [RateLimitFilter](#ratelimitfilter) - [SecurityPolicy](#securitypolicy) - [SecurityPolicyList](#securitypolicylist) @@ -116,7 +115,7 @@ _Appears in:_ | Field | Description | | --- | --- | | `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | targetRef is the name of the resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. | -| `rateLimit` _[RateLimitFilterSpec](#ratelimitfilterspec)_ | RateLimit allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. | +| `rateLimit` _[RateLimitSpec](#ratelimitspec)_ | RateLimit allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. | | `loadBalancer` _[LoadBalancer](#loadbalancer)_ | LoadBalancer policy to apply when routing traffic from the gateway to the backend endpoints | @@ -835,7 +834,7 @@ _Appears in:_ GlobalRateLimit defines global rate limit configuration. _Appears in:_ -- [RateLimitFilterSpec](#ratelimitfilterspec) +- [RateLimitSpec](#ratelimitspec) | Field | Description | | --- | --- | @@ -1459,38 +1458,6 @@ _Appears in:_ -#### RateLimitFilter - - - -RateLimitFilter allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. - - - -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `RateLimitFilter` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `spec` _[RateLimitFilterSpec](#ratelimitfilterspec)_ | Spec defines the desired state of RateLimitFilter. | - - -#### RateLimitFilterSpec - - - -RateLimitFilterSpec defines the desired state of RateLimitFilter. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -- [RateLimitFilter](#ratelimitfilter) - -| Field | Description | -| --- | --- | -| `type` _[RateLimitType](#ratelimittype)_ | Type decides the scope for the RateLimits. Valid RateLimitType values are "Global". | -| `global` _[GlobalRateLimit](#globalratelimit)_ | Global defines global rate limit configuration. | - - #### RateLimitRedisSettings @@ -1536,6 +1503,21 @@ _Appears in:_ | `sourceCIDR` _[SourceMatch](#sourcematch)_ | SourceCIDR is the client IP Address range to match on. | +#### RateLimitSpec + + + +RateLimitSpec defines the desired state of RateLimitSpec. + +_Appears in:_ +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) + +| Field | Description | +| --- | --- | +| `type` _[RateLimitType](#ratelimittype)_ | Type decides the scope for the RateLimits. Valid RateLimitType values are "Global". | +| `global` _[GlobalRateLimit](#globalratelimit)_ | Global defines global rate limit configuration. | + + #### RateLimitType _Underlying type:_ `string` @@ -1543,7 +1525,7 @@ _Underlying type:_ `string` RateLimitType specifies the types of RateLimiting. _Appears in:_ -- [RateLimitFilterSpec](#ratelimitfilterspec) +- [RateLimitSpec](#ratelimitspec) diff --git a/site/content/en/latest/user/rate-limit.md b/site/content/en/latest/user/rate-limit.md index cee28080b9c..c27eefaf90a 100644 --- a/site/content/en/latest/user/rate-limit.md +++ b/site/content/en/latest/user/rate-limit.md @@ -14,8 +14,8 @@ Envoy Gateway supports [Global rate limiting][], where the rate limit is common i.e. if the data plane has 2 replicas of Envoy running, and the rate limit is 10 requests/second, this limit is common and will be hit if 5 requests pass through the first replica and 5 requests pass through the second replica within the same second. -Envoy Gateway introduces a new CRD called [RateLimitFilter][] that allows the user to describe their rate limit intent. This instantiated resource -can be linked to a [HTTPRoute][] or [GRPCRoute][] resource using an [ExtensionRef][] filter. +Envoy Gateway introduces a new CRD called [BackendTrafficPolicy][] that allows the user to describe their rate limit intent. This instantiated resource +can be linked to a [Gateway][], [HTTPRoute][] or [GRPCRoute][] resource. ## Prerequisites @@ -131,20 +131,26 @@ with a value set to `one`. ```shell cat < Date: Thu, 26 Oct 2023 23:11:08 -0500 Subject: [PATCH 08/55] CEL validation: implement validateProvider for EnvoyProxy (#2081) * use v1.27.1 for CEL validation test Signed-off-by: zirain * implement validateProvider with CEL Signed-off-by: zirain * use regex for IPv4 Signed-off-by: zirain * bump ENVTEST_K8S_VERSION to 1.27.1 Signed-off-by: zirain * update with arko's comment Signed-off-by: zirain --------- Signed-off-by: zirain --- api/v1alpha1/envoyproxy_types.go | 3 + .../validation/envoyproxy_validate.go | 2 + .../gateway.envoyproxy.io_envoyproxies.yaml | 10 ++ .../provider/kubernetes/kubernetes_test.go | 60 +++++--- .../provider/kubernetes/predicates_test.go | 17 ++- internal/provider/kubernetes/test/utils.go | 15 +- test/cel-validation/envoyproxy_test.go | 140 +++++++++++++++++- tools/make/golang.mk | 5 +- tools/make/kube.mk | 5 +- 9 files changed, 213 insertions(+), 44 deletions(-) diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index 76da4babce1..23a7942688f 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -122,6 +122,9 @@ type EnvoyProxyKubernetesProvider struct { // are applied. // // +optional + // +kubebuilder:validation:XValidation:message="allocateLoadBalancerNodePorts can only be set for LoadBalancer type",rule="!has(self.allocateLoadBalancerNodePorts) || self.type == 'LoadBalancer'" + // +kubebuilder:validation:XValidation:message="loadBalancerIP can only be set for LoadBalancer type",rule="!has(self.loadBalancerIP) || self.type == 'LoadBalancer'" + // +kubebuilder:validation:XValidation:message="loadBalancerIP must be a valid IPv4 address",rule="!has(self.loadBalancerIP) || self.loadBalancerIP.matches(r\"^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4})\")" EnvoyService *KubernetesServiceSpec `json:"envoyService,omitempty"` } diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go index 6ebf9703036..6c608f0e0f7 100644 --- a/api/v1alpha1/validation/envoyproxy_validate.go +++ b/api/v1alpha1/validation/envoyproxy_validate.go @@ -66,6 +66,7 @@ func validateEnvoyProxySpec(spec *egv1a1.EnvoyProxySpec) error { return utilerrors.NewAggregate(errs) } +// TODO: remove this function if CEL validation became stable func validateProvider(spec *egv1a1.EnvoyProxySpec) []error { var errs []error if spec != nil && spec.Provider != nil { @@ -80,6 +81,7 @@ func validateProvider(spec *egv1a1.EnvoyProxySpec) []error { return errs } +// TODO: remove this function if CEL validation became stable func validateService(spec *egv1a1.EnvoyProxySpec) []error { var errs []error if spec.Provider.Kubernetes != nil && spec.Provider.Kubernetes.EnvoyService != nil { 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 1818421f26a..fdcb534cb67 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -5280,6 +5280,16 @@ spec: - NodePort type: string type: object + x-kubernetes-validations: + - message: allocateLoadBalancerNodePorts can only be set for + LoadBalancer type + rule: '!has(self.allocateLoadBalancerNodePorts) || self.type + == ''LoadBalancer''' + - message: loadBalancerIP can only be set for LoadBalancer + type + rule: '!has(self.loadBalancerIP) || self.type == ''LoadBalancer''' + - message: loadBalancerIP must be a valid IPv4 address + rule: '!has(self.loadBalancerIP) || self.loadBalancerIP.matches(r"^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})")' type: object type: description: Type is the type of resource provider to use. A resource diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index 871874b5a90..e15baa505ab 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -99,7 +99,7 @@ func startEnv() (*envtest.Environment, *rest.Config, error) { return env, cfg, nil } -func testGatewayClassController(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { +func testGatewayClassController(ctx context.Context, t *testing.T, provider *Provider, _ *message.ProviderResources) { cli := provider.manager.GetClient() gc := test.GetGatewayClass("test-gc-controllername", egv1a1.GatewayControllerName) @@ -171,7 +171,7 @@ func testGatewayClassWithParamRef(ctx context.Context, t *testing.T, provider *P gc := test.GetGatewayClass("gc-with-param-ref", egv1a1.GatewayControllerName) gc.Spec.ParametersRef = &gwapiv1.ParametersReference{ Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindEnvoyProxy), + Kind: egv1a1.KindEnvoyProxy, Name: epName, Namespace: gatewayapi.NamespacePtr(testNs), } @@ -562,6 +562,7 @@ func testAuthenFilter(ctx context.Context, t *testing.T, provider *Provider, res BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -744,6 +745,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -779,15 +781,6 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour }, }, }, - BackendRefs: []gwapiv1.HTTPBackendRef{ - { - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "test", - }, - }, - }, - }, Filters: []gwapiv1.HTTPRouteFilter{ { Type: gwapiv1.HTTPRouteFilterType("RequestRedirect"), @@ -839,6 +832,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -891,6 +885,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -954,6 +949,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -1006,6 +1002,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -1069,6 +1066,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -1121,6 +1119,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -1131,6 +1130,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour RequestMirror: &gwapiv1.HTTPRequestMirrorFilter{ BackendRef: gwapiv1.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }, @@ -1185,6 +1185,11 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour // Ensure the Service is in the resource map. require.Eventually(t, func() bool { + // The redirect test case does not have a service. + if testCase.name == "redirect-httproute" { + return true + } + res, ok := resources.GatewayAPIResources.Load("httproute-test") if !ok { return false @@ -1226,6 +1231,9 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc Name: "test", Port: gwapiv1.PortNumber(int32(8080)), Protocol: gwapiv1.TLSProtocolType, + TLS: &gwapiv1.GatewayTLSConfig{ + Mode: ptr.To(gwapiv1.TLSModePassthrough), + }, }, }, }, @@ -1270,6 +1278,7 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc { BackendObjectReference: gwapiv1a2.BackendObjectReference{ Name: "test", + Port: ptr.To(gwapiv1.PortNumber(90)), }, }, }, @@ -1371,6 +1380,9 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov Name: "tlstest", Port: gwapiv1.PortNumber(int32(8043)), Protocol: gwapiv1.TLSProtocolType, + TLS: &gwapiv1.GatewayTLSConfig{ + Mode: ptr.To(gwapiv1.TLSModePassthrough), + }, }, }, }, @@ -1405,6 +1417,7 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov BackendRefs: []gwapiv1a2.BackendRef{{ BackendObjectReference: gwapiv1a2.BackendObjectReference{ Name: "test-common-svc", + Port: ptr.To(gwapiv1.PortNumber(90)), }}, }}, }, @@ -1434,6 +1447,7 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: "test-common-svc", + Port: ptr.To(gwapiv1.PortNumber(80)), }, }, }}, @@ -1669,13 +1683,13 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "watched-http-route", }, watchedGateway.Name, - types.NamespacedName{Name: watchedSvc.Name}) + types.NamespacedName{Name: watchedSvc.Name}, 80) watchedHTTPRoute.Spec.Rules[0].Filters = []gwapiv1.HTTPRouteFilter{ { Type: gwapiv1.HTTPRouteFilterExtensionRef, ExtensionRef: &gwapiv1.LocalObjectReference{ Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindAuthenticationFilter), + Kind: egv1a1.KindAuthenticationFilter, Name: gwapiv1.ObjectName(watchedAuthenFilter.Name), }, }, @@ -1691,13 +1705,13 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "non-watched-http-route", }, nonWatchedGateway.Name, - types.NamespacedName{Name: nonWatchedSvc.Name}) + types.NamespacedName{Name: nonWatchedSvc.Name}, 8001) nonWatchedHTTPRoute.Spec.Rules[0].Filters = []gwapiv1.HTTPRouteFilter{ { Type: gwapiv1.HTTPRouteFilterExtensionRef, ExtensionRef: &gwapiv1.LocalObjectReference{ Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindAuthenticationFilter), + Kind: egv1a1.KindAuthenticationFilter, Name: gwapiv1.ObjectName(nonWatchedAuthenFilter.Name), }, }, @@ -1713,7 +1727,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "watched-grpc-route", }, watchedGateway.Name, - types.NamespacedName{Name: watchedSvc.Name}) + types.NamespacedName{Name: watchedSvc.Name}, 80) require.NoError(t, cli.Create(ctx, watchedGRPCRoute)) defer func() { require.NoError(t, cli.Delete(ctx, watchedGRPCRoute)) @@ -1725,7 +1739,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "non-watched-grpc-route", }, nonWatchedGateway.Name, - types.NamespacedName{Name: nonWatchedNS.Name}) + types.NamespacedName{Name: nonWatchedNS.Name}, 8001) require.NoError(t, cli.Create(ctx, nonWatchedGRPCRoute)) defer func() { require.NoError(t, cli.Delete(ctx, nonWatchedGRPCRoute)) @@ -1737,7 +1751,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "watched-tcp-route", }, watchedGateway.Name, - types.NamespacedName{Name: watchedSvc.Name}) + types.NamespacedName{Name: watchedSvc.Name}, 80) require.NoError(t, cli.Create(ctx, watchedTCPRoute)) defer func() { require.NoError(t, cli.Delete(ctx, watchedTCPRoute)) @@ -1749,7 +1763,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "non-watched-tcp-route", }, nonWatchedGateway.Name, - types.NamespacedName{Name: nonWatchedNS.Name}) + types.NamespacedName{Name: nonWatchedNS.Name}, 80) require.NoError(t, cli.Create(ctx, nonWatchedTCPRoute)) defer func() { require.NoError(t, cli.Delete(ctx, nonWatchedTCPRoute)) @@ -1761,7 +1775,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "watched-tls-route", }, watchedGateway.Name, - types.NamespacedName{Name: watchedSvc.Name}) + types.NamespacedName{Name: watchedSvc.Name}, 443) require.NoError(t, cli.Create(ctx, watchedTLSRoute)) defer func() { require.NoError(t, cli.Delete(ctx, watchedTLSRoute)) @@ -1773,7 +1787,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "non-watched-tls-route", }, nonWatchedGateway.Name, - types.NamespacedName{Name: nonWatchedNS.Name}) + types.NamespacedName{Name: nonWatchedNS.Name}, 443) require.NoError(t, cli.Create(ctx, nonWatchedTLSRoute)) defer func() { require.NoError(t, cli.Delete(ctx, nonWatchedTLSRoute)) @@ -1785,7 +1799,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "watched-udp-route", }, watchedGateway.Name, - types.NamespacedName{Name: watchedSvc.Name}) + types.NamespacedName{Name: watchedSvc.Name}, 80) require.NoError(t, cli.Create(ctx, watchedUDPRoute)) defer func() { require.NoError(t, cli.Delete(ctx, watchedUDPRoute)) @@ -1797,7 +1811,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { Name: "non-watched-udp-route", }, nonWatchedGateway.Name, - types.NamespacedName{Name: nonWatchedNS.Name}) + types.NamespacedName{Name: nonWatchedNS.Name}, 80) require.NoError(t, cli.Create(ctx, nonWatchedUDPRoute)) defer func() { require.NoError(t, cli.Delete(ctx, nonWatchedUDPRoute)) diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index 2bd311e95ee..18eeba59550 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -126,6 +126,7 @@ func TestGatewayClassHasMatchingNamespaceLabels(t *testing.T) { }, "scheduled-status-test", types.NamespacedName{Name: "service"}, + 80, )) require.Equal(t, tc.expect, res) }) @@ -263,7 +264,7 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { configs: []client.Object{ test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), sampleGateway, - test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}), + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, endpointSlice: test.GetEndpointSlice(types.NamespacedName{Name: "endpointslice"}, "other-service"), expect: false, @@ -273,7 +274,7 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { configs: []client.Object{ test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), sampleGateway, - test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}), + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, endpointSlice: test.GetEndpointSlice(types.NamespacedName{Name: "endpointslice"}, "service"), expect: true, @@ -358,7 +359,7 @@ func TestValidateServiceForReconcile(t *testing.T) { configs: []client.Object{ test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), sampleGateway, - test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}), + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, @@ -370,7 +371,7 @@ func TestValidateServiceForReconcile(t *testing.T) { name: "route service routes exist but with non-existing gateway reference", configs: []client.Object{ test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), - test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}), + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, @@ -380,7 +381,7 @@ func TestValidateServiceForReconcile(t *testing.T) { configs: []client.Object{ test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), sampleGateway, - test.GetGRPCRoute(types.NamespacedName{Name: "grpcroute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}), + test.GetGRPCRoute(types.NamespacedName{Name: "grpcroute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, @@ -391,7 +392,7 @@ func TestValidateServiceForReconcile(t *testing.T) { test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), sampleGateway, test.GetTLSRoute(types.NamespacedName{Name: "tlsroute-test"}, "scheduled-status-test", - types.NamespacedName{Name: "service"}), + types.NamespacedName{Name: "service"}, 443), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, @@ -402,7 +403,7 @@ func TestValidateServiceForReconcile(t *testing.T) { test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), sampleGateway, test.GetUDPRoute(types.NamespacedName{Name: "udproute-test"}, "scheduled-status-test", - types.NamespacedName{Name: "service"}), + types.NamespacedName{Name: "service"}, 80), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, @@ -413,7 +414,7 @@ func TestValidateServiceForReconcile(t *testing.T) { test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), sampleGateway, test.GetTCPRoute(types.NamespacedName{Name: "tcproute-test"}, "scheduled-status-test", - types.NamespacedName{Name: "service"}), + types.NamespacedName{Name: "service"}, 80), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, diff --git a/internal/provider/kubernetes/test/utils.go b/internal/provider/kubernetes/test/utils.go index f139d02f69a..94e0e69dc0e 100644 --- a/internal/provider/kubernetes/test/utils.go +++ b/internal/provider/kubernetes/test/utils.go @@ -92,7 +92,7 @@ func GetSecret(nsname types.NamespacedName) *corev1.Secret { } // GetHTTPRoute returns a sample HTTPRoute with a parent reference. -func GetHTTPRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName) *gwapiv1.HTTPRoute { +func GetHTTPRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName, port int32) *gwapiv1.HTTPRoute { return &gwapiv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Namespace: nsName.Namespace, @@ -111,6 +111,7 @@ func GetHTTPRoute(nsName types.NamespacedName, parent string, serviceName types. BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: gwapiv1.ObjectName(serviceName.Name), + Port: ptr.To(gwapiv1.PortNumber(port)), }, }, }, @@ -122,7 +123,7 @@ func GetHTTPRoute(nsName types.NamespacedName, parent string, serviceName types. } // GetGRPCRoute returns a sample GRPCRoute with a parent reference. -func GetGRPCRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName) *gwapiv1a2.GRPCRoute { +func GetGRPCRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName, port int32) *gwapiv1a2.GRPCRoute { return &gwapiv1a2.GRPCRoute{ ObjectMeta: metav1.ObjectMeta{ Namespace: nsName.Namespace, @@ -141,6 +142,7 @@ func GetGRPCRoute(nsName types.NamespacedName, parent string, serviceName types. BackendRef: gwapiv1.BackendRef{ BackendObjectReference: gwapiv1.BackendObjectReference{ Name: gwapiv1.ObjectName(serviceName.Name), + Port: ptr.To(gwapiv1.PortNumber(port)), }, }, }, @@ -152,7 +154,7 @@ func GetGRPCRoute(nsName types.NamespacedName, parent string, serviceName types. } // GetTLSRoute returns a sample TLSRoute with a parent reference. -func GetTLSRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName) *gwapiv1a2.TLSRoute { +func GetTLSRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName, port int32) *gwapiv1a2.TLSRoute { return &gwapiv1a2.TLSRoute{ ObjectMeta: metav1.ObjectMeta{ Namespace: nsName.Namespace, @@ -170,6 +172,7 @@ func GetTLSRoute(nsName types.NamespacedName, parent string, serviceName types.N { BackendObjectReference: gwapiv1a2.BackendObjectReference{ Name: gwapiv1a2.ObjectName(serviceName.Name), + Port: ptr.To(gwapiv1.PortNumber(port)), }, }, }, @@ -180,7 +183,7 @@ func GetTLSRoute(nsName types.NamespacedName, parent string, serviceName types.N } // GetTCPRoute returns a sample TCPRoute with a parent reference. -func GetTCPRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName) *gwapiv1a2.TCPRoute { +func GetTCPRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName, port int32) *gwapiv1a2.TCPRoute { return &gwapiv1a2.TCPRoute{ ObjectMeta: metav1.ObjectMeta{ Namespace: nsName.Namespace, @@ -198,6 +201,7 @@ func GetTCPRoute(nsName types.NamespacedName, parent string, serviceName types.N { BackendObjectReference: gwapiv1a2.BackendObjectReference{ Name: gwapiv1a2.ObjectName(serviceName.Name), + Port: ptr.To(gwapiv1a2.PortNumber(port)), }, }, }, @@ -208,7 +212,7 @@ func GetTCPRoute(nsName types.NamespacedName, parent string, serviceName types.N } // GetUDPRoute returns a sample UDPRoute with a parent reference. -func GetUDPRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName) *gwapiv1a2.UDPRoute { +func GetUDPRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName, port int32) *gwapiv1a2.UDPRoute { return &gwapiv1a2.UDPRoute{ ObjectMeta: metav1.ObjectMeta{ Namespace: nsName.Namespace, @@ -226,6 +230,7 @@ func GetUDPRoute(nsName types.NamespacedName, parent string, serviceName types.N { BackendObjectReference: gwapiv1a2.BackendObjectReference{ Name: gwapiv1a2.ObjectName(serviceName.Name), + Port: ptr.To(gwapiv1a2.PortNumber(port)), }, }, }, diff --git a/test/cel-validation/envoyproxy_test.go b/test/cel-validation/envoyproxy_test.go index 919a1ec9241..99912faff16 100644 --- a/test/cel-validation/envoyproxy_test.go +++ b/test/cel-validation/envoyproxy_test.go @@ -3,10 +3,10 @@ // The full text of the Apache license is available in the LICENSE file at // the root of the repo. -//go:build validation -// +build validation +//go:build celvalidation +// +build celvalidation -package cel_validation +package celvalidation import ( "context" @@ -18,6 +18,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/utils/ptr" ) func TestEnvoyProxyProvider(t *testing.T) { @@ -54,6 +55,139 @@ func TestEnvoyProxyProvider(t *testing.T) { }, wantErrors: []string{"Unsupported value: \"foo\": supported values: \"Kubernetes\""}, }, + { + desc: "invalid service type", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceType("foo")), + }, + }, + }, + } + }, + wantErrors: []string{"Unsupported value: \"foo\": supported values: \"ClusterIP\", \"LoadBalancer\", \"NodePort\""}, + }, + { + desc: "allocateLoadBalancerNodePorts-pass-case1", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeLoadBalancer), + AllocateLoadBalancerNodePorts: ptr.To(true), + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "allocateLoadBalancerNodePorts-pass-case2", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeClusterIP), + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "allocateLoadBalancerNodePorts-fail", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeClusterIP), + AllocateLoadBalancerNodePorts: ptr.To(true), + }, + }, + }, + } + }, + wantErrors: []string{"allocateLoadBalancerNodePorts can only be set for LoadBalancer type"}, + }, + { + desc: "loadBalancerIP-pass-case1", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeLoadBalancer), + LoadBalancerIP: ptr.To("20.205.243.166"), // github ip for test only + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "loadBalancerIP-pass-case2", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeClusterIP), + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "loadBalancerIP-fail-case1", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeClusterIP), + LoadBalancerIP: ptr.To("a.b.c.d"), + }, + }, + }, + } + }, + wantErrors: []string{"loadBalancerIP can only be set for LoadBalancer type"}, + }, + { + desc: "loadBalancerIP-fail-case2", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeLoadBalancer), + LoadBalancerIP: ptr.To("a.b.c.d"), + }, + }, + }, + } + }, + wantErrors: []string{"loadBalancerIP must be a valid IPv4 address"}, + }, } for _, tc := range cases { diff --git a/tools/make/golang.mk b/tools/make/golang.mk index b0142e7e180..4cfd8c5ebc8 100644 --- a/tools/make/golang.mk +++ b/tools/make/golang.mk @@ -52,9 +52,10 @@ go.testdata.complete: ## Override test ouputdata go test -timeout 30s github.com/envoyproxy/gateway/internal/gatewayapi --override-testdata=true .PHONY: go.test.coverage -go.test.coverage: kube-test $(tools/setup-envtest) ## Run go unit and integration tests in GitHub Actions +go.test.coverage: $(tools/setup-envtest) ## Run go unit and integration tests in GitHub Actions @$(LOG_TARGET) - KUBEBUILDER_ASSETS="$(shell $(tools/setup-envtest) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... --tags=integration -race -coverprofile=coverage.xml -covermode=atomic + KUBEBUILDER_ASSETS="$(shell $(tools/setup-envtest) use $(ENVTEST_K8S_VERSION) -p path)" \ + go test ./... --tags=integration,celvalidation -race -coverprofile=coverage.xml -covermode=atomic .PHONY: go.clean go.clean: ## Clean the building output files diff --git a/tools/make/kube.mk b/tools/make/kube.mk index a12aa103270..a27e1edb40f 100644 --- a/tools/make/kube.mk +++ b/tools/make/kube.mk @@ -1,5 +1,5 @@ # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION ?= 1.24.1 +ENVTEST_K8S_VERSION ?= 1.27.1 # GATEWAY_API_VERSION refers to the version of Gateway API CRDs. # For more details, see https://gateway-api.sigs.k8s.io/guides/getting-started/#installing-gateway-api GATEWAY_API_VERSION ?= $(shell go list -m -f '{{.Version}}' sigs.k8s.io/gateway-api) @@ -48,8 +48,7 @@ kube-generate: $(tools/controller-gen) ## Generate code containing DeepCopy, Dee .PHONY: kube-test kube-test: manifests generate $(tools/setup-envtest) ## Run Kubernetes provider tests. @$(LOG_TARGET) - KUBEBUILDER_ASSETS="$(shell $(tools/setup-envtest) use $(ENVTEST_K8S_VERSION) -p path)" go test --tags=integration ./... -coverprofile cover.out - KUBEBUILDER_ASSETS="$(shell $(tools/setup-envtest) use $(ENVTEST_K8S_VERSION) -p path)" go test --tags=celvalidation ./... -coverprofile cover.out + KUBEBUILDER_ASSETS="$(shell $(tools/setup-envtest) use $(ENVTEST_K8S_VERSION) -p path)" go test --tags=integration,celvalidation ./... -coverprofile cover.out ##@ Kubernetes Deployment From 727d64a0c5d3a91b078c201e861767c2d339f68d Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Fri, 27 Oct 2023 00:57:26 -0700 Subject: [PATCH 09/55] add shortnames for EG CRDs (#2084) * `btp` for `BackendTrafficPolicy` * `ctp` for `ClientTrafficPolicy` * `sp` for `SecurityPolicy` * `epp` for `EnvoyPatchPolicy` * `eproxy` for `EnvoyProxy` Signed-off-by: Arko Dasgupta --- api/v1alpha1/backendtrafficpolicy_types.go | 2 +- api/v1alpha1/clienttrafficpolicy_types.go | 1 + api/v1alpha1/envoypatchpolicy_types.go | 1 + api/v1alpha1/envoyproxy_types.go | 1 + api/v1alpha1/securitypolicy_types.go | 1 + .../generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml | 2 +- .../generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml | 2 ++ .../generated/gateway.envoyproxy.io_envoypatchpolicies.yaml | 2 ++ .../crds/generated/gateway.envoyproxy.io_envoyproxies.yaml | 2 ++ .../crds/generated/gateway.envoyproxy.io_securitypolicies.yaml | 2 ++ 10 files changed, 14 insertions(+), 2 deletions(-) diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go index 1d092a31dc5..44fa5688715 100644 --- a/api/v1alpha1/backendtrafficpolicy_types.go +++ b/api/v1alpha1/backendtrafficpolicy_types.go @@ -16,7 +16,7 @@ const ( ) // +kubebuilder:object:root=true -// +kubebuilder:resource:shortName=btpolicy +// +kubebuilder:resource:shortName=btp // +kubebuilder:subresource:status // +kubebuilder:subresource:overrideStrategy // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index fe516b9d185..4e8cdd29a51 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -17,6 +17,7 @@ const ( ) // +kubebuilder:object:root=true +// +kubebuilder:resource:shortName=ctp // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` diff --git a/api/v1alpha1/envoypatchpolicy_types.go b/api/v1alpha1/envoypatchpolicy_types.go index 012ac42a989..30c7f8652c0 100644 --- a/api/v1alpha1/envoypatchpolicy_types.go +++ b/api/v1alpha1/envoypatchpolicy_types.go @@ -17,6 +17,7 @@ const ( ) // +kubebuilder:object:root=true +// +kubebuilder:resource:shortName=epp // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index 23a7942688f..4aa7156cb8c 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -15,6 +15,7 @@ const ( ) // +kubebuilder:object:root=true +// +kubebuilder:resource:shortName=eproxy // +kubebuilder:subresource:status // EnvoyProxy is the schema for the envoyproxies API. diff --git a/api/v1alpha1/securitypolicy_types.go b/api/v1alpha1/securitypolicy_types.go index c9d346f100f..c64396bff3b 100644 --- a/api/v1alpha1/securitypolicy_types.go +++ b/api/v1alpha1/securitypolicy_types.go @@ -16,6 +16,7 @@ const ( ) // +kubebuilder:object:root=true +// +kubebuilder:resource:shortName=sp // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index ea1d2d6a420..8a8e2283ddb 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -12,7 +12,7 @@ spec: listKind: BackendTrafficPolicyList plural: backendtrafficpolicies shortNames: - - btpolicy + - btp singular: backendtrafficpolicy scope: Namespaced versions: diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index be2be2cda76..c34aba25627 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -11,6 +11,8 @@ spec: kind: ClientTrafficPolicy listKind: ClientTrafficPolicyList plural: clienttrafficpolicies + shortNames: + - ctp singular: clienttrafficpolicy scope: Namespaced versions: diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml index a28d1f31175..e5b61e5d87c 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml @@ -11,6 +11,8 @@ spec: kind: EnvoyPatchPolicy listKind: EnvoyPatchPolicyList plural: envoypatchpolicies + shortNames: + - epp singular: envoypatchpolicy scope: Namespaced versions: 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 fdcb534cb67..71699ffb5b3 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -11,6 +11,8 @@ spec: kind: EnvoyProxy listKind: EnvoyProxyList plural: envoyproxies + shortNames: + - eproxy singular: envoyproxy scope: Namespaced versions: diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index d371e6b02ca..2c7c91aa529 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -11,6 +11,8 @@ spec: kind: SecurityPolicy listKind: SecurityPolicyList plural: securitypolicies + shortNames: + - sp singular: securitypolicy scope: Namespaced versions: From 845e8749215611c723e131156edcdbd9fcddc0e2 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Fri, 27 Oct 2023 17:09:08 +0800 Subject: [PATCH 10/55] feat: add subscribed message metrics instrumentations (#2080) * feat: add subscribed message metrics instrumentations Signed-off-by: bitliu * update Signed-off-by: bitliu * update Signed-off-by: bitliu * update Signed-off-by: bitliu * update Signed-off-by: bitliu --------- Signed-off-by: bitliu --- internal/gatewayapi/runner/runner.go | 6 +- internal/globalratelimit/runner/runner.go | 5 +- internal/infrastructure/runner/runner.go | 6 +- internal/message/metrics.go | 22 ++++ internal/message/watchutil.go | 48 +++++++- internal/message/watchutil_test.go | 8 +- internal/provider/kubernetes/controller.go | 121 ++++++++++++--------- internal/xds/server/runner/runner.go | 6 +- internal/xds/translator/runner/runner.go | 5 +- 9 files changed, 159 insertions(+), 68 deletions(-) create mode 100644 internal/message/metrics.go diff --git a/internal/gatewayapi/runner/runner.go b/internal/gatewayapi/runner/runner.go index 941286b2f58..835ce10fd05 100644 --- a/internal/gatewayapi/runner/runner.go +++ b/internal/gatewayapi/runner/runner.go @@ -49,8 +49,8 @@ func (r *Runner) Start(ctx context.Context) (err error) { } func (r *Runner) subscribeAndTranslate(ctx context.Context) { - message.HandleSubscription(r.ProviderResources.GatewayAPIResources.Subscribe(ctx), - func(update message.Update[string, *gatewayapi.Resources]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentGatewayAPIRunner), Message: "provider-resources"}, r.ProviderResources.GatewayAPIResources.Subscribe(ctx), + func(update message.Update[string, *gatewayapi.Resources], errChan chan error) { r.Logger.Info("received an update") val := update.Value @@ -93,6 +93,7 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { for key, val := range result.InfraIR { if err := val.Validate(); err != nil { r.Logger.Error(err, "unable to validate infra ir, skipped sending it") + errChan <- err } else { r.InfraIR.Store(key, val) newKeys = append(newKeys, key) @@ -102,6 +103,7 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { for key, val := range result.XdsIR { if err := val.Validate(); err != nil { r.Logger.Error(err, "unable to validate xds ir, skipped sending it") + errChan <- err } else { r.XdsIR.Store(key, val) } diff --git a/internal/globalratelimit/runner/runner.go b/internal/globalratelimit/runner/runner.go index 8e64322965f..a5ff5fed73a 100644 --- a/internal/globalratelimit/runner/runner.go +++ b/internal/globalratelimit/runner/runner.go @@ -111,13 +111,14 @@ func (r *Runner) serveXdsConfigServer(ctx context.Context) { func (r *Runner) subscribeAndTranslate(ctx context.Context) { // Subscribe to resources. - message.HandleSubscription(r.XdsIR.Subscribe(ctx), - func(update message.Update[string, *ir.Xds]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentGlobalRateLimitRunner), Message: "xds-ir"}, r.XdsIR.Subscribe(ctx), + func(update message.Update[string, *ir.Xds], errChan chan error) { r.Logger.Info("received a notification") if update.Delete { if err := r.addNewSnapshot(ctx, nil); err != nil { r.Logger.Error(err, "failed to update the config snapshot") + errChan <- err } } else { // Translate to ratelimit xDS Config. diff --git a/internal/infrastructure/runner/runner.go b/internal/infrastructure/runner/runner.go index 98859a2e88b..452e346f174 100644 --- a/internal/infrastructure/runner/runner.go +++ b/internal/infrastructure/runner/runner.go @@ -54,19 +54,21 @@ func (r *Runner) Start(ctx context.Context) (err error) { func (r *Runner) subscribeToProxyInfraIR(ctx context.Context) { // Subscribe to resources - message.HandleSubscription(r.InfraIR.Subscribe(ctx), - func(update message.Update[string, *ir.Infra]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentInfrastructureRunner), Message: "infra-ir"}, r.InfraIR.Subscribe(ctx), + func(update message.Update[string, *ir.Infra], errChan chan error) { r.Logger.Info("received an update") val := update.Value if update.Delete { if err := r.mgr.DeleteProxyInfra(ctx, val); err != nil { r.Logger.Error(err, "failed to delete infra") + errChan <- err } } else { // Manage the proxy infra. if err := r.mgr.CreateOrUpdateProxyInfra(ctx, val); err != nil { r.Logger.Error(err, "failed to create new infra") + errChan <- err } } }, diff --git a/internal/message/metrics.go b/internal/message/metrics.go new file mode 100644 index 00000000000..a78c9f87cce --- /dev/null +++ b/internal/message/metrics.go @@ -0,0 +1,22 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package message + +import "github.com/envoyproxy/gateway/internal/metrics" + +var ( + watchableDepth = metrics.NewGauge("watchable_depth", "Current depth of watchable queue.") + + watchableSubscribedDurationSeconds = metrics.NewHistogram("watchable_subscribed_duration_seconds", "How long in seconds a subscribed watchable is handled.", []float64{0.001, 0.01, 0.1, 1, 5, 10}) + + watchableSubscribedTotal = metrics.NewCounter("watchable_subscribed_total", "Total number of subscribed watchable.") + + watchableSubscribedErrorsTotal = metrics.NewCounter("watchable_subscribed_errors_total", "Total number of subscribed watchable errors.") + + runnerLabel = metrics.NewLabel("runner") + + messageLabel = metrics.NewLabel("message") +) diff --git a/internal/message/watchutil.go b/internal/message/watchutil.go index 29cecc37a9f..b938f276b7d 100644 --- a/internal/message/watchutil.go +++ b/internal/message/watchutil.go @@ -6,11 +6,36 @@ package message import ( + "time" + "github.com/telepresenceio/watchable" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/logging" + "github.com/envoyproxy/gateway/internal/metrics" ) type Update[K comparable, V any] watchable.Update[K, V] +var logger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("watchable") + +type Metadata struct { + Runner string + Message string +} + +func (m Metadata) LabelValues() []metrics.LabelValue { + labels := make([]metrics.LabelValue, 0, 2) + if m.Runner != "" { + labels = append(labels, runnerLabel.Value(m.Runner)) + } + if m.Message != "" { + labels = append(labels, messageLabel.Value(m.Message)) + } + + return labels +} + // HandleSubscription takes a channel returned by // watchable.Map.Subscribe() (or .SubscribeSubset()), and calls the // given function for each initial value in the map, and for any @@ -20,20 +45,37 @@ type Update[K comparable, V any] watchable.Update[K, V] // it handles the case where the watchable.Map already contains // entries before .Subscribe is called. func HandleSubscription[K comparable, V any]( + meta Metadata, subscription <-chan watchable.Snapshot[K, V], - handle func(Update[K, V]), + handle func(updateFunc Update[K, V], errChans chan error), ) { + //TODO: find a suitable value + errChans := make(chan error, 10) + go func() { + for err := range errChans { + logger.WithValues("runner", meta.Runner).Error(err, "observed an error") + watchableSubscribedErrorsTotal.With(meta.LabelValues()...).Increment() + } + }() + if snapshot, ok := <-subscription; ok { for k, v := range snapshot.State { + startHandleTime := time.Now() handle(Update[K, V]{ Key: k, Value: v, - }) + }, errChans) + watchableSubscribedTotal.With(meta.LabelValues()...).Increment() + watchableSubscribedDurationSeconds.With(meta.LabelValues()...).Record(time.Since(startHandleTime).Seconds()) } } for snapshot := range subscription { + watchableDepth.With(meta.LabelValues()...).Record(float64(len(subscription))) for _, update := range snapshot.Updates { - handle(Update[K, V](update)) + startHandleTime := time.Now() + handle(Update[K, V](update), errChans) + watchableSubscribedTotal.With(meta.LabelValues()...).Increment() + watchableSubscribedDurationSeconds.With(meta.LabelValues()...).Record(time.Since(startHandleTime).Seconds()) } } } diff --git a/internal/message/watchutil_test.go b/internal/message/watchutil_test.go index 39674ed7eec..8e76a2554be 100644 --- a/internal/message/watchutil_test.go +++ b/internal/message/watchutil_test.go @@ -23,8 +23,9 @@ func TestHandleSubscriptionAlreadyClosed(t *testing.T) { var calls int message.HandleSubscription[string, any]( + message.Metadata{Runner: "demo", Message: "demo"}, ch, - func(message.Update[string, any]) { calls++ }, + func(update message.Update[string, any], errChans chan error) { calls++ }, ) assert.Equal(t, 0, calls) } @@ -47,8 +48,9 @@ func TestHandleSubscriptionAlreadyInitialized(t *testing.T) { var storeCalls int var deleteCalls int message.HandleSubscription[string, any]( + message.Metadata{Runner: "demo", Message: "demo"}, m.Subscribe(context.Background()), - func(update message.Update[string, any]) { + func(update message.Update[string, any], errChans chan error) { end() if update.Delete { deleteCalls++ @@ -121,7 +123,7 @@ func TestXdsIRUpdates(t *testing.T) { }() updates := 0 - message.HandleSubscription(snapshotC, func(u message.Update[string, *ir.Xds]) { + message.HandleSubscription(message.Metadata{Runner: "demo", Message: "demo"}, snapshotC, func(u message.Update[string, *ir.Xds], errChans chan error) { end() if u.Key == "test" { updates += 1 diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index be6df0d1356..1980ba6b835 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -30,7 +30,7 @@ import ( gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" mcsapi "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/api/v1alpha1/validation" "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/gatewayapi" @@ -69,7 +69,7 @@ type gatewayAPIReconciler struct { store *kubernetesProviderStore namespace string namespaceLabels []string - envoyGateway *egv1a1.EnvoyGateway + envoyGateway *v1alpha1.EnvoyGateway mergeGateways bool resources *message.ProviderResources @@ -94,7 +94,7 @@ func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status. byNamespaceSelector := cfg.EnvoyGateway.Provider != nil && cfg.EnvoyGateway.Provider.Kubernetes != nil && cfg.EnvoyGateway.Provider.Kubernetes.Watch != nil && - cfg.EnvoyGateway.Provider.Kubernetes.Watch.Type == egv1a1.KubernetesWatchModeTypeNamespaceSelectors && + cfg.EnvoyGateway.Provider.Kubernetes.Watch.Type == v1alpha1.KubernetesWatchModeTypeNamespaceSelectors && len(cfg.EnvoyGateway.Provider.Kubernetes.Watch.NamespaceSelectors) != 0 if byNamespaceSelector { namespaceLabels = cfg.EnvoyGateway.Provider.Kubernetes.Watch.NamespaceSelectors @@ -138,7 +138,7 @@ type resourceMappings struct { allAssociatedRefGrants map[types.NamespacedName]*gwapiv1b1.ReferenceGrant // authenFilters is a map of AuthenticationFilters, where the key is the // namespaced name of the AuthenticationFilter. - authenFilters map[types.NamespacedName]*egv1a1.AuthenticationFilter + authenFilters map[types.NamespacedName]*v1alpha1.AuthenticationFilter // extensionRefFilters is a map of filters managed by an extension. // The key is the namespaced name of the filter and the value is the // unstructured form of the resource. @@ -150,7 +150,7 @@ func newResourceMapping() *resourceMappings { allAssociatedNamespaces: map[string]struct{}{}, allAssociatedBackendRefs: map[gwapiv1.BackendObjectReference]struct{}{}, allAssociatedRefGrants: map[types.NamespacedName]*gwapiv1b1.ReferenceGrant{}, - authenFilters: map[types.NamespacedName]*egv1a1.AuthenticationFilter{}, + authenFilters: map[types.NamespacedName]*v1alpha1.AuthenticationFilter{}, extensionRefFilters: map[types.NamespacedName]unstructured.Unstructured{}, } } @@ -275,7 +275,7 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques // Add all EnvoyPatchPolicies if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy { - envoyPatchPolicies := egv1a1.EnvoyPatchPolicyList{} + envoyPatchPolicies := v1alpha1.EnvoyPatchPolicyList{} if err := r.client.List(ctx, &envoyPatchPolicies); err != nil { return reconcile.Result{}, fmt.Errorf("error listing EnvoyPatchPolicies: %v", err) } @@ -284,13 +284,13 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques policy := policy // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer - policy.Status = egv1a1.EnvoyPatchPolicyStatus{} + policy.Status = v1alpha1.EnvoyPatchPolicyStatus{} resourceTree.EnvoyPatchPolicies = append(resourceTree.EnvoyPatchPolicies, &policy) } } // Add all ClientTrafficPolicies - clientTrafficPolicies := egv1a1.ClientTrafficPolicyList{} + clientTrafficPolicies := v1alpha1.ClientTrafficPolicyList{} if err := r.client.List(ctx, &clientTrafficPolicies); err != nil { return reconcile.Result{}, fmt.Errorf("error listing ClientTrafficPolicies: %v", err) } @@ -299,13 +299,13 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques policy := policy // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer - policy.Status = egv1a1.ClientTrafficPolicyStatus{} + policy.Status = v1alpha1.ClientTrafficPolicyStatus{} resourceTree.ClientTrafficPolicies = append(resourceTree.ClientTrafficPolicies, &policy) } // Add all BackendTrafficPolicies - backendTrafficPolicies := egv1a1.BackendTrafficPolicyList{} + backendTrafficPolicies := v1alpha1.BackendTrafficPolicyList{} if err := r.client.List(ctx, &backendTrafficPolicies); err != nil { return reconcile.Result{}, fmt.Errorf("error listing BackendTrafficPolicies: %v", err) } @@ -314,12 +314,12 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques policy := policy // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer - policy.Status = egv1a1.BackendTrafficPolicyStatus{} + policy.Status = v1alpha1.BackendTrafficPolicyStatus{} resourceTree.BackendTrafficPolicies = append(resourceTree.BackendTrafficPolicies, &policy) } // Add all SecurityPolicies - securityPolicies := egv1a1.SecurityPolicyList{} + securityPolicies := v1alpha1.SecurityPolicyList{} if err := r.client.List(ctx, &securityPolicies); err != nil { return reconcile.Result{}, fmt.Errorf("error listing SecurityPolicies: %v", err) } @@ -328,7 +328,7 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques policy := policy // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer - policy.Status = egv1a1.SecurityPolicyStatus{} + policy.Status = v1alpha1.SecurityPolicyStatus{} resourceTree.SecurityPolicies = append(resourceTree.SecurityPolicies, &policy) } @@ -1028,8 +1028,8 @@ func (r *gatewayAPIReconciler) addFinalizer(ctx context.Context, gc *gwapiv1.Gat func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // Gateway object status updater go func() { - message.HandleSubscription(r.resources.GatewayStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1.GatewayStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "gateway-status"}, r.resources.GatewayStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1.GatewayStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1038,6 +1038,7 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { gtw := new(gwapiv1.Gateway) if err := r.client.Get(ctx, update.Key, gtw); err != nil { r.log.Error(err, "gateway not found", "namespace", gtw.Namespace, "name", gtw.Name) + errChan <- err return } // Set the updated Status and call the status update @@ -1050,8 +1051,8 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // HTTPRoute object status updater go func() { - message.HandleSubscription(r.resources.HTTPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1.HTTPRouteStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "httproute-status"}, r.resources.HTTPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1.HTTPRouteStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1064,7 +1065,9 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { Mutator: status.MutatorFunc(func(obj client.Object) client.Object { h, ok := obj.(*gwapiv1.HTTPRoute) if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) } hCopy := h.DeepCopy() hCopy.Status.Parents = val.Parents @@ -1078,8 +1081,8 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // GRPCRoute object status updater go func() { - message.HandleSubscription(r.resources.GRPCRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.GRPCRouteStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "grpcroute-status"}, r.resources.GRPCRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.GRPCRouteStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1092,7 +1095,9 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { Mutator: status.MutatorFunc(func(obj client.Object) client.Object { h, ok := obj.(*gwapiv1a2.GRPCRoute) if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) } hCopy := h.DeepCopy() hCopy.Status.Parents = val.Parents @@ -1106,8 +1111,8 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // TLSRoute object status updater go func() { - message.HandleSubscription(r.resources.TLSRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.TLSRouteStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tlsroute-status"}, r.resources.TLSRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.TLSRouteStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1120,7 +1125,9 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { Mutator: status.MutatorFunc(func(obj client.Object) client.Object { t, ok := obj.(*gwapiv1a2.TLSRoute) if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) } tCopy := t.DeepCopy() tCopy.Status.Parents = val.Parents @@ -1134,8 +1141,8 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // TCPRoute object status updater go func() { - message.HandleSubscription(r.resources.TCPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.TCPRouteStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tcproute-status"}, r.resources.TCPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.TCPRouteStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1148,7 +1155,9 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { Mutator: status.MutatorFunc(func(obj client.Object) client.Object { t, ok := obj.(*gwapiv1a2.TCPRoute) if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) } tCopy := t.DeepCopy() tCopy.Status.Parents = val.Parents @@ -1162,8 +1171,8 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // UDPRoute object status updater go func() { - message.HandleSubscription(r.resources.UDPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.UDPRouteStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "udproute-status"}, r.resources.UDPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.UDPRouteStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1176,7 +1185,9 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { Mutator: status.MutatorFunc(func(obj client.Object) client.Object { t, ok := obj.(*gwapiv1a2.UDPRoute) if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) } tCopy := t.DeepCopy() tCopy.Status.Parents = val.Parents @@ -1190,8 +1201,8 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // EnvoyPatchPolicy object status updater go func() { - message.HandleSubscription(r.resources.EnvoyPatchPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *egv1a1.EnvoyPatchPolicyStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "envoypatchpolicy-status"}, r.resources.EnvoyPatchPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.EnvoyPatchPolicyStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1200,11 +1211,13 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { val := update.Value r.statusUpdater.Send(status.Update{ NamespacedName: key, - Resource: new(egv1a1.EnvoyPatchPolicy), + Resource: new(v1alpha1.EnvoyPatchPolicy), Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*egv1a1.EnvoyPatchPolicy) + t, ok := obj.(*v1alpha1.EnvoyPatchPolicy) if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) } tCopy := t.DeepCopy() tCopy.Status = *val @@ -1218,8 +1231,8 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // ClientTrafficPolicy object status updater go func() { - message.HandleSubscription(r.resources.ClientTrafficPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *egv1a1.ClientTrafficPolicyStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "clienttrafficpolicy-status"}, r.resources.ClientTrafficPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.ClientTrafficPolicyStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1228,11 +1241,13 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { val := update.Value r.statusUpdater.Send(status.Update{ NamespacedName: key, - Resource: new(egv1a1.ClientTrafficPolicy), + Resource: new(v1alpha1.ClientTrafficPolicy), Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*egv1a1.ClientTrafficPolicy) + t, ok := obj.(*v1alpha1.ClientTrafficPolicy) if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) } tCopy := t.DeepCopy() tCopy.Status = *val @@ -1246,8 +1261,8 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { // BackendTrafficPolicy object status updater go func() { - message.HandleSubscription(r.resources.BackendTrafficPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *egv1a1.BackendTrafficPolicyStatus]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "backendtrafficpolicy-status"}, r.resources.BackendTrafficPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.BackendTrafficPolicyStatus], errChan chan error) { // skip delete updates. if update.Delete { return @@ -1256,11 +1271,13 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { val := update.Value r.statusUpdater.Send(status.Update{ NamespacedName: key, - Resource: new(egv1a1.BackendTrafficPolicy), + Resource: new(v1alpha1.BackendTrafficPolicy), Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*egv1a1.BackendTrafficPolicy) + t, ok := obj.(*v1alpha1.BackendTrafficPolicy) if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) } tCopy := t.DeepCopy() tCopy.Status = *val @@ -1294,7 +1311,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M epPredicates = append(epPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyProxy{}), + source.Kind(mgr.GetCache(), &v1alpha1.EnvoyProxy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), epPredicates..., ); err != nil { @@ -1518,7 +1535,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M afPredicates = append(afPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.AuthenticationFilter{}), + source.Kind(mgr.GetCache(), &v1alpha1.AuthenticationFilter{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), afPredicates..., ); err != nil { @@ -1533,7 +1550,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy { // Watch EnvoyPatchPolicy CRUDs if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyPatchPolicy{}), + source.Kind(mgr.GetCache(), &v1alpha1.EnvoyPatchPolicy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), eppPredicates..., ); err != nil { @@ -1548,7 +1565,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.ClientTrafficPolicy{}), + source.Kind(mgr.GetCache(), &v1alpha1.ClientTrafficPolicy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), ctpPredicates..., ); err != nil { @@ -1562,7 +1579,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.BackendTrafficPolicy{}), + source.Kind(mgr.GetCache(), &v1alpha1.BackendTrafficPolicy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), btpPredicates..., ); err != nil { @@ -1597,7 +1614,7 @@ func (r *gatewayAPIReconciler) enqueueClass(_ context.Context, _ client.Object) } func (r *gatewayAPIReconciler) hasManagedClass(obj client.Object) bool { - ep, ok := obj.(*egv1a1.EnvoyProxy) + ep, ok := obj.(*v1alpha1.EnvoyProxy) if !ok { panic(fmt.Sprintf("unsupported object type %T", obj)) } @@ -1635,7 +1652,7 @@ func (r *gatewayAPIReconciler) processParamsRef(ctx context.Context, gc *gwapiv1 return fmt.Errorf("unsupported parametersRef for gatewayclass %s", gc.Name) } - epList := new(egv1a1.EnvoyProxyList) + epList := new(v1alpha1.EnvoyProxyList) // The EnvoyProxy must be in the same namespace as EG. if err := r.client.List(ctx, epList, &client.ListOptions{Namespace: r.namespace}); err != nil { diff --git a/internal/xds/server/runner/runner.go b/internal/xds/server/runner/runner.go index 7147eb200a1..bb18976932f 100644 --- a/internal/xds/server/runner/runner.go +++ b/internal/xds/server/runner/runner.go @@ -133,8 +133,8 @@ func registerServer(srv serverv3.Server, g *grpc.Server) { func (r *Runner) subscribeAndTranslate(ctx context.Context) { // Subscribe to resources - message.HandleSubscription(r.Xds.Subscribe(ctx), - func(update message.Update[string, *xdstypes.ResourceVersionTable]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentXdsServerRunner), Message: "xds"}, r.Xds.Subscribe(ctx), + func(update message.Update[string, *xdstypes.ResourceVersionTable], errChan chan error) { key := update.Key val := update.Value @@ -145,6 +145,7 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { } else if val != nil && val.XdsResources != nil { if r.cache == nil { r.Logger.Error(err, "failed to init snapshot cache") + errChan <- err } else { // Update snapshot cache err = r.cache.GenerateNewSnapshot(key, val.XdsResources) @@ -152,6 +153,7 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { } if err != nil { r.Logger.Error(err, "failed to generate a snapshot") + errChan <- err } }, ) diff --git a/internal/xds/translator/runner/runner.go b/internal/xds/translator/runner/runner.go index 17ff6c8619a..7d5364c1085 100644 --- a/internal/xds/translator/runner/runner.go +++ b/internal/xds/translator/runner/runner.go @@ -49,8 +49,8 @@ func (r *Runner) Start(ctx context.Context) (err error) { func (r *Runner) subscribeAndTranslate(ctx context.Context) { // Subscribe to resources - message.HandleSubscription(r.XdsIR.Subscribe(ctx), - func(update message.Update[string, *ir.Xds]) { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentXdsTranslatorRunner), Message: "xds-ir"}, r.XdsIR.Subscribe(ctx), + func(update message.Update[string, *ir.Xds], errChan chan error) { r.Logger.Info("received an update") key := update.Key val := update.Value @@ -80,6 +80,7 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { result, err := t.Translate(val) if err != nil { r.Logger.Error(err, "failed to translate xds ir") + errChan <- err return } From 364710f447c9d1eaff07e56dc394204625c6c47f Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Sat, 28 Oct 2023 00:25:58 +0800 Subject: [PATCH 11/55] feat: remove AuthenticationFilter in favor of SecurityPolicy (#2086) remove Authenticationfilter in favor of SecurityPolicy fix e2e fix test and add policies to egctl translate command add docs for jwt remove crd clear docs address comments update security policy status fix e2e test Signed-off-by: huabing zhao --- api/v1alpha1/cors_types.go | 24 + ...enticationfilter_types.go => jwt_types.go} | 87 +-- api/v1alpha1/securitypolicy_types.go | 108 ---- api/v1alpha1/shared_types.go | 40 ++ .../validation/authenticationfilter.go | 116 ---- .../validation/authenticationfilter_test.go | 451 --------------- api/v1alpha1/zz_generated.deepcopy.go | 106 ---- ...y.envoyproxy.io_authenticationfilters.yaml | 131 ----- charts/gateway-helm/templates/_rbac.tpl | 2 - .../kubernetes/{authn => jwt}/grpc-jwt.yaml | 22 +- examples/kubernetes/{authn => jwt}/jwks.json | 0 examples/kubernetes/{authn => jwt}/jwt.yaml | 35 +- examples/kubernetes/{authn => jwt}/test.jwt | 0 .../{authn => jwt}/with-different-claim.jwt | 0 ...jwt-single-route-single-match-to-xds.yaml} | 22 +- ...single-route-single-match-to-xds.all.json} | 0 ...single-route-single-match-to-xds.all.yaml} | 0 ...-route-single-match-to-xds.bootstrap.yaml} | 0 ...le-route-single-match-to-xds.cluster.yaml} | 0 ...e-route-single-match-to-xds.endpoint.yaml} | 0 ...e-route-single-match-to-xds.listener.yaml} | 0 ...ngle-route-single-match-to-xds.route.yaml} | 0 internal/cmd/egctl/translate.go | 48 +- internal/cmd/egctl/translate_test.go | 18 +- internal/gatewayapi/filters.go | 18 - internal/gatewayapi/helpers.go | 23 - internal/gatewayapi/helpers_test.go | 74 --- internal/gatewayapi/resource.go | 2 - internal/gatewayapi/route.go | 6 +- .../grpcroute-with-valid-authenfilter.in.yaml | 49 -- ...grpcroute-with-valid-authenfilter.out.yaml | 128 ----- ...with-non-existent-authenfilter-ref.in.yaml | 43 -- ...ith-non-existent-authenfilter-ref.out.yaml | 114 ---- ...with-non-matching-authenfilter-ref.in.yaml | 57 -- ...ith-non-matching-authenfilter-ref.out.yaml | 114 ---- .../httproute-with-valid-authenfilter.in.yaml | 55 -- ...httproute-with-valid-authenfilter.out.yaml | 138 ----- ...ith-valid-multi-match-authenfilter.in.yaml | 69 --- ...th-valid-multi-match-authenfilter.out.yaml | 175 ------ ...lid-multi-match-multi-authenfilter.in.yaml | 85 --- ...id-multi-match-multi-authenfilter.out.yaml | 179 ------ ...-multiple-gateways-multiple-routes.in.yaml | 19 - ...multiple-gateways-multiple-routes.out.yaml | 13 - internal/gatewayapi/zz_generated.deepcopy.go | 11 - internal/ir/xds.go | 45 -- internal/ir/xds_test.go | 2 +- internal/ir/zz_generated.deepcopy.go | 47 -- internal/provider/kubernetes/controller.go | 147 ++--- internal/provider/kubernetes/filters.go | 30 - .../provider/kubernetes/kubernetes_test.go | 327 +---------- internal/provider/kubernetes/predicates.go | 49 -- internal/provider/kubernetes/routes.go | 106 +--- internal/provider/kubernetes/routes_test.go | 185 ------- internal/provider/kubernetes/test/utils.go | 52 -- internal/xds/translator/authentication.go | 317 ----------- internal/xds/translator/httpfilters.go | 11 - .../authn-multi-route-multi-provider.yaml | 70 --- .../authn-multi-route-single-provider.yaml | 51 -- .../testdata/in/xds-ir/authn-ratelimit.yaml | 70 --- .../authn-single-route-single-match.yaml | 26 - ...ml => jwt-multi-route-multi-provider.yaml} | 0 ...l => jwt-multi-route-single-provider.yaml} | 0 ...uthn-ratelimit.yaml => jwt-ratelimit.yaml} | 0 ...aml => jwt-single-route-single-match.yaml} | 0 ...n-multi-route-multi-provider.clusters.yaml | 81 --- ...-multi-route-multi-provider.endpoints.yaml | 33 -- ...-multi-route-multi-provider.listeners.yaml | 113 ---- ...thn-multi-route-multi-provider.routes.yaml | 25 - ...-multi-route-single-provider.clusters.yaml | 59 -- ...multi-route-single-provider.endpoints.yaml | 22 - ...multi-route-single-provider.listeners.yaml | 93 ---- ...hn-multi-route-single-provider.routes.yaml | 25 - .../xds-ir/jwt-authn-ratelimit.clusters.yaml | 105 ---- .../xds-ir/jwt-authn-ratelimit.endpoints.yaml | 44 -- .../xds-ir/jwt-authn-ratelimit.listeners.yaml | 63 --- .../xds-ir/jwt-authn-ratelimit.routes.yaml | 46 -- ...hn-single-route-single-match.clusters.yaml | 45 -- ...n-single-route-single-match.endpoints.yaml | 11 - ...n-single-route-single-match.listeners.yaml | 53 -- ...uthn-single-route-single-match.routes.yaml | 16 - ...-multi-route-multi-provider.clusters.yaml} | 0 ...multi-route-multi-provider.endpoints.yaml} | 0 ...multi-route-multi-provider.listeners.yaml} | 0 ...wt-multi-route-multi-provider.routes.yaml} | 0 ...multi-route-single-provider.clusters.yaml} | 0 ...ulti-route-single-provider.endpoints.yaml} | 0 ...ulti-route-single-provider.listeners.yaml} | 0 ...t-multi-route-single-provider.routes.yaml} | 0 ...sters.yaml => jwt-ratelimit.clusters.yaml} | 0 ...ints.yaml => jwt-ratelimit.endpoints.yaml} | 0 ...ners.yaml => jwt-ratelimit.listeners.yaml} | 0 ....routes.yaml => jwt-ratelimit.routes.yaml} | 0 ...t-single-route-single-match.clusters.yaml} | 0 ...-single-route-single-match.endpoints.yaml} | 0 ...-single-route-single-match.listeners.yaml} | 0 ...jwt-single-route-single-match.routes.yaml} | 0 internal/xds/translator/translator.go | 5 - internal/xds/translator/translator_test.go | 24 +- site/content/en/latest/api/extension_types.md | 63 --- site/content/en/latest/design/rate-limit.md | 27 +- .../latest/design/request-authentication.md | 515 ------------------ .../user/{authn.md => jwt-authentication.md} | 45 +- .../testdata/ratelimit-based-jwt-claims.yaml | 39 +- tools/crd-ref-docs/config.yaml | 2 +- 104 files changed, 331 insertions(+), 5340 deletions(-) create mode 100644 api/v1alpha1/cors_types.go rename api/v1alpha1/{authenticationfilter_types.go => jwt_types.go} (54%) delete mode 100644 api/v1alpha1/validation/authenticationfilter.go delete mode 100644 api/v1alpha1/validation/authenticationfilter_test.go delete mode 100644 charts/gateway-helm/crds/generated/gateway.envoyproxy.io_authenticationfilters.yaml rename examples/kubernetes/{authn => jwt}/grpc-jwt.yaml (53%) rename examples/kubernetes/{authn => jwt}/jwks.json (100%) rename examples/kubernetes/{authn => jwt}/jwt.yaml (56%) rename examples/kubernetes/{authn => jwt}/test.jwt (100%) rename examples/kubernetes/{authn => jwt}/with-different-claim.jwt (100%) rename internal/cmd/egctl/testdata/translate/in/{authn-single-route-single-match-to-xds.yaml => jwt-single-route-single-match-to-xds.yaml} (83%) rename internal/cmd/egctl/testdata/translate/out/{authn-single-route-single-match-to-xds.all.json => jwt-single-route-single-match-to-xds.all.json} (100%) rename internal/cmd/egctl/testdata/translate/out/{authn-single-route-single-match-to-xds.all.yaml => jwt-single-route-single-match-to-xds.all.yaml} (100%) rename internal/cmd/egctl/testdata/translate/out/{authn-single-route-single-match-to-xds.bootstrap.yaml => jwt-single-route-single-match-to-xds.bootstrap.yaml} (100%) rename internal/cmd/egctl/testdata/translate/out/{authn-single-route-single-match-to-xds.cluster.yaml => jwt-single-route-single-match-to-xds.cluster.yaml} (100%) rename internal/cmd/egctl/testdata/translate/out/{authn-single-route-single-match-to-xds.endpoint.yaml => jwt-single-route-single-match-to-xds.endpoint.yaml} (100%) rename internal/cmd/egctl/testdata/translate/out/{authn-single-route-single-match-to-xds.listener.yaml => jwt-single-route-single-match-to-xds.listener.yaml} (100%) rename internal/cmd/egctl/testdata/translate/out/{authn-single-route-single-match-to-xds.route.yaml => jwt-single-route-single-match-to-xds.route.yaml} (100%) delete mode 100644 internal/gatewayapi/testdata/grpcroute-with-valid-authenfilter.in.yaml delete mode 100644 internal/gatewayapi/testdata/grpcroute-with-valid-authenfilter.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-non-existent-authenfilter-ref.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-non-existent-authenfilter-ref.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-non-matching-authenfilter-ref.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-non-matching-authenfilter-ref.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-valid-authenfilter.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-valid-authenfilter.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-valid-multi-match-authenfilter.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-valid-multi-match-authenfilter.out.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-valid-multi-match-multi-authenfilter.in.yaml delete mode 100644 internal/gatewayapi/testdata/httproute-with-valid-multi-match-multi-authenfilter.out.yaml delete mode 100644 internal/xds/translator/authentication.go delete mode 100644 internal/xds/translator/testdata/in/xds-ir/authn-multi-route-multi-provider.yaml delete mode 100644 internal/xds/translator/testdata/in/xds-ir/authn-multi-route-single-provider.yaml delete mode 100644 internal/xds/translator/testdata/in/xds-ir/authn-ratelimit.yaml delete mode 100644 internal/xds/translator/testdata/in/xds-ir/authn-single-route-single-match.yaml rename internal/xds/translator/testdata/in/xds-ir/{jwt-authn-multi-route-multi-provider.yaml => jwt-multi-route-multi-provider.yaml} (100%) rename internal/xds/translator/testdata/in/xds-ir/{jwt-authn-multi-route-single-provider.yaml => jwt-multi-route-single-provider.yaml} (100%) rename internal/xds/translator/testdata/in/xds-ir/{jwt-authn-ratelimit.yaml => jwt-ratelimit.yaml} (100%) rename internal/xds/translator/testdata/in/xds-ir/{jwt-authn-single-route-single-match.yaml => jwt-single-route-single-match.yaml} (100%) delete mode 100755 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.clusters.yaml delete mode 100755 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.endpoints.yaml delete mode 100755 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.listeners.yaml delete mode 100755 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.routes.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.clusters.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.endpoints.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.listeners.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.routes.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.clusters.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.endpoints.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.listeners.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.routes.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.clusters.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.endpoints.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.listeners.yaml delete mode 100644 internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.routes.yaml rename internal/xds/translator/testdata/out/xds-ir/{authn-multi-route-multi-provider.clusters.yaml => jwt-multi-route-multi-provider.clusters.yaml} (100%) mode change 100644 => 100755 rename internal/xds/translator/testdata/out/xds-ir/{authn-multi-route-multi-provider.endpoints.yaml => jwt-multi-route-multi-provider.endpoints.yaml} (100%) mode change 100644 => 100755 rename internal/xds/translator/testdata/out/xds-ir/{authn-multi-route-multi-provider.listeners.yaml => jwt-multi-route-multi-provider.listeners.yaml} (100%) mode change 100644 => 100755 rename internal/xds/translator/testdata/out/xds-ir/{authn-multi-route-multi-provider.routes.yaml => jwt-multi-route-multi-provider.routes.yaml} (100%) mode change 100644 => 100755 rename internal/xds/translator/testdata/out/xds-ir/{authn-multi-route-single-provider.clusters.yaml => jwt-multi-route-single-provider.clusters.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-multi-route-single-provider.endpoints.yaml => jwt-multi-route-single-provider.endpoints.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-multi-route-single-provider.listeners.yaml => jwt-multi-route-single-provider.listeners.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-multi-route-single-provider.routes.yaml => jwt-multi-route-single-provider.routes.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-ratelimit.clusters.yaml => jwt-ratelimit.clusters.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-ratelimit.endpoints.yaml => jwt-ratelimit.endpoints.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-ratelimit.listeners.yaml => jwt-ratelimit.listeners.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-ratelimit.routes.yaml => jwt-ratelimit.routes.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-single-route-single-match.clusters.yaml => jwt-single-route-single-match.clusters.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-single-route-single-match.endpoints.yaml => jwt-single-route-single-match.endpoints.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-single-route-single-match.listeners.yaml => jwt-single-route-single-match.listeners.yaml} (100%) rename internal/xds/translator/testdata/out/xds-ir/{authn-single-route-single-match.routes.yaml => jwt-single-route-single-match.routes.yaml} (100%) delete mode 100644 site/content/en/latest/design/request-authentication.md rename site/content/en/latest/user/{authn.md => jwt-authentication.md} (67%) diff --git a/api/v1alpha1/cors_types.go b/api/v1alpha1/cors_types.go new file mode 100644 index 00000000000..34a415f903b --- /dev/null +++ b/api/v1alpha1/cors_types.go @@ -0,0 +1,24 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package v1alpha1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// CORS defines the configuration for Cross-Origin Resource Sharing (CORS). +type CORS struct { + // AllowOrigins defines the origins that are allowed to make requests. + // +kubebuilder:validation:MinItems=1 + AllowOrigins []StringMatch `json:"allowOrigins,omitempty" yaml:"allowOrigins"` + // AllowMethods defines the methods that are allowed to make requests. + // +kubebuilder:validation:MinItems=1 + AllowMethods []string `json:"allowMethods,omitempty" yaml:"allowMethods"` + // AllowHeaders defines the headers that are allowed to be sent with requests. + AllowHeaders []string `json:"allowHeaders,omitempty" yaml:"allowHeaders,omitempty"` + // ExposeHeaders defines the headers that can be exposed in the responses. + ExposeHeaders []string `json:"exposeHeaders,omitempty" yaml:"exposeHeaders,omitempty"` + // MaxAge defines how long the results of a preflight request can be cached. + MaxAge *metav1.Duration `json:"maxAge,omitempty" yaml:"maxAge,omitempty"` +} diff --git a/api/v1alpha1/authenticationfilter_types.go b/api/v1alpha1/jwt_types.go similarity index 54% rename from api/v1alpha1/authenticationfilter_types.go rename to api/v1alpha1/jwt_types.go index 7907ddef2ea..f35ea8e087b 100644 --- a/api/v1alpha1/authenticationfilter_types.go +++ b/api/v1alpha1/jwt_types.go @@ -5,72 +5,22 @@ package v1alpha1 -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) +// JWT defines the configuration for JSON Web Token (JWT) authentication. +type JWT struct { -const ( - // KindAuthenticationFilter is the name of the AuthenticationFilter kind. - KindAuthenticationFilter = "AuthenticationFilter" -) - -// +kubebuilder:object:root=true -// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` - -type AuthenticationFilter struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - // Spec defines the desired state of the AuthenticationFilter type. - Spec AuthenticationFilterSpec `json:"spec"` - - // Note: The status sub-resource has been excluded but may be added in the future. -} - -// 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"` - - // Claim is the JWT Claim that should be saved into the header : it can be a nested claim of type - // (eg. "claim.nested.key", "sub"). The nested claim name must use dot "." - // to separate the JSON name path. - Claim string `json:"claim"` -} - -// AuthenticationFilterSpec defines the desired state of the AuthenticationFilter type. -// +union -type AuthenticationFilterSpec struct { - // Type defines the type of authentication provider to use. Supported provider types - // are "JWT". + // Providers defines the JSON Web Token (JWT) authentication provider type. // - // +unionDiscriminator - Type AuthenticationFilterType `json:"type"` - - // JWT defines the JSON Web Token (JWT) authentication provider type. When multiple - // jwtProviders are specified, the JWT is considered valid if any of the providers - // successfully validate the JWT. For additional details, see - // https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. + // When multiple JWT providers are specified, the JWT is considered valid if + // any of the providers successfully validate the JWT. For additional details, + // see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. // + // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=4 - // +optional - JwtProviders []JwtAuthenticationFilterProvider `json:"jwtProviders,omitempty"` + Providers []JWTProvider `json:"providers"` } -// AuthenticationFilterType is a type of authentication provider. -// +kubebuilder:validation:Enum=JWT -type AuthenticationFilterType string - -const ( - // JwtAuthenticationFilterProviderType is a provider that uses JSON Web Token (JWT) - // for authenticating requests.. - JwtAuthenticationFilterProviderType AuthenticationFilterType = "JWT" -) - -// JwtAuthenticationFilterProvider defines the JSON Web Token (JWT) authentication provider type -// and how JWTs should be verified: -type JwtAuthenticationFilterProvider struct { +// JWTProvider defines how a JSON Web Token (JWT) can be verified. +type JWTProvider struct { // Name defines a unique name for the JWT provider. A name can have a variety of forms, // including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. // @@ -120,15 +70,14 @@ type RemoteJWKS struct { // TODO: Add TBD remote JWKS fields based on defined use cases. } -//+kubebuilder:object:root=true +// ClaimToHeader defines a configuration to convert JWT claims into HTTP headers +type ClaimToHeader struct { -// AuthenticationFilterList contains a list of AuthenticationFilter. -type AuthenticationFilterList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []AuthenticationFilter `json:"items"` -} + // Header defines the name of the HTTP request header that the JWT Claim will be saved into. + Header string `json:"header"` -func init() { - SchemeBuilder.Register(&AuthenticationFilter{}, &AuthenticationFilterList{}) + // Claim is the JWT Claim that should be saved into the header : it can be a nested claim of type + // (eg. "claim.nested.key", "sub"). The nested claim name must use dot "." + // to separate the JSON name path. + Claim string `json:"claim"` } diff --git a/api/v1alpha1/securitypolicy_types.go b/api/v1alpha1/securitypolicy_types.go index c64396bff3b..7adece4cbca 100644 --- a/api/v1alpha1/securitypolicy_types.go +++ b/api/v1alpha1/securitypolicy_types.go @@ -54,114 +54,6 @@ type SecurityPolicySpec struct { JWT *JWT `json:"jwt,omitempty"` } -// CORS defines the configuration for Cross-Origin Resource Sharing (CORS). -type CORS struct { - // AllowOrigins defines the origins that are allowed to make requests. - // +kubebuilder:validation:MinItems=1 - AllowOrigins []StringMatch `json:"allowOrigins,omitempty" yaml:"allowOrigins"` - // AllowMethods defines the methods that are allowed to make requests. - // +kubebuilder:validation:MinItems=1 - AllowMethods []string `json:"allowMethods,omitempty" yaml:"allowMethods"` - // AllowHeaders defines the headers that are allowed to be sent with requests. - AllowHeaders []string `json:"allowHeaders,omitempty" yaml:"allowHeaders,omitempty"` - // ExposeHeaders defines the headers that can be exposed in the responses. - ExposeHeaders []string `json:"exposeHeaders,omitempty" yaml:"exposeHeaders,omitempty"` - // MaxAge defines how long the results of a preflight request can be cached. - MaxAge *metav1.Duration `json:"maxAge,omitempty" yaml:"maxAge,omitempty"` -} - -// JWT defines the configuration for JSON Web Token (JWT) authentication. -type JWT struct { - - // Providers defines the JSON Web Token (JWT) authentication provider type. - // - // When multiple JWT providers are specified, the JWT is considered valid if - // any of the providers successfully validate the JWT. For additional details, - // see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. - // - // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=4 - Providers []JWTProvider `json:"providers"` -} - -// JWTProvider defines how a JSON Web Token (JWT) can be verified. -type JWTProvider struct { - // Name defines a unique name for the JWT provider. A name can have a variety of forms, - // including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=253 - Name string `json:"name"` - - // Issuer is the principal that issued the JWT and takes the form of a URL or email address. - // For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 for - // URL format and https://rfc-editor.org/rfc/rfc5322.html for email format. If not provided, - // the JWT issuer is not checked. - // - // +kubebuilder:validation:MaxLength=253 - // +optional - Issuer string `json:"issuer,omitempty"` - - // Audiences is a list of JWT audiences allowed access. For additional details, see - // https://tools.ietf.org/html/rfc7519#section-4.1.3. If not provided, JWT audiences - // are not checked. - // - // +kubebuilder:validation:MaxItems=8 - // +optional - Audiences []string `json:"audiences,omitempty"` - - // RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote - // HTTP/HTTPS endpoint. - RemoteJWKS RemoteJWKS `json:"remoteJWKS"` - - // ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers - // For examples, following config: - // The claim must be of type; string, int, double, bool. Array type claims are not supported - // - ClaimToHeaders []ClaimToHeader `json:"claimToHeaders,omitempty"` - // TODO: Add TBD JWT fields based on defined use cases. -} - -// StringMatch defines how to match any strings. -// This is a general purpose match condition that can be used by other EG APIs -// that need to match against a string. -type StringMatch struct { - // Type specifies how to match against a string. - // - // +optional - // +kubebuilder:default=Exact - Type *MatchType `json:"type,omitempty"` - - // Value specifies the string value that the match must have. - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=1024 - Value string `json:"value"` -} - -// MatchType specifies the semantics of how a string value should be compared. -// Valid MatchType values are "Exact", "Prefix", "Suffix", "RegularExpression". -// -// +kubebuilder:validation:Enum=Exact;Prefix;Suffix;RegularExpression -type MatchType string - -const ( - // MatchExact :the input string must match exactly the match value. - MatchExact MatchType = "Exact" - - // MatchPrefix :the input string must start with the match value. - MatchPrefix MatchType = "Prefix" - - // MatchSuffix :the input string must end with the match value. - MatchSuffix MatchType = "Suffix" - - // MatchRegularExpression :The input string must match the regular expression - // specified in the match value. - // The regex string must adhere to the syntax documented in - // https://github.com/google/re2/wiki/Syntax. - MatchRegularExpression MatchType = "RegularExpression" -) - // SecurityPolicyStatus defines the state of SecurityPolicy type SecurityPolicyStatus struct { // Conditions describe the current conditions of the SecurityPolicy. diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index bbda8a16ec3..84938be0585 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -235,3 +235,43 @@ const ( XDSHTTPListener XDSTranslatorHook = "HTTPListener" XDSTranslation XDSTranslatorHook = "Translation" ) + +// StringMatch defines how to match any strings. +// This is a general purpose match condition that can be used by other EG APIs +// that need to match against a string. +type StringMatch struct { + // Type specifies how to match against a string. + // + // +optional + // +kubebuilder:default=Exact + Type *MatchType `json:"type,omitempty"` + + // Value specifies the string value that the match must have. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 + Value string `json:"value"` +} + +// MatchType specifies the semantics of how a string value should be compared. +// Valid MatchType values are "Exact", "Prefix", "Suffix", "RegularExpression". +// +// +kubebuilder:validation:Enum=Exact;Prefix;Suffix;RegularExpression +type MatchType string + +const ( + // MatchExact :the input string must match exactly the match value. + MatchExact MatchType = "Exact" + + // MatchPrefix :the input string must start with the match value. + MatchPrefix MatchType = "Prefix" + + // MatchSuffix :the input string must end with the match value. + MatchSuffix MatchType = "Suffix" + + // MatchRegularExpression :The input string must match the regular expression + // specified in the match value. + // The regex string must adhere to the syntax documented in + // https://github.com/google/re2/wiki/Syntax. + MatchRegularExpression MatchType = "RegularExpression" +) diff --git a/api/v1alpha1/validation/authenticationfilter.go b/api/v1alpha1/validation/authenticationfilter.go deleted file mode 100644 index 378a63459fe..00000000000 --- a/api/v1alpha1/validation/authenticationfilter.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright Envoy Gateway Authors -// SPDX-License-Identifier: Apache-2.0 -// The full text of the Apache license is available in the LICENSE file at -// the root of the repo. - -package validation - -import ( - "errors" - "fmt" - "net/mail" - "net/url" - - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/validation" - - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" -) - -// TODO zhaohuabing remove this file after deprecating authentication filter -// ValidateAuthenticationFilter validates the provided filter. The only supported -// ValidateAuthenticationFilter type is "JWT". -func ValidateAuthenticationFilter(filter *egv1a1.AuthenticationFilter) error { - var errs []error - if filter == nil { - return errors.New("filter is nil") - } - if err := validateAuthenticationFilterSpec(&filter.Spec); err != nil { - errs = append(errs, errors.New("filter is nil")) - } - - return utilerrors.NewAggregate(errs) -} - -// validateAuthenticationFilterSpec validates the provided spec. The only supported -// ValidateAuthenticationFilter type is "JWT". -func validateAuthenticationFilterSpec(spec *egv1a1.AuthenticationFilterSpec) error { - var errs []error - - switch { - case spec == nil: - errs = append(errs, errors.New("spec is nil")) - case spec.Type != egv1a1.JwtAuthenticationFilterProviderType: - errs = append(errs, fmt.Errorf("unsupported authenticationfilter type: %v", spec.Type)) - case len(spec.JwtProviders) == 0: - errs = append(errs, fmt.Errorf("at least one provider must be specified for type %v", spec.Type)) - } - - // Return early if any errors exist. - if len(errs) != 0 { - return utilerrors.NewAggregate(errs) - } - - if err := ValidateJwtProviders(spec.JwtProviders); err != nil { - errs = append(errs, err) - } - - return utilerrors.NewAggregate(errs) -} - -// ValidateJwtProviders validates the provided JWT authentication filter providers. -func ValidateJwtProviders(providers []egv1a1.JwtAuthenticationFilterProvider) error { - var errs []error - - var names []string - for _, provider := range providers { - switch { - case len(provider.Name) == 0: - errs = append(errs, errors.New("jwt provider cannot be an empty string")) - case len(provider.Issuer) != 0: - // Issuer can take the format of a URL or an email address. - if _, err := url.ParseRequestURI(provider.Issuer); err != nil { - _, err := mail.ParseAddress(provider.Issuer) - if err != nil { - errs = append(errs, fmt.Errorf("invalid issuer; must be a URL or email address: %v", err)) - } - } - case len(provider.RemoteJWKS.URI) == 0: - errs = append(errs, fmt.Errorf("uri must be set for remote JWKS provider: %s", provider.Name)) - } - if _, err := url.ParseRequestURI(provider.RemoteJWKS.URI); err != nil { - errs = append(errs, fmt.Errorf("invalid remote JWKS URI: %v", err)) - } - - if len(errs) == 0 { - if strErrs := validation.IsQualifiedName(provider.Name); len(strErrs) != 0 { - for _, strErr := range strErrs { - errs = append(errs, errors.New(strErr)) - } - } - // Ensure uniqueness among provider names. - if names == nil { - names = append(names, provider.Name) - } else { - for _, name := range names { - if name == provider.Name { - errs = append(errs, fmt.Errorf("provider name %s must be unique", provider.Name)) - } else { - names = append(names, provider.Name) - } - } - } - } - - for _, claimToHeader := range provider.ClaimToHeaders { - switch { - case len(claimToHeader.Header) == 0: - errs = append(errs, fmt.Errorf("header must be set for claimToHeader provider: %s", claimToHeader.Header)) - case len(claimToHeader.Claim) == 0: - errs = append(errs, fmt.Errorf("claim must be set for claimToHeader provider: %s", claimToHeader.Claim)) - } - } - } - - return utilerrors.NewAggregate(errs) -} diff --git a/api/v1alpha1/validation/authenticationfilter_test.go b/api/v1alpha1/validation/authenticationfilter_test.go deleted file mode 100644 index 86470be158f..00000000000 --- a/api/v1alpha1/validation/authenticationfilter_test.go +++ /dev/null @@ -1,451 +0,0 @@ -// Copyright Envoy Gateway Authors -// SPDX-License-Identifier: Apache-2.0 -// The full text of the Apache license is available in the LICENSE file at -// the root of the repo. - -package validation - -import ( - "testing" - - "github.com/stretchr/testify/require" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" -) - -// TODO zhaohuabing remove this file after deprecating authentication filter -func TestValidateAuthenticationFilter(t *testing.T) { - testCases := []struct { - name string - filter *egv1a1.AuthenticationFilter - expected bool - }{ - { - name: "nil authentication filter", - filter: nil, - expected: false, - }, - { - name: "valid authentication filter with url", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - expected: true, - }, - { - name: "valid authentication filter with email", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "test@test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - expected: true, - }, - { - name: "valid authentication filter with jwtClaimToHeader", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "test@test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - ClaimToHeaders: []egv1a1.ClaimToHeader{ - { - Header: "test", - Claim: "test", - }, - }, - }, - }, - }, - }, - expected: true, - }, - { - name: "unqualified authentication provider name", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "unqualified_...", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "unspecified provider name", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "non unique provider names", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "unique", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - { - Name: "non-unique", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - { - Name: "non-unique", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "invalid issuer uri", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "http://invalid url.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "http://www.test.local", - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "inivalid issuer email", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "test@!123...", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "invalid remote jwks uri", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "http://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "invalid/local", - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "unspecified remote jwks uri", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "", - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "unspecified jwtClaimToHeader headerName", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "test@test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - ClaimToHeaders: []egv1a1.ClaimToHeader{ - { - Header: "", - Claim: "test", - }, - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "unspecified jwtClaimToHeader claimName", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "test@test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - ClaimToHeaders: []egv1a1.ClaimToHeader{ - { - Header: "test", - Claim: "", - }, - }, - }, - }, - }, - }, - expected: false, - }, - { - name: "unspecified issuer", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - expected: true, - }, - { - name: "unspecified audiences", - filter: &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "https://www.test.local", - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - expected: true, - }, - } - - for i := range testCases { - tc := testCases[i] - t.Run(tc.name, func(t *testing.T) { - err := ValidateAuthenticationFilter(tc.filter) - if tc.expected { - require.NoError(t, err) - } else { - require.Error(t, err) - } - }) - } -} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 603df02472e..cfbcad0acb7 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -17,86 +17,6 @@ import ( apisv1 "sigs.k8s.io/gateway-api/apis/v1" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AuthenticationFilter) DeepCopyInto(out *AuthenticationFilter) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationFilter. -func (in *AuthenticationFilter) DeepCopy() *AuthenticationFilter { - if in == nil { - return nil - } - out := new(AuthenticationFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *AuthenticationFilter) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AuthenticationFilterList) DeepCopyInto(out *AuthenticationFilterList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]AuthenticationFilter, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationFilterList. -func (in *AuthenticationFilterList) DeepCopy() *AuthenticationFilterList { - if in == nil { - return nil - } - out := new(AuthenticationFilterList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *AuthenticationFilterList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AuthenticationFilterSpec) DeepCopyInto(out *AuthenticationFilterSpec) { - *out = *in - if in.JwtProviders != nil { - in, out := &in.JwtProviders, &out.JwtProviders - *out = make([]JwtAuthenticationFilterProvider, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationFilterSpec. -func (in *AuthenticationFilterSpec) DeepCopy() *AuthenticationFilterSpec { - if in == nil { - return nil - } - out := new(AuthenticationFilterSpec) - 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 @@ -1346,32 +1266,6 @@ func (in *JWTProvider) DeepCopy() *JWTProvider { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JwtAuthenticationFilterProvider) DeepCopyInto(out *JwtAuthenticationFilterProvider) { - *out = *in - if in.Audiences != nil { - in, out := &in.Audiences, &out.Audiences - *out = make([]string, len(*in)) - copy(*out, *in) - } - out.RemoteJWKS = in.RemoteJWKS - if in.ClaimToHeaders != nil { - in, out := &in.ClaimToHeaders, &out.ClaimToHeaders - *out = make([]ClaimToHeader, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JwtAuthenticationFilterProvider. -func (in *JwtAuthenticationFilterProvider) DeepCopy() *JwtAuthenticationFilterProvider { - if in == nil { - return nil - } - out := new(JwtAuthenticationFilterProvider) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubernetesContainerSpec) DeepCopyInto(out *KubernetesContainerSpec) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_authenticationfilters.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_authenticationfilters.yaml deleted file mode 100644 index 8c85e6ca6d1..00000000000 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_authenticationfilters.yaml +++ /dev/null @@ -1,131 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.13.0 - name: authenticationfilters.gateway.envoyproxy.io -spec: - group: gateway.envoyproxy.io - names: - kind: AuthenticationFilter - listKind: AuthenticationFilterList - plural: authenticationfilters - singular: authenticationfilter - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of the AuthenticationFilter - type. - properties: - jwtProviders: - description: JWT defines the JSON Web Token (JWT) authentication provider - type. When multiple jwtProviders are specified, the JWT is considered - valid if any of the providers successfully validate the JWT. For - additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. - items: - description: 'JwtAuthenticationFilterProvider defines the JSON Web - Token (JWT) authentication provider type and how JWTs should be - verified:' - properties: - audiences: - description: Audiences is a list of JWT audiences allowed access. - For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.3. - If not provided, JWT audiences are not checked. - items: - type: string - maxItems: 8 - type: array - claimToHeaders: - description: 'ClaimToHeaders is a list of JWT claims that must - be extracted into HTTP request headers For examples, following - config: The claim must be of type; string, int, double, bool. - Array type claims are not supported' - items: - description: ClaimToHeader defines a configuration to convert - JWT claims into HTTP headers - properties: - claim: - description: 'Claim is the JWT Claim that should be saved - into the header : it can be a nested claim of type (eg. - "claim.nested.key", "sub"). The nested claim name must - use dot "." to separate the JSON name path.' - type: string - header: - description: Header defines the name of the HTTP request - header that the JWT Claim will be saved into. - type: string - required: - - claim - - header - type: object - type: array - issuer: - description: Issuer is the principal that issued the JWT and - takes the form of a URL or email address. For additional details, - see https://tools.ietf.org/html/rfc7519#section-4.1.1 for - URL format and https://rfc-editor.org/rfc/rfc5322.html for - email format. If not provided, the JWT issuer is not checked. - maxLength: 253 - type: string - name: - description: Name defines a unique name for the JWT provider. - A name can have a variety of forms, including RFC1123 subdomains, - RFC 1123 labels, or RFC 1035 labels. - maxLength: 253 - minLength: 1 - type: string - remoteJWKS: - description: RemoteJWKS defines how to fetch and cache JSON - Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. - properties: - uri: - description: URI is the HTTPS URI to fetch the JWKS. Envoy's - system trust bundle is used to validate the server certificate. - maxLength: 253 - minLength: 1 - type: string - required: - - uri - type: object - required: - - name - - remoteJWKS - type: object - maxItems: 4 - type: array - type: - description: Type defines the type of authentication provider to use. - Supported provider types are "JWT". - enum: - - JWT - type: string - required: - - type - type: object - required: - - spec - type: object - served: true - storage: true - subresources: {} diff --git a/charts/gateway-helm/templates/_rbac.tpl b/charts/gateway-helm/templates/_rbac.tpl index f0107bb6fe1..68cbe6be8fa 100644 --- a/charts/gateway-helm/templates/_rbac.tpl +++ b/charts/gateway-helm/templates/_rbac.tpl @@ -64,12 +64,10 @@ apiGroups: - gateway.envoyproxy.io resources: - envoyproxies -- authenticationfilters - envoypatchpolicies - clienttrafficpolicies - backendtrafficpolicies - securitypolicies -- ratelimitfilters verbs: - get - list diff --git a/examples/kubernetes/authn/grpc-jwt.yaml b/examples/kubernetes/jwt/grpc-jwt.yaml similarity index 53% rename from examples/kubernetes/authn/grpc-jwt.yaml rename to examples/kubernetes/jwt/grpc-jwt.yaml index 7fa0e048f85..a5da840eb66 100644 --- a/examples/kubernetes/authn/grpc-jwt.yaml +++ b/examples/kubernetes/jwt/grpc-jwt.yaml @@ -1,13 +1,17 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: AuthenticationFilter +kind: SecurityPolicy metadata: name: jwt-example spec: - type: JWT - jwtProviders: - - name: example - remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + targetRef: + group: gateway.networking.k8s.io + kind: GRPCRoute + name: yages + jwt: + providers: + - name: example + remoteJWKS: + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json --- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GRPCRoute @@ -27,9 +31,3 @@ spec: name: yages port: 9000 weight: 1 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: jwt-example - type: ExtensionRef diff --git a/examples/kubernetes/authn/jwks.json b/examples/kubernetes/jwt/jwks.json similarity index 100% rename from examples/kubernetes/authn/jwks.json rename to examples/kubernetes/jwt/jwks.json diff --git a/examples/kubernetes/authn/jwt.yaml b/examples/kubernetes/jwt/jwt.yaml similarity index 56% rename from examples/kubernetes/authn/jwt.yaml rename to examples/kubernetes/jwt/jwt.yaml index 86e78eb1b20..dcf580edde9 100644 --- a/examples/kubernetes/authn/jwt.yaml +++ b/examples/kubernetes/jwt/jwt.yaml @@ -1,18 +1,22 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: AuthenticationFilter +kind: SecurityPolicy metadata: name: jwt-example spec: - type: JWT - jwtProviders: - - name: example - remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: foo + jwt: + providers: + - name: example + remoteJWKS: + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: - name: backend + name: foo spec: parentRefs: - name: eg @@ -25,16 +29,21 @@ spec: name: backend port: 3000 weight: 1 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: jwt-example - type: ExtensionRef matches: - path: type: PathPrefix value: /foo +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: bar +spec: + parentRefs: + - name: eg + hostnames: + - "www.example.com" + rules: - backendRefs: - group: "" kind: Service diff --git a/examples/kubernetes/authn/test.jwt b/examples/kubernetes/jwt/test.jwt similarity index 100% rename from examples/kubernetes/authn/test.jwt rename to examples/kubernetes/jwt/test.jwt diff --git a/examples/kubernetes/authn/with-different-claim.jwt b/examples/kubernetes/jwt/with-different-claim.jwt similarity index 100% rename from examples/kubernetes/authn/with-different-claim.jwt rename to examples/kubernetes/jwt/with-different-claim.jwt diff --git a/internal/cmd/egctl/testdata/translate/in/authn-single-route-single-match-to-xds.yaml b/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml similarity index 83% rename from internal/cmd/egctl/testdata/translate/in/authn-single-route-single-match-to-xds.yaml rename to internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml index ca56711986b..2b41c1a3eb4 100644 --- a/internal/cmd/egctl/testdata/translate/in/authn-single-route-single-match-to-xds.yaml +++ b/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml @@ -71,15 +71,19 @@ spec: fieldPath: metadata.namespace --- apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: AuthenticationFilter +kind: SecurityPolicy metadata: name: jwt-example spec: - type: JWT - jwtProviders: - - name: example - remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend + jwt: + providers: + - name: example + remoteJWKS: + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute @@ -97,12 +101,6 @@ spec: name: backend port: 3000 weight: 1 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: jwt-example - type: ExtensionRef matches: - path: type: PathPrefix diff --git a/internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json similarity index 100% rename from internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.all.json rename to internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json diff --git a/internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml similarity index 100% rename from internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.all.yaml rename to internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml diff --git a/internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.bootstrap.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml similarity index 100% rename from internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.bootstrap.yaml rename to internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml diff --git a/internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.cluster.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.cluster.yaml similarity index 100% rename from internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.cluster.yaml rename to internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.cluster.yaml diff --git a/internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.endpoint.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.endpoint.yaml similarity index 100% rename from internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.endpoint.yaml rename to internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.endpoint.yaml diff --git a/internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.listener.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml similarity index 100% rename from internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.listener.yaml rename to internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml diff --git a/internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.route.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.route.yaml similarity index 100% rename from internal/cmd/egctl/testdata/translate/out/authn-single-route-single-match-to-xds.route.yaml rename to internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.route.yaml diff --git a/internal/cmd/egctl/translate.go b/internal/cmd/egctl/translate.go index 5850f96a1fa..47ab944f424 100644 --- a/internal/cmd/egctl/translate.go +++ b/internal/cmd/egctl/translate.go @@ -738,34 +738,62 @@ func kubernetesYAMLToResources(str string, addMissingResources bool) (*gatewayap Spec: typedSpec.(v1.ServiceSpec), } resources.Services = append(resources.Services, service) - case egv1a1.KindAuthenticationFilter: + case egv1a1.KindEnvoyPatchPolicy: typedSpec := spec.Interface() - authenticationFilter := &egv1a1.AuthenticationFilter{ + envoyPatchPolicy := &egv1a1.EnvoyPatchPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, + Kind: egv1a1.KindEnvoyPatchPolicy, APIVersion: egv1a1.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: name, }, - Spec: typedSpec.(egv1a1.AuthenticationFilterSpec), + Spec: typedSpec.(egv1a1.EnvoyPatchPolicySpec), } - resources.AuthenticationFilters = append(resources.AuthenticationFilters, authenticationFilter) - case egv1a1.KindEnvoyPatchPolicy: + resources.EnvoyPatchPolicies = append(resources.EnvoyPatchPolicies, envoyPatchPolicy) + case egv1a1.KindClientTrafficPolicy: typedSpec := spec.Interface() - envoyPatchPolicy := &egv1a1.EnvoyPatchPolicy{ + clientTrafficPolicy := &egv1a1.ClientTrafficPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindEnvoyPatchPolicy, + Kind: egv1a1.KindClientTrafficPolicy, APIVersion: egv1a1.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: name, }, - Spec: typedSpec.(egv1a1.EnvoyPatchPolicySpec), + Spec: typedSpec.(egv1a1.ClientTrafficPolicySpec), } - resources.EnvoyPatchPolicies = append(resources.EnvoyPatchPolicies, envoyPatchPolicy) + resources.ClientTrafficPolicies = append(resources.ClientTrafficPolicies, clientTrafficPolicy) + case egv1a1.KindBackendTrafficPolicy: + typedSpec := spec.Interface() + backendTrafficPolicy := &egv1a1.BackendTrafficPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindBackendTrafficPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: typedSpec.(egv1a1.BackendTrafficPolicySpec), + } + resources.BackendTrafficPolicies = append(resources.BackendTrafficPolicies, backendTrafficPolicy) + case egv1a1.KindSecurityPolicy: + typedSpec := spec.Interface() + securityPolicy := &egv1a1.SecurityPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: egv1a1.KindSecurityPolicy, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: typedSpec.(egv1a1.SecurityPolicySpec), + } + resources.SecurityPolicies = append(resources.SecurityPolicies, securityPolicy) } } diff --git a/internal/cmd/egctl/translate_test.go b/internal/cmd/egctl/translate_test.go index 03ab44345a1..d9cd598174a 100644 --- a/internal/cmd/egctl/translate_test.go +++ b/internal/cmd/egctl/translate_test.go @@ -111,27 +111,27 @@ func TestTranslate(t *testing.T) { expect: true, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", output: jsonOutput, expect: true, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", output: yamlOutput, expect: true, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", expect: true, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", output: yamlOutput, @@ -139,7 +139,7 @@ func TestTranslate(t *testing.T) { expect: false, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", output: yamlOutput, @@ -147,7 +147,7 @@ func TestTranslate(t *testing.T) { expect: true, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", output: yamlOutput, @@ -155,7 +155,7 @@ func TestTranslate(t *testing.T) { expect: true, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", output: yamlOutput, @@ -163,7 +163,7 @@ func TestTranslate(t *testing.T) { expect: true, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", output: yamlOutput, @@ -171,7 +171,7 @@ func TestTranslate(t *testing.T) { expect: true, }, { - name: "authn-single-route-single-match-to-xds", + name: "jwt-single-route-single-match-to-xds", from: "gateway-api", to: "xds", output: yamlOutput, diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go index 961b2fd6ec4..73dcf54ca7f 100644 --- a/internal/gatewayapi/filters.go +++ b/internal/gatewayapi/filters.go @@ -13,7 +13,6 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" ) @@ -57,8 +56,6 @@ type HTTPFilterIR struct { Mirrors []*ir.RouteDestination - RequestAuthentication *ir.RequestAuthentication - ExtensionRefs []*ir.UnstructuredRef } @@ -662,21 +659,6 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec } filterNs := filterContext.Route.GetNamespace() - // Set the filter context and return early if a matching AuthenticationFilter is found. - if string(extFilter.Kind) == egv1a1.KindAuthenticationFilter { - for _, authenFilter := range resources.AuthenticationFilters { - if authenFilter.Namespace == filterNs && - authenFilter.Name == string(extFilter.Name) { - filterContext.HTTPFilterIR.RequestAuthentication = &ir.RequestAuthentication{ - JWT: &ir.JwtRequestAuthentication{ - Providers: authenFilter.Spec.JwtProviders, - }, - } - return - } - } - } - // This list of resources will be empty unless an extension is loaded (and introduces resources) for _, res := range resources.ExtensionRefFilters { if res.GetKind() == string(extFilter.Kind) && res.GetName() == string(extFilter.Name) && res.GetNamespace() == filterNs { diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index fc221085af3..1c5392262a9 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -16,7 +16,6 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" ) @@ -189,9 +188,6 @@ func ValidateHTTPRouteFilter(filter *gwapiv1.HTTPRouteFilter, extGKs ...schema.G switch { case filter.ExtensionRef == nil: return errors.New("extensionRef field must be specified for an extended filter") - case string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - string(filter.ExtensionRef.Kind) == egv1a1.KindAuthenticationFilter: - return nil default: for _, gk := range extGKs { if filter.ExtensionRef.Group == gwapiv1.Group(gk.Group) && @@ -206,14 +202,6 @@ func ValidateHTTPRouteFilter(filter *gwapiv1.HTTPRouteFilter, extGKs ...schema.G } } -// IsAuthnHTTPFilter returns true if the provided filter is an AuthenticationFilter. -func IsAuthnHTTPFilter(filter *gwapiv1.HTTPRouteFilter) bool { - return filter.Type == gwapiv1.HTTPRouteFilterExtensionRef && - filter.ExtensionRef != nil && - string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - string(filter.ExtensionRef.Kind) == egv1a1.KindAuthenticationFilter -} - // ValidateGRPCRouteFilter validates the provided filter within GRPCRoute. func ValidateGRPCRouteFilter(filter *v1alpha2.GRPCRouteFilter, extGKs ...schema.GroupKind) error { switch { @@ -227,9 +215,6 @@ func ValidateGRPCRouteFilter(filter *v1alpha2.GRPCRouteFilter, extGKs ...schema. switch { case filter.ExtensionRef == nil: return errors.New("extensionRef field must be specified for an extended filter") - case string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - string(filter.ExtensionRef.Kind) == egv1a1.KindAuthenticationFilter: - return nil default: for _, gk := range extGKs { if filter.ExtensionRef.Group == gwapiv1.Group(gk.Group) && @@ -244,14 +229,6 @@ func ValidateGRPCRouteFilter(filter *v1alpha2.GRPCRouteFilter, extGKs ...schema. } } -// IsAuthnGRPCFilter returns true if the provided filter is an AuthenticationFilter. -func IsAuthnGRPCFilter(filter *v1alpha2.GRPCRouteFilter) bool { - return filter.Type == v1alpha2.GRPCRouteFilterExtensionRef && - filter.ExtensionRef != nil && - string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - string(filter.ExtensionRef.Kind) == egv1a1.KindAuthenticationFilter -} - // GatewayOwnerLabels returns the Gateway Owner labels using // the provided namespace and name as the values. func GatewayOwnerLabels(namespace, name string) map[string]string { diff --git a/internal/gatewayapi/helpers_test.go b/internal/gatewayapi/helpers_test.go index 6ded00f8c72..6c8f6623067 100644 --- a/internal/gatewayapi/helpers_test.go +++ b/internal/gatewayapi/helpers_test.go @@ -18,8 +18,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) func TestValidateGRPCFilterRef(t *testing.T) { @@ -92,42 +90,6 @@ func TestValidateGRPCFilterRef(t *testing.T) { }, expected: false, }, - { - name: "invalid authenticationfilter group", - filter: &gwapiv1a2.GRPCRouteFilter{ - Type: gwapiv1a2.GRPCRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: "UnsupportedGroup", - Kind: egv1a1.KindAuthenticationFilter, - Name: "test", - }, - }, - expected: false, - }, - { - name: "invalid authenticationfilter kind", - filter: &gwapiv1a2.GRPCRouteFilter{ - Type: gwapiv1a2.GRPCRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: "UnsupportedKind", - Name: "test", - }, - }, - expected: false, - }, - { - name: "valid authenticationfilter", - filter: &gwapiv1a2.GRPCRouteFilter{ - Type: gwapiv1a2.GRPCRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: egv1a1.KindAuthenticationFilter, - Name: "test", - }, - }, - expected: true, - }, } for _, tc := range testCases { tc := tc @@ -195,42 +157,6 @@ func TestValidateHTTPFilterRef(t *testing.T) { }, expected: false, }, - { - name: "invalid authenticationfilter group", - filter: &gwapiv1.HTTPRouteFilter{ - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: "UnsupportedGroup", - Kind: egv1a1.KindAuthenticationFilter, - Name: "test", - }, - }, - expected: false, - }, - { - name: "invalid authenticationfilter kind", - filter: &gwapiv1.HTTPRouteFilter{ - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: "UnsupportedKind", - Name: "test", - }, - }, - expected: false, - }, - { - name: "valid authenticationfilter", - filter: &gwapiv1.HTTPRouteFilter{ - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: egv1a1.KindAuthenticationFilter, - Name: "test", - }, - }, - expected: true, - }, { name: "valid extension resource", filter: &gwapiv1.HTTPRouteFilter{ diff --git a/internal/gatewayapi/resource.go b/internal/gatewayapi/resource.go index 6bd0fc4f696..2251d346674 100644 --- a/internal/gatewayapi/resource.go +++ b/internal/gatewayapi/resource.go @@ -40,7 +40,6 @@ type Resources struct { ServiceImports []*mcsapi.ServiceImport `json:"serviceImports,omitempty" yaml:"serviceImports,omitempty"` EndpointSlices []*discoveryv1.EndpointSlice `json:"endpointSlices,omitempty" yaml:"endpointSlices,omitempty"` Secrets []*v1.Secret `json:"secrets,omitempty" yaml:"secrets,omitempty"` - AuthenticationFilters []*egv1a1.AuthenticationFilter `json:"authenticationFilters,omitempty" yaml:"authenticationFilters,omitempty"` EnvoyProxy *egv1a1.EnvoyProxy `json:"envoyProxy,omitempty" yaml:"envoyProxy,omitempty"` ExtensionRefFilters []unstructured.Unstructured `json:"extensionRefFilters,omitempty" yaml:"extensionRefFilters,omitempty"` EnvoyPatchPolicies []*egv1a1.EnvoyPatchPolicy `json:"envoyPatchPolicies,omitempty" yaml:"envoyPatchPolicies,omitempty"` @@ -60,7 +59,6 @@ func NewResources() *Resources { Secrets: []*v1.Secret{}, ReferenceGrants: []*gwapiv1b1.ReferenceGrant{}, Namespaces: []*v1.Namespace{}, - AuthenticationFilters: []*egv1a1.AuthenticationFilter{}, ExtensionRefFilters: []unstructured.Unstructured{}, EnvoyPatchPolicies: []*egv1a1.EnvoyPatchPolicy{}, ClientTrafficPolicies: []*egv1a1.ClientTrafficPolicy{}, diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index fed00642f59..90814694d50 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -314,9 +314,6 @@ func applyHTTPFiltersContextToIRRoute(httpFiltersContext *HTTPFiltersContext, ir if httpFiltersContext.Mirrors != nil { irRoute.Mirrors = httpFiltersContext.Mirrors } - if httpFiltersContext.RequestAuthentication != nil { - irRoute.RequestAuthentication = httpFiltersContext.RequestAuthentication - } if len(httpFiltersContext.ExtensionRefs) > 0 { irRoute.ExtensionRefs = httpFiltersContext.ExtensionRefs @@ -557,8 +554,9 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route DirectResponse: routeRoute.DirectResponse, URLRewrite: routeRoute.URLRewrite, Mirrors: routeRoute.Mirrors, - RequestAuthentication: routeRoute.RequestAuthentication, RateLimit: routeRoute.RateLimit, + CORS: routeRoute.CORS, + JWT: routeRoute.JWT, Timeout: routeRoute.Timeout, ExtensionRefs: routeRoute.ExtensionRefs, } diff --git a/internal/gatewayapi/testdata/grpcroute-with-valid-authenfilter.in.yaml b/internal/gatewayapi/testdata/grpcroute-with-valid-authenfilter.in.yaml deleted file mode 100644 index 9c46c74c843..00000000000 --- a/internal/gatewayapi/testdata/grpcroute-with-valid-authenfilter.in.yaml +++ /dev/null @@ -1,49 +0,0 @@ -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 -grpcRoutes: -- apiVersion: gateway.networking.k8s.io/v1alpha2 - kind: GRPCRoute - metadata: - namespace: default - name: grpcroute-1 - spec: - parentRefs: - - namespace: envoy-gateway - name: gateway-1 - sectionName: http - rules: - - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - backendRefs: - - name: service-1 - port: 8080 -authenticationFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: AuthenticationFilter - metadata: - namespace: default - name: test - spec: - type: JWT - jwtProviders: - - name: test - issuer: https://www.test.local - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/grpcroute-with-valid-authenfilter.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-valid-authenfilter.out.yaml deleted file mode 100644 index b36321651d8..00000000000 --- a/internal/gatewayapi/testdata/grpcroute-with-valid-authenfilter.out.yaml +++ /dev/null @@ -1,128 +0,0 @@ -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 -grpcRoutes: -- apiVersion: gateway.networking.k8s.io/v1alpha2 - kind: GRPCRoute - metadata: - creationTimestamp: null - name: grpcroute-1 - namespace: default - spec: - parentRefs: - - name: gateway-1 - namespace: envoy-gateway - sectionName: http - rules: - - backendRefs: - - name: service-1 - port: 8080 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - type: ExtensionRef - 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: "" - ports: - - containerPort: 10080 - name: http - 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: true - name: envoy-gateway/gateway-1/http - port: 10080 - routes: - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: grpcroute/default/grpcroute-1/rule/0 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: '*' - name: grpcroute/default/grpcroute-1/rule/0/match/-1/* - requestAuthentication: - jwt: - providers: - - issuer: https://www.test.local - name: test - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/httproute-with-non-existent-authenfilter-ref.in.yaml b/internal/gatewayapi/testdata/httproute-with-non-existent-authenfilter-ref.in.yaml deleted file mode 100644 index 5785df85e16..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-non-existent-authenfilter-ref.in.yaml +++ /dev/null @@ -1,43 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: non-exist - diff --git a/internal/gatewayapi/testdata/httproute-with-non-existent-authenfilter-ref.out.yaml b/internal/gatewayapi/testdata/httproute-with-non-existent-authenfilter-ref.out.yaml deleted file mode 100644 index 919f22bf257..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-non-existent-authenfilter-ref.out.yaml +++ /dev/null @@ -1,114 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - name: http - port: 80 - protocol: HTTP - status: - listeners: - - attachedRoutes: 0 - conditions: - - lastTransitionTime: null - message: Sending translated listener configuration to the data plane - reason: Programmed - status: "True" - type: Programmed - - lastTransitionTime: null - message: Listener has been successfully translated - reason: Accepted - status: "True" - type: Accepted - - lastTransitionTime: null - message: Listener references have been resolved - reason: ResolvedRefs - status: "True" - type: ResolvedRefs - name: http - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: non-exist - type: ExtensionRef - matches: - - path: - value: / - status: - parents: - - conditions: - - lastTransitionTime: null - message: 'Reference default/non-exist not found for filter type: AuthenticationFilter' - reason: UnsupportedValue - status: "False" - type: Accepted - - lastTransitionTime: null - message: 'Reference default/non-exist not found for filter type: AuthenticationFilter' - reason: BackendNotFound - status: "False" - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 diff --git a/internal/gatewayapi/testdata/httproute-with-non-matching-authenfilter-ref.in.yaml b/internal/gatewayapi/testdata/httproute-with-non-matching-authenfilter-ref.in.yaml deleted file mode 100644 index 86569b96053..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-non-matching-authenfilter-ref.in.yaml +++ /dev/null @@ -1,57 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test -authenticationFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: AuthenticationFilter - metadata: - name: example1 - namespace: default - spec: - type: JWT - jwtProviders: - - name: example1 - issuer: https://www.example1.com - audiences: - - foo.com - remoteJwks: - uri: https://foo.com/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/httproute-with-non-matching-authenfilter-ref.out.yaml b/internal/gatewayapi/testdata/httproute-with-non-matching-authenfilter-ref.out.yaml deleted file mode 100644 index b61269b4370..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-non-matching-authenfilter-ref.out.yaml +++ /dev/null @@ -1,114 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - name: http - port: 80 - protocol: HTTP - status: - listeners: - - attachedRoutes: 0 - conditions: - - lastTransitionTime: null - message: Sending translated listener configuration to the data plane - reason: Programmed - status: "True" - type: Programmed - - lastTransitionTime: null - message: Listener has been successfully translated - reason: Accepted - status: "True" - type: Accepted - - lastTransitionTime: null - message: Listener references have been resolved - reason: ResolvedRefs - status: "True" - type: ResolvedRefs - name: http - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - type: ExtensionRef - matches: - - path: - value: / - status: - parents: - - conditions: - - lastTransitionTime: null - message: 'Reference default/test not found for filter type: AuthenticationFilter' - reason: UnsupportedValue - status: "False" - type: Accepted - - lastTransitionTime: null - message: 'Reference default/test not found for filter type: AuthenticationFilter' - reason: BackendNotFound - status: "False" - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 diff --git a/internal/gatewayapi/testdata/httproute-with-valid-authenfilter.in.yaml b/internal/gatewayapi/testdata/httproute-with-valid-authenfilter.in.yaml deleted file mode 100644 index 9534510f851..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-valid-authenfilter.in.yaml +++ /dev/null @@ -1,55 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test -authenticationFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: AuthenticationFilter - metadata: - namespace: default - name: test - spec: - type: JWT - jwtProviders: - - name: test - issuer: https://www.test.local - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/httproute-with-valid-authenfilter.out.yaml b/internal/gatewayapi/testdata/httproute-with-valid-authenfilter.out.yaml deleted file mode 100644 index ef2b7de94f8..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-valid-authenfilter.out.yaml +++ /dev/null @@ -1,138 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - type: ExtensionRef - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 - routes: - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: httproute/default/httproute-1/rule/0 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: gateway.envoyproxy.io - name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io - pathMatch: - distinct: false - name: "" - prefix: / - requestAuthentication: - jwt: - providers: - - issuer: https://www.test.local - name: test - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/httproute-with-valid-multi-match-authenfilter.in.yaml b/internal/gatewayapi/testdata/httproute-with-valid-multi-match-authenfilter.in.yaml deleted file mode 100644 index 2517962aefd..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-valid-multi-match-authenfilter.in.yaml +++ /dev/null @@ -1,69 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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: - type: Exact - value: "/test/path/1" - backendRefs: - - name: service-1 - port: 8080 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - - matches: - - path: - type: Exact - value: "/test/path/2" - backendRefs: - - name: service-1 - port: 8080 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test -authenticationFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: AuthenticationFilter - metadata: - namespace: default - name: test - spec: - type: JWT - jwtProviders: - - name: test - issuer: https://www.test.local - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/httproute-with-valid-multi-match-authenfilter.out.yaml b/internal/gatewayapi/testdata/httproute-with-valid-multi-match-authenfilter.out.yaml deleted file mode 100644 index e88afb72488..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-valid-multi-match-authenfilter.out.yaml +++ /dev/null @@ -1,175 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - type: ExtensionRef - matches: - - path: - type: Exact - value: /test/path/1 - - backendRefs: - - name: service-1 - port: 8080 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - type: ExtensionRef - matches: - - path: - type: Exact - value: /test/path/2 - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 - routes: - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: httproute/default/httproute-1/rule/0 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: gateway.envoyproxy.io - name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io - pathMatch: - distinct: false - exact: /test/path/1 - name: "" - requestAuthentication: - jwt: - providers: - - issuer: https://www.test.local - name: test - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: httproute/default/httproute-1/rule/1 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: gateway.envoyproxy.io - name: httproute/default/httproute-1/rule/1/match/0/gateway_envoyproxy_io - pathMatch: - distinct: false - exact: /test/path/2 - name: "" - requestAuthentication: - jwt: - providers: - - issuer: https://www.test.local - name: test - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/httproute-with-valid-multi-match-multi-authenfilter.in.yaml b/internal/gatewayapi/testdata/httproute-with-valid-multi-match-multi-authenfilter.in.yaml deleted file mode 100644 index 22460f60151..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-valid-multi-match-multi-authenfilter.in.yaml +++ /dev/null @@ -1,85 +0,0 @@ -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 - hostname: "*.envoyproxy.io" - 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: - type: Exact - value: "/test/path/1" - backendRefs: - - name: service-1 - port: 8080 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test1 - - matches: - - path: - type: Exact - value: "/test/path/2" - backendRefs: - - name: service-1 - port: 8080 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test2 -authenticationFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: AuthenticationFilter - metadata: - namespace: default - name: test1 - spec: - type: JWT - jwtProviders: - - name: test1 - issuer: https://www.test1.local - remoteJWKS: - uri: https://test1.local/jwt/public-key/jwks.json -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: AuthenticationFilter - metadata: - namespace: default - name: test2 - spec: - type: JWT - jwtProviders: - - name: test2 - issuer: https://www.test2.local - remoteJWKS: - uri: https://test2.local/jwt/public-key/jwks.json - - name: test3 - issuer: https://www.test3.local - remoteJWKS: - uri: https://test3.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/httproute-with-valid-multi-match-multi-authenfilter.out.yaml b/internal/gatewayapi/testdata/httproute-with-valid-multi-match-multi-authenfilter.out.yaml deleted file mode 100644 index 9cc518431ef..00000000000 --- a/internal/gatewayapi/testdata/httproute-with-valid-multi-match-multi-authenfilter.out.yaml +++ /dev/null @@ -1,179 +0,0 @@ -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 - hostname: '*.envoyproxy.io' - 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 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test1 - type: ExtensionRef - matches: - - path: - type: Exact - value: /test/path/1 - - backendRefs: - - name: service-1 - port: 8080 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test2 - type: ExtensionRef - matches: - - path: - type: Exact - value: /test/path/2 - 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: "" - ports: - - containerPort: 10080 - name: http - 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: - - '*.envoyproxy.io' - isHTTP2: false - name: envoy-gateway/gateway-1/http - port: 10080 - routes: - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: httproute/default/httproute-1/rule/0 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: gateway.envoyproxy.io - name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io - pathMatch: - distinct: false - exact: /test/path/1 - name: "" - requestAuthentication: - jwt: - providers: - - issuer: https://www.test1.local - name: test1 - remoteJWKS: - uri: https://test1.local/jwt/public-key/jwks.json - - backendWeights: - invalid: 0 - valid: 0 - destination: - name: httproute/default/httproute-1/rule/1 - settings: - - endpoints: - - host: 7.7.7.7 - port: 8080 - weight: 1 - hostname: gateway.envoyproxy.io - name: httproute/default/httproute-1/rule/1/match/0/gateway_envoyproxy_io - pathMatch: - distinct: false - exact: /test/path/2 - name: "" - requestAuthentication: - jwt: - providers: - - issuer: https://www.test2.local - name: test2 - remoteJWKS: - uri: https://test2.local/jwt/public-key/jwks.json - - issuer: https://www.test3.local - name: test3 - remoteJWKS: - uri: https://test3.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.in.yaml b/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.in.yaml index aeca411f058..b88c25a8808 100644 --- a/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.in.yaml +++ b/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.in.yaml @@ -60,12 +60,6 @@ httpRoutes: backendRefs: - name: service-1 port: 8080 - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: @@ -85,16 +79,3 @@ httpRoutes: backendRefs: - name: service-2 port: 8080 -authenticationFilters: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: AuthenticationFilter - metadata: - namespace: default - name: test - spec: - type: JWT - jwtProviders: - - name: test - issuer: https://www.test.local - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json diff --git a/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml b/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml index 1f91380625f..b7a57690426 100755 --- a/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml +++ b/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml @@ -125,12 +125,6 @@ httpRoutes: - backendRefs: - name: service-1 port: 8080 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: test - type: ExtensionRef matches: - path: value: / @@ -248,13 +242,6 @@ xdsIR: distinct: false name: "" prefix: / - requestAuthentication: - jwt: - providers: - - issuer: https://www.test.local - name: test - remoteJWKS: - uri: https://test.local/jwt/public-key/jwks.json - address: 0.0.0.0 hostnames: - '*' diff --git a/internal/gatewayapi/zz_generated.deepcopy.go b/internal/gatewayapi/zz_generated.deepcopy.go index 56969b4480a..56335dc5bc9 100644 --- a/internal/gatewayapi/zz_generated.deepcopy.go +++ b/internal/gatewayapi/zz_generated.deepcopy.go @@ -160,17 +160,6 @@ func (in *Resources) DeepCopyInto(out *Resources) { } } } - if in.AuthenticationFilters != nil { - in, out := &in.AuthenticationFilters, &out.AuthenticationFilters - *out = make([]*apiv1alpha1.AuthenticationFilter, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(apiv1alpha1.AuthenticationFilter) - (*in).DeepCopyInto(*out) - } - } - } if in.EnvoyProxy != nil { in, out := &in.EnvoyProxy, &out.EnvoyProxy *out = new(apiv1alpha1.EnvoyProxy) diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 6a7a0041918..c0aa13ffbf6 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -44,7 +44,6 @@ var ( ErrAddHeaderEmptyName = errors.New("header modifier filter cannot configure a header without a name to be added") ErrAddHeaderDuplicate = errors.New("header modifier filter attempts to add the same header more than once (case insensitive)") ErrRemoveHeaderDuplicate = errors.New("header modifier filter attempts to remove the same header more than once (case insensitive)") - ErrRequestAuthenRequiresJwt = errors.New("jwt field is required when request authentication is set") ErrLoadBalancerInvalid = errors.New("loadBalancer setting is invalid, only one setting can be set") ) @@ -273,8 +272,6 @@ type HTTPRoute struct { // RateLimit defines the more specific match conditions as well as limits for ratelimiting // the requests on this route. RateLimit *RateLimit `json:"rateLimit,omitempty" yaml:"rateLimit,omitempty"` - // RequestAuthentication defines the schema for authenticating HTTP requests. //TODO zhaohuabing remove this field - RequestAuthentication *RequestAuthentication `json:"requestAuthentication,omitempty" yaml:"requestAuthentication,omitempty"` // Timeout is the time until which entire response is received from the upstream. Timeout *metav1.Duration `json:"timeout,omitempty" yaml:"timeout,omitempty"` // load balancer policy to use when routing to the backend endpoints. @@ -296,28 +293,6 @@ type UnstructuredRef struct { Object *unstructured.Unstructured `json:"object,omitempty" yaml:"object,omitempty"` } -// RequestAuthentication defines the schema for authenticating HTTP requests. -// Only one of "jwt" can be specified. -// -// TODO: Add support for additional request authentication providers, i.e. OIDC. -// -// +k8s:deepcopy-gen=true -// TODO zhaohuabing remove this type -type RequestAuthentication struct { - // JWT defines the schema for authenticating HTTP requests using JSON Web Tokens (JWT). - JWT *JwtRequestAuthentication `json:"jwt,omitempty" yaml:"jwt,omitempty"` -} - -// JwtRequestAuthentication defines the schema for authenticating HTTP requests using -// JSON Web Tokens (JWT). -// -// +k8s:deepcopy-gen=true -// TODO zhaohuabing remove this type -type JwtRequestAuthentication struct { - // Providers defines a list of JSON Web Token (JWT) authentication providers. - Providers []egv1a1.JwtAuthenticationFilterProvider `json:"providers,omitempty" yaml:"providers,omitempty"` -} - // CORS holds the Cross-Origin Resource Sharing (CORS) policy for the route. // // +k8s:deepcopy-gen=true @@ -444,16 +419,6 @@ func (h HTTPRoute) Validate() error { } } } - if h.RequestAuthentication != nil { - switch { - case h.RequestAuthentication.JWT == nil: - errs = multierror.Append(errs, ErrRequestAuthenRequiresJwt) - default: - if err := h.RequestAuthentication.JWT.Validate(); err != nil { - errs = multierror.Append(errs, err) - } - } - } if h.LoadBalancer != nil { if err := h.LoadBalancer.Validate(); err != nil { errs = multierror.Append(errs, err) @@ -468,16 +433,6 @@ func (h HTTPRoute) Validate() error { return errs } -func (j *JwtRequestAuthentication) Validate() error { - var errs error - - if err := validation.ValidateJwtProviders(j.Providers); err != nil { - errs = multierror.Append(errs, err) - } - - return errs -} - func (j *JWT) validate() error { var errs error diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index 17ca9878751..2fb249ddcba 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -1067,7 +1067,7 @@ func TestValidateStringMatch(t *testing.T) { } } -func TestValidateJwtRequestAuthentication(t *testing.T) { +func TestValidateJWT(t *testing.T) { tests := []struct { name string input JWT diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 8044ec291a5..7ebe840dd5a 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -441,11 +441,6 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = new(RateLimit) (*in).DeepCopyInto(*out) } - if in.RequestAuthentication != nil { - in, out := &in.RequestAuthentication, &out.RequestAuthentication - *out = new(RequestAuthentication) - (*in).DeepCopyInto(*out) - } if in.Timeout != nil { in, out := &in.Timeout, &out.Timeout *out = new(v1.Duration) @@ -607,28 +602,6 @@ func (in *JWT) DeepCopy() *JWT { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JwtRequestAuthentication) DeepCopyInto(out *JwtRequestAuthentication) { - *out = *in - if in.Providers != nil { - in, out := &in.Providers, &out.Providers - *out = make([]v1alpha1.JwtAuthenticationFilterProvider, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JwtRequestAuthentication. -func (in *JwtRequestAuthentication) DeepCopy() *JwtRequestAuthentication { - if in == nil { - return nil - } - out := new(JwtRequestAuthentication) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LeastRequest) DeepCopyInto(out *LeastRequest) { *out = *in @@ -926,26 +899,6 @@ func (in *Redirect) DeepCopy() *Redirect { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RequestAuthentication) DeepCopyInto(out *RequestAuthentication) { - *out = *in - if in.JWT != nil { - in, out := &in.JWT, &out.JWT - *out = new(JwtRequestAuthentication) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestAuthentication. -func (in *RequestAuthentication) DeepCopy() *RequestAuthentication { - if in == nil { - return nil - } - out := new(RequestAuthentication) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RoundRobin) DeepCopyInto(out *RoundRobin) { *out = *in diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 1980ba6b835..97ade72126b 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -42,23 +42,19 @@ import ( ) const ( - classGatewayIndex = "classGatewayIndex" - gatewayTLSRouteIndex = "gatewayTLSRouteIndex" - gatewayHTTPRouteIndex = "gatewayHTTPRouteIndex" - gatewayGRPCRouteIndex = "gatewayGRPCRouteIndex" - gatewayTCPRouteIndex = "gatewayTCPRouteIndex" - gatewayUDPRouteIndex = "gatewayUDPRouteIndex" - secretGatewayIndex = "secretGatewayIndex" - targetRefGrantRouteIndex = "targetRefGrantRouteIndex" - backendHTTPRouteIndex = "backendHTTPRouteIndex" - backendGRPCRouteIndex = "backendGRPCRouteIndex" - backendTLSRouteIndex = "backendTLSRouteIndex" - backendTCPRouteIndex = "backendTCPRouteIndex" - backendUDPRouteIndex = "backendUDPRouteIndex" - authenFilterHTTPRouteIndex = "authenHTTPRouteIndex" - rateLimitFilterHTTPRouteIndex = "rateLimitHTTPRouteIndex" - authenFilterGRPCRouteIndex = "authenGRPCRouteIndex" - rateLimitFilterGRPCRouteIndex = "rateLimitGRPCRouteIndex" + classGatewayIndex = "classGatewayIndex" + gatewayTLSRouteIndex = "gatewayTLSRouteIndex" + gatewayHTTPRouteIndex = "gatewayHTTPRouteIndex" + gatewayGRPCRouteIndex = "gatewayGRPCRouteIndex" + gatewayTCPRouteIndex = "gatewayTCPRouteIndex" + gatewayUDPRouteIndex = "gatewayUDPRouteIndex" + secretGatewayIndex = "secretGatewayIndex" + targetRefGrantRouteIndex = "targetRefGrantRouteIndex" + backendHTTPRouteIndex = "backendHTTPRouteIndex" + backendGRPCRouteIndex = "backendGRPCRouteIndex" + backendTLSRouteIndex = "backendTLSRouteIndex" + backendTCPRouteIndex = "backendTCPRouteIndex" + backendUDPRouteIndex = "backendUDPRouteIndex" ) type gatewayAPIReconciler struct { @@ -136,9 +132,6 @@ type resourceMappings struct { allAssociatedBackendRefs map[gwapiv1.BackendObjectReference]struct{} // Map for storing referenceGrant NamespaceNames for BackendRefs, SecretRefs. allAssociatedRefGrants map[types.NamespacedName]*gwapiv1b1.ReferenceGrant - // authenFilters is a map of AuthenticationFilters, where the key is the - // namespaced name of the AuthenticationFilter. - authenFilters map[types.NamespacedName]*v1alpha1.AuthenticationFilter // extensionRefFilters is a map of filters managed by an extension. // The key is the namespaced name of the filter and the value is the // unstructured form of the resource. @@ -150,7 +143,6 @@ func newResourceMapping() *resourceMappings { allAssociatedNamespaces: map[string]struct{}{}, allAssociatedBackendRefs: map[gwapiv1.BackendObjectReference]struct{}{}, allAssociatedRefGrants: map[types.NamespacedName]*gwapiv1b1.ReferenceGrant{}, - authenFilters: map[types.NamespacedName]*v1alpha1.AuthenticationFilter{}, extensionRefFilters: map[types.NamespacedName]unstructured.Unstructured{}, } } @@ -653,9 +645,6 @@ func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error { // addHTTPRouteIndexers adds indexing on HTTPRoute. // - For Service, ServiceImports objects that are referenced in HTTPRoute objects via `.spec.rules.backendRefs`. // This helps in querying for HTTPRoutes that are affected by a particular Service CRUD. -// - For AuthenticationFilter objects that are referenced in HTTPRoute objects via -// `.spec.rules[].filters`. This helps in querying for HTTPRoutes that are affected by a -// particular AuthenticationFilter CRUD. func addHTTPRouteIndexers(ctx context.Context, mgr manager.Manager) error { if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, gatewayHTTPRouteIndex, gatewayHTTPRouteIndexFunc); err != nil { return err @@ -665,34 +654,9 @@ func addHTTPRouteIndexers(ctx context.Context, mgr manager.Manager) error { return err } - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, authenFilterHTTPRouteIndex, authenFilterHTTPRouteIndexFunc); err != nil { - return err - } - return nil } -func authenFilterHTTPRouteIndexFunc(rawObj client.Object) []string { - httproute := rawObj.(*gwapiv1.HTTPRoute) - var filters []string - for _, rule := range httproute.Spec.Rules { - for i := range rule.Filters { - filter := rule.Filters[i] - if gatewayapi.IsAuthnHTTPFilter(&filter) { - if err := gatewayapi.ValidateHTTPRouteFilter(&filter); err == nil { - filters = append(filters, - types.NamespacedName{ - Namespace: httproute.Namespace, - Name: string(filter.ExtensionRef.Name), - }.String(), - ) - } - } - } - } - return filters -} - func gatewayHTTPRouteIndexFunc(rawObj client.Object) []string { httproute := rawObj.(*gwapiv1.HTTPRoute) var gateways []string @@ -743,10 +707,6 @@ func addGRPCRouteIndexers(ctx context.Context, mgr manager.Manager) error { return err } - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.GRPCRoute{}, authenFilterGRPCRouteIndex, authenFilterGRPCRouteIndexFunc); err != nil { - return err - } - return nil } @@ -788,27 +748,6 @@ func backendGRPCRouteIndexFunc(rawObj client.Object) []string { return backendRefs } -func authenFilterGRPCRouteIndexFunc(rawObj client.Object) []string { - grpcroute := rawObj.(*gwapiv1a2.GRPCRoute) - var filters []string - for _, rule := range grpcroute.Spec.Rules { - for i := range rule.Filters { - filter := rule.Filters[i] - if gatewayapi.IsAuthnGRPCFilter(&filter) { - if err := gatewayapi.ValidateGRPCRouteFilter(&filter); err == nil { - filters = append(filters, - types.NamespacedName{ - Namespace: grpcroute.Namespace, - Name: string(filter.ExtensionRef.Name), - }.String(), - ) - } - } - } - } - return filters -} - // addTLSRouteIndexers adds indexing on TLSRoute, for Service objects that are // referenced in TLSRoute objects via `.spec.rules.backendRefs`. This helps in // querying for TLSRoutes that are affected by a particular Service CRUD. @@ -1288,6 +1227,36 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { ) r.log.Info("backendTrafficPolicy status subscriber shutting down") }() + + // SecurityPolicy object status updater + go func() { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "securitypolicy-status"}, r.resources.SecurityPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.SecurityPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.SecurityPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.SecurityPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("securityPolicy status subscriber shutting down") + }() } // watchResources watches gateway api resources. @@ -1526,22 +1495,6 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } - // Watch AuthenticationFilter CRUDs and enqueue associated HTTPRoute objects. - afPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.httpRoutesForAuthenticationFilter), - } - if len(r.namespaceLabels) != 0 { - afPredicates = append(afPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) - } - if err := c.Watch( - source.Kind(mgr.GetCache(), &v1alpha1.AuthenticationFilter{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - afPredicates..., - ); err != nil { - return err - } - // Watch EnvoyPatchPolicy if enabled in config eppPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} if len(r.namespaceLabels) != 0 { @@ -1586,6 +1539,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } + // Watch SecurityPolicy + spPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + if len(r.namespaceLabels) != 0 { + spPredicates = append(spPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + } + + if err := c.Watch( + source.Kind(mgr.GetCache(), &v1alpha1.SecurityPolicy{}), + handler.EnqueueRequestsFromMapFunc(r.enqueueClass), + spPredicates..., + ); err != nil { + return err + } + r.log.Info("Watching gatewayAPI related objects") // Watch any additional GVKs from the registered extension. diff --git a/internal/provider/kubernetes/filters.go b/internal/provider/kubernetes/filters.go index bd3266a7040..d526e06d12e 100644 --- a/internal/provider/kubernetes/filters.go +++ b/internal/provider/kubernetes/filters.go @@ -10,38 +10,8 @@ import ( "fmt" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) -func (r *gatewayAPIReconciler) getAuthenticationFilters(ctx context.Context) ([]egv1a1.AuthenticationFilter, error) { - authenList := new(egv1a1.AuthenticationFilterList) - if err := r.client.List(ctx, authenList); err != nil { - return nil, fmt.Errorf("failed to list AuthenticationFilters: %v", err) - } - - authens := authenList.Items - if len(r.namespaceLabels) != 0 { - var as []egv1a1.AuthenticationFilter - for _, a := range authens { - ns := a.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return nil, fmt.Errorf("failed to check namespace labels for AuthenicationFilter %s in namespace %s: %s", a.GetName(), ns, err) - } - - if ok { - as = append(as, a) - } - } - - authens = as - } - - return authens, nil -} - func (r *gatewayAPIReconciler) getExtensionRefFilters(ctx context.Context) ([]unstructured.Unstructured, error) { var resourceItems []unstructured.Unstructured for _, gvk := range r.extGVKs { diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index e15baa505ab..cc3763edc9a 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -73,7 +73,6 @@ func TestProvider(t *testing.T) { "gateway scheduled status": testGatewayScheduledStatus, "httproute": testHTTPRoute, "tlsroute": testTLSRoute, - "authentication filter": testAuthenFilter, "stale service cleanup route deletion": testServiceCleanupForMultipleRoutes, } for name, tc := range testcases { @@ -354,286 +353,6 @@ func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Pro assert.Equal(t, gw.Spec, res.Gateways[0].Spec) } -// Test that even when resources such as the Service/Deployment get hashed names (because of a gateway with a very long name) -func testLongNameHashedResources(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { - cli := provider.manager.GetClient() - - gc := test.GetGatewayClass("envoy-gateway-class", egv1a1.GatewayControllerName) - require.NoError(t, cli.Create(ctx, gc)) - - // Ensure the GatewayClass reports "Ready". - require.Eventually(t, func() bool { - if err := cli.Get(ctx, types.NamespacedName{Name: gc.Name}, gc); err != nil { - return false - } - - for _, cond := range gc.Status.Conditions { - if cond.Type == string(gwapiv1.GatewayClassConditionStatusAccepted) && cond.Status == metav1.ConditionTrue { - return true - } - } - - return false - }, defaultWait, defaultTick) - - defer func() { - require.NoError(t, cli.Delete(ctx, gc)) - }() - - // Create the namespace for the Gateway under test. - ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "envoy-gateway"}} - require.NoError(t, cli.Create(ctx, ns)) - - gw := &gwapiv1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "gatewaywithaverylongnamethatwillresultinhashedresources", - Namespace: ns.Name, - }, - Spec: gwapiv1.GatewaySpec{ - GatewayClassName: gwapiv1.ObjectName(gc.Name), - Listeners: []gwapiv1.Listener{ - { - Name: "test", - Port: gwapiv1.PortNumber(int32(8080)), - Protocol: gwapiv1.HTTPProtocolType, - }, - }, - }, - } - require.NoError(t, cli.Create(ctx, gw)) - - // Ensure the Gateway is ready and gets an address. - ready := false - hasAddress := false - require.Eventually(t, func() bool { - if err := cli.Get(ctx, types.NamespacedName{Namespace: gw.Namespace, Name: gw.Name}, gw); err != nil { - return false - } - - for _, cond := range gw.Status.Conditions { - fmt.Printf("Condition: %v\n", cond) - if cond.Type == string(gwapiv1.GatewayConditionProgrammed) && cond.Status == metav1.ConditionTrue { - ready = true - } - } - - if gw.Status.Addresses != nil { - hasAddress = len(gw.Status.Addresses) >= 1 - } - - return ready && hasAddress - }, defaultWait, defaultTick) - - defer func() { - require.NoError(t, cli.Delete(ctx, gw)) - }() - - // Ensure the gatewayclass has been finalized. - require.Eventually(t, func() bool { - err := cli.Get(ctx, types.NamespacedName{Name: gc.Name}, gc) - return err == nil && slices.Contains(gc.Finalizers, gatewayClassFinalizer) - }, defaultWait, defaultTick) - - // Ensure the number of Gateways in the Gateway resource table is as expected. - require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load("envoy-gateway-class") - return len(res.Gateways) == 1 - }, defaultWait, defaultTick) - - // Ensure the test Gateway in the Gateway resources is as expected. - key := types.NamespacedName{ - Namespace: gw.Namespace, - Name: gw.Name, - } - require.Eventually(t, func() bool { - return cli.Get(ctx, key, gw) == nil - }, defaultWait, defaultTick) - res, _ := resources.GatewayAPIResources.Load("envoy-gateway-class") - // Only check if the spec is equal - // The watchable map will not store a resource - // with an updated status if the spec has not changed - // to eliminate this endless loop: - // reconcile->store->translate->update-status->reconcile - assert.Equal(t, gw.Spec, res.Gateways[0].Spec) -} - -func testAuthenFilter(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { - cli := provider.manager.GetClient() - - gc := test.GetGatewayClass("authen-test", egv1a1.GatewayControllerName) - require.NoError(t, cli.Create(ctx, gc)) - - // Ensure the GatewayClass reports ready. - require.Eventually(t, func() bool { - if err := cli.Get(ctx, types.NamespacedName{Name: gc.Name}, gc); err != nil { - return false - } - - for _, cond := range gc.Status.Conditions { - if cond.Type == string(gwapiv1.GatewayClassConditionStatusAccepted) && cond.Status == metav1.ConditionTrue { - return true - } - } - - return false - }, defaultWait, defaultTick) - - defer func() { - require.NoError(t, cli.Delete(ctx, gc)) - }() - - // Create the namespace for the Gateway under test. - ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "authen-test"}} - require.NoError(t, cli.Create(ctx, ns)) - - gw := &gwapiv1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "authen-test", - Namespace: ns.Name, - }, - Spec: gwapiv1.GatewaySpec{ - GatewayClassName: gwapiv1.ObjectName(gc.Name), - Listeners: []gwapiv1.Listener{ - { - Name: "test", - Port: gwapiv1.PortNumber(int32(8080)), - Protocol: gwapiv1.HTTPProtocolType, - }, - }, - }, - } - require.NoError(t, cli.Create(ctx, gw)) - - defer func() { - require.NoError(t, cli.Delete(ctx, gw)) - }() - - svc := test.GetService(types.NamespacedName{Namespace: ns.Name, Name: "test"}, nil, map[string]int32{ - "http": 80, - "https": 443, - }) - - require.NoError(t, cli.Create(ctx, svc)) - - defer func() { - require.NoError(t, cli.Delete(ctx, svc)) - }() - - authenFilter := test.GetAuthenticationFilter("test-authen", ns.Name) - - require.NoError(t, cli.Create(ctx, authenFilter)) - - defer func() { - require.NoError(t, cli.Delete(ctx, authenFilter)) - }() - - var testCases = []struct { - name string - route gwapiv1.HTTPRoute - }{ - { - name: "authenfilter-httproute", - route: gwapiv1.HTTPRoute{ - ObjectMeta: metav1.ObjectMeta{ - Name: "httproute-authenfilter-test", - Namespace: ns.Name, - }, - Spec: gwapiv1.HTTPRouteSpec{ - CommonRouteSpec: gwapiv1.CommonRouteSpec{ - ParentRefs: []gwapiv1.ParentReference{ - { - Name: gwapiv1.ObjectName(gw.Name), - }, - }, - }, - Hostnames: []gwapiv1.Hostname{"test.hostname.local"}, - Rules: []gwapiv1.HTTPRouteRule{ - { - Matches: []gwapiv1.HTTPRouteMatch{ - { - Path: &gwapiv1.HTTPPathMatch{ - Type: ptr.To(gwapiv1.PathMatchPathPrefix), - Value: ptr.To("/authenfilter/"), - }, - }, - }, - BackendRefs: []gwapiv1.HTTPBackendRef{ - { - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "test", - Port: ptr.To(gwapiv1.PortNumber(80)), - }, - }, - }, - }, - Filters: []gwapiv1.HTTPRouteFilter{ - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindAuthenticationFilter), - Name: gwapiv1.ObjectName(authenFilter.Name), - }, - }, - }, - }, - }, - }, - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - require.NoError(t, cli.Create(ctx, &testCase.route)) - defer func() { - require.NoError(t, cli.Delete(ctx, &testCase.route)) - }() - - require.Eventually(t, func() bool { - return resources.GatewayAPIResources.Len() != 0 - }, defaultWait, defaultTick) - - // Ensure the test HTTPRoute in the HTTPRoute resources is as expected. - key := types.NamespacedName{ - Namespace: testCase.route.Namespace, - Name: testCase.route.Name, - } - require.Eventually(t, func() bool { - return cli.Get(ctx, key, &testCase.route) == nil - }, defaultWait, defaultTick) - - require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("authen-test") - return ok && - len(res.HTTPRoutes) != 0 && - assert.Equal(t, testCase.route.Spec, res.HTTPRoutes[0].Spec) - }, defaultWait, defaultTick) - - // Ensure the AuthenticationFilter is in the resource map. - require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("authen-test") - return ok && - len(res.AuthenticationFilters) != 0 && - assert.Equal(t, authenFilter.Spec, res.AuthenticationFilters[0].Spec) - }, defaultWait, defaultTick) - - // Update the authn filter. - authenFilter.Spec.JwtProviders = append(authenFilter.Spec.JwtProviders, test.GetAuthenticationProvider("test2")) - require.NoError(t, cli.Update(ctx, authenFilter)) - - // Ensure the AuthenticationFilter in the resource map has been updated. - require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("authen-test") - return ok && - len(res.AuthenticationFilters) != 0 && - assert.Equal(t, 2, len(res.AuthenticationFilters[0].Spec.JwtProviders)) - }, defaultWait, defaultTick) - }) - } -} - func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { cli := provider.manager.GetClient() @@ -696,14 +415,6 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour require.NoError(t, cli.Delete(ctx, svc)) }() - authenFilter := test.GetAuthenticationFilter("test-authen", ns.Name) - - require.NoError(t, cli.Create(ctx, authenFilter)) - - defer func() { - require.NoError(t, cli.Delete(ctx, authenFilter)) - }() - redirectHostname := gwapiv1.PreciseHostname("redirect.hostname.local") redirectPort := gwapiv1.PortNumber(8443) redirectStatus := 301 @@ -1645,18 +1356,6 @@ func TestNamespaceSelectorsProvider(t *testing.T) { _, ok := resources.GatewayStatuses.Load(types.NamespacedName{Name: "non-watched-gateway", Namespace: nonWatchedNS.Name}) require.Equal(t, false, ok) - watchedAuthenFilter := test.GetAuthenticationFilter("watched-authen", watchedNS.Name) - require.NoError(t, cli.Create(ctx, watchedAuthenFilter)) - defer func() { - require.NoError(t, cli.Delete(ctx, watchedAuthenFilter)) - }() - - nonWatchedAuthenFilter := test.GetAuthenticationFilter("non-watched-authen", nonWatchedNS.Name) - require.NoError(t, cli.Create(ctx, nonWatchedAuthenFilter)) - defer func() { - require.NoError(t, cli.Delete(ctx, nonWatchedAuthenFilter)) - }() - watchedSvc := test.GetService(types.NamespacedName{Namespace: watchedNS.Name, Name: "watched-service"}, nil, map[string]int32{ "http": 80, "https": 443, @@ -1684,16 +1383,7 @@ func TestNamespaceSelectorsProvider(t *testing.T) { }, watchedGateway.Name, types.NamespacedName{Name: watchedSvc.Name}, 80) - watchedHTTPRoute.Spec.Rules[0].Filters = []gwapiv1.HTTPRouteFilter{ - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: egv1a1.KindAuthenticationFilter, - Name: gwapiv1.ObjectName(watchedAuthenFilter.Name), - }, - }, - } + require.NoError(t, cli.Create(ctx, watchedHTTPRoute)) defer func() { require.NoError(t, cli.Delete(ctx, watchedHTTPRoute)) @@ -1706,16 +1396,6 @@ func TestNamespaceSelectorsProvider(t *testing.T) { }, nonWatchedGateway.Name, types.NamespacedName{Name: nonWatchedSvc.Name}, 8001) - nonWatchedHTTPRoute.Spec.Rules[0].Filters = []gwapiv1.HTTPRouteFilter{ - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: egv1a1.KindAuthenticationFilter, - Name: gwapiv1.ObjectName(nonWatchedAuthenFilter.Name), - }, - }, - } require.NoError(t, cli.Create(ctx, nonWatchedHTTPRoute)) defer func() { require.NoError(t, cli.Delete(ctx, nonWatchedHTTPRoute)) @@ -1848,9 +1528,4 @@ func TestNamespaceSelectorsProvider(t *testing.T) { return res != nil && len(res.GRPCRoutes) == 1 }, defaultWait, defaultTick) - require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) - return res != nil && len(res.AuthenticationFilters) == 1 - }, defaultWait, defaultTick) - } diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index 343ef469d1b..9a98bff1035 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -19,7 +19,6 @@ import ( gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" mcsapi "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/provider/utils" ) @@ -325,54 +324,6 @@ func (r *gatewayAPIReconciler) validateDeploymentForReconcile(obj client.Object) return false } -// httpRoutesForAuthenticationFilter tries finding HTTPRoute referents of the provided -// AuthenticationFilter and returns true if any exist. -func (r *gatewayAPIReconciler) httpRoutesForAuthenticationFilter(obj client.Object) bool { - ctx := context.Background() - filter, ok := obj.(*egv1a1.AuthenticationFilter) - if !ok { - r.log.Info("unexpected object type, bypassing reconciliation", "object", obj) - return false - } - - // Check if the AuthenticationFilter belongs to a managed HTTPRoute. - httpRouteList := &gwapiv1.HTTPRouteList{} - if err := r.client.List(ctx, httpRouteList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(authenFilterHTTPRouteIndex, utils.NamespacedName(filter).String()), - }); err != nil { - r.log.Error(err, "unable to find associated HTTPRoutes") - return false - } - - httpRoutes := r.filterHTTPRoutesByNamespaceLabels(httpRouteList.Items) - - return len(httpRoutes) != 0 -} - -func (r *gatewayAPIReconciler) filterHTTPRoutesByNamespaceLabels(httpRoutes []gwapiv1.HTTPRoute) []gwapiv1.HTTPRoute { - if len(r.namespaceLabels) == 0 { - return httpRoutes - } - - var routes []gwapiv1.HTTPRoute - for _, route := range httpRoutes { - ns := route.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - r.log.Error(err, "failed to check namespace labels for HTTPRoute", - "namespace", ns, - "name", route.GetName(), - ) - continue - } - - if ok { - routes = append(routes, route) - } - } - return routes -} - // envoyDeploymentForGateway returns the Envoy Deployment, returning nil if the Deployment doesn't exist. func (r *gatewayAPIReconciler) envoyDeploymentForGateway(ctx context.Context, gateway *gwapiv1.Gateway) (*appsv1.Deployment, error) { key := types.NamespacedName{ diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index c8876e28166..a85277f9a29 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -17,7 +17,6 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/provider/utils" ) @@ -108,17 +107,6 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { grpcRouteList := &gwapiv1a2.GRPCRouteList{} - // An GRPCRoute may reference an AuthenticationFilter, - // so add them to the resource map first (if they exist). - authenFilters, err := r.getAuthenticationFilters(ctx) - if err != nil { - return err - } - for i := range authenFilters { - filter := authenFilters[i] - resourceMap.authenFilters[utils.NamespacedName(&filter)] = &filter - } - if err := r.client.List(ctx, grpcRouteList, &client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayGRPCRouteIndex, gatewayNamespaceName), }); err != nil { @@ -202,34 +190,23 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam } if filter.Type == gwapiv1a2.GRPCRouteFilterExtensionRef { // NOTE: filters must be in the same namespace as the GRPCRoute - switch string(filter.ExtensionRef.Kind) { - case egv1a1.KindAuthenticationFilter: - key := types.NamespacedName{ - Namespace: grpcRoute.Namespace, - Name: string(filter.ExtensionRef.Name), - } - authFilter, ok := resourceMap.authenFilters[key] - if !ok { - r.log.Error(err, "AuthenticationFilter not found; bypassing rule", "index", i) - continue - } + // Check if it's a Kind managed by an extension and add to resourceTree + key := types.NamespacedName{ + Namespace: grpcRoute.Namespace, + Name: string(filter.ExtensionRef.Name), + } + extRefFilter, ok := resourceMap.extensionRefFilters[key] + if !ok { + r.log.Error( + errors.New("filter not found; bypassing rule"), + "Filter not found; bypassing rule", + "name", + filter.ExtensionRef.Name, "index", i) + continue + } - resourceTree.AuthenticationFilters = append(resourceTree.AuthenticationFilters, authFilter) - default: - // If the Kind does not match any Envoy Gateway resources, check if it's a Kind - // managed by an extension and add to resourceTree - key := types.NamespacedName{ - Namespace: grpcRoute.Namespace, - Name: string(filter.ExtensionRef.Name), - } - extRefFilter, ok := resourceMap.extensionRefFilters[key] - if !ok { - r.log.Error(err, "Filter not found; bypassing rule", "name", filter.ExtensionRef.Name, "index", i) - continue - } + resourceTree.ExtensionRefFilters = append(resourceTree.ExtensionRefFilters, extRefFilter) - resourceTree.ExtensionRefFilters = append(resourceTree.ExtensionRefFilters, extRefFilter) - } } } } @@ -250,17 +227,6 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { httpRouteList := &gwapiv1.HTTPRouteList{} - // An HTTPRoute may reference an AuthenticationFilter, or a filter managed - // by an extension so add them to the resource map first (if they exist). - authenFilters, err := r.getAuthenticationFilters(ctx) - if err != nil { - return err - } - for i := range authenFilters { - filter := authenFilters[i] - resourceMap.authenFilters[utils.NamespacedName(&filter)] = &filter - } - extensionRefFilters, err := r.getExtensionRefFilters(ctx) if err != nil { return err @@ -408,34 +374,22 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam } } else if filter.Type == gwapiv1.HTTPRouteFilterExtensionRef { // NOTE: filters must be in the same namespace as the HTTPRoute - switch string(filter.ExtensionRef.Kind) { - case egv1a1.KindAuthenticationFilter: - key := types.NamespacedName{ - Namespace: httpRoute.Namespace, - Name: string(filter.ExtensionRef.Name), - } - authFilter, ok := resourceMap.authenFilters[key] - if !ok { - r.log.Error(err, "AuthenticationFilter not found; bypassing rule", "index", i) - continue - } - - resourceTree.AuthenticationFilters = append(resourceTree.AuthenticationFilters, authFilter) - default: - // If the Kind does not match any Envoy Gateway resources, check if it's a Kind - // managed by an extension and add to resourceTree - key := types.NamespacedName{ - Namespace: httpRoute.Namespace, - Name: string(filter.ExtensionRef.Name), - } - extRefFilter, ok := resourceMap.extensionRefFilters[key] - if !ok { - r.log.Error(err, "Filter not found; bypassing rule", "name", filter.ExtensionRef.Name, "index", i) - continue - } - - resourceTree.ExtensionRefFilters = append(resourceTree.ExtensionRefFilters, extRefFilter) + // Check if it's a Kind managed by an extension and add to resourceTree + key := types.NamespacedName{ + Namespace: httpRoute.Namespace, + Name: string(filter.ExtensionRef.Name), } + extRefFilter, ok := resourceMap.extensionRefFilters[key] + if !ok { + r.log.Error( + errors.New("filter not found; bypassing rule"), + "Filter not found; bypassing rule", + "name", filter.ExtensionRef.Name, + "index", i) + continue + } + + resourceTree.ExtensionRefFilters = append(resourceTree.ExtensionRefFilters, extRefFilter) } } } diff --git a/internal/provider/kubernetes/routes_test.go b/internal/provider/kubernetes/routes_test.go index 681af679a93..cb126d3f2a1 100644 --- a/internal/provider/kubernetes/routes_test.go +++ b/internal/provider/kubernetes/routes_test.go @@ -63,7 +63,6 @@ func TestProcessHTTPRoutes(t *testing.T) { testCases := []struct { name string routes []*gwapiv1.HTTPRoute - authenFilters []*egv1a1.AuthenticationFilter extensionFilters []*unstructured.Unstructured extensionAPIGroups []schema.GroupVersionKind expected bool @@ -112,85 +111,6 @@ func TestProcessHTTPRoutes(t *testing.T) { }, expected: true, }, - { - name: "httproute with one authenticationfilter", - routes: []*gwapiv1.HTTPRoute{ - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: gwapiv1.HTTPRouteSpec{ - CommonRouteSpec: gwapiv1.CommonRouteSpec{ - ParentRefs: []gwapiv1.ParentReference{ - { - Name: "test", - }, - }, - }, - Rules: []gwapiv1.HTTPRouteRule{ - { - Matches: []gwapiv1.HTTPRouteMatch{ - { - Path: &gwapiv1.HTTPPathMatch{ - Type: ptr.To(gwapiv1.PathMatchPathPrefix), - Value: ptr.To("/"), - }, - }, - }, - Filters: []gwapiv1.HTTPRouteFilter{ - { - Type: gwapiv1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindAuthenticationFilter), - Name: gwapiv1.ObjectName("test"), - }, - }, - }, - BackendRefs: []gwapiv1.HTTPBackendRef{ - { - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Group: gatewayapi.GroupPtr(corev1.GroupName), - Kind: gatewayapi.KindPtr(gatewayapi.KindService), - Name: "test", - }, - }, - }, - }, - }, - }, - }, - }, - }, - authenFilters: []*egv1a1.AuthenticationFilter{ - { - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - }, - expected: true, - }, { name: "httproute with one filter_from_extension", routes: []*gwapiv1.HTTPRoute{ @@ -287,9 +207,6 @@ func TestProcessHTTPRoutes(t *testing.T) { for _, route := range tc.routes { objs = append(objs, route) } - for _, filter := range tc.authenFilters { - objs = append(objs, filter) - } for _, filter := range tc.extensionFilters { objs = append(objs, filter) } @@ -310,16 +227,6 @@ func TestProcessHTTPRoutes(t *testing.T) { require.NoError(t, err) // Ensure the resource tree and map are as expected. require.Equal(t, tc.routes, resourceTree.HTTPRoutes) - // NOTE: filters must be in the same namespace as the HTTPRoute - if tc.authenFilters != nil { - for i, filter := range tc.authenFilters { - key := types.NamespacedName{ - Namespace: tc.routes[i].Namespace, - Name: filter.Name, - } - require.Equal(t, filter, resourceMap.authenFilters[key]) - } - } if tc.extensionFilters != nil { for i, filter := range tc.extensionFilters { key := types.NamespacedName{ @@ -370,7 +277,6 @@ func TestProcessGRPCRoutes(t *testing.T) { testCases := []struct { name string routes []*gwapiv1a2.GRPCRoute - authenFilters []*egv1a1.AuthenticationFilter extensionAPIGroups []schema.GroupVersionKind expected bool }{ @@ -417,84 +323,6 @@ func TestProcessGRPCRoutes(t *testing.T) { }, expected: true, }, - { - name: "grpcroute with one authenticationfilter", - routes: []*gwapiv1a2.GRPCRoute{ - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: gwapiv1a2.GRPCRouteSpec{ - CommonRouteSpec: gwapiv1.CommonRouteSpec{ - ParentRefs: []gwapiv1.ParentReference{ - { - Name: "test", - }, - }, - }, - Rules: []gwapiv1a2.GRPCRouteRule{ - { - Matches: []gwapiv1a2.GRPCRouteMatch{ - { - Method: &gwapiv1a2.GRPCMethodMatch{ - Method: ptr.To("Ping"), - }, - }, - }, - Filters: []gwapiv1a2.GRPCRouteFilter{ - { - Type: gwapiv1a2.GRPCRouteFilterExtensionRef, - ExtensionRef: &gwapiv1.LocalObjectReference{ - Group: gwapiv1.Group(egv1a1.GroupVersion.Group), - Kind: gwapiv1.Kind(egv1a1.KindAuthenticationFilter), - Name: gwapiv1.ObjectName("test"), - }, - }, - }, - BackendRefs: []gwapiv1a2.GRPCBackendRef{ - { - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Group: gatewayapi.GroupPtr(corev1.GroupName), - Kind: gatewayapi.KindPtr(gatewayapi.KindService), - Name: "test", - }, - }, - }, - }, - }, - }, - }, - }, - }, - authenFilters: []*egv1a1.AuthenticationFilter{ - { - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - Name: "test", - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{ - { - Name: "test", - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - }, - }, - }, - }, - }, - expected: true, - }, } for i := range testCases { @@ -518,9 +346,6 @@ func TestProcessGRPCRoutes(t *testing.T) { for _, route := range tc.routes { objs = append(objs, route) } - for _, filter := range tc.authenFilters { - objs = append(objs, filter) - } if len(tc.extensionAPIGroups) > 0 { r.extGVKs = append(r.extGVKs, tc.extensionAPIGroups...) } @@ -538,16 +363,6 @@ func TestProcessGRPCRoutes(t *testing.T) { require.NoError(t, err) // Ensure the resource tree and map are as expected. require.Equal(t, tc.routes, resourceTree.GRPCRoutes) - // NOTE: filters must be in the same namespace as the HTTPRoute - if tc.authenFilters != nil { - for i, filter := range tc.authenFilters { - key := types.NamespacedName{ - Namespace: tc.routes[i].Namespace, - Name: filter.Name, - } - require.Equal(t, filter, resourceMap.authenFilters[key]) - } - } } else { require.Error(t, err) } diff --git a/internal/provider/kubernetes/test/utils.go b/internal/provider/kubernetes/test/utils.go index 94e0e69dc0e..539b2ab594f 100644 --- a/internal/provider/kubernetes/test/utils.go +++ b/internal/provider/kubernetes/test/utils.go @@ -314,55 +314,3 @@ func GetEndpointSlice(nsName types.NamespacedName, svcName string) *discoveryv1. }, } } - -// GetAuthenticationFilter returns a pointer to an AuthenticationFilter with the -// provided ns/name. The AuthenticationFilter uses a JWT provider with dummy issuer, -// audiences, and remoteJWKS settings. -func GetAuthenticationFilter(name, ns string) *egv1a1.AuthenticationFilter { - provider := GetAuthenticationProvider("test") - return &egv1a1.AuthenticationFilter{ - TypeMeta: metav1.TypeMeta{ - Kind: egv1a1.KindAuthenticationFilter, - APIVersion: egv1a1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: ns, - Name: name, - }, - Spec: egv1a1.AuthenticationFilterSpec{ - Type: egv1a1.JwtAuthenticationFilterProviderType, - JwtProviders: []egv1a1.JwtAuthenticationFilterProvider{provider}, - }, - } -} - -// GetAuthenticationProvider returns a JwtAuthenticationFilterProvider using the provided name. -func GetAuthenticationProvider(name string) egv1a1.JwtAuthenticationFilterProvider { - return egv1a1.JwtAuthenticationFilterProvider{ - Name: name, - Issuer: "https://www.test.local", - Audiences: []string{"test.local"}, - RemoteJWKS: egv1a1.RemoteJWKS{ - URI: "https://test.local/jwt/public-key/jwks.json", - }, - } -} - -func ContainsAuthenFilter(hroute *gwapiv1.HTTPRoute) bool { - if hroute == nil { - return false - } - - for _, rule := range hroute.Spec.Rules { - for _, filter := range rule.Filters { - if filter.Type == gwapiv1.HTTPRouteFilterExtensionRef && - filter.ExtensionRef != nil && - string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && - filter.ExtensionRef.Kind == egv1a1.KindAuthenticationFilter { - return true - } - } - } - - return false -} diff --git a/internal/xds/translator/authentication.go b/internal/xds/translator/authentication.go deleted file mode 100644 index 17fd874edd4..00000000000 --- a/internal/xds/translator/authentication.go +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright Envoy Gateway Authors -// SPDX-License-Identifier: Apache-2.0 -// The full text of the Apache license is available in the LICENSE file at -// the root of the repo. - -package translator - -import ( - "errors" - "fmt" - "net" - "net/url" - "strconv" - "strings" - - corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" - jwtauthnv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/jwt_authn/v3" - hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "github.com/envoyproxy/go-control-plane/pkg/resource/v3" - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/envoyproxy/gateway/api/v1alpha1" - "github.com/envoyproxy/gateway/internal/ir" - "github.com/envoyproxy/gateway/internal/utils/ptr" - "github.com/envoyproxy/gateway/internal/xds/types" -) - -// TODO zhaohuabing remove this file after deprecating authentication filter -// patchHCMWithJwtAuthnFilter builds and appends the Jwt Filter to the HTTP -// Connection Manager if applicable, and it does not already exist. -func patchHCMWithJwtAuthnFilter(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error { - if mgr == nil { - return errors.New("hcm is nil") - } - - if irListener == nil { - return errors.New("ir listener is nil") - } - - if !listenerContainsJwtAuthn(irListener) { - return nil - } - - // Return early if filter already exists. - for _, httpFilter := range mgr.HttpFilters { - if httpFilter.Name == jwtAuthnFilter { - return nil - } - } - - jwtFilter, err := buildHCMJwtFilter(irListener) - if err != nil { - return err - } - - // Ensure the authn filter is the first and the terminal filter is the last in the chain. - mgr.HttpFilters = append([]*hcmv3.HttpFilter{jwtFilter}, mgr.HttpFilters...) - - return nil -} - -// buildHCMJwtFilter returns a JWT authn HTTP filter from the provided IR listener. -func buildHCMJwtFilter(irListener *ir.HTTPListener) (*hcmv3.HttpFilter, error) { - jwtAuthnProto, err := buildJwtAuthn(irListener) - if err != nil { - return nil, err - } - - if err := jwtAuthnProto.ValidateAll(); err != nil { - return nil, err - } - - jwtAuthnAny, err := anypb.New(jwtAuthnProto) - if err != nil { - return nil, err - } - - return &hcmv3.HttpFilter{ - Name: jwtAuthnFilter, - ConfigType: &hcmv3.HttpFilter_TypedConfig{ - TypedConfig: jwtAuthnAny, - }, - }, nil -} - -// buildJwtAuthn returns a JwtAuthentication based on the provided IR HTTPListener. -func buildJwtAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, error) { - jwtProviders := make(map[string]*jwtauthnv3.JwtProvider) - reqMap := make(map[string]*jwtauthnv3.JwtRequirement) - - for _, route := range irListener.Routes { - if route != nil && routeContainsJwtAuthn(route) { - var reqs []*jwtauthnv3.JwtRequirement - for i := range route.RequestAuthentication.JWT.Providers { - irProvider := route.RequestAuthentication.JWT.Providers[i] - // Create the cluster for the remote jwks, if it doesn't exist. - jwksCluster, err := newJwksCluster(&irProvider) - if err != nil { - return nil, err - } - - remote := &jwtauthnv3.JwtProvider_RemoteJwks{ - RemoteJwks: &jwtauthnv3.RemoteJwks{ - HttpUri: &corev3.HttpUri{ - Uri: irProvider.RemoteJWKS.URI, - HttpUpstreamType: &corev3.HttpUri_Cluster{ - Cluster: jwksCluster.name, - }, - Timeout: &durationpb.Duration{Seconds: 5}, - }, - CacheDuration: &durationpb.Duration{Seconds: 5 * 60}, - AsyncFetch: &jwtauthnv3.JwksAsyncFetch{}, - RetryPolicy: &corev3.RetryPolicy{}, - }, - } - - claimToHeaders := []*jwtauthnv3.JwtClaimToHeader{} - for _, claimToHeader := range irProvider.ClaimToHeaders { - claimToHeader := &jwtauthnv3.JwtClaimToHeader{HeaderName: claimToHeader.Header, ClaimName: claimToHeader.Claim} - claimToHeaders = append(claimToHeaders, claimToHeader) - } - jwtProvider := &jwtauthnv3.JwtProvider{ - Issuer: irProvider.Issuer, - Audiences: irProvider.Audiences, - JwksSourceSpecifier: remote, - PayloadInMetadata: irProvider.Issuer, - ClaimToHeaders: claimToHeaders, - } - - providerKey := fmt.Sprintf("%s/%s", route.Name, irProvider.Name) - jwtProviders[providerKey] = jwtProvider - reqs = append(reqs, &jwtauthnv3.JwtRequirement{ - RequiresType: &jwtauthnv3.JwtRequirement_ProviderName{ - ProviderName: providerKey, - }, - }) - } - if len(reqs) == 1 { - reqMap[route.Name] = reqs[0] - } else { - orListReqs := &jwtauthnv3.JwtRequirement{ - RequiresType: &jwtauthnv3.JwtRequirement_RequiresAny{ - RequiresAny: &jwtauthnv3.JwtRequirementOrList{ - Requirements: reqs, - }, - }, - } - reqMap[route.Name] = orListReqs - } - } - } - - return &jwtauthnv3.JwtAuthentication{ - RequirementMap: reqMap, - Providers: jwtProviders, - }, nil -} - -// patchRouteWithJwtConfig patches the provided route with a JWT PerRouteConfig, if the -// route doesn't contain it. -func patchRouteWithJwtConfig(route *routev3.Route, irRoute *ir.HTTPRoute) error { - if route == nil { - return errors.New("xds route is nil") - } - if irRoute == nil { - return errors.New("ir route is nil") - } - - filterCfg := route.GetTypedPerFilterConfig() - if _, ok := filterCfg[jwtAuthnFilter]; !ok { - if !routeContainsJwtAuthn(irRoute) { - return nil - } - - routeCfgProto := &jwtauthnv3.PerRouteConfig{ - RequirementSpecifier: &jwtauthnv3.PerRouteConfig_RequirementName{RequirementName: irRoute.Name}} - - routeCfgAny, err := anypb.New(routeCfgProto) - if err != nil { - return err - } - - if filterCfg == nil { - route.TypedPerFilterConfig = make(map[string]*anypb.Any) - } - - route.TypedPerFilterConfig[jwtAuthnFilter] = routeCfgAny - } - - return nil -} - -// createJwksClusters creates JWKS clusters from the provided routes, if needed. -func createJwksClusters(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRoute) error { - if tCtx == nil || - tCtx.XdsResources == nil || - tCtx.XdsResources[resource.ClusterType] == nil || - len(routes) == 0 { - return nil - } - - for _, route := range routes { - if routeContainsJwtAuthn(route) { - for i := range route.RequestAuthentication.JWT.Providers { - provider := route.RequestAuthentication.JWT.Providers[i] - jwks, err := newJwksCluster(&provider) - epType := DefaultEndpointType - if jwks.isStatic { - epType = Static - } - if err != nil { - return err - } - ds := &ir.DestinationSetting{ - Weight: ptr.To(uint32(1)), - Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(jwks.hostname, jwks.port)}, - } - tSocket, err := buildXdsUpstreamTLSSocket() - if err != nil { - return err - } - if err := addXdsCluster(tCtx, &xdsClusterArgs{ - name: jwks.name, - settings: []*ir.DestinationSetting{ds}, - tSocket: tSocket, - protocol: DefaultProtocol, - endpointType: epType, - }); err != nil && !errors.Is(err, ErrXdsClusterExists) { - return err - } - } - } - } - - return nil -} - -// newJwksCluster returns a jwksCluster from the provided provider. -func newJwksCluster(provider *v1alpha1.JwtAuthenticationFilterProvider) (*jwksCluster, error) { - static := false - if provider == nil { - return nil, errors.New("nil provider") - } - - u, err := url.Parse(provider.RemoteJWKS.URI) - if err != nil { - return nil, err - } - - var strPort string - switch u.Scheme { - case "https": - strPort = "443" - default: - return nil, fmt.Errorf("unsupported JWKS URI scheme %s", u.Scheme) - } - - if u.Port() != "" { - strPort = u.Port() - } - - name := fmt.Sprintf("%s_%s", strings.ReplaceAll(u.Hostname(), ".", "_"), strPort) - - port, err := strconv.Atoi(strPort) - if err != nil { - return nil, err - } - - if ip := net.ParseIP(u.Hostname()); ip != nil { - if v4 := ip.To4(); v4 != nil { - static = true - } - } - - return &jwksCluster{ - name: name, - hostname: u.Hostname(), - port: uint32(port), - isStatic: static, - }, nil -} - -// listenerContainsJwtAuthn returns true if JWT authentication exists for the -// provided listener. -func listenerContainsJwtAuthn(irListener *ir.HTTPListener) bool { - if irListener == nil { - return false - } - - for _, route := range irListener.Routes { - if routeContainsJwtAuthn(route) { - return true - } - } - - return false -} - -// routeContainsJwtAuthn returns true if JWT authentication exists for the -// provided route. -func routeContainsJwtAuthn(irRoute *ir.HTTPRoute) bool { - if irRoute == nil { - return false - } - - if irRoute != nil && - irRoute.RequestAuthentication != nil && - irRoute.RequestAuthentication.JWT != nil && - irRoute.RequestAuthentication.JWT.Providers != nil && - len(irRoute.RequestAuthentication.JWT.Providers) > 0 { - return true - } - - return false -} diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index 4aba259b1e5..a9ddb99ad5a 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -100,12 +100,6 @@ func (t *Translator) patchHCMWithFilters( // https://github.com/envoyproxy/gateway/issues/882 t.patchHCMWithRateLimit(mgr, irListener) - // Add the jwt authn filter, if needed. - // TODO zhaohuabing remove this after deprecating authentication filter - if err := patchHCMWithJwtAuthnFilter(mgr, irListener); err != nil { - return err - } - // Add the cors filter, if needed if err := patchHCMWithCORSFilter(mgr, irListener); err != nil { return err @@ -135,11 +129,6 @@ func patchRouteWithFilters( return nil } - // Add the jwt per route config to the route, if needed. // TODO zhaohuabing remove this after deprecating authentication filter - if err := patchRouteWithJwtConfig(route, irRoute); err != nil { - return nil - } - // Add the cors per route config to the route, if needed. if err := patchRouteWithCORSConfig(route, irRoute); err != nil { return err diff --git a/internal/xds/translator/testdata/in/xds-ir/authn-multi-route-multi-provider.yaml b/internal/xds/translator/testdata/in/xds-ir/authn-multi-route-multi-provider.yaml deleted file mode 100644 index 6640b280be1..00000000000 --- a/internal/xds/translator/testdata/in/xds-ir/authn-multi-route-multi-provider.yaml +++ /dev/null @@ -1,70 +0,0 @@ -http: -- name: "first-listener" - address: "0.0.0.0" - port: 10080 - hostnames: - - "*" - routes: - - name: "first-route-www.test.com" - hostname: "*" - pathMatch: - exact: "foo/bar" - requestAuthentication: - jwt: - providers: - - name: example - issuer: https://www.example.com - audiences: - - foo.com - remoteJWKS: - uri: https://localhost/jwt/public-key/jwks.json - claimToHeaders: - - header: one-route-example-key1 - claim: claim.neteased.key - - name: example2 - issuer: https://www.two.example.com - audiences: - - one.foo.com - - two.foo.com - remoteJWKS: - uri: https://192.168.1.250:8080/jwt/public-key/jwks.json - claimToHeaders: - - header: one-route-example2-key1 - claim: claim.neteased.key - - header: one-route-example2-key2 - claim: name - destination: - name: "first-route-www.test.com-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 - - name: "second-route-www.test.com" - hostname: "*" - pathMatch: - exact: "foo/baz" - requestAuthentication: - jwt: - providers: - - name: example - issuer: https://www.example.com - audiences: - - foo.com - remoteJWKS: - uri: https://localhost/jwt/public-key/jwks.json - claimToHeaders: - - header: second-route-example-key1 - claim: claim.neteased.key - - name: example2 - issuer: https://www.two.example.com - audiences: - - one.foo.com - - two.foo.com - remoteJWKS: - uri: https://192.168.1.250:8080/jwt/public-key/jwks.json - destination: - name: "second-route-www.test.com-dest" - settings: - - endpoints: - - host: "5.6.7.8" - port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/authn-multi-route-single-provider.yaml b/internal/xds/translator/testdata/in/xds-ir/authn-multi-route-single-provider.yaml deleted file mode 100644 index fbd1b6784dd..00000000000 --- a/internal/xds/translator/testdata/in/xds-ir/authn-multi-route-single-provider.yaml +++ /dev/null @@ -1,51 +0,0 @@ -accesslog: - text: - - path: "/dev/stdout" -http: -- name: "first-listener" - address: "0.0.0.0" - port: 10080 - hostnames: - - "*" - routes: - - name: "first-route" - hostname: "*" - pathMatch: - exact: "foo/bar" - requestAuthentication: - jwt: - providers: - - name: example - issuer: https://www.example.com - audiences: - - foo.com - remoteJWKS: - uri: https://localhost/jwt/public-key/jwks.json - claimToHeaders: - - header: first-route-key - claim: claim.neteased.key - destination: - name: "first-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 - - name: "second-route" - hostname: "*" - pathMatch: - exact: "foo/baz" - requestAuthentication: - jwt: - providers: - - name: example - issuer: https://www.example.com - audiences: - - foo.com - remoteJWKS: - uri: https://localhost/jwt/public-key/jwks.json - destination: - name: "second-route-dest" - settings: - - endpoints: - - host: "5.6.7.8" - port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/authn-ratelimit.yaml b/internal/xds/translator/testdata/in/xds-ir/authn-ratelimit.yaml deleted file mode 100644 index 75b442cc9a3..00000000000 --- a/internal/xds/translator/testdata/in/xds-ir/authn-ratelimit.yaml +++ /dev/null @@ -1,70 +0,0 @@ -http: -- name: "first-listener" - address: "0.0.0.0" - port: 10080 - hostnames: - - "*" - routes: - - name: "first-route" - hostname: "*" - rateLimit: - global: - rules: - - headerMatches: - - name: "x-user-id" - exact: "one" - limit: - requests: 5 - unit: second - pathMatch: - exact: "foo/bar" - destination: - name: "first-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 - requestAuthentication: - jwt: - providers: - - name: example - issuer: https://www.example.com - audiences: - - foo.com - remoteJWKS: - uri: https://192.168.1.250/jwt/public-key/jwks.json - - name: "second-route" - hostname: "*" - rateLimit: - global: - rules: - - headerMatches: - - name: "x-user-id" - distinct: true - limit: - requests: 5 - unit: second - pathMatch: - exact: "example" - destination: - name: "second-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 - - name: "third-route" - hostname: "*" - rateLimit: - global: - rules: - - limit: - requests: 5 - unit: second - pathMatch: - exact: "test" - destination: - name: "third-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/authn-single-route-single-match.yaml b/internal/xds/translator/testdata/in/xds-ir/authn-single-route-single-match.yaml deleted file mode 100644 index 03cbbb26528..00000000000 --- a/internal/xds/translator/testdata/in/xds-ir/authn-single-route-single-match.yaml +++ /dev/null @@ -1,26 +0,0 @@ -http: -- name: "first-listener" - address: "0.0.0.0" - port: 10080 - hostnames: - - "*" - routes: - - name: "first-route" - hostname: "*" - pathMatch: - exact: "foo/bar" - requestAuthentication: - jwt: - providers: - - name: example - issuer: https://www.example.com - audiences: - - foo.com - remoteJWKS: - uri: https://localhost/jwt/public-key/jwks.json - destination: - name: "first-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-multi-provider.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-multi-route-multi-provider.yaml similarity index 100% rename from internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-multi-provider.yaml rename to internal/xds/translator/testdata/in/xds-ir/jwt-multi-route-multi-provider.yaml diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-single-provider.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-multi-route-single-provider.yaml similarity index 100% rename from internal/xds/translator/testdata/in/xds-ir/jwt-authn-multi-route-single-provider.yaml rename to internal/xds/translator/testdata/in/xds-ir/jwt-multi-route-single-provider.yaml diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-authn-ratelimit.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-ratelimit.yaml similarity index 100% rename from internal/xds/translator/testdata/in/xds-ir/jwt-authn-ratelimit.yaml rename to internal/xds/translator/testdata/in/xds-ir/jwt-ratelimit.yaml diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-authn-single-route-single-match.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-single-route-single-match.yaml similarity index 100% rename from internal/xds/translator/testdata/in/xds-ir/jwt-authn-single-route-single-match.yaml rename to internal/xds/translator/testdata/in/xds-ir/jwt-single-route-single-match.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.clusters.yaml deleted file mode 100755 index bf7f010954b..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.clusters.yaml +++ /dev/null @@ -1,81 +0,0 @@ -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: first-route-www.test.com-dest - lbPolicy: LEAST_REQUEST - name: first-route-www.test.com-dest - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - type: EDS -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: second-route-www.test.com-dest - lbPolicy: LEAST_REQUEST - name: second-route-www.test.com-dest - 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 -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: "192_168_1_250_8080" - lbPolicy: LEAST_REQUEST - name: "192_168_1_250_8080" - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - 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: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.endpoints.yaml deleted file mode 100755 index 7d394e5f496..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.endpoints.yaml +++ /dev/null @@ -1,33 +0,0 @@ -- clusterName: first-route-www.test.com-dest - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 1.2.3.4 - portValue: 50000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} -- clusterName: second-route-www.test.com-dest - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 5.6.7.8 - portValue: 50000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} -- clusterName: "192_168_1_250_8080" - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 192.168.1.250 - portValue: 8080 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.listeners.yaml deleted file mode 100755 index 1eec8005ef8..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.listeners.yaml +++ /dev/null @@ -1,113 +0,0 @@ -- 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.jwt_authn - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication - providers: - first-route-www.test.com/example: - audiences: - - foo.com - claimToHeaders: - - claimName: claim.neteased.key - headerName: one-route-example-key1 - 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: {} - first-route-www.test.com/example2: - audiences: - - one.foo.com - - two.foo.com - claimToHeaders: - - claimName: claim.neteased.key - headerName: one-route-example2-key1 - - claimName: name - headerName: one-route-example2-key2 - issuer: https://www.two.example.com - payloadInMetadata: https://www.two.example.com - remoteJwks: - asyncFetch: {} - cacheDuration: 300s - httpUri: - cluster: "192_168_1_250_8080" - timeout: 5s - uri: https://192.168.1.250:8080/jwt/public-key/jwks.json - retryPolicy: {} - second-route-www.test.com/example: - audiences: - - foo.com - claimToHeaders: - - claimName: claim.neteased.key - headerName: second-route-example-key1 - 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: {} - second-route-www.test.com/example2: - audiences: - - one.foo.com - - two.foo.com - issuer: https://www.two.example.com - payloadInMetadata: https://www.two.example.com - remoteJwks: - asyncFetch: {} - cacheDuration: 300s - httpUri: - cluster: "192_168_1_250_8080" - timeout: 5s - uri: https://192.168.1.250:8080/jwt/public-key/jwks.json - retryPolicy: {} - requirementMap: - first-route-www.test.com: - requiresAny: - requirements: - - providerName: first-route-www.test.com/example - - providerName: first-route-www.test.com/example2 - second-route-www.test.com: - requiresAny: - requirements: - - providerName: second-route-www.test.com/example - - providerName: second-route-www.test.com/example2 - - name: envoy.filters.http.router - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - mergeSlashes: true - normalizePath: true - pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT - rds: - configSource: - ads: {} - resourceApiVersion: V3 - routeConfigName: first-listener - statPrefix: http - upgradeConfigs: - - upgradeType: websocket - useRemoteAddress: true - name: first-listener - perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.routes.yaml deleted file mode 100755 index 630157c4b40..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-multi-provider.routes.yaml +++ /dev/null @@ -1,25 +0,0 @@ -- ignorePortInHostMatching: true - name: first-listener - virtualHosts: - - domains: - - '*' - name: first-listener/* - routes: - - match: - path: foo/bar - name: first-route-www.test.com - route: - cluster: first-route-www.test.com-dest - typedPerFilterConfig: - envoy.filters.http.jwt_authn: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig - requirementName: first-route-www.test.com - - match: - path: foo/baz - name: second-route-www.test.com - route: - cluster: second-route-www.test.com-dest - typedPerFilterConfig: - envoy.filters.http.jwt_authn: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig - requirementName: second-route-www.test.com diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.clusters.yaml deleted file mode 100644 index 35bc85eaf5b..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.clusters.yaml +++ /dev/null @@ -1,59 +0,0 @@ -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: first-route-dest - lbPolicy: LEAST_REQUEST - name: first-route-dest - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - type: EDS -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: second-route-dest - lbPolicy: LEAST_REQUEST - name: second-route-dest - 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/jwt-authn-multi-route-single-provider.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.endpoints.yaml deleted file mode 100644 index b321ca1f8e7..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.endpoints.yaml +++ /dev/null @@ -1,22 +0,0 @@ -- clusterName: first-route-dest - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 1.2.3.4 - portValue: 50000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} -- clusterName: second-route-dest - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 5.6.7.8 - portValue: 50000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.listeners.yaml deleted file mode 100644 index 133530ef79f..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.listeners.yaml +++ /dev/null @@ -1,93 +0,0 @@ -- accessLog: - - filter: - responseFlagFilter: - flags: - - NR - name: envoy.access_loggers.file - typedConfig: - '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - logFormat: - textFormatSource: - inlineString: | - {"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"} - path: /dev/stdout - 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 - accessLog: - - name: envoy.access_loggers.file - typedConfig: - '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - logFormat: - textFormatSource: - inlineString: | - {"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"} - path: /dev/stdout - commonHttpProtocolOptions: - headersWithUnderscoresAction: REJECT_REQUEST - http2ProtocolOptions: - initialConnectionWindowSize: 1048576 - 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 - claimToHeaders: - - claimName: claim.neteased.key - headerName: first-route-key - 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: {} - second-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 - second-route: - providerName: second-route/example - - name: envoy.filters.http.router - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - mergeSlashes: true - normalizePath: true - pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT - rds: - configSource: - ads: {} - resourceApiVersion: V3 - routeConfigName: first-listener - statPrefix: http - upgradeConfigs: - - upgradeType: websocket - useRemoteAddress: true - name: first-listener - perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.routes.yaml deleted file mode 100644 index 2078809a694..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-multi-route-single-provider.routes.yaml +++ /dev/null @@ -1,25 +0,0 @@ -- ignorePortInHostMatching: true - name: first-listener - virtualHosts: - - domains: - - '*' - name: first-listener/* - routes: - - match: - path: foo/bar - 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 - - match: - path: foo/baz - name: second-route - route: - cluster: second-route-dest - typedPerFilterConfig: - envoy.filters.http.jwt_authn: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig - requirementName: second-route diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.clusters.yaml deleted file mode 100644 index 868cdb1b6c2..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.clusters.yaml +++ /dev/null @@ -1,105 +0,0 @@ -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: first-route-dest - lbPolicy: LEAST_REQUEST - name: first-route-dest - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - type: EDS -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: second-route-dest - lbPolicy: LEAST_REQUEST - name: second-route-dest - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - type: EDS -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: third-route-dest - lbPolicy: LEAST_REQUEST - name: third-route-dest - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - type: EDS -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - dnsRefreshRate: 30s - lbPolicy: LEAST_REQUEST - loadAssignment: - clusterName: ratelimit_cluster - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: envoy-ratelimit.envoy-gateway-system.svc.cluster.local - portValue: 8081 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} - name: ratelimit_cluster - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - respectDnsTtl: true - transportSocket: - name: envoy.transport_sockets.tls - typedConfig: - '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - commonTlsContext: - tlsCertificates: - - certificateChain: - filename: /certs/tls.crt - privateKey: - filename: /certs/tls.key - validationContext: - trustedCa: - filename: /certs/ca.crt - type: STRICT_DNS - typedExtensionProtocolOptions: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicitHttpConfig: - http2ProtocolOptions: {} -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: "192_168_1_250_443" - lbPolicy: LEAST_REQUEST - name: "192_168_1_250_443" - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - 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: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.endpoints.yaml deleted file mode 100644 index d8d04b17185..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.endpoints.yaml +++ /dev/null @@ -1,44 +0,0 @@ -- clusterName: first-route-dest - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 1.2.3.4 - portValue: 50000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} -- clusterName: second-route-dest - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 1.2.3.4 - portValue: 50000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} -- clusterName: third-route-dest - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 1.2.3.4 - portValue: 50000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} -- clusterName: "192_168_1_250_443" - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 192.168.1.250 - portValue: 443 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.listeners.yaml deleted file mode 100644 index 8ff2832d64b..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.listeners.yaml +++ /dev/null @@ -1,63 +0,0 @@ -- 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.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: "192_168_1_250_443" - timeout: 5s - uri: https://192.168.1.250/jwt/public-key/jwks.json - retryPolicy: {} - requirementMap: - first-route: - providerName: first-route/example - - name: envoy.filters.http.ratelimit - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit - domain: first-listener - enableXRatelimitHeaders: DRAFT_VERSION_03 - rateLimitService: - grpcService: - envoyGrpc: - clusterName: ratelimit_cluster - transportApiVersion: V3 - - name: envoy.filters.http.router - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - mergeSlashes: true - normalizePath: true - pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT - rds: - configSource: - ads: {} - resourceApiVersion: V3 - routeConfigName: first-listener - statPrefix: http - upgradeConfigs: - - upgradeType: websocket - useRemoteAddress: true - name: first-listener - perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.routes.yaml deleted file mode 100644 index 0223e989d39..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-ratelimit.routes.yaml +++ /dev/null @@ -1,46 +0,0 @@ -- ignorePortInHostMatching: true - name: first-listener - virtualHosts: - - domains: - - '*' - name: first-listener/* - routes: - - match: - path: foo/bar - name: first-route - route: - cluster: first-route-dest - rateLimits: - - actions: - - headerValueMatch: - descriptorKey: first-route-key-rule-0-match-0 - descriptorValue: first-route-value-rule-0-match-0 - expectMatch: true - headers: - - name: x-user-id - stringMatch: - exact: one - typedPerFilterConfig: - envoy.filters.http.jwt_authn: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig - requirementName: first-route - - match: - path: example - name: second-route - route: - cluster: second-route-dest - rateLimits: - - actions: - - requestHeaders: - descriptorKey: second-route-key-rule-0-match-0 - headerName: x-user-id - - match: - path: test - name: third-route - route: - cluster: third-route-dest - rateLimits: - - actions: - - genericKey: - descriptorKey: third-route-key-rule-0-match--1 - descriptorValue: third-route-value-rule-0-match--1 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.clusters.yaml deleted file mode 100644 index 7a0c933174e..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.clusters.yaml +++ /dev/null @@ -1,45 +0,0 @@ -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - edsClusterConfig: - edsConfig: - ads: {} - resourceApiVersion: V3 - serviceName: first-route-dest - lbPolicy: LEAST_REQUEST - name: first-route-dest - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - type: EDS -- 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/jwt-authn-single-route-single-match.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.endpoints.yaml deleted file mode 100644 index 0d68b430c20..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.endpoints.yaml +++ /dev/null @@ -1,11 +0,0 @@ -- clusterName: first-route-dest - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: 1.2.3.4 - portValue: 50000 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.listeners.yaml deleted file mode 100644 index 9a095ee2e29..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.listeners.yaml +++ /dev/null @@ -1,53 +0,0 @@ -- 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.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 - mergeSlashes: true - normalizePath: true - pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT - rds: - configSource: - ads: {} - resourceApiVersion: V3 - routeConfigName: first-listener - statPrefix: http - upgradeConfigs: - - upgradeType: websocket - useRemoteAddress: true - name: first-listener - perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.routes.yaml deleted file mode 100644 index c73bec09093..00000000000 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-authn-single-route-single-match.routes.yaml +++ /dev/null @@ -1,16 +0,0 @@ -- ignorePortInHostMatching: true - name: first-listener - virtualHosts: - - domains: - - '*' - name: first-listener/* - routes: - - match: - path: foo/bar - 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 diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-multi-route-multi-provider.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.clusters.yaml old mode 100644 new mode 100755 similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-multi-route-multi-provider.clusters.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.clusters.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-multi-route-multi-provider.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.endpoints.yaml old mode 100644 new mode 100755 similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-multi-route-multi-provider.endpoints.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.endpoints.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-multi-route-multi-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml old mode 100644 new mode 100755 similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-multi-route-multi-provider.listeners.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-multi-route-multi-provider.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.routes.yaml old mode 100644 new mode 100755 similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-multi-route-multi-provider.routes.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.routes.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-multi-route-single-provider.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.clusters.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-multi-route-single-provider.clusters.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.clusters.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-multi-route-single-provider.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.endpoints.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-multi-route-single-provider.endpoints.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.endpoints.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-multi-route-single-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-multi-route-single-provider.listeners.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-multi-route-single-provider.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.routes.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-multi-route-single-provider.routes.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.routes.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-ratelimit.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.clusters.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-ratelimit.clusters.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.clusters.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-ratelimit.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.endpoints.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-ratelimit.endpoints.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.endpoints.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-ratelimit.listeners.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-ratelimit.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.routes.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-ratelimit.routes.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.routes.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-single-route-single-match.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.clusters.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-single-route-single-match.clusters.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.clusters.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-single-route-single-match.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.endpoints.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-single-route-single-match.endpoints.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.endpoints.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-single-route-single-match.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-single-route-single-match.listeners.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml diff --git a/internal/xds/translator/testdata/out/xds-ir/authn-single-route-single-match.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.routes.yaml similarity index 100% rename from internal/xds/translator/testdata/out/xds-ir/authn-single-route-single-match.routes.yaml rename to internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.routes.yaml diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index e13f8f4cc93..82fd0937aef 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -254,11 +254,6 @@ func (t *Translator) processHTTPListenerXdsTranslation(tCtx *types.ResourceVersi return err } - // Create authn jwks clusters, if needed. // TODO zhaohuabing remove this after deprecating authentication filter - if err := createJwksClusters(tCtx, httpListener.Routes); err != nil { - return err - } - // Create authn jwks clusters, if needed. if err := createJWKSClusters(tCtx, httpListener.Routes); err != nil { return err diff --git a/internal/xds/translator/translator_test.go b/internal/xds/translator/translator_test.go index 6c6fd275397..15fac37f495 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -90,10 +90,6 @@ func TestTranslateXds(t *testing.T) { name: "simple-tls", requireSecrets: true, }, - { - name: "mixed-tls-jwt-authn", - requireSecrets: true, - }, { name: "tls-route-passthrough", }, @@ -151,18 +147,6 @@ func TestTranslateXds(t *testing.T) { { name: "ratelimit-sourceip", }, - { - name: "authn-single-route-single-match", - }, - { - name: "authn-multi-route-single-provider", - }, - { - name: "authn-multi-route-multi-provider", - }, - { - name: "authn-ratelimit", - }, { name: "accesslog", }, @@ -194,16 +178,16 @@ func TestTranslateXds(t *testing.T) { name: "cors", }, { - name: "jwt-authn-multi-route-multi-provider", + name: "jwt-multi-route-multi-provider", }, { - name: "jwt-authn-multi-route-single-provider", + name: "jwt-multi-route-single-provider", }, { - name: "jwt-authn-ratelimit", + name: "jwt-ratelimit", }, { - name: "jwt-authn-single-route-single-match", + name: "jwt-single-route-single-match", }, } diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 310aa30de47..a76e5d3d52d 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -14,7 +14,6 @@ API group. ### Resource Types -- [AuthenticationFilter](#authenticationfilter) - [BackendTrafficPolicy](#backendtrafficpolicy) - [BackendTrafficPolicyList](#backendtrafficpolicylist) - [ClientTrafficPolicy](#clienttrafficpolicy) @@ -28,48 +27,6 @@ API group. -#### AuthenticationFilter - - - - - - - -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `AuthenticationFilter` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `spec` _[AuthenticationFilterSpec](#authenticationfilterspec)_ | Spec defines the desired state of the AuthenticationFilter type. | - - -#### AuthenticationFilterSpec - - - -AuthenticationFilterSpec defines the desired state of the AuthenticationFilter type. - -_Appears in:_ -- [AuthenticationFilter](#authenticationfilter) - -| Field | Description | -| --- | --- | -| `type` _[AuthenticationFilterType](#authenticationfiltertype)_ | Type defines the type of authentication provider to use. Supported provider types are "JWT". | -| `jwtProviders` _[JwtAuthenticationFilterProvider](#jwtauthenticationfilterprovider) array_ | JWT defines the JSON Web Token (JWT) authentication provider type. When multiple jwtProviders are specified, the JWT is considered valid if any of the providers successfully validate the JWT. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. | - - -#### AuthenticationFilterType - -_Underlying type:_ `string` - -AuthenticationFilterType is a type of authentication provider. - -_Appears in:_ -- [AuthenticationFilterSpec](#authenticationfilterspec) - - - #### BackendTrafficPolicy @@ -158,7 +115,6 @@ ClaimToHeader defines a configuration to convert JWT claims into HTTP headers _Appears in:_ - [JWTProvider](#jwtprovider) -- [JwtAuthenticationFilterProvider](#jwtauthenticationfilterprovider) | Field | Description | | --- | --- | @@ -939,24 +895,6 @@ _Appears in:_ | `claimToHeaders` _[ClaimToHeader](#claimtoheader) array_ | ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers For examples, following config: The claim must be of type; string, int, double, bool. Array type claims are not supported | -#### JwtAuthenticationFilterProvider - - - -JwtAuthenticationFilterProvider defines the JSON Web Token (JWT) authentication provider type and how JWTs should be verified: - -_Appears in:_ -- [AuthenticationFilterSpec](#authenticationfilterspec) - -| Field | Description | -| --- | --- | -| `name` _string_ | Name defines a unique name for the JWT provider. A name can have a variety of forms, including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. | -| `issuer` _string_ | Issuer is the principal that issued the JWT and takes the form of a URL or email address. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 for URL format and https://rfc-editor.org/rfc/rfc5322.html for email format. If not provided, the JWT issuer is not checked. | -| `audiences` _string array_ | Audiences is a list of JWT audiences allowed access. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.3. If not provided, JWT audiences are not checked. | -| `remoteJWKS` _[RemoteJWKS](#remotejwks)_ | RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. | -| `claimToHeaders` _[ClaimToHeader](#claimtoheader) array_ | ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers For examples, following config: The claim must be of type; string, int, double, bool. Array type claims are not supported | - - #### KubernetesContainerSpec @@ -1577,7 +1515,6 @@ RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote _Appears in:_ - [JWTProvider](#jwtprovider) -- [JwtAuthenticationFilterProvider](#jwtauthenticationfilterprovider) | Field | Description | | --- | --- | diff --git a/site/content/en/latest/design/rate-limit.md b/site/content/en/latest/design/rate-limit.md index d7ee194e580..d2f68c7e78d 100644 --- a/site/content/en/latest/design/rate-limit.md +++ b/site/content/en/latest/design/rate-limit.md @@ -220,18 +220,22 @@ will be rate limited at 10 requests/hour. ```yaml apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: AuthenticationFilter +kind: SecurityPolicy metadata: name: jwt-example spec: - type: JWT - jwtProviders: - - name: example - remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json - claimToHeaders: - - claim: name - header: custom-request-header + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: eg + jwt: + providers: + - name: example + remoteJWKS: + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + claimToHeaders: + - claim: name + header: custom-request-header --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: RateLimitFilter @@ -266,11 +270,6 @@ spec: port: 3000 weight: 1 filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: jwt-example - type: ExtensionRef - type: ExtensionRef extensionRef: group: gateway.envoyproxy.io diff --git a/site/content/en/latest/design/request-authentication.md b/site/content/en/latest/design/request-authentication.md deleted file mode 100644 index 82682bf2a0b..00000000000 --- a/site/content/en/latest/design/request-authentication.md +++ /dev/null @@ -1,515 +0,0 @@ ---- -title: "Request Authentication Design" ---- - -## Overview - -[Issue 336][] specifies the need for exposing a user-facing API to configure request authentication. Request -authentication is defined as an authentication mechanism to be enforced by Envoy on a per-request basis. A connection -will be rejected if it contains invalid authentication information, based on the `AuthenticationFilter` API type -proposed in this design document. - -Envoy Gateway leverages [Gateway API][] for configuring managed Envoy proxies. Gateway API defines core, extended, and -implementation-specific API [support levels][] for implementers such as Envoy Gateway to expose features. Since -implementing request authentication is not covered by `Core` or `Extended` APIs, an `Implementation-specific` API will -be created for this purpose. - -## Goals - -* Define an API for configuring request authentication. -* Implement [JWT] as the first supported authentication type. -* Allow users that manage routes, e.g. [HTTPRoute][], to authenticate matching requests before forwarding to a backend - service. -* Support HTTPRoutes as an Authentication API referent. HTTPRoute provides multiple [extension points][]. The - [HTTPRouteFilter][] is the extension point supported by the Authentication API. - -## Non-Goals - -* Allow infrastructure administrators to override or establish default authentication policies. -* Support referents other than HTTPRoute. -* Support Gateway API extension points other than HTTPRouteFilter. - -## Use-Cases - -These use-cases are presented as an aid for how users may attempt to utilize the outputs of the design. They are not an -exhaustive list of features for authentication support in Envoy Gateway. - -As a Service Producer, I need the ability to: -* Authenticate a request before forwarding it to a backend service. -* Have different authentication mechanisms per route rule. -* Choose from different authentication mechanisms supported by Envoy, e.g. OIDC. - -### Authentication API Type - -The Authentication API type defines authentication configuration for authenticating requests through managed Envoy -proxies. - -```go -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - -) - -type AuthenticationFilter struct { - metav1.TypeMeta - metav1.ObjectMeta - - // Spec defines the desired state of the Authentication type. - Spec AuthenticationFilterSpec - - // Note: The status sub-resource has been excluded but may be added in the future. -} - -// AuthenticationFilterSpec defines the desired state of the AuthenticationFilter type. -// +union -type AuthenticationFilterSpec struct { - // Type defines the type of authentication provider to use. Supported provider types are: - // - // * JWT: A provider that uses JSON Web Token (JWT) for authenticating requests. - // - // +unionDiscriminator - Type AuthenticationFilterType - - // JWT defines the JSON Web Token (JWT) authentication provider type. When multiple - // jwtProviders are specified, the JWT is considered valid if any of the providers - // successfully validate the JWT. - JwtProviders []JwtAuthenticationFilterProvider -} - -... -``` - -Refer to [PR 773][] for the detailed AuthenticationFilter API spec. - -The status subresource is not included in the AuthenticationFilter API. Status will be surfaced by an HTTPRoute that -references an AuthenticationFilter. For example, an HTTPRoute will surface the `ResolvedRefs=False` status condition if it -references an AuthenticationFilter that does not exist. It may be beneficial to add AuthenticationFilter status fields in the future -based on defined use-cases. For example, a remote [JWKS][] can be validated based on the specified URI and have an -appropriate status condition surfaced. - -#### AuthenticationFilter Example - -The following is an AuthenticationFilter example with one JWT authentication provider: - -```yaml -apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: AuthenticationFilter -metadata: - name: example -spec: - type: JWT - jwtProviders: - - name: example - issuer: https://www.example.com - audiences: - - foo.com - remoteJwks: - uri: https://foo.com/jwt/public-key/jwks.json - -``` - -__Note:__ `type` is a union type, allowing only one of any supported provider type such as `jwtProviders` to be -specified. - -The following is an example HTTPRoute configured to use the above JWT authentication provider: - -```yaml -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: HTTPRoute -metadata: - name: example -spec: - parentRefs: - - name: eg - hostnames: - - www.example.com - rules: - - matches: - - path: - type: PathPrefix - value: /foo - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: example - backendRefs: - - name: backend - port: 3000 -``` - -Requests for `www.example.com/foo` will be authenticated using the referenced JWT provider before being forwarded to the -backend service named "backend". - -## Implementation Details - -The JWT authentication type is translated to an Envoy [JWT authentication filter][] and a cluster is created for each -remote [JWKS][]. The following examples provide additional details on how Gateway API and AuthenticationFilter resources are -translated into Envoy configuration. - -### Example 1: One Route with One JWT Provider - -The following cluster is created from the above HTTPRoute and AuthenticationFilter: - -```yaml -dynamic_clusters: - - name: foo.com|443 - load_assignment: - cluster_name: foo.com|443 - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: foo.com - port_value: 443 - transport_socket: - name: envoy.transport_sockets.tls - typed_config: - "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - sni: foo.com - common_tls_context: - validation_context: - match_subject_alt_names: - - exact: "*.foo.com" - trusted_ca: - filename: /etc/ssl/certs/ca-certificates.crt -``` - -A JWT authentication HTTP filter is added to the HTTP Connection Manager. For example: - -```yaml -dynamic_resources: - dynamic_listeners: - - name: example_listener - address: - socket_address: - address: 1.2.3.4 - port_value: 80 - filter_chains: - - filters: - - name: envoy.http_connection_manager - http_filters: - - name: envoy.filters.http.jwt_authn - typed_config: - "@type": type.googleapis.com/envoy.config.filter.http.jwt_authn.v2alpha.JwtAuthentication -``` - -This JWT authentication HTTP filter contains two fields: -* The `providers` field specifies how a JWT should be verified, such as where to extract the token, where to fetch the - public key ([JWKS][]) and where to output its payload. This field is built from the source resource `namespace-name`, and - the JWT provider name of an AuthenticationFilter. -* The `rules` field specifies matching rules and their requirements. If a request matches a rule, its requirement - applies. The requirement specifies which JWT providers should be used. This field is built from a HTTPRoute - `matches` rule that references the AuthenticationFilter. When a referenced Authentication specifies multiple - `jwtProviders`, the JWT is considered valid if __any__ of the providers successfully validate the JWT. - -The following JWT authentication HTTP filter `providers` configuration is created from the above AuthenticationFilter. - -```yaml -providers: - example: - issuer: https://www.example.com - audiences: - - foo.com - remote_jwks: - http_uri: - uri: https://foo.com/jwt/public-key/jwks.json - cluster: example_jwks_cluster - timeout: 1s -``` - -The following JWT authentication HTTP filter `rules` configuration is created from the above HTTPRoute. - -```yaml -rules: - - match: - prefix: /foo - requires: - provider_name: default-example-example -``` - -### Example 2: Two HTTPRoutes with Different AuthenticationFilters - -The following example contains: -* Two HTTPRoutes with different hostnames. -* Each HTTPRoute references a different AuthenticationFilter. -* Each AuthenticationFilter contains a different JWT provider. - -```yaml -apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: AuthenticationFilter -metadata: - name: example1 -spec: - type: JWT - jwtProviders: - - name: example1 - issuer: https://www.example1.com - audiences: - - foo.com - remoteJwks: - uri: https://foo.com/jwt/public-key/jwks.json ---- -apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: AuthenticationFilter -metadata: - name: example2 -spec: - type: JWT - jwtProviders: - - name: example2 - issuer: https://www.example2.com - audiences: - - bar.com - remoteJwks: - uri: https://bar.com/jwt/public-key/jwks.json ---- -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: HTTPRoute -metadata: - name: example1 -spec: - hostnames: - - www.example1.com - parentRefs: - - group: gateway.networking.k8s.io - kind: Gateway - name: eg - rules: - - matches: - - path: - type: PathPrefix - value: /foo - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: example1 - backendRefs: - - name: backend - port: 3000 ---- -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: HTTPRoute -metadata: - name: example2 -spec: - hostnames: - - www.example2.com - parentRefs: - - group: gateway.networking.k8s.io - kind: Gateway - name: eg - rules: - - matches: - - path: - type: PathPrefix - value: /bar - filters: - - type: ExtensionRef - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: example2 - backendRefs: - - name: backend2 - port: 3000 -``` - -The following xDS configuration is created from the above example resources: - -```yaml -configs: -... -dynamic_listeners: - - name: default-eg-http - ... - default_filter_chain: - filters: - - name: envoy.filters.network.http_connection_manager - typed_config: - '@type': >- - type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - stat_prefix: http - rds: - config_source: - ... - route_config_name: default-eg-http - http_filters: - - name: envoy.filters.http.jwt_authn - typed_config: - '@type': >- - type.googleapis.com/envoy.config.filter.http.jwt_authn.v2alpha.JwtAuthentication - providers: - default-example1-example1: - issuer: https://www.example1.com - audiences: - - foo.com - remote_jwks: - http_uri: - uri: https://foo.com/jwt/public-key/jwks.json - cluster: default-example1-example1-jwt - default-example2-example2: - issuer: https://www.example2.com - audiences: - - bar.com - remote_jwks: - http_uri: - uri: https://bar.com/jwt/public-key/jwks.json - cluster: default-example2-example2-jwt - rules: - - match: - exact: /foo - requires: - provider_name: default-example1-example1 - - match: - exact: /bar - requires: - provider_name: default-example2-example2 - - name: envoy.filters.http.router - typed_config: - '@type': >- - type.googleapis.com/envoy.extensions.filters.http.router.v3.Router -dynamic_route_configs: - - route_config: - '@type': type.googleapis.com/envoy.config.route.v3.RouteConfiguration - name: default-eg-http - virtual_hosts: - - name: default-eg-http - domains: - - '*' - routes: - - match: - prefix: /foo - headers: - - name: ':authority' - string_match: - exact: www.example1.com - route: - cluster: default-backend-rule-0-match-0-www.example1.com - - match: - prefix: /bar - headers: - - name: ':authority' - string_match: - exact: www.example2.com - route: - cluster: default-backend2-rule-0-match-0-www.example2.com -dynamic_active_clusters: - - cluster: - name: default-backend-rule-0-match-0-www.example.com - ... - endpoints: - - locality: {} - lb_endpoints: - - endpoint: - address: - socket_address: - address: $BACKEND_SERVICE1_IP - port_value: 3000 - - cluster: - '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster - name: default-backend-rule-1-match-0-www.example.com - ... - endpoints: - - locality: {} - lb_endpoints: - - endpoint: - address: - socket_address: - address: $BACKEND_SERVICE2_IP - port_value: 3000 -... -``` - -__Note:__ The JWT provider cluster and route is omitted from the above example for brevity. - -### Implementation Outline - -* Update the Kubernetes provider to get/watch AuthenticationFilter resources that are referenced by managed HTTPRoutes. - Add the referenced AuthenticationFilter object to the resource map and publish it. -* Update the resource translator to include the AuthenticationFilter API in HTTPRoute processing. -* Update the xDS translator to translate an AuthenticationFilter into xDS resources. The translator should perform the - following: - * Convert a list of JWT rules from the xds IR into an Envoy JWT filter config. - * Create a JWT authentication HTTP filter. - * Build the HTTP Connection Manager (HCM) HTTP filters. - * Build the HCM. - * When building the Listener, create an HCM for each filter-chain. - -## Adding Authentication Types - -Additional authentication types can be added in the future through the `AuthenticationFilterType` API. For -example, to add the `Foo` authentication type: - -Define the `Foo` authentication provider: - -```go -package v1alpha1 - -// FooAuthenticationFilterProvider defines the "Foo" authentication filter provider type. -type FooAuthenticationFilterProvider struct { - // TODO: Define fields of the Foo authentication filter provider type. -} -``` - -Add the `FooAuthenticationFilterProvider` type to `AuthenticationFilterSpec`: - -```go -package v1alpha1 - -type AuthenticationFilterSpec struct { - ... - - // Foo defines the Foo authentication type. For additional - // details, see: - // - // - // - // +optional - Foo *FooAuthenticationFilterProvider -} -``` - -Lastly, add the type to the `AuthenticationType` enum: - -```go -// AuthenticationType is a type of authentication provider. -// +kubebuilder:validation:Enum=JWT,FOO -type AuthenticationFilterType string - -const ( - // JwtAuthenticationProviderType is the JWT authentication provider type. - FooAuthenticationFilterProviderType AuthenticationFilterType = "FOO" -) -``` - -The AuthenticationFilter API should support additional authentication types in the future, for example: -- OAuth2 -- OIDC - -## Outstanding Questions - -- If Envoy Gateway owns the AuthenticationFilter API, is an xDS IR equivalent needed? -- Should local [JWKS][] be implemented before remote [JWKS][]? -- How should Envoy obtain the trusted CA for a remote [JWKS][]? -- Should HTTPS be the only supported scheme for remote [JWKS][]? -- Should OR'ing JWT providers be supported? -- Should Authentication provide status? -- Are the API field validation rules acceptable? - -[Issue 336]: https://github.com/envoyproxy/gateway/issues/336 -[Gateway API]: https://gateway-api.sigs.k8s.io/ -[support levels]: https://gateway-api.sigs.k8s.io/concepts/conformance/?h=extended#2-support-levels -[JWT]: https://jwt.io/ -[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute/ -[extension points]: https://gateway-api.sigs.k8s.io/concepts/api-overview/?h=extension#extension-points -[HTTPRouteFilter]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilter -[JWKS]: https://www.rfc-editor.org/rfc/rfc7517 -[JWT authentication filter]: https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter#config-http-filters-jwt-authn -[PR 773]: https://github.com/envoyproxy/gateway/pull/733 diff --git a/site/content/en/latest/user/authn.md b/site/content/en/latest/user/jwt-authentication.md similarity index 67% rename from site/content/en/latest/user/authn.md rename to site/content/en/latest/user/jwt-authentication.md index 18409cb5dee..239bca9b88c 100644 --- a/site/content/en/latest/user/authn.md +++ b/site/content/en/latest/user/jwt-authentication.md @@ -1,12 +1,15 @@ --- -title: "Request Authentication" +title: "JWT Authentication" --- This guide provides instructions for configuring [JSON Web Token (JWT)][jwt] authentication. JWT authentication checks if an incoming request has a valid JWT before routing the request to a backend service. Currently, Envoy Gateway only supports validating a JWT from an HTTP header, e.g. `Authorization: Bearer `. -## Installation +Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure JWT authentication. +This instantiated resource can be linked to a [Gateway][Gateway], [HTTPRoute][HTTPRoute] or [GRPCRoute][GRPCRoute] resource. + +## Prerequisites Follow the steps from the [Quickstart](quickstart.md) guide to install Envoy Gateway and the example manifest. For GRPC - follow the steps from the [GRPC Routing](grpc-routing.md) example. @@ -14,39 +17,42 @@ Before proceeding, you should be able to query the example backend using HTTP or ## Configuration -Allow requests with a valid JWT by creating an [AuthenticationFilter][] and referencing it from the example HTTPRoute or GRPCRoute. +Allow requests with a valid JWT by creating an [SecurityPolicy][SecurityPolicy] and attaching it to the example +HTTPRoute or GRPCRoute. ### HTTPRoute ```shell -kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/authn/jwt.yaml +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/jwt/jwt.yaml ``` -The HTTPRoute is now updated to authenticate requests for `/foo` and allow unauthenticated requests to `/bar`. The -`/foo` route rule references an AuthenticationFilter that provides the JWT authentication configuration. +Two HTTPRoute has been created, one for `/foo` and another for `/bar`. A SecurityPolicy has been created and targeted +HTTPRoute foo to authenticate requests for `/foo`. The HTTPRoute bar is not targeted by the SecurityPolicy and will allow +unauthenticated requests to `/bar`. Verify the HTTPRoute configuration and status: ```shell -kubectl get httproute/backend -o yaml +kubectl get httproute/foo -o yaml +kubectl get httproute/bar -o yaml ``` -The AuthenticationFilter is configured for JWT authentication and uses a single [JSON Web Key Set (JWKS)][jwks] +The SecurityPolicy is configured for JWT authentication and uses a single [JSON Web Key Set (JWKS)][jwks] provider for authenticating the JWT. -Verify the AuthenticationFilter configuration: +Verify the SecurityPolicy configuration: ```shell -kubectl get authenticationfilter/jwt-example -o yaml +kubectl get securitypolicy/jwt-example -o yaml ``` ### GRPCRoute ```shell -kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/authn/grtpc-jwt.yaml +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/jwt/grtpc-jwt.yaml ``` -The GRPCRoute is now updated to authenticate all requests to `yages` service, by referencing an AuthenticationFilter that provides the JWT authentication configuration. +A SecurityPolicy has been created and targeted GRPCRoute yages to authenticate all requests for `yages` service.. Verify the GRPCRoute configuration and status: @@ -54,13 +60,13 @@ Verify the GRPCRoute configuration and status: kubectl get grpcroute/yages -o yaml ``` -The AuthenticationFilter is configured for JWT authentication and uses a single [JSON Web Key Set (JWKS)][jwks] +The SecurityPolicy is configured for JWT authentication and uses a single [JSON Web Key Set (JWKS)][jwks] provider for authenticating the JWT. -Verify the AuthenticationFilter configuration: +Verify the SecurityPolicy configuration: ```shell -kubectl get authenticationfilter/jwt-example -o yaml +kubectl get securitypolicy/jwt-example -o yaml ``` ## Testing @@ -146,16 +152,19 @@ You should see the below response Follow the steps from the [Quickstart](quickstart.md) guide to uninstall Envoy Gateway and the example manifest. -Delete the AuthenticationFilter: +Delete the SecurityPolicy: ```shell -kubectl delete authenticationfilter/jwt-example +kubectl delete securitypolicy/jwt-example ``` ## Next Steps Checkout the [Developer Guide](../../contributions/develop/) to get involved in the project. +[SecurityPolicy]: https://gateway.envoyproxy.io/latest/design/security-policy [jwt]: https://tools.ietf.org/html/rfc7519 -[AuthenticationFilter]: https://gateway.envoyproxy.io/latest/api/extension_types.html#authenticationfilter [jwks]: https://tools.ietf.org/html/rfc7517 +[Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway +[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute +[GRPCRoute]: https://gateway-api.sigs.k8s.io/api-types/grpcroute diff --git a/test/e2e/testdata/ratelimit-based-jwt-claims.yaml b/test/e2e/testdata/ratelimit-based-jwt-claims.yaml index 9a2f1342120..edfcb8ad6aa 100644 --- a/test/e2e/testdata/ratelimit-based-jwt-claims.yaml +++ b/test/e2e/testdata/ratelimit-based-jwt-claims.yaml @@ -1,17 +1,22 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: AuthenticationFilter +kind: SecurityPolicy metadata: name: jwt-example namespace: gateway-conformance-infra spec: - type: JWT - jwtProviders: - - name: example - remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json - claimToHeaders: - - claim: name - header: x-claim-name + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: http-ratelimit-based-jwt-claims + namespace: gateway-conformance-infra + jwt: + providers: + - name: example + remoteJWKS: + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + claimToHeaders: + - claim: name + header: x-claim-name --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy @@ -48,16 +53,20 @@ spec: - backendRefs: - name: infra-backend-v1 port: 8080 - filters: - - extensionRef: - group: gateway.envoyproxy.io - kind: AuthenticationFilter - name: jwt-example - type: ExtensionRef matches: - path: type: PathPrefix value: /foo +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-no-ratelimit + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: - backendRefs: - name: infra-backend-v1 port: 8080 diff --git a/tools/crd-ref-docs/config.yaml b/tools/crd-ref-docs/config.yaml index 89963f55d8f..cd95e3d8d4a 100644 --- a/tools/crd-ref-docs/config.yaml +++ b/tools/crd-ref-docs/config.yaml @@ -1,7 +1,7 @@ processor: # RE2 regular expressions describing types that should be excluded from the generated documentation. ignoreTypes: - - "(EnvoyProxy|AuthenticationFilter)List$" + - "(EnvoyProxy)List$" # RE2 regular expressions describing type fields that should be excluded from the generated documentation. ignoreFields: - "status$" From ef7a2a49a32e3329c79a711f4052a57d2a96919a Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Fri, 27 Oct 2023 16:26:21 -0700 Subject: [PATCH 12/55] Skip RateLimitBasedJwtClaimsTest test (#2096) Relates to https://github.com/envoyproxy/gateway/issues/2095 Signed-off-by: Arko Dasgupta --- test/e2e/e2e_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 1c6d5b22f92..0c7db9c2e65 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -41,9 +41,12 @@ func TestE2E(t *testing.T) { *flags.GatewayClassName, *flags.CleanupBaseResources, *flags.ShowDebug, *flags.SupportedFeatures, *flags.ExemptFeatures) cSuite := suite.New(suite.Options{ - Client: client, - GatewayClassName: *flags.GatewayClassName, - Debug: *flags.ShowDebug, + Client: client, + GatewayClassName: *flags.GatewayClassName, + Debug: *flags.ShowDebug, + SkipTests: []string{ + tests.RateLimitBasedJwtClaimsTest.ShortName, + }, CleanupBaseResources: *flags.CleanupBaseResources, FS: &Manifests, }) From 1ebace9dec42177a53457163efa69bd50bce2261 Mon Sep 17 00:00:00 2001 From: Alice Wasko Date: Fri, 27 Oct 2023 17:02:53 -0700 Subject: [PATCH 13/55] add more crd (mostly CEL) validation (#2087) * add more crd validation Signed-off-by: Alice Wasko * remove sectionName CEL validation until it is supported Signed-off-by: Alice Wasko * add cel to forbid sectionName until it is supported Signed-off-by: Alice Wasko --------- Signed-off-by: Alice Wasko Signed-off-by: Arko Dasgupta Co-authored-by: Arko Dasgupta --- api/v1alpha1/backendtrafficpolicy_types.go | 6 +- api/v1alpha1/clienttrafficpolicy_types.go | 4 + api/v1alpha1/securitypolicy_types.go | 4 + ....envoyproxy.io_backendtrafficpolicies.yaml | 9 +- ...y.envoyproxy.io_clienttrafficpolicies.yaml | 7 + ...ateway.envoyproxy.io_securitypolicies.yaml | 7 + .../backendtrafficpolicy_test.go | 186 ++++++++++++++++++ .../clienttrafficpolicy_test.go | 170 ++++++++++++++++ test/cel-validation/securitypolicy_test.go | 171 ++++++++++++++++ 9 files changed, 558 insertions(+), 6 deletions(-) create mode 100644 test/cel-validation/backendtrafficpolicy_test.go create mode 100644 test/cel-validation/clienttrafficpolicy_test.go create mode 100644 test/cel-validation/securitypolicy_test.go diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go index 44fa5688715..65a71e90e60 100644 --- a/api/v1alpha1/backendtrafficpolicy_types.go +++ b/api/v1alpha1/backendtrafficpolicy_types.go @@ -18,7 +18,6 @@ const ( // +kubebuilder:object:root=true // +kubebuilder:resource:shortName=btp // +kubebuilder:subresource:status -// +kubebuilder:subresource:overrideStrategy // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` // @@ -37,8 +36,9 @@ type BackendTrafficPolicy struct { // spec defines the desired state of BackendTrafficPolicy. type BackendTrafficPolicySpec struct { - - // +kubebuilder:validation:XValidation:rule="self.kind == 'Gateway' || self.kind == 'HTTPRoute' || self.kind == 'GRPCRoute' || self.kind == 'UDPRoute' || self.kind == 'TCPRoute' || self.kind == 'TLSRoute'", message="this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute" + // +kubebuilder:validation:XValidation:rule="self.group == 'gateway.networking.k8s.io'", message="this policy can only have a targetRef.group of gateway.networking.k8s.io" + // +kubebuilder:validation:XValidation:rule="self.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'UDPRoute', 'TCPRoute', 'TLSRoute']", message="this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute" + // +kubebuilder:validation:XValidation:rule="!has(self.sectionName)",message="this policy does not yet support the sectionName field" // // targetRef is the name of the resource this policy // is being attached to. diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 4e8cdd29a51..43907dba96a 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -37,6 +37,10 @@ type ClientTrafficPolicy struct { // ClientTrafficPolicySpec defines the desired state of ClientTrafficPolicy. type ClientTrafficPolicySpec struct { + // +kubebuilder:validation:XValidation:rule="self.group == 'gateway.networking.k8s.io'", message="this policy can only have a targetRef.group of gateway.networking.k8s.io" + // +kubebuilder:validation:XValidation:rule="self.kind == 'Gateway'", message="this policy can only have a targetRef.kind of Gateway" + // +kubebuilder:validation:XValidation:rule="!has(self.sectionName)",message="this policy does not yet support the sectionName field" + // // TargetRef is the name of the Gateway resource this policy // is being attached to. // This Policy and the TargetRef MUST be in the same namespace diff --git a/api/v1alpha1/securitypolicy_types.go b/api/v1alpha1/securitypolicy_types.go index 7adece4cbca..21cac85398d 100644 --- a/api/v1alpha1/securitypolicy_types.go +++ b/api/v1alpha1/securitypolicy_types.go @@ -36,6 +36,10 @@ type SecurityPolicy struct { // SecurityPolicySpec defines the desired state of SecurityPolicy. type SecurityPolicySpec struct { + // +kubebuilder:validation:XValidation:rule="self.group == 'gateway.networking.k8s.io'", message="this policy can only have a targetRef.group of gateway.networking.k8s.io" + // +kubebuilder:validation:XValidation:rule="self.kind == 'Gateway'", message="this policy can only have a targetRef.kind of Gateway" + // +kubebuilder:validation:XValidation:rule="!has(self.sectionName)",message="this policy does not yet support the sectionName field" + // // TargetRef is the name of the Gateway resource this policy // is being attached to. // This Policy and the TargetRef MUST be in the same namespace diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 8a8e2283ddb..be8c6c3d760 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -264,10 +264,13 @@ spec: - name type: object x-kubernetes-validations: + - message: this policy can only have a targetRef.group of gateway.networking.k8s.io + rule: self.group == 'gateway.networking.k8s.io' - message: this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute - rule: self.kind == 'Gateway' || self.kind == 'HTTPRoute' || self.kind - == 'GRPCRoute' || self.kind == 'UDPRoute' || self.kind == 'TCPRoute' - || self.kind == 'TLSRoute' + rule: self.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'UDPRoute', + 'TCPRoute', 'TLSRoute'] + - message: this policy does not yet support the sectionName field + rule: '!has(self.sectionName)' required: - targetRef type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index c34aba25627..7e0edba928f 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -93,6 +93,13 @@ spec: - kind - name type: object + x-kubernetes-validations: + - message: this policy can only have a targetRef.group of gateway.networking.k8s.io + rule: self.group == 'gateway.networking.k8s.io' + - message: this policy can only have a targetRef.kind of Gateway + rule: self.kind == 'Gateway' + - message: this policy does not yet support the sectionName field + rule: '!has(self.sectionName)' tcpKeepalive: description: TcpKeepalive settings associated with the downstream client connection. If defined, sets SO_KEEPALIVE on the listener diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 2c7c91aa529..544e8dbe867 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -235,6 +235,13 @@ spec: - kind - name type: object + x-kubernetes-validations: + - message: this policy can only have a targetRef.group of gateway.networking.k8s.io + rule: self.group == 'gateway.networking.k8s.io' + - message: this policy can only have a targetRef.kind of Gateway + rule: self.kind == 'Gateway' + - message: this policy does not yet support the sectionName field + rule: '!has(self.sectionName)' required: - targetRef type: object diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go new file mode 100644 index 00000000000..b49870c0dc7 --- /dev/null +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -0,0 +1,186 @@ +// 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 celvalidation +// +build celvalidation + +package celvalidation + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +func TestBackendTrafficPolicyTarget(t *testing.T) { + ctx := context.Background() + baseBTP := egv1a1.BackendTrafficPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "btp", + Namespace: metav1.NamespaceDefault, + }, + Spec: egv1a1.BackendTrafficPolicySpec{}, + } + + sectionName := gwapiv1a2.SectionName("foo") + + cases := []struct { + desc string + mutate func(btp *egv1a1.BackendTrafficPolicy) + mutateStatus func(btp *egv1a1.BackendTrafficPolicy) + wantErrors []string + }{ + { + desc: "valid gateway targetRef", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "valid httproute targetRef", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("HTTPRoute"), + Name: gwapiv1a2.ObjectName("httpbin-route"), + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "no targetRef", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{} + }, + wantErrors: []string{ + "spec.targetRef.kind: Invalid value: \"\": spec.targetRef.kind in body should be at least 1 chars long", + "spec.targetRef.name: Invalid value: \"\": spec.targetRef.name in body should be at least 1 chars long", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute", + }, + }, + { + desc: "targetRef unsupported kind", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("foo"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute", + }, + }, + { + desc: "targetRef unsupported group", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("foo"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + }, + }, + { + desc: "targetRef unsupported group and kind", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("foo"), + Kind: gwapiv1a2.Kind("bar"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute", + }, + }, + { + desc: "sectionName disabled until supported", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + SectionName: §ionName, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy does not yet support the sectionName field", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + btp := baseBTP.DeepCopy() + btp.Name = fmt.Sprintf("btp-%v", time.Now().UnixNano()) + + if tc.mutate != nil { + tc.mutate(btp) + } + err := c.Create(ctx, btp) + + if tc.mutateStatus != nil { + tc.mutateStatus(btp) + err = c.Status().Update(ctx, btp) + } + + if (len(tc.wantErrors) != 0) != (err != nil) { + t.Fatalf("Unexpected response while creating BackendTrafficPolicy; got err=\n%v\n;want error=%v", err, tc.wantErrors) + } + + var missingErrorStrings []string + for _, wantError := range tc.wantErrors { + if !strings.Contains(strings.ToLower(err.Error()), strings.ToLower(wantError)) { + missingErrorStrings = append(missingErrorStrings, wantError) + } + } + if len(missingErrorStrings) != 0 { + t.Errorf("Unexpected response while creating BackendTrafficPolicy; got err=\n%v\n;missing strings within error=%q", err, missingErrorStrings) + } + }) + } +} diff --git a/test/cel-validation/clienttrafficpolicy_test.go b/test/cel-validation/clienttrafficpolicy_test.go new file mode 100644 index 00000000000..b0449b78f51 --- /dev/null +++ b/test/cel-validation/clienttrafficpolicy_test.go @@ -0,0 +1,170 @@ +// 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 celvalidation +// +build celvalidation + +package celvalidation + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +func TestClientTrafficPolicyTarget(t *testing.T) { + ctx := context.Background() + baseCTP := egv1a1.ClientTrafficPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ctp", + Namespace: metav1.NamespaceDefault, + }, + Spec: egv1a1.ClientTrafficPolicySpec{}, + } + + sectionName := gwapiv1a2.SectionName("foo") + + cases := []struct { + desc string + mutate func(ctp *egv1a1.ClientTrafficPolicy) + mutateStatus func(ctp *egv1a1.ClientTrafficPolicy) + wantErrors []string + }{ + { + desc: "valid targetRef", + mutate: func(ctp *egv1a1.ClientTrafficPolicy) { + ctp.Spec = egv1a1.ClientTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "no targetRef", + mutate: func(ctp *egv1a1.ClientTrafficPolicy) { + ctp.Spec = egv1a1.ClientTrafficPolicySpec{} + }, + wantErrors: []string{ + "spec.targetRef.kind: Invalid value: \"\": spec.targetRef.kind in body should be at least 1 chars long", + "spec.targetRef.name: Invalid value: \"\": spec.targetRef.name in body should be at least 1 chars long", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway", + }, + }, + { + desc: "targetRef unsupported kind", + mutate: func(ctp *egv1a1.ClientTrafficPolicy) { + ctp.Spec = egv1a1.ClientTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("foo"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway", + }, + }, + { + desc: "targetRef unsupported group", + mutate: func(ctp *egv1a1.ClientTrafficPolicy) { + ctp.Spec = egv1a1.ClientTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("foo"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + }, + }, + { + desc: "targetRef unsupported group and kind", + mutate: func(ctp *egv1a1.ClientTrafficPolicy) { + ctp.Spec = egv1a1.ClientTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("foo"), + Kind: gwapiv1a2.Kind("bar"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway", + }, + }, + { + desc: "sectionName disabled until supported", + mutate: func(ctp *egv1a1.ClientTrafficPolicy) { + ctp.Spec = egv1a1.ClientTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + }, + SectionName: §ionName, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy does not yet support the sectionName field", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + ctp := baseCTP.DeepCopy() + ctp.Name = fmt.Sprintf("ctp-%v", time.Now().UnixNano()) + + if tc.mutate != nil { + tc.mutate(ctp) + } + err := c.Create(ctx, ctp) + + if tc.mutateStatus != nil { + tc.mutateStatus(ctp) + err = c.Status().Update(ctx, ctp) + } + + if (len(tc.wantErrors) != 0) != (err != nil) { + t.Fatalf("Unexpected response while creating ClientTrafficPolicy; got err=\n%v\n;want error=%v", err, tc.wantErrors) + } + + var missingErrorStrings []string + for _, wantError := range tc.wantErrors { + if !strings.Contains(strings.ToLower(err.Error()), strings.ToLower(wantError)) { + missingErrorStrings = append(missingErrorStrings, wantError) + } + } + if len(missingErrorStrings) != 0 { + t.Errorf("Unexpected response while creating ClientTrafficPolicy; got err=\n%v\n;missing strings within error=%q", err, missingErrorStrings) + } + }) + } +} diff --git a/test/cel-validation/securitypolicy_test.go b/test/cel-validation/securitypolicy_test.go new file mode 100644 index 00000000000..7b634f2f1e5 --- /dev/null +++ b/test/cel-validation/securitypolicy_test.go @@ -0,0 +1,171 @@ +// 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 celvalidation +// +build celvalidation + +package celvalidation + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +func TestSecurityPolicyTarget(t *testing.T) { + ctx := context.Background() + baseSP := egv1a1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sp", + Namespace: metav1.NamespaceDefault, + }, + Spec: egv1a1.SecurityPolicySpec{}, + } + + sectionName := gwapiv1a2.SectionName("foo") + + cases := []struct { + desc string + mutate func(sp *egv1a1.SecurityPolicy) + mutateStatus func(sp *egv1a1.SecurityPolicy) + wantErrors []string + }{ + { + desc: "valid targetRef", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "no targetRef", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{} + }, + wantErrors: []string{ + "spec.targetRef.kind: Invalid value: \"\": spec.targetRef.kind in body should be at least 1 chars long", + "spec.targetRef.name: Invalid value: \"\": spec.targetRef.name in body should be at least 1 chars long", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway", + }, + }, + { + desc: "targetRef unsupported kind", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("foo"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway", + }, + }, + { + desc: "targetRef unsupported group", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("foo"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + }, + }, + { + desc: "targetRef unsupported group and kind", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("foo"), + Kind: gwapiv1a2.Kind("bar"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.group of gateway.networking.k8s.io", + "spec.targetRef: Invalid value: \"object\": this policy can only have a targetRef.kind of Gateway", + }, + }, + { + desc: "sectionName disabled until supported", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + SectionName: §ionName, + }, + } + }, + wantErrors: []string{ + "spec.targetRef: Invalid value: \"object\": this policy does not yet support the sectionName field", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + sp := baseSP.DeepCopy() + sp.Name = fmt.Sprintf("sp-%v", time.Now().UnixNano()) + + if tc.mutate != nil { + tc.mutate(sp) + } + err := c.Create(ctx, sp) + + if tc.mutateStatus != nil { + tc.mutateStatus(sp) + err = c.Status().Update(ctx, sp) + } + + if (len(tc.wantErrors) != 0) != (err != nil) { + t.Fatalf("Unexpected response while creating SecurityPolicy; got err=\n%v\n;want error=%v", err, tc.wantErrors) + } + + var missingErrorStrings []string + for _, wantError := range tc.wantErrors { + if !strings.Contains(strings.ToLower(err.Error()), strings.ToLower(wantError)) { + missingErrorStrings = append(missingErrorStrings, wantError) + } + } + if len(missingErrorStrings) != 0 { + t.Errorf("Unexpected response while creating SecurityPolicy; got err=\n%v\n;missing strings within error=%q", err, missingErrorStrings) + } + }) + } +} From 4cb4547aeea4e3f1517907159d7312ea3c735843 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Fri, 27 Oct 2023 17:24:20 -0700 Subject: [PATCH 14/55] Update version and release notes for v0.6.0-rc.1 (#2094) Signed-off-by: Arko Dasgupta Signed-off-by: Arko Dasgupta --- VERSION | 2 +- release-notes/v0.6.0-rc.1.yaml | 72 ++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 release-notes/v0.6.0-rc.1.yaml diff --git a/VERSION b/VERSION index b043aa648f5..01b366027cd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.5.0 +v0.6.0-rc.1 diff --git a/release-notes/v0.6.0-rc.1.yaml b/release-notes/v0.6.0-rc.1.yaml new file mode 100644 index 00000000000..6e7809c6bb0 --- /dev/null +++ b/release-notes/v0.6.0-rc.1.yaml @@ -0,0 +1,72 @@ +date: Oct 27, 2023 + +changes: + - area: documentation + change: | + Introduced a new website based on Hugo + Added Grafana dashboards and integration docs for EnvoyProxy metrics + Added Grafana integration docs for Gateway API metrics + + - area: installation + change: | + Added Support for configuring Envoy Gateway Label and Annotations using Helm + Increased default Resource defaults for Envoy Gateway to 100m CPU and 256Mi Memory + Fixes Helm values for EnvoyGateway startup configuration + Added opt-in field to skip creating control plane TLS Certificates allowing users to bring their own certificates. + + - area: api + change: | + Upgraded to Gateway API v1.0.0 + Added the ClientTrafficPolicy CRD with Keep Alive Support + Added the BackendTrafficPolicy CRD with RateLimit and LoadBalancer Support + Added the SecurityPolicy CRD with CORS and JWT Support + Added EnvoyGateway Metrics with Prometheus and OpenTelemetry support + Added Support for InitContainers in EnvoyProxy CRD + Added Support for LoadBalancerIP in EnvoyProxy CRD + Added Support for AllocateLoadBalancerNodePorts in EnvoyProxy CRD + Added Support for LoadBalancerClass in EnvoyProxy CRD + Added Support for selecting EnvoyProxy stats to be generated + Added Support for enabling EnvoyProxy Virtual Host metrics + Added Support for Merging Gateway resources onto the same infrastructure + + breaking-change: | + Removed the AuthenticationFilter CRD + Removed the RateLimitFilter CRD + Enabled EnvoyProxy Prometheus Endpoint by default with an option to disable it + Updated the Bootstrap field within the EnvoyProxy CRD with an additional value + field to specify bootstrap config + + - area: ci-tooling-testing + change: | + + - area: conformance + change: | + + - area: watchable + change: | + Improved caching of resource by implementing a compare function agnostic of resource order + + - area: translator + breaking-change: | + Added support for routing to EndpointSlice endpoints + Added support for HTTPRoute Timeouts + Added support for multiple RequestMirror filters per HTTPRoute rule + Use / instead of - in IR Route Names + Added Support to ignore ports in Host header + + - area: providers + change: | + Added the generationChangedPredicate to most resources to limit resource reconiliation + Improved reconiliation by using the same enqueue request for all resources + Added support for reconciling ServiceImport CRD + Added support for selectively watching resources based on Namespace Selector + + - area: xds + change: | + Fixed Layered Runtime warnings + Upgraded to the latest version of go-control-plane that fixed xDS Resource ordering issues for ADS. + Added HTTP2 Keep Alives to the xds connection + + - area: cli + change: | + Added Support for egctl stats command From f3015279d39635a49af081867696b6b8eb41bc09 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Sat, 28 Oct 2023 10:44:01 +0800 Subject: [PATCH 15/55] Fix TestE2E/RateLimitBasedJwtClaims test (#2097) * Revert "Skip RateLimitBasedJwtClaimsTest test (#2096)" This reverts commit ef7a2a49a32e3329c79a711f4052a57d2a96919a. fix e2e test Signed-off-by: huabing zhao * fix XValidation Signed-off-by: huabing zhao --------- Signed-off-by: huabing zhao --- api/v1alpha1/securitypolicy_types.go | 2 +- .../gateway.envoyproxy.io_securitypolicies.yaml | 4 ++-- examples/kubernetes/jwt/grpc-jwt.yaml | 2 +- examples/kubernetes/jwt/jwt.yaml | 2 +- .../in/jwt-single-route-single-match-to-xds.yaml | 2 +- .../out/jwt-single-route-single-match-to-xds.all.json | 2 +- .../out/jwt-single-route-single-match-to-xds.all.yaml | 2 +- .../jwt-single-route-single-match-to-xds.listener.yaml | 2 +- site/content/en/latest/design/rate-limit.md | 2 +- site/content/en/latest/design/security-policy.md | 2 +- site/content/en/latest/user/rate-limit.md | 2 +- site/content/en/v0.5.0/design/rate-limit.md | 2 +- site/content/en/v0.5.0/user/rate-limit.md | 2 +- test/e2e/e2e_test.go | 9 +++------ test/e2e/testdata/ratelimit-based-jwt-claims.yaml | 2 +- 15 files changed, 18 insertions(+), 21 deletions(-) diff --git a/api/v1alpha1/securitypolicy_types.go b/api/v1alpha1/securitypolicy_types.go index 21cac85398d..e5c60882003 100644 --- a/api/v1alpha1/securitypolicy_types.go +++ b/api/v1alpha1/securitypolicy_types.go @@ -37,7 +37,7 @@ type SecurityPolicy struct { // SecurityPolicySpec defines the desired state of SecurityPolicy. type SecurityPolicySpec struct { // +kubebuilder:validation:XValidation:rule="self.group == 'gateway.networking.k8s.io'", message="this policy can only have a targetRef.group of gateway.networking.k8s.io" - // +kubebuilder:validation:XValidation:rule="self.kind == 'Gateway'", message="this policy can only have a targetRef.kind of Gateway" + // +kubebuilder:validation:XValidation:rule="self.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute']", message="this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute" // +kubebuilder:validation:XValidation:rule="!has(self.sectionName)",message="this policy does not yet support the sectionName field" // // TargetRef is the name of the Gateway resource this policy diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 544e8dbe867..7fefb8b9d77 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -238,8 +238,8 @@ spec: x-kubernetes-validations: - message: this policy can only have a targetRef.group of gateway.networking.k8s.io rule: self.group == 'gateway.networking.k8s.io' - - message: this policy can only have a targetRef.kind of Gateway - rule: self.kind == 'Gateway' + - message: this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute + rule: self.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute'] - message: this policy does not yet support the sectionName field rule: '!has(self.sectionName)' required: diff --git a/examples/kubernetes/jwt/grpc-jwt.yaml b/examples/kubernetes/jwt/grpc-jwt.yaml index a5da840eb66..c992f524fe8 100644 --- a/examples/kubernetes/jwt/grpc-jwt.yaml +++ b/examples/kubernetes/jwt/grpc-jwt.yaml @@ -11,7 +11,7 @@ spec: providers: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json --- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GRPCRoute diff --git a/examples/kubernetes/jwt/jwt.yaml b/examples/kubernetes/jwt/jwt.yaml index dcf580edde9..46381b13a2f 100644 --- a/examples/kubernetes/jwt/jwt.yaml +++ b/examples/kubernetes/jwt/jwt.yaml @@ -11,7 +11,7 @@ spec: providers: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute diff --git a/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml b/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml index 2b41c1a3eb4..14efe586c4e 100644 --- a/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml +++ b/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml @@ -83,7 +83,7 @@ spec: providers: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json index 6b6655a7989..9adf09f0e52 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json @@ -397,7 +397,7 @@ "httpUri": { "cluster": "raw_githubusercontent_com_443", "timeout": "5s", - "uri": "https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json" + "uri": "https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json" }, "retryPolicy": {} } diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml index 165e110d67b..1eb76aa4ce6 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml @@ -238,7 +238,7 @@ xds: httpUri: cluster: raw_githubusercontent_com_443 timeout: 5s - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json retryPolicy: {} requirementMap: httproute/envoy-gateway-system/backend/rule/0/match/0/www_example_com: diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml index 38158d8d227..273ca89e7c7 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml @@ -54,7 +54,7 @@ xds: httpUri: cluster: raw_githubusercontent_com_443 timeout: 5s - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json retryPolicy: {} requirementMap: httproute/envoy-gateway-system/backend/rule/0/match/0/www_example_com: diff --git a/site/content/en/latest/design/rate-limit.md b/site/content/en/latest/design/rate-limit.md index d2f68c7e78d..e35d44c8239 100644 --- a/site/content/en/latest/design/rate-limit.md +++ b/site/content/en/latest/design/rate-limit.md @@ -232,7 +232,7 @@ spec: providers: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json claimToHeaders: - claim: name header: custom-request-header diff --git a/site/content/en/latest/design/security-policy.md b/site/content/en/latest/design/security-policy.md index 89508d5727f..b7413b92ad0 100644 --- a/site/content/en/latest/design/security-policy.md +++ b/site/content/en/latest/design/security-policy.md @@ -73,7 +73,7 @@ spec: providers: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/site/content/en/latest/user/rate-limit.md b/site/content/en/latest/user/rate-limit.md index c27eefaf90a..e8a38ac7740 100644 --- a/site/content/en/latest/user/rate-limit.md +++ b/site/content/en/latest/user/rate-limit.md @@ -607,7 +607,7 @@ spec: jwtProviders: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json claimToHeaders: - claim: name header: x-claim-name diff --git a/site/content/en/v0.5.0/design/rate-limit.md b/site/content/en/v0.5.0/design/rate-limit.md index 28ebbab8b36..5a8288a79d1 100644 --- a/site/content/en/v0.5.0/design/rate-limit.md +++ b/site/content/en/v0.5.0/design/rate-limit.md @@ -228,7 +228,7 @@ spec: jwtProviders: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json claimToHeaders: - claim: name header: custom-request-header diff --git a/site/content/en/v0.5.0/user/rate-limit.md b/site/content/en/v0.5.0/user/rate-limit.md index 3c780c730a6..2bb1169daf6 100644 --- a/site/content/en/v0.5.0/user/rate-limit.md +++ b/site/content/en/v0.5.0/user/rate-limit.md @@ -590,7 +590,7 @@ spec: jwtProviders: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json claimToHeaders: - claim: name header: x-claim-name diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 0c7db9c2e65..1c6d5b22f92 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -41,12 +41,9 @@ func TestE2E(t *testing.T) { *flags.GatewayClassName, *flags.CleanupBaseResources, *flags.ShowDebug, *flags.SupportedFeatures, *flags.ExemptFeatures) cSuite := suite.New(suite.Options{ - Client: client, - GatewayClassName: *flags.GatewayClassName, - Debug: *flags.ShowDebug, - SkipTests: []string{ - tests.RateLimitBasedJwtClaimsTest.ShortName, - }, + Client: client, + GatewayClassName: *flags.GatewayClassName, + Debug: *flags.ShowDebug, CleanupBaseResources: *flags.CleanupBaseResources, FS: &Manifests, }) diff --git a/test/e2e/testdata/ratelimit-based-jwt-claims.yaml b/test/e2e/testdata/ratelimit-based-jwt-claims.yaml index edfcb8ad6aa..d16e9c1ebdb 100644 --- a/test/e2e/testdata/ratelimit-based-jwt-claims.yaml +++ b/test/e2e/testdata/ratelimit-based-jwt-claims.yaml @@ -13,7 +13,7 @@ spec: providers: - name: example remoteJWKS: - uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/jwks.json + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json claimToHeaders: - claim: name header: x-claim-name From fae8cd8da2879c717fc225fc31ce092a9a216454 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Sat, 28 Oct 2023 03:04:17 -0700 Subject: [PATCH 16/55] add a newer PR reference in rc release docs (#2101) Signed-off-by: Arko Dasgupta --- site/content/en/latest/contributions/RELEASING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/content/en/latest/contributions/RELEASING.md b/site/content/en/latest/contributions/RELEASING.md index f5ec7954f27..f81d5be457d 100644 --- a/site/content/en/latest/contributions/RELEASING.md +++ b/site/content/en/latest/contributions/RELEASING.md @@ -44,7 +44,7 @@ export GITHUB_REMOTE=origin git push ${GITHUB_REMOTE} release/v${MAJOR_VERSION}.${MINOR_VERSION} ``` -7. Create a topic branch for updating the Envoy proxy image to the tag supported by the release. Reference [PR #958][] +7. Create a topic branch for updating the Envoy proxy image and Envoy Ratelimit image to the tag supported by the release. Reference [PR #2098][] for additional details on updating the image tag. 8. Sign, commit, and push your changes to your fork. 9. Submit a [Pull Request][] to merge the changes into the `release/v${MAJOR_VERSION}.${MINOR_VERSION}` branch. Do not @@ -247,6 +247,6 @@ It's important that the world knows about the release. Use the following steps t [release]: https://github.com/envoyproxy/gateway/releases [Generate]: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes [PR #635]: https://github.com/envoyproxy/gateway/pull/635 -[PR #958]: https://github.com/envoyproxy/gateway/pull/958 +[PR #2098]: https://github.com/envoyproxy/gateway/pull/2098 [PR #1002]: https://github.com/envoyproxy/gateway/pull/1002 [VERSION]: https://github.com/envoyproxy/gateway/blob/main/VERSION From 77445dec77f1dbf64e343f0dd2d7537b6c9b7eb3 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Sat, 28 Oct 2023 23:57:59 +0800 Subject: [PATCH 17/55] fix: panic when using nil xdsRouteAction (#2104) Signed-off-by: bitliu --- internal/xds/translator/ratelimit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/xds/translator/ratelimit.go b/internal/xds/translator/ratelimit.go index 36d5c4aa020..6a347904079 100644 --- a/internal/xds/translator/ratelimit.go +++ b/internal/xds/translator/ratelimit.go @@ -128,7 +128,7 @@ func (t *Translator) buildRateLimitFilter(irListener *ir.HTTPListener) *hcmv3.Ht // patchRouteWithRateLimit builds rate limit actions and appends to the route. func patchRouteWithRateLimit(xdsRouteAction *routev3.RouteAction, irRoute *ir.HTTPRoute) error { //nolint:unparam // Return early if no rate limit config exists. - if irRoute.RateLimit == nil || irRoute.RateLimit.Global == nil { + if irRoute.RateLimit == nil || irRoute.RateLimit.Global == nil || xdsRouteAction == nil { return nil } From d65ab597196bba840c9ec87dca2676d6b0502a77 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Sat, 28 Oct 2023 23:51:37 -0700 Subject: [PATCH 18/55] remove cors, jwt, rl assignment from route translator (#2105) All the translations and assignments now happen in the policy translators Signed-off-by: Arko Dasgupta --- internal/gatewayapi/route.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 90814694d50..4edc6cce86c 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -554,9 +554,6 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route DirectResponse: routeRoute.DirectResponse, URLRewrite: routeRoute.URLRewrite, Mirrors: routeRoute.Mirrors, - RateLimit: routeRoute.RateLimit, - CORS: routeRoute.CORS, - JWT: routeRoute.JWT, Timeout: routeRoute.Timeout, ExtensionRefs: routeRoute.ExtensionRefs, } From ef5e450d3e7590d1b41869194fc2b395f26c0491 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Mon, 30 Oct 2023 23:24:11 +0800 Subject: [PATCH 19/55] fix: use lowercases of eg admin config fields (#2107) --- api/v1alpha1/envoygateway_types.go | 4 ++-- site/content/en/latest/api/extension_types.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v1alpha1/envoygateway_types.go b/api/v1alpha1/envoygateway_types.go index bfbf4101e50..88357b12e6b 100644 --- a/api/v1alpha1/envoygateway_types.go +++ b/api/v1alpha1/envoygateway_types.go @@ -445,11 +445,11 @@ type EnvoyGatewayAdmin struct { // EnableDumpConfig defines if enable dump config in Envoy Gateway logs. // // +optional - EnableDumpConfig bool + EnableDumpConfig bool `json:"enableDumpConfig,omitempty"` // EnablePprof defines if enable pprof in Envoy Gateway Admin Server. // // +optional - EnablePprof bool + EnablePprof bool `json:"enablePprof,omitempty"` } // EnvoyGatewayAdminAddress defines the Envoy Gateway Admin Address configuration. diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index a76e5d3d52d..881d1e6b594 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -275,8 +275,8 @@ _Appears in:_ | Field | Description | | --- | --- | | `address` _[EnvoyGatewayAdminAddress](#envoygatewayadminaddress)_ | Address defines the address of Envoy Gateway Admin Server. | -| `EnableDumpConfig` _boolean_ | EnableDumpConfig defines if enable dump config in Envoy Gateway logs. | -| `EnablePprof` _boolean_ | EnablePprof defines if enable pprof in Envoy Gateway Admin Server. | +| `enableDumpConfig` _boolean_ | EnableDumpConfig defines if enable dump config in Envoy Gateway logs. | +| `enablePprof` _boolean_ | EnablePprof defines if enable pprof in Envoy Gateway Admin Server. | #### EnvoyGatewayAdminAddress From 40472687d2806183b0d443fa793705d06c6a037d Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Mon, 30 Oct 2023 23:25:19 +0800 Subject: [PATCH 20/55] fix: testGatewayClassWithParamRef e2e test flaky (#2114) --- internal/provider/kubernetes/kubernetes_test.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index cc3763edc9a..4eab96cd5a1 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -196,9 +196,19 @@ func testGatewayClassWithParamRef(ctx context.Context, t *testing.T, provider *P }, defaultWait, defaultTick) // Ensure the resource map contains the EnvoyProxy. - res, ok := resources.GatewayAPIResources.Load(gc.Name) - assert.Equal(t, ok, true) - assert.Equal(t, res.EnvoyProxy.Spec, ep.Spec) + require.Eventually(t, func() bool { + res, ok := resources.GatewayAPIResources.Load(gc.Name) + if !ok { + return false + } + + if res.EnvoyProxy != nil { + assert.Equal(t, res.EnvoyProxy.Spec, ep.Spec) + return true + } + + return false + }, defaultWait, defaultTick) } func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { From bf93a4eb4b7565c3a7a5e4a69b9d0f11bd751a8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 08:28:21 -0700 Subject: [PATCH 21/55] build(deps): bump sigs.k8s.io/yaml from 1.3.0 to 1.4.0 (#2118) Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.3.0 to 1.4.0. - [Release notes](https://github.com/kubernetes-sigs/yaml/releases) - [Changelog](https://github.com/kubernetes-sigs/yaml/blob/master/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/yaml/compare/v1.3.0...v1.4.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/yaml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 061b2188694..b08b8852929 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 sigs.k8s.io/controller-runtime v0.16.3 sigs.k8s.io/gateway-api v1.0.0-rc2 - sigs.k8s.io/yaml v1.3.0 + sigs.k8s.io/yaml v1.4.0 ) require ( diff --git a/go.sum b/go.sum index 9c0770ae263..e1f0b86a1b5 100644 --- a/go.sum +++ b/go.sum @@ -227,6 +227,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -780,5 +781,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kF sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From 58146ff83c6c6e3df5496e879d9abdc06d9cb270 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 08:29:25 -0700 Subject: [PATCH 22/55] build(deps): bump github.com/bufbuild/buf from 1.27.1 to 1.27.2 in /tools/src/buf (#2121) build(deps): bump github.com/bufbuild/buf in /tools/src/buf Bumps [github.com/bufbuild/buf](https://github.com/bufbuild/buf) from 1.27.1 to 1.27.2. - [Release notes](https://github.com/bufbuild/buf/releases) - [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md) - [Commits](https://github.com/bufbuild/buf/compare/v1.27.1...v1.27.2) --- updated-dependencies: - dependency-name: github.com/bufbuild/buf dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/src/buf/go.mod | 4 ++-- tools/src/buf/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/src/buf/go.mod b/tools/src/buf/go.mod index ecf3c7def3b..ca67bfa9ce6 100644 --- a/tools/src/buf/go.mod +++ b/tools/src/buf/go.mod @@ -2,7 +2,7 @@ module local go 1.19 -require github.com/bufbuild/buf v1.27.1 +require github.com/bufbuild/buf v1.27.2 require ( connectrpc.com/connect v1.11.1 // indirect @@ -29,7 +29,7 @@ require ( github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jdx/go-netrc v1.0.0 // indirect - github.com/klauspost/compress v1.17.1 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/term v0.5.0 // indirect diff --git a/tools/src/buf/go.sum b/tools/src/buf/go.sum index 8344ecbf3af..bcec058a5b3 100644 --- a/tools/src/buf/go.sum +++ b/tools/src/buf/go.sum @@ -6,8 +6,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25 github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/bufbuild/buf v1.27.1 h1:r8nmR+QLdpzgMr/F6+ua0awewMKGVf3uHsW0/UoUeME= -github.com/bufbuild/buf v1.27.1/go.mod h1:BTXcNcZU8rvEZv2MdmVGpEyNgrXQ2UYO9u8H8yLmOdM= +github.com/bufbuild/buf v1.27.2 h1:uX2kvZfPfRoOsrxUW4LwpykSyH+wI5dUnIG0QWHDCCU= +github.com/bufbuild/buf v1.27.2/go.mod h1:7RImDhFDqhEsdK5wbuMhoVSlnrMggGGcd3s9WozvHtM= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -67,8 +67,8 @@ github.com/jdx/go-netrc v1.0.0/go.mod h1:Gh9eFQJnoTNIRHXl2j5bJXA1u84hQWJWgGh569z github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g= -github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= From d1cbf5e5d78f5c09f380eadabeaef50e146deaf6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 08:30:00 -0700 Subject: [PATCH 23/55] build(deps): bump github.com/go-logr/logr from 1.2.4 to 1.3.0 (#2117) Bumps [github.com/go-logr/logr](https://github.com/go-logr/logr) from 1.2.4 to 1.3.0. - [Release notes](https://github.com/go-logr/logr/releases) - [Changelog](https://github.com/go-logr/logr/blob/master/CHANGELOG.md) - [Commits](https://github.com/go-logr/logr/compare/v1.2.4...v1.3.0) --- updated-dependencies: - dependency-name: github.com/go-logr/logr dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index b08b8852929..04b55416d37 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 github.com/evanphx/json-patch/v5 v5.7.0 github.com/go-logfmt/logfmt v0.6.0 - github.com/go-logr/logr v1.2.4 + github.com/go-logr/logr v1.3.0 github.com/go-logr/zapr v1.2.4 github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.5.3 diff --git a/go.sum b/go.sum index e1f0b86a1b5..cfe9c2fb0c9 100644 --- a/go.sum +++ b/go.sum @@ -128,8 +128,9 @@ github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= From 7b6344d72a03f3d1052b58ae99be25d948ad834e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 08:30:37 -0700 Subject: [PATCH 24/55] build(deps): bump envoyproxy/toolshed from actions-v0.0.25 to 0.1.2 (#2116) Bumps [envoyproxy/toolshed](https://github.com/envoyproxy/toolshed) from actions-v0.0.25 to 0.1.2. This release includes the previously tagged commit. - [Release notes](https://github.com/envoyproxy/toolshed/releases) - [Commits](https://github.com/envoyproxy/toolshed/compare/actions-v0.0.25...actions-v0.1.2) --- updated-dependencies: - dependency-name: envoyproxy/toolshed dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/retest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/retest.yaml b/.github/workflows/retest.yaml index aab16fa3ad1..4acd9584681 100644 --- a/.github/workflows/retest.yaml +++ b/.github/workflows/retest.yaml @@ -22,6 +22,6 @@ jobs: pull-requests: write actions: write steps: - - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.0.25 + - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.1.2 with: token: ${{ secrets.GITHUB_TOKEN }} From 55230996de631ae42ef6593d18633137ef1a36b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 08:31:15 -0700 Subject: [PATCH 25/55] build(deps): bump actions/setup-node from 3 to 4 (#2115) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 8466d940cc0..0c8e82b2a58 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -44,7 +44,7 @@ jobs: extended: true - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '18' From 268a6ef1318dcd6b1249170f00e216d80f5f6c2e Mon Sep 17 00:00:00 2001 From: zirain Date: Mon, 30 Oct 2023 11:14:06 -0500 Subject: [PATCH 26/55] chore: add more EnvoyProxy cases (#2120) Signed-off-by: zirain --- test/cel-validation/envoyproxy_test.go | 36 +++++++++++++++++++------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/test/cel-validation/envoyproxy_test.go b/test/cel-validation/envoyproxy_test.go index 99912faff16..1d029655f7c 100644 --- a/test/cel-validation/envoyproxy_test.go +++ b/test/cel-validation/envoyproxy_test.go @@ -122,7 +122,7 @@ func TestEnvoyProxyProvider(t *testing.T) { wantErrors: []string{"allocateLoadBalancerNodePorts can only be set for LoadBalancer type"}, }, { - desc: "loadBalancerIP-pass-case1", + desc: "ServiceTypeLoadBalancer-with-valid-IP", mutate: func(envoy *egv1a1.EnvoyProxy) { envoy.Spec = egv1a1.EnvoyProxySpec{ Provider: &egv1a1.EnvoyProxyProvider{ @@ -139,14 +139,14 @@ func TestEnvoyProxyProvider(t *testing.T) { wantErrors: []string{}, }, { - desc: "loadBalancerIP-pass-case2", + desc: "ServiceTypeLoadBalancer-with-empty-IP", mutate: func(envoy *egv1a1.EnvoyProxy) { envoy.Spec = egv1a1.EnvoyProxySpec{ Provider: &egv1a1.EnvoyProxyProvider{ Type: egv1a1.ProviderTypeKubernetes, Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ EnvoyService: &egv1a1.KubernetesServiceSpec{ - Type: ptr.To(egv1a1.ServiceTypeClusterIP), + Type: ptr.To(egv1a1.ServiceTypeLoadBalancer), }, }, }, @@ -155,38 +155,54 @@ func TestEnvoyProxyProvider(t *testing.T) { wantErrors: []string{}, }, { - desc: "loadBalancerIP-fail-case1", + desc: "ServiceTypeLoadBalancer-with-invalid-IP", mutate: func(envoy *egv1a1.EnvoyProxy) { envoy.Spec = egv1a1.EnvoyProxySpec{ Provider: &egv1a1.EnvoyProxyProvider{ Type: egv1a1.ProviderTypeKubernetes, Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ EnvoyService: &egv1a1.KubernetesServiceSpec{ - Type: ptr.To(egv1a1.ServiceTypeClusterIP), + Type: ptr.To(egv1a1.ServiceTypeLoadBalancer), LoadBalancerIP: ptr.To("a.b.c.d"), }, }, }, } }, - wantErrors: []string{"loadBalancerIP can only be set for LoadBalancer type"}, + wantErrors: []string{"loadBalancerIP must be a valid IPv4 address"}, }, { - desc: "loadBalancerIP-fail-case2", + desc: "ServiceTypeClusterIP-with-empty-IP", mutate: func(envoy *egv1a1.EnvoyProxy) { envoy.Spec = egv1a1.EnvoyProxySpec{ Provider: &egv1a1.EnvoyProxyProvider{ Type: egv1a1.ProviderTypeKubernetes, Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ EnvoyService: &egv1a1.KubernetesServiceSpec{ - Type: ptr.To(egv1a1.ServiceTypeLoadBalancer), - LoadBalancerIP: ptr.To("a.b.c.d"), + Type: ptr.To(egv1a1.ServiceTypeClusterIP), }, }, }, } }, - wantErrors: []string{"loadBalancerIP must be a valid IPv4 address"}, + wantErrors: []string{}, + }, + { + desc: "ServiceTypeClusterIP-with-LoadBalancerIP", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeClusterIP), + LoadBalancerIP: ptr.To("20.205.243.166"), // github ip for test only + }, + }, + }, + } + }, + wantErrors: []string{"loadBalancerIP can only be set for LoadBalancer type"}, }, } From be86295cd2f8092caad32258565d10ffeb4f53a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 09:16:27 -0700 Subject: [PATCH 27/55] build(deps): bump github.com/golangci/golangci-lint from 1.55.0 to 1.55.1 in /tools/src/golangci-lint (#2119) build(deps): bump github.com/golangci/golangci-lint Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.55.0 to 1.55.1. - [Release notes](https://github.com/golangci/golangci-lint/releases) - [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md) - [Commits](https://github.com/golangci/golangci-lint/compare/v1.55.0...v1.55.1) --- updated-dependencies: - dependency-name: github.com/golangci/golangci-lint dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/src/golangci-lint/go.mod | 8 ++++---- tools/src/golangci-lint/go.sum | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/src/golangci-lint/go.mod b/tools/src/golangci-lint/go.mod index db1ab45f0eb..0f4db103723 100644 --- a/tools/src/golangci-lint/go.mod +++ b/tools/src/golangci-lint/go.mod @@ -2,7 +2,7 @@ module local go 1.20 -require github.com/golangci/golangci-lint v1.55.0 +require github.com/golangci/golangci-lint v1.55.1 require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect @@ -67,9 +67,9 @@ require ( github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect github.com/golangci/misspell v0.4.1 // indirect - github.com/golangci/revgrep v0.5.0 // indirect + github.com/golangci/revgrep v0.5.2 // indirect github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect @@ -131,7 +131,7 @@ require ( github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.24.0 // indirect - github.com/securego/gosec/v2 v2.18.1 // indirect + github.com/securego/gosec/v2 v2.18.2 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect diff --git a/tools/src/golangci-lint/go.sum b/tools/src/golangci-lint/go.sum index 6ecebef021d..44df080f2e0 100644 --- a/tools/src/golangci-lint/go.sum +++ b/tools/src/golangci-lint/go.sum @@ -226,16 +226,16 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6 github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e h1:ULcKCDV1LOZPFxGZaA6TlQbiM3J2GCPnkx/bGF6sX/g= github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e/go.mod h1:Pm5KhLPA8gSnQwrQ6ukebRcapGb/BG9iUkdaiCcGHJM= -github.com/golangci/golangci-lint v1.55.0 h1:ePpc6YhM1ZV8kHU8dwmHDHAdeedZHdK8cmTXlkkRdi8= -github.com/golangci/golangci-lint v1.55.0/go.mod h1:Z/OawFQ4yqFo2/plDYlIjoZlJeVYkRcqS9dW55p0FXg= +github.com/golangci/golangci-lint v1.55.1 h1:DL2j9Eeapg1N3WEkKnQFX5L40SYtjZZJjGVdyEgNrDc= +github.com/golangci/golangci-lint v1.55.1/go.mod h1:z00biPRqjo5MISKV1+RWgONf2KvrPDmfqxHpHKB6bI4= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= github.com/golangci/misspell v0.4.1 h1:+y73iSicVy2PqyX7kmUefHusENlrP9YwuHZHPLGQj/g= github.com/golangci/misspell v0.4.1/go.mod h1:9mAN1quEo3DlpbaIKKyEvRxK1pwqR9s/Sea1bJCtlNI= -github.com/golangci/revgrep v0.5.0 h1:GGBqHFtFOeHiSUQtFVZXPJtVZYOGB4iVlAjaoFRBQvY= -github.com/golangci/revgrep v0.5.0/go.mod h1:bjAMA+Sh/QUfTDcHzxfyHxr4xKvllVr/0sCv2e7jJHA= +github.com/golangci/revgrep v0.5.2 h1:EndcWoRhcnfj2NHQ+28hyuXpLMF+dQmCN+YaeeIl4FU= +github.com/golangci/revgrep v0.5.2/go.mod h1:bjAMA+Sh/QUfTDcHzxfyHxr4xKvllVr/0sCv2e7jJHA= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -252,8 +252,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -399,8 +399,8 @@ github.com/nunnatsa/ginkgolinter v0.14.0 h1:XQPNmw+kZz5cC/HbFK3mQutpjzAQv1dHregR github.com/nunnatsa/ginkgolinter v0.14.0/go.mod h1:cm2xaqCUCRd7qcP4DqbVvpcyEMkuLM9CF0wY6VASohk= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= -github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.11.0 h1:OKBD80J/mLBrwnzXqGtFCzprFSGioo30JcmR4APsNwc= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -463,8 +463,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.24.0 h1:MKNzmXtGh5N0y74Z/CIaJh4GlB364l0K1RUT08WSWAc= github.com/sashamelentyev/usestdlibvars v1.24.0/go.mod h1:9cYkq+gYJ+a5W2RPdhfaSCnTVUC1OQP/bSiiBhq3OZE= -github.com/securego/gosec/v2 v2.18.1 h1:xnnehWg7dIW8qrRPGm8ykY21zp2MueKyC99Vlcuj96I= -github.com/securego/gosec/v2 v2.18.1/go.mod h1:ZUTcKD9gAFip1lLGHWCjkoBQJyaEzePTNzjwlL2HHoE= +github.com/securego/gosec/v2 v2.18.2 h1:DkDt3wCiOtAHf1XkiXZBhQ6m6mK/b9T/wD257R3/c+I= +github.com/securego/gosec/v2 v2.18.2/go.mod h1:xUuqSF6i0So56Y2wwohWAmB07EdBkUN6crbLlHwbyJs= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= From b45ae24d2ed875bd2b15a832c2669240f0b301ab Mon Sep 17 00:00:00 2001 From: Sachin Maurya <57769917+slayer321@users.noreply.github.com> Date: Tue, 31 Oct 2023 07:12:06 +0530 Subject: [PATCH 28/55] feat: CEL Validation in BackendTrafficPolicy (#2110) * feat: CEL Validation in BackendTrafficPolicy Signed-off-by: slayer321 * leastRequest with consistentHash nil test Signed-off-by: slayer321 --------- Signed-off-by: slayer321 --- api/v1alpha1/loadbalancer_types.go | 2 + ....envoyproxy.io_backendtrafficpolicies.yaml | 5 ++ .../backendtrafficpolicy_test.go | 59 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go index d512b6902c7..b4e36a342a5 100644 --- a/api/v1alpha1/loadbalancer_types.go +++ b/api/v1alpha1/loadbalancer_types.go @@ -7,6 +7,8 @@ package v1alpha1 // LoadBalancer defines the load balancer policy to be applied. // +union +// +// +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? has(self.consistentHash) : !has(self.consistentHash)",message="If LoadBalancer type is consistentHash, consistentHash field needs to be set." type LoadBalancer struct { // Type decides the type of Load Balancer policy. // Valid RateLimitType values are diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index be8c6c3d760..3d1edb778cc 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -74,6 +74,11 @@ spec: required: - type type: object + x-kubernetes-validations: + - message: If LoadBalancer type is consistentHash, consistentHash + field needs to be set. + rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash) + : !has(self.consistentHash)' rateLimit: description: RateLimit allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index b49870c0dc7..673efd308b8 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -151,6 +151,65 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { "spec.targetRef: Invalid value: \"object\": this policy does not yet support the sectionName field", }, }, + { + desc: "consistentHash field not nil when type is consistentHash", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "SourceIP", + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "consistentHash field nil when type is consistentHash", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + }, + } + }, + wantErrors: []string{ + "spec.loadBalancer: Invalid value: \"object\": If LoadBalancer type is consistentHash, consistentHash field needs to be set", + }, + }, + { + desc: "leastRequest with ConsistentHash nil", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.LeastRequestLoadBalancerType, + }, + } + }, + wantErrors: []string{}, + }, } for _, tc := range cases { From 046a593fe66b4a30c9964edb29e3b2c1d7375078 Mon Sep 17 00:00:00 2001 From: zirain Date: Mon, 30 Oct 2023 21:21:49 -0500 Subject: [PATCH 29/55] e2e: eg controlplane metrics (#2106) * e2e: eg controlplane metrics Signed-off-by: zirain * update Signed-off-by: zirain * update Signed-off-by: zirain * update name Signed-off-by: zirain * rename Signed-off-by: zirain * wait more Signed-off-by: zirain * add comment Signed-off-by: zirain * update Signed-off-by: zirain --------- Signed-off-by: zirain --- test/e2e/testdata/prometheus.yaml | 17 +++++++ test/e2e/tests/controlplane.go | 76 +++++++++++++++++++++++++++++++ test/e2e/tests/metric.go | 22 +++++---- 3 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 test/e2e/testdata/prometheus.yaml create mode 100644 test/e2e/tests/controlplane.go diff --git a/test/e2e/testdata/prometheus.yaml b/test/e2e/testdata/prometheus.yaml new file mode 100644 index 00000000000..d33db1d2dea --- /dev/null +++ b/test/e2e/testdata/prometheus.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: envoy-gateway-metrics-lb + namespace: envoy-gateway-system + labels: + control-plane: envoy-gateway +spec: + selector: + control-plane: envoy-gateway + app.kubernetes.io/instance: eg + ports: + - name: http-metrics + port: 19001 + protocol: TCP + targetPort: 19001 + type: LoadBalancer diff --git a/test/e2e/tests/controlplane.go b/test/e2e/tests/controlplane.go new file mode 100644 index 00000000000..7149c2546b6 --- /dev/null +++ b/test/e2e/tests/controlplane.go @@ -0,0 +1,76 @@ +// 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 ( + "context" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, ControlPlaneMetricTest) +} + +var ControlPlaneMetricTest = suite.ConformanceTest{ + ShortName: "ControlPlane", + Description: "Make sure control plane prometheus endpoint is working", + Manifests: []string{"testdata/prometheus.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("Prometheus", func(t *testing.T) { + nn := types.NamespacedName{Name: "envoy-gateway-metrics-lb", Namespace: "envoy-gateway-system"} + if err := wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, true, + func(_ context.Context) (done bool, err error) { + svc := corev1.Service{} + if err := suite.Client.Get(context.Background(), nn, &svc); err != nil { + return false, nil + } + + host := "" + switch svc.Spec.Type { + case corev1.ServiceTypeLoadBalancer: + for _, ing := range svc.Status.LoadBalancer.Ingress { + if ing.IP != "" { + host = ing.IP + break + } + } + default: + // do nothing + } + + if host == "" { + return false, nil + } + + return true, nil + }); err != nil { + t.Errorf("failed to get service %s : %v", nn.String(), err) + } + + // too much flakes in the test if timeout is 1 minute + // this should not take so long, but we give it a long timeout to be safe, and poll every second + if err := wait.PollUntilContextTimeout(context.TODO(), time.Second, 2*time.Minute, true, + func(_ context.Context) (done bool, err error) { + if err := ScrapeMetrics(t, suite.Client, nn, 19001, "/metrics"); err != nil { + t.Logf("failed to get metric: %v", err) + return false, nil + } + return true, nil + }); err != nil { + t.Errorf("failed to scrape metrics: %v", err) + } + }) + }, +} diff --git a/test/e2e/tests/metric.go b/test/e2e/tests/metric.go index 0f312dc07b5..2c9a8c296c3 100644 --- a/test/e2e/tests/metric.go +++ b/test/e2e/tests/metric.go @@ -59,7 +59,7 @@ var MetricTest = suite.ConformanceTest{ if err := ScrapeMetrics(t, suite.Client, types.NamespacedName{ Namespace: "envoy-gateway-system", Name: "same-namespace-gw-metrics", - }, "/stats/prometheus"); err != nil { + }, 19001, "/stats/prometheus"); err != nil { t.Logf("failed to get metric: %v", err) return false, nil } @@ -93,7 +93,7 @@ var MetricTest = suite.ConformanceTest{ if err := ScrapeMetrics(t, suite.Client, types.NamespacedName{ Namespace: "monitoring", Name: "otel-collecot-prometheus", - }, "/metrics"); err != nil { + }, 19001, "/metrics"); err != nil { t.Logf("failed to get metric: %v", err) return false, nil } @@ -105,19 +105,25 @@ var MetricTest = suite.ConformanceTest{ }, } -func ScrapeMetrics(t *testing.T, c client.Client, nn types.NamespacedName, path string) error { +func ScrapeMetrics(t *testing.T, c client.Client, nn types.NamespacedName, port int32, path string) error { svc := corev1.Service{} if err := c.Get(context.Background(), nn, &svc); err != nil { return err } host := "" - for _, ing := range svc.Status.LoadBalancer.Ingress { - if ing.IP != "" { - host = ing.IP - break + switch svc.Spec.Type { + case corev1.ServiceTypeLoadBalancer: + for _, ing := range svc.Status.LoadBalancer.Ingress { + if ing.IP != "" { + host = ing.IP + break + } } + default: + host = fmt.Sprintf("%s.%s.svc", nn.Name, nn.Namespace) } - url := fmt.Sprintf("http://%s:19001%s", host, path) + + url := fmt.Sprintf("http://%s:%d%s", host, port, path) t.Logf("try to request: %s", url) httpClient := http.Client{ From 179d265efe24ca88b5461884a911b13daa9fb9fd Mon Sep 17 00:00:00 2001 From: tmsnan Date: Tue, 31 Oct 2023 14:03:25 +0800 Subject: [PATCH 30/55] chore: fix http2_protocol_options warning message (#2048) chore:fix http2_protocol_options warning message Signed-off-by: zhaonan --- .../translate/out/default-resources.all.yaml | 18 ++++++++---------- .../translate/out/envoy-patch-policy.all.yaml | 9 ++++----- .../out/from-gateway-api-to-xds.all.json | 13 ++++++------- .../out/from-gateway-api-to-xds.all.yaml | 9 ++++----- .../out/from-gateway-api-to-xds.bootstrap.yaml | 9 ++++----- ...t-single-route-single-match-to-xds.all.json | 13 ++++++------- ...t-single-route-single-match-to-xds.all.yaml | 9 ++++----- ...le-route-single-match-to-xds.bootstrap.yaml | 9 ++++----- .../proxy/testdata/deployments/custom.yaml | 9 ++++----- .../custom_with_initcontainers.yaml | 9 ++++----- .../testdata/deployments/default-env.yaml | 9 ++++----- .../proxy/testdata/deployments/default.yaml | 9 ++++----- .../deployments/enable-prometheus.yaml | 9 ++++----- .../testdata/deployments/extension-env.yaml | 9 ++++----- .../proxy/testdata/deployments/volumes.yaml | 9 ++++----- internal/xds/bootstrap/bootstrap.yaml.tpl | 9 ++++----- .../testdata/custom-stats-matcher.yaml | 9 ++++----- .../bootstrap/testdata/disable-prometheus.yaml | 9 ++++----- .../bootstrap/testdata/enable-prometheus.yaml | 9 ++++----- .../xds/bootstrap/testdata/otel-metrics.yaml | 9 ++++----- internal/xds/translator/cluster_test.go | 1 - 21 files changed, 88 insertions(+), 110 deletions(-) diff --git a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml index bfc39f0543d..06afc627840 100644 --- a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml @@ -98,13 +98,12 @@ envoyProxy: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: @@ -510,10 +509,6 @@ xds: name: prometheus_stats type: STATIC - connectTimeout: 10s - http2ProtocolOptions: - connectionKeepalive: - interval: 30s - timeout: 5s loadAssignment: clusterName: xds_cluster endpoints: @@ -550,7 +545,10 @@ xds: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicitHttpConfig: - http2ProtocolOptions: {} + http2ProtocolOptions: + connectionKeepalive: + interval: 30s + timeout: 5s listeners: - address: socketAddress: diff --git a/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml b/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml index e8682fc8261..fb054e518bb 100644 --- a/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml @@ -42,10 +42,6 @@ xds: name: prometheus_stats type: STATIC - connectTimeout: 10s - http2ProtocolOptions: - connectionKeepalive: - interval: 30s - timeout: 5s loadAssignment: clusterName: xds_cluster endpoints: @@ -82,7 +78,10 @@ xds: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicitHttpConfig: - http2ProtocolOptions: {} + http2ProtocolOptions: + connectionKeepalive: + interval: 30s + timeout: 5s listeners: - address: socketAddress: diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json index 2411af45366..53fc117ef6e 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json @@ -72,12 +72,6 @@ }, { "connectTimeout": "10s", - "http2ProtocolOptions": { - "connectionKeepalive": { - "interval": "30s", - "timeout": "5s" - } - }, "loadAssignment": { "clusterName": "xds_cluster", "endpoints": [ @@ -136,7 +130,12 @@ "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", "explicitHttpConfig": { - "http2ProtocolOptions": {} + "http2ProtocolOptions": { + "connectionKeepalive": { + "interval": "30s", + "timeout": "5s" + } + } } } } diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml index d02b1de377c..40cee9b63a0 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml @@ -42,10 +42,6 @@ xds: name: prometheus_stats type: STATIC - connectTimeout: 10s - http2ProtocolOptions: - connectionKeepalive: - interval: 30s - timeout: 5s loadAssignment: clusterName: xds_cluster endpoints: @@ -82,7 +78,10 @@ xds: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicitHttpConfig: - http2ProtocolOptions: {} + http2ProtocolOptions: + connectionKeepalive: + interval: 30s + timeout: 5s listeners: - address: socketAddress: diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml index e57ac7b1c00..27b7bc7bb2a 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml @@ -41,10 +41,6 @@ xds: name: prometheus_stats type: STATIC - connectTimeout: 10s - http2ProtocolOptions: - connectionKeepalive: - interval: 30s - timeout: 5s loadAssignment: clusterName: xds_cluster endpoints: @@ -81,7 +77,10 @@ xds: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicitHttpConfig: - http2ProtocolOptions: {} + http2ProtocolOptions: + connectionKeepalive: + interval: 30s + timeout: 5s listeners: - address: socketAddress: diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json index 9adf09f0e52..11c9c3261e2 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json @@ -72,12 +72,6 @@ }, { "connectTimeout": "10s", - "http2ProtocolOptions": { - "connectionKeepalive": { - "interval": "30s", - "timeout": "5s" - } - }, "loadAssignment": { "clusterName": "xds_cluster", "endpoints": [ @@ -136,7 +130,12 @@ "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", "explicitHttpConfig": { - "http2ProtocolOptions": {} + "http2ProtocolOptions": { + "connectionKeepalive": { + "interval": "30s", + "timeout": "5s" + } + } } } } diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml index 1eb76aa4ce6..c5470eebb98 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml @@ -42,10 +42,6 @@ xds: name: prometheus_stats type: STATIC - connectTimeout: 10s - http2ProtocolOptions: - connectionKeepalive: - interval: 30s - timeout: 5s loadAssignment: clusterName: xds_cluster endpoints: @@ -82,7 +78,10 @@ xds: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicitHttpConfig: - http2ProtocolOptions: {} + http2ProtocolOptions: + connectionKeepalive: + interval: 30s + timeout: 5s listeners: - address: socketAddress: diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml index 169f3f954c6..e92c54f0dbc 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml @@ -41,10 +41,6 @@ xds: name: prometheus_stats type: STATIC - connectTimeout: 10s - http2ProtocolOptions: - connectionKeepalive: - interval: 30s - timeout: 5s loadAssignment: clusterName: xds_cluster endpoints: @@ -81,7 +77,10 @@ xds: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicitHttpConfig: - http2ProtocolOptions: {} + http2ProtocolOptions: + connectionKeepalive: + interval: 30s + timeout: 5s listeners: - address: socketAddress: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml index c6958c0a503..03c4ec7b993 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml @@ -108,13 +108,12 @@ spec: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml index d9f4466506e..b8aa8192d25 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml @@ -108,13 +108,12 @@ spec: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml index e9621ada58d..e6b1a8bd9cf 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml @@ -106,13 +106,12 @@ spec: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml index 14a29c0b4ec..b735c371a13 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml @@ -104,13 +104,12 @@ spec: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml index 9f296515f07..7732de9f065 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml @@ -130,13 +130,12 @@ spec: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml index a9d3bd9e5e5..172511c44ac 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml @@ -106,13 +106,12 @@ spec: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml index 002247177c5..bdebfe89faf 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml @@ -106,13 +106,12 @@ spec: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/xds/bootstrap/bootstrap.yaml.tpl b/internal/xds/bootstrap/bootstrap.yaml.tpl index 61eea5c7eb8..4828729a816 100644 --- a/internal/xds/bootstrap/bootstrap.yaml.tpl +++ b/internal/xds/bootstrap/bootstrap.yaml.tpl @@ -141,13 +141,12 @@ static_resources: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml b/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml index 0360bde351b..9fac5a316c5 100644 --- a/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml +++ b/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml @@ -99,13 +99,12 @@ static_resources: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/xds/bootstrap/testdata/disable-prometheus.yaml b/internal/xds/bootstrap/testdata/disable-prometheus.yaml index d3bb7cc7d05..4cfe3d7d2b0 100644 --- a/internal/xds/bootstrap/testdata/disable-prometheus.yaml +++ b/internal/xds/bootstrap/testdata/disable-prometheus.yaml @@ -67,13 +67,12 @@ static_resources: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/xds/bootstrap/testdata/enable-prometheus.yaml b/internal/xds/bootstrap/testdata/enable-prometheus.yaml index 1f777d63293..667729dadf1 100644 --- a/internal/xds/bootstrap/testdata/enable-prometheus.yaml +++ b/internal/xds/bootstrap/testdata/enable-prometheus.yaml @@ -89,13 +89,12 @@ static_resources: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/xds/bootstrap/testdata/otel-metrics.yaml b/internal/xds/bootstrap/testdata/otel-metrics.yaml index 72c1e1d6c96..c4e4a6b750b 100644 --- a/internal/xds/bootstrap/testdata/otel-metrics.yaml +++ b/internal/xds/bootstrap/testdata/otel-metrics.yaml @@ -92,13 +92,12 @@ static_resources: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" explicit_http_config: - http2_protocol_options: {} + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s name: xds_cluster type: STRICT_DNS - http2_protocol_options: - connection_keepalive: - interval: 30s - timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: diff --git a/internal/xds/translator/cluster_test.go b/internal/xds/translator/cluster_test.go index 00ade71f487..30235b6d4d6 100644 --- a/internal/xds/translator/cluster_test.go +++ b/internal/xds/translator/cluster_test.go @@ -41,7 +41,6 @@ func TestBuildXdsCluster(t *testing.T) { require.Equal(t, bootstrapXdsCluster.TransportSocket, dynamicXdsCluster.TransportSocket) assert.True(t, proto.Equal(bootstrapXdsCluster.TransportSocket, dynamicXdsCluster.TransportSocket)) assert.True(t, proto.Equal(bootstrapXdsCluster.ConnectTimeout, dynamicXdsCluster.ConnectTimeout)) - assert.True(t, proto.Equal(bootstrapXdsCluster.TypedExtensionProtocolOptions[extensionOptionsKey], dynamicXdsCluster.TypedExtensionProtocolOptions[extensionOptionsKey])) } func TestBuildXdsClusterLoadAssignment(t *testing.T) { From 57e1aec00037fce0914d14fc81afdc4a861e8f26 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Tue, 31 Oct 2023 15:46:58 +0800 Subject: [PATCH 31/55] fix Failed to update SecurityPolicy status (#2128) fix #2127 Signed-off-by: Huabing Zhao --- charts/gateway-helm/templates/_rbac.tpl | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/gateway-helm/templates/_rbac.tpl b/charts/gateway-helm/templates/_rbac.tpl index 68cbe6be8fa..c009b66a33b 100644 --- a/charts/gateway-helm/templates/_rbac.tpl +++ b/charts/gateway-helm/templates/_rbac.tpl @@ -83,6 +83,7 @@ resources: - envoypatchpolicies/status - clienttrafficpolicies/status - backendtrafficpolicies/status +- securitypolicies/status verbs: - update {{- end }} From 71c09f285fcc88ddaf234a7c3864263d8a5bbbd0 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Tue, 31 Oct 2023 18:23:52 +0800 Subject: [PATCH 32/55] fix: add missing status equal for SecurityPolicy (#2134) --- internal/status/status.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/status/status.go b/internal/status/status.go index 0a86125cabf..5ffa6ed4ad1 100644 --- a/internal/status/status.go +++ b/internal/status/status.go @@ -169,6 +169,7 @@ func (u *UpdateWriter) Send(update Update) { // GRPCRoute // EnvoyPatchPolicy // ClientTrafficPolicy +// SecurityPolicy func isStatusEqual(objA, objB interface{}) bool { opts := cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime") switch a := objA.(type) { @@ -232,6 +233,12 @@ func isStatusEqual(objA, objB interface{}) bool { return true } } + case *egv1a1.SecurityPolicy: + if b, ok := objB.(*egv1a1.SecurityPolicy); ok { + if cmp.Equal(a.Status, b.Status, opts) { + return true + } + } } return false From df1e20900f3d6e8030f3a10445a3e3b1c87e5258 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Wed, 1 Nov 2023 07:01:40 +0800 Subject: [PATCH 33/55] fix jwt doc (#2135) Signed-off-by: huabing zhao --- site/content/en/latest/user/jwt-authentication.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/content/en/latest/user/jwt-authentication.md b/site/content/en/latest/user/jwt-authentication.md index 239bca9b88c..1b6bfe0b5a6 100644 --- a/site/content/en/latest/user/jwt-authentication.md +++ b/site/content/en/latest/user/jwt-authentication.md @@ -49,7 +49,7 @@ kubectl get securitypolicy/jwt-example -o yaml ### GRPCRoute ```shell -kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/jwt/grtpc-jwt.yaml +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/jwt/grpc-jwt.yaml ``` A SecurityPolicy has been created and targeted GRPCRoute yages to authenticate all requests for `yages` service.. @@ -91,7 +91,7 @@ A `401` HTTP response code should be returned. Get the JWT used for testing request authentication: ```shell -TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - +TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - ``` __Note:__ The above command decodes and returns the token's payload. You can replace `f2` with `f1` to view the token's @@ -128,7 +128,7 @@ Error invoking method "yages.Echo/Ping": rpc error: code = Unauthenticated desc Get the JWT used for testing request authentication: ```shell -TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/authn/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - +TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - ``` __Note:__ The above command decodes and returns the token's payload. You can replace `f2` with `f1` to view the token's From 3dd0ee7840871eff5b2089036cba67b93054ecb7 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Tue, 31 Oct 2023 17:55:18 -0700 Subject: [PATCH 34/55] Bump Gateway API to v1.0.0 (#2142) --- charts/gateway-helm/crds/gatewayapi-crds.yaml | 18 ++--- go.mod | 28 +++---- go.sum | 81 ++++++++++++------- internal/ir/xds.go | 17 ++-- tools/github-actions/setup-deps/action.yaml | 2 +- 5 files changed, 87 insertions(+), 59 deletions(-) diff --git a/charts/gateway-helm/crds/gatewayapi-crds.yaml b/charts/gateway-helm/crds/gatewayapi-crds.yaml index fa7d880dad8..bbb71f11f65 100644 --- a/charts/gateway-helm/crds/gatewayapi-crds.yaml +++ b/charts/gateway-helm/crds/gatewayapi-crds.yaml @@ -24,7 +24,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null labels: @@ -509,7 +509,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io @@ -1009,7 +1009,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gateways.gateway.networking.k8s.io @@ -2817,7 +2817,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: grpcroutes.gateway.networking.k8s.io @@ -4547,7 +4547,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: httproutes.gateway.networking.k8s.io @@ -9509,7 +9509,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: referencegrants.gateway.networking.k8s.io @@ -9798,7 +9798,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tcproutes.gateway.networking.k8s.io @@ -10439,7 +10439,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tlsroutes.gateway.networking.k8s.io @@ -11129,7 +11129,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 - gateway.networking.k8s.io/bundle-version: v1.0.0-rc2 + gateway.networking.k8s.io/bundle-version: v1.0.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: udproutes.gateway.networking.k8s.io diff --git a/go.mod b/go.mod index 04b55416d37..5e39e1b2ad4 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway -go 1.20 +go 1.21 require ( github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 @@ -31,7 +31,7 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.19.0 go.opentelemetry.io/proto/otlp v1.0.0 go.uber.org/zap v1.26.0 - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e + golang.org/x/exp v0.0.0-20231006140011-7918f672742d google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v3 v3.0.1 @@ -41,9 +41,9 @@ require ( k8s.io/cli-runtime v0.28.3 k8s.io/client-go v0.28.3 k8s.io/kubectl v0.28.3 - k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 + k8s.io/utils v0.0.0-20230726121419-3b25d923346b sigs.k8s.io/controller-runtime v0.16.3 - sigs.k8s.io/gateway-api v1.0.0-rc2 + sigs.k8s.io/gateway-api v1.0.0 sigs.k8s.io/yaml v1.4.0 ) @@ -67,14 +67,14 @@ require ( github.com/chai2010/gettext-go v1.0.2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch v5.7.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect github.com/go-errors/errors v1.4.2 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/btree v1.0.1 // indirect github.com/google/gnostic-models v0.6.8 // indirect @@ -83,7 +83,7 @@ require ( github.com/google/uuid v1.3.1 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -102,7 +102,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.17.0 github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/tsaarni/x500dn v1.0.0 // indirect @@ -110,13 +110,13 @@ require ( go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect @@ -124,10 +124,10 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/component-base v0.28.3 // indirect k8s.io/klog/v2 v2.100.1 // indirect - k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // 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 sigs.k8s.io/mcs-api v0.1.0 - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect ) diff --git a/go.sum b/go.sum index cfe9c2fb0c9..ac8b12b981f 100644 --- a/go.sum +++ b/go.sum @@ -28,6 +28,7 @@ github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPp github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -71,7 +72,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/datawire/dlib v1.3.0 h1:KkmyXU1kwm3oPBk1ypR70YbcOlEXWzEbx5RE0iRXTGk= +github.com/datawire/dlib v1.3.0/go.mod h1:NiGDmetmbkBvtznpWSx6C0vA0s0LK9aHna3LJDqjruk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -100,8 +103,8 @@ github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 h1:yz9/p/8Q github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7/go.mod h1:NmJBO+gDMvSQWvcSWq8wmlgkDmHHAkx1SCxEGva5hKU= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= +github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= @@ -110,8 +113,8 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= @@ -149,8 +152,9 @@ github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwds github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= @@ -180,13 +184,15 @@ github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/ github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -195,6 +201,7 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -213,6 +220,7 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -238,6 +246,7 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -272,8 +281,8 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= @@ -300,6 +309,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -359,12 +369,14 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 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.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= 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.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= @@ -397,17 +409,19 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -447,6 +461,7 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/telepresenceio/telepresence/rpc/v2 v2.6.8 h1:q5V85LBT9bA/c4YPa/kMvJGyKZDgBPJTftlAMqJx7j4= +github.com/telepresenceio/telepresence/rpc/v2 v2.6.8/go.mod h1:VlgfRoXaW6Tl8IZbHmMWhITne8HY09/wOFtABHGj3ic= github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7 h1:GMw3nEaOVyi+tNiGko5kAeRtoiEIpXNHmISyZ7fpw14= github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7/go.mod h1:ihJ97e2gsd8GuzFF/I3B1qcik3XZLpXjumQifXi8Slg= github.com/tetratelabs/multierror v1.1.1 h1:84JfJvfmnYC5y4877Ag3c4PkCUmQwq6sGI6iRfBATKI= @@ -469,6 +484,7 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= @@ -503,6 +519,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -521,9 +538,10 @@ golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -532,6 +550,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -545,7 +564,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -554,14 +572,16 @@ golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -570,6 +590,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -601,11 +622,13 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= @@ -614,6 +637,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -638,7 +663,9 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -650,8 +677,8 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -752,21 +779,21 @@ k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= 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-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +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.28.3 h1:H1Peu1O3EbN9zHkJCcvhiJ4NUj6lb88sGPO5wrWIM6k= k8s.io/kubectl v0.28.3/go.mod h1:RDAudrth/2wQ3Sg46fbKKl4/g+XImzvbsSRZdP2RiyE= 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-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 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.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= -sigs.k8s.io/gateway-api v1.0.0-rc2 h1:+7rq7j5fehUkMkgnJyL90mtXrVnz8aj5SXsRqIEW3Mk= -sigs.k8s.io/gateway-api v1.0.0-rc2/go.mod h1:+QpYENjk9s31/abu2Pv5BpK2v88UQDK2aeQCwCvy6ck= +sigs.k8s.io/gateway-api v1.0.0 h1:iPTStSv41+d9p0xFydll6d7f7MOBGuqXM6p2/zVYMAs= +sigs.k8s.io/gateway-api v1.0.0/go.mod h1:4cUgr0Lnp5FZ0Cdq8FdRwCvpiWws7LVhLHGIudLlf4c= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kind v0.8.1/go.mod h1:oNKTxUVPYkV9lWzY6CVMNluVq8cBsyq+UgPJdvA3uu4= @@ -778,8 +805,8 @@ sigs.k8s.io/mcs-api v0.1.0 h1:edDbg0oRGfXw8TmZjKYep06LcJLv/qcYLidejnUp0PM= sigs.k8s.io/mcs-api v0.1.0/go.mod h1:gGiAryeFNB4GBsq2LBmVqSgKoobLxt+p7ii/WG5QYYw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/internal/ir/xds.go b/internal/ir/xds.go index c0aa13ffbf6..262a3891ff5 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -6,6 +6,7 @@ package ir import ( + "cmp" "errors" "net" "reflect" @@ -79,19 +80,19 @@ func (x *Xds) Equal(y *Xds) bool { // sort ensures the listeners are in a consistent order. func (x *Xds) sort() { - slices.SortFunc(x.HTTP, func(l1, l2 *HTTPListener) bool { - return l1.Name < l2.Name + slices.SortFunc(x.HTTP, func(l1, l2 *HTTPListener) int { + return cmp.Compare(l1.Name, l2.Name) }) for _, l := range x.HTTP { - slices.SortFunc(l.Routes, func(r1, r2 *HTTPRoute) bool { - return r1.Name < r2.Name + slices.SortFunc(l.Routes, func(r1, r2 *HTTPRoute) int { + return cmp.Compare(r1.Name, r2.Name) }) } - slices.SortFunc(x.TCP, func(l1, l2 *TCPListener) bool { - return l1.Name < l2.Name + slices.SortFunc(x.TCP, func(l1, l2 *TCPListener) int { + return cmp.Compare(l1.Name, l2.Name) }) - slices.SortFunc(x.UDP, func(l1, l2 *UDPListener) bool { - return l1.Name < l2.Name + slices.SortFunc(x.UDP, func(l1, l2 *UDPListener) int { + return cmp.Compare(l1.Name, l2.Name) }) } diff --git a/tools/github-actions/setup-deps/action.yaml b/tools/github-actions/setup-deps/action.yaml index 22e3e557b8a..31974e29d12 100644 --- a/tools/github-actions/setup-deps/action.yaml +++ b/tools/github-actions/setup-deps/action.yaml @@ -6,5 +6,5 @@ runs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.20.x + go-version: 1.21.x cache: true From 2b3bc9f37d289b6bf659d5a76677530371cc98e4 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Tue, 31 Oct 2023 17:59:15 -0700 Subject: [PATCH 35/55] Enable HTTPRouteRewritePath test (#2112) * Enable HTTPRouteRewritePath test Fixes: https://github.com/envoyproxy/gateway/issues/2004 Signed-off-by: Arko Dasgupta * fix prefix match Signed-off-by: Arko Dasgupta * make testdata Signed-off-by: Arko Dasgupta * fix path match Signed-off-by: Arko Dasgupta * rm trailing / Signed-off-by: Arko Dasgupta * sort on path match type Signed-off-by: Arko Dasgupta * make testdata Signed-off-by: Arko Dasgupta * temp var Signed-off-by: Arko Dasgupta * fix url rewrite Signed-off-by: Arko Dasgupta --------- Signed-off-by: Arko Dasgupta --- .../translate/out/multiple-xds.route.json | 2 +- internal/gatewayapi/sort.go | 41 +++++++++++++++++-- .../grpcroute-with-service-match.out.yaml | 8 ++-- ...h-single-rule-with-multiple-rules.out.yaml | 20 ++++----- internal/xds/translator/route.go | 29 +++++++++---- ...e-rewrite-root-path-url-prefix.routes.yaml | 7 +++- test/conformance/conformance_test.go | 1 - .../experimental_conformance_test.go | 1 - 8 files changed, 80 insertions(+), 29 deletions(-) diff --git a/internal/cmd/egctl/testdata/translate/out/multiple-xds.route.json b/internal/cmd/egctl/testdata/translate/out/multiple-xds.route.json index 748a5d4f37e..c2d43139edd 100644 --- a/internal/cmd/egctl/testdata/translate/out/multiple-xds.route.json +++ b/internal/cmd/egctl/testdata/translate/out/multiple-xds.route.json @@ -48,7 +48,7 @@ "routes": [ { "match": { - "prefix": "/v2/" + "pathSeparatedPrefix": "/v2" }, "name": "httproute/default/backend/rule/0/match/0/www_example2_com", "route": { diff --git a/internal/gatewayapi/sort.go b/internal/gatewayapi/sort.go index 589d564cf3f..00a5fc6389d 100644 --- a/internal/gatewayapi/sort.go +++ b/internal/gatewayapi/sort.go @@ -16,7 +16,42 @@ 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 characters in a matching path. + + // 1. Sort based on path match type + // Exact > PathPrefix > RegularExpression + if x[i].PathMatch != nil && x[i].PathMatch.Exact != nil { + if x[j].PathMatch != nil { + if x[j].PathMatch.Prefix != nil { + return false + } + if x[j].PathMatch.SafeRegex != nil { + return false + } + } + } + if x[i].PathMatch != nil && x[i].PathMatch.Prefix != nil { + if x[j].PathMatch != nil { + if x[j].PathMatch.Exact != nil { + return true + } + if x[j].PathMatch.SafeRegex != nil { + return false + } + } + } + if x[i].PathMatch != nil && x[i].PathMatch.SafeRegex != nil { + if x[j].PathMatch != nil { + if x[j].PathMatch.Exact != nil { + return true + } + if x[j].PathMatch.Prefix != nil { + return true + } + } + } + // Equal case + + // 2. Sort based on characters in a matching path. pCountI := pathMatchCount(x[i].PathMatch) pCountJ := pathMatchCount(x[j].PathMatch) if pCountI < pCountJ { @@ -27,7 +62,7 @@ func (x XdsIRRoutes) Less(i, j int) bool { } // Equal case - // 2. Sort based on the number of Header matches. + // 3. Sort based on the number of Header matches. hCountI := len(x[i].HeaderMatches) hCountJ := len(x[j].HeaderMatches) if hCountI < hCountJ { @@ -38,7 +73,7 @@ func (x XdsIRRoutes) Less(i, j int) bool { } // Equal case - // 3. Sort based on the number of Query param matches. + // 4. Sort based on the number of Query param matches. qCountI := len(x[i].QueryParamMatches) qCountJ := len(x[j].QueryParamMatches) return qCountI < qCountJ diff --git a/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml index 4406f205c53..55e3230098b 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml @@ -119,11 +119,11 @@ xdsIR: port: 8080 weight: 1 hostname: '*' - name: grpcroute/default/grpcroute-1/rule/0/match/1/* + name: grpcroute/default/grpcroute-1/rule/0/match/0/* pathMatch: distinct: false name: "" - safeRegex: /com.[A-Z]+/[A-Za-z_][A-Za-z_0-9]* + prefix: /com.ExampleExact - backendWeights: invalid: 0 valid: 0 @@ -135,8 +135,8 @@ xdsIR: port: 8080 weight: 1 hostname: '*' - name: grpcroute/default/grpcroute-1/rule/0/match/0/* + name: grpcroute/default/grpcroute-1/rule/0/match/1/* pathMatch: distinct: false name: "" - prefix: /com.ExampleExact + safeRegex: /com.[A-Z]+/[A-Za-z_][A-Za-z_0-9]* diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml index 33d4418d46a..c5e10904d8e 100644 --- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml @@ -137,7 +137,7 @@ xdsIR: invalid: 0 valid: 0 destination: - name: httproute/default/httproute-1/rule/2 + name: httproute/default/httproute-1/rule/0 settings: - endpoints: - host: 7.7.7.7 @@ -145,18 +145,18 @@ xdsIR: weight: 1 headerMatches: - distinct: false + exact: exact name: Header-1 - safeRegex: '*regex*' hostname: '*' - name: httproute/default/httproute-1/rule/2/match/0/* + name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false + exact: /exact name: "" - safeRegex: '*regex*' queryParamMatches: - distinct: false + exact: exact name: QueryParam-1 - safeRegex: '*regex*' - backendWeights: invalid: 0 valid: 0 @@ -177,7 +177,7 @@ xdsIR: invalid: 0 valid: 0 destination: - name: httproute/default/httproute-1/rule/0 + name: httproute/default/httproute-1/rule/2 settings: - endpoints: - host: 7.7.7.7 @@ -185,15 +185,15 @@ xdsIR: weight: 1 headerMatches: - distinct: false - exact: exact name: Header-1 + safeRegex: '*regex*' hostname: '*' - name: httproute/default/httproute-1/rule/0/match/0/* + name: httproute/default/httproute-1/rule/2/match/0/* pathMatch: distinct: false - exact: /exact name: "" + safeRegex: '*regex*' queryParamMatches: - distinct: false - exact: exact name: QueryParam-1 + safeRegex: '*regex*' diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go index e9546e22772..e69a953f6bc 100644 --- a/internal/xds/translator/route.go +++ b/internal/xds/translator/route.go @@ -43,7 +43,7 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute) *routev3.Route { case httpRoute.Redirect != nil: router.Action = &routev3.Route_Redirect{Redirect: buildXdsRedirectAction(httpRoute.Redirect)} case httpRoute.URLRewrite != nil: - routeAction := buildXdsURLRewriteAction(httpRoute.Destination.Name, httpRoute.URLRewrite) + routeAction := buildXdsURLRewriteAction(httpRoute.Destination.Name, httpRoute.URLRewrite, httpRoute.PathMatch) if httpRoute.Mirrors != nil { routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirrors) } @@ -101,14 +101,15 @@ func buildXdsRouteMatch(pathMatch *ir.StringMatch, headerMatches []*ir.StringMat Path: *pathMatch.Exact, } } else if pathMatch.Prefix != nil { - // when the prefix ends with "/", use RouteMatch_Prefix - if strings.HasSuffix(*pathMatch.Prefix, "/") { + if *pathMatch.Prefix == "/" { outMatch.PathSpecifier = &routev3.RouteMatch_Prefix{ - Prefix: *pathMatch.Prefix, + Prefix: "/", } } else { + // Remove trailing / + trimmedPrefix := strings.TrimSuffix(*pathMatch.Prefix, "/") outMatch.PathSpecifier = &routev3.RouteMatch_PathSeparatedPrefix{ - PathSeparatedPrefix: *pathMatch.Prefix, + PathSeparatedPrefix: trimmedPrefix, } } } else if pathMatch.SafeRegex != nil { @@ -252,7 +253,7 @@ func buildXdsRedirectAction(redirection *ir.Redirect) *routev3.RedirectAction { return routeAction } -func buildXdsURLRewriteAction(destName string, urlRewrite *ir.URLRewrite) *routev3.RouteAction { +func buildXdsURLRewriteAction(destName string, urlRewrite *ir.URLRewrite, pathMatch *ir.StringMatch) *routev3.RouteAction { routeAction := &routev3.RouteAction{ ClusterSpecifier: &routev3.RouteAction_Cluster{ Cluster: destName, @@ -268,7 +269,21 @@ func buildXdsURLRewriteAction(destName string, urlRewrite *ir.URLRewrite) *route Substitution: *urlRewrite.Path.FullReplace, } } else if urlRewrite.Path.PrefixMatchReplace != nil { - routeAction.PrefixRewrite = *urlRewrite.Path.PrefixMatchReplace + // Circumvent the case of "//" when the replace string is "/" + // An empty replace string does not seem to solve the issue so we are using + // a regex match and replace instead + // Remove this workaround once https://github.com/envoyproxy/envoy/issues/26055 is fixed + if pathMatch != nil && pathMatch.Prefix != nil && + (*urlRewrite.Path.PrefixMatchReplace == "" || *urlRewrite.Path.PrefixMatchReplace == "/") { + routeAction.RegexRewrite = &matcherv3.RegexMatchAndSubstitute{ + Pattern: &matcherv3.RegexMatcher{ + Regex: "^" + *pathMatch.Prefix + `\/*`, + }, + Substitution: "/", + } + } else { + routeAction.PrefixRewrite = *urlRewrite.Path.PrefixMatchReplace + } } } diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.routes.yaml index 1604805cc9b..2bf01099ad2 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.routes.yaml @@ -10,8 +10,11 @@ - name: :authority stringMatch: exact: gateway.envoyproxy.io - prefix: /origin/ + pathSeparatedPrefix: /origin name: rewrite-route route: cluster: rewrite-route-dest - prefixRewrite: / + regexRewrite: + pattern: + regex: ^/origin/\/* + substitution: / diff --git a/test/conformance/conformance_test.go b/test/conformance/conformance_test.go index eeb8898ffc7..0e08a5a1ad1 100644 --- a/test/conformance/conformance_test.go +++ b/test/conformance/conformance_test.go @@ -48,7 +48,6 @@ func TestGatewayAPIConformance(t *testing.T) { CleanupBaseResources: *flags.CleanupBaseResources, SupportedFeatures: suite.AllFeatures, SkipTests: []string{ - tests.HTTPRouteRewritePath.ShortName, tests.GatewayStaticAddresses.ShortName, tests.GatewayWithAttachedRoutes.ShortName, tests.HTTPRouteBackendProtocolH2C.ShortName, diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index fd4a5620973..a6a308cbbce 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -97,7 +97,6 @@ func experimentalConformance(t *testing.T) { CleanupBaseResources: *flags.CleanupBaseResources, SupportedFeatures: suite.AllFeatures, SkipTests: []string{ - tests.HTTPRouteRewritePath.ShortName, tests.GatewayStaticAddresses.ShortName, tests.GatewayWithAttachedRoutes.ShortName, tests.HTTPRouteBackendProtocolH2C.ShortName, From 0c5b054f53b5f22a5bfe96ca8266706e74a6fc78 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Wed, 1 Nov 2023 09:56:02 +0800 Subject: [PATCH 36/55] helm: remove kube-rbac-proxy and update metrics service (#2108) --- .../templates/envoy-gateway-deployment.yaml | 17 ----------------- .../templates/metrics-reader-rbac.yaml | 12 ------------ charts/gateway-helm/values.tmpl.yaml | 18 +++--------------- site/content/en/latest/install/api.md | 13 +++---------- 4 files changed, 6 insertions(+), 54 deletions(-) delete mode 100644 charts/gateway-helm/templates/metrics-reader-rbac.yaml diff --git a/charts/gateway-helm/templates/envoy-gateway-deployment.yaml b/charts/gateway-helm/templates/envoy-gateway-deployment.yaml index 8bcd26a0b0f..52e9c419fd9 100644 --- a/charts/gateway-helm/templates/envoy-gateway-deployment.yaml +++ b/charts/gateway-helm/templates/envoy-gateway-deployment.yaml @@ -71,23 +71,6 @@ spec: - mountPath: /certs name: certs readOnly: true - - args: - - --secure-listen-address=0.0.0.0:8443 - - --upstream=http://127.0.0.1:8080/ - - --logtostderr=true - - --v=0 - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ .Values.kubernetesClusterDomain }} - image: {{ .Values.deployment.kubeRbacProxy.image.repository }}:{{ .Values.deployment.kubeRbacProxy.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.deployment.kubeRbacProxy.imagePullPolicy }} - name: kube-rbac-proxy - ports: - - containerPort: 8443 - name: https - protocol: TCP - resources: {{- toYaml .Values.deployment.kubeRbacProxy.resources | nindent 10 - }} securityContext: runAsNonRoot: true serviceAccountName: envoy-gateway diff --git a/charts/gateway-helm/templates/metrics-reader-rbac.yaml b/charts/gateway-helm/templates/metrics-reader-rbac.yaml deleted file mode 100644 index 3b77e714185..00000000000 --- a/charts/gateway-helm/templates/metrics-reader-rbac.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "eg.fullname" . }}-metrics-reader - namespace: '{{ .Release.Namespace }}' - labels: - {{- include "eg.labels" . | nindent 4 }} -rules: -- nonResourceURLs: - - /metrics - verbs: - - get diff --git a/charts/gateway-helm/values.tmpl.yaml b/charts/gateway-helm/values.tmpl.yaml index ce5519ae040..b4236aa37c8 100644 --- a/charts/gateway-helm/values.tmpl.yaml +++ b/charts/gateway-helm/values.tmpl.yaml @@ -13,18 +13,6 @@ deployment: requests: cpu: 100m memory: 256Mi - kubeRbacProxy: - image: - repository: gcr.io/kubebuilder/kube-rbac-proxy - tag: v0.14.1 - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 5m - memory: 64Mi ports: - name: grpc port: 18000 @@ -49,10 +37,10 @@ config: envoyGatewayMetricsService: ports: - - name: https - port: 8443 + - name: http + port: 19001 protocol: TCP - targetPort: https + targetPort: 19001 createNamespace: false diff --git a/site/content/en/latest/install/api.md b/site/content/en/latest/install/api.md index f6c859863b0..253d528bdfb 100644 --- a/site/content/en/latest/install/api.md +++ b/site/content/en/latest/install/api.md @@ -40,13 +40,6 @@ The Helm chart for Envoy Gateway | deployment.envoyGateway.resources.limits.memory | string | `"1024Mi"` | | | deployment.envoyGateway.resources.requests.cpu | string | `"100m"` | | | deployment.envoyGateway.resources.requests.memory | string | `"256Mi"` | | -| deployment.kubeRbacProxy.image.repository | string | `"gcr.io/kubebuilder/kube-rbac-proxy"` | | -| deployment.kubeRbacProxy.image.tag | string | `"v0.14.1"` | | -| deployment.kubeRbacProxy.imagePullPolicy | string | `"IfNotPresent"` | | -| deployment.kubeRbacProxy.resources.limits.cpu | string | `"500m"` | | -| deployment.kubeRbacProxy.resources.limits.memory | string | `"128Mi"` | | -| deployment.kubeRbacProxy.resources.requests.cpu | string | `"5m"` | | -| deployment.kubeRbacProxy.resources.requests.memory | string | `"64Mi"` | | | deployment.pod.annotations | object | `{}` | | | deployment.pod.labels | object | `{}` | | | deployment.ports[0].name | string | `"grpc"` | | @@ -56,9 +49,9 @@ The Helm chart for Envoy Gateway | deployment.ports[1].port | int | `18001` | | | deployment.ports[1].targetPort | int | `18001` | | | deployment.replicas | int | `1` | | -| envoyGatewayMetricsService.ports[0].name | string | `"https"` | | -| envoyGatewayMetricsService.ports[0].port | int | `8443` | | +| envoyGatewayMetricsService.ports[0].name | string | `"http"` | | +| envoyGatewayMetricsService.ports[0].port | int | `19001` | | | envoyGatewayMetricsService.ports[0].protocol | string | `"TCP"` | | -| envoyGatewayMetricsService.ports[0].targetPort | string | `"https"` | | +| envoyGatewayMetricsService.ports[0].targetPort | int | `19001` | | | kubernetesClusterDomain | string | `"cluster.local"` | | From d0dc987aa717b2c283f01c654e695a1af1f12c54 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Wed, 1 Nov 2023 10:15:38 +0800 Subject: [PATCH 37/55] doc: user doc for CORS (#2137) * cors docs Signed-off-by: huabing zhao * address comments Signed-off-by: huabing zhao --------- Signed-off-by: huabing zhao --- internal/gatewayapi/securitypolicy.go | 2 +- internal/xds/translator/httpfilters.go | 2 +- internal/xds/translator/route.go | 2 +- site/content/en/latest/user/cors.md | 122 +++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 site/content/en/latest/user/cors.md diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 1b52af2bbf9..0866275203d 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -317,7 +317,7 @@ func (t *Translator) buildCORS(policy *egv1a1.SecurityPolicy) *ir.CORS { }) case egv1a1.MatchRegularExpression: allowOrigins = append(allowOrigins, &ir.StringMatch{ - SafeRegex: &origin.Value, + SafeRegex: &origin.Value, // TODO zhaohuabing: check if the value is a valid regex }) } } diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index a9ddb99ad5a..5318450ac9a 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -136,7 +136,7 @@ func patchRouteWithFilters( // Add the jwt per route config to the route, if needed. if err := patchRouteWithJWTConfig(route, irRoute); err != nil { - return nil + return err } return nil diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go index e69a953f6bc..e6fb30a41a4 100644 --- a/internal/xds/translator/route.go +++ b/internal/xds/translator/route.go @@ -78,7 +78,7 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute) *routev3.Route { // Add per route filter configs to the route, if needed. if err := patchRouteWithFilters(router, httpRoute); err != nil { - return nil + return nil // TODO zhaohuabing we need to handle this error } return router diff --git a/site/content/en/latest/user/cors.md b/site/content/en/latest/user/cors.md new file mode 100644 index 00000000000..c8192c62864 --- /dev/null +++ b/site/content/en/latest/user/cors.md @@ -0,0 +1,122 @@ +--- +title: "CORS" +--- + +This guide provides instructions for configuring [Cross-Origin Resource Sharing (CORS)][cors] on Envoy Gateway. +CORS defines a way for client web applications that are loaded in one domain to interact with resources in a different +domain. + +Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure CORS. +This instantiated resource can be linked to a [Gateway][Gateway], [HTTPRoute][HTTPRoute] or [GRPCRoute][GRPCRoute] resource. + +## Prerequisites + +Follow the steps from the [Quickstart](quickstart.md) guide to install Envoy Gateway and the example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +## Configuration + +The below example defines a SecurityPolicy that allows CORS requests from `www.foo.com`. + +```shell +cat < /dev/null +``` + +You should see the below response, indicating that the request from `http://www.foo.com` is allowed: + +```shell +< access-control-allow-origin: http://www.foo.com +< access-control-allow-methods: GET, POST +< access-control-allow-headers: x-header-1, x-header-2 +< access-control-max-age: 86400 +< access-control-expose-headers: x-header-3, x-header-4 +``` + +If you try to send a request from `http://www.bar.com`, you should see the below response: + +```shell +curl -H "Origin: http://www.bar.com" \ + -H "Host: www.example.com" \ + -H "Access-Control-Request-Method: GET" \ + -X OPTIONS -v -s \ + http://$GATEWAY_HOST \ + 1> /dev/null +``` + +You won't see any CORS headers in the response, indicating that the request from `http://www.bar.com` was not allowed. + +Note: CORS specification requires that the browsers to send a preflight request to the server to ask if it's allowed +to access the limited resource in another domains. The browsers are supposed to follow the response from the server to +determine whether to send the actual request or not. The CORS filter only response to the preflight requests according to +its configuration. It won't deny any requests. The browsers are responsible for enforcing the CORS policy. + +```shell + +## Clean-Up + +Follow the steps from the [Quickstart](quickstart.md) guide to uninstall Envoy Gateway and the example manifest. + +Delete the SecurityPolicy: + +```shell +kubectl delete securitypolicy/cors-example +``` + +## Next Steps + +Checkout the [Developer Guide](../../contributions/develop/) to get involved in the project. + +[SecurityPolicy]: https://gateway.envoyproxy.io/latest/design/security-policy +[cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS +[Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway +[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute +[GRPCRoute]: https://gateway-api.sigs.k8s.io/api-types/grpcroute From 6e81fb3abddf72819de888f3ba4fe4f0481d874c Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Wed, 1 Nov 2023 11:07:28 +0800 Subject: [PATCH 38/55] fix(ci): bump go version to 1.21 (#2144) * fix(ci): bump go version to 1.21 Signed-off-by: bitliu * update Signed-off-by: bitliu --------- Signed-off-by: bitliu --- .github/workflows/latest_release.yaml | 1 + tools/src/controller-gen/go.mod | 2 +- tools/src/crd-ref-docs/go.mod | 2 +- tools/src/golangci-lint/go.mod | 2 +- tools/src/helm-docs/go.mod | 2 +- tools/src/kind/go.mod | 2 +- tools/src/protoc-gen-go-grpc/go.mod | 2 +- tools/src/protoc-gen-go/go.mod | 2 +- tools/src/setup-envtest/go.mod | 2 +- 9 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/latest_release.yaml b/.github/workflows/latest_release.yaml index 7932371be0b..f261e061786 100644 --- a/.github/workflows/latest_release.yaml +++ b/.github/workflows/latest_release.yaml @@ -12,6 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 + - uses: ./tools/github-actions/setup-deps - name: Generate Release Manifests run: make generate-manifests IMAGE=envoyproxy/gateway-dev TAG=latest OUTPUT_DIR=release-artifacts diff --git a/tools/src/controller-gen/go.mod b/tools/src/controller-gen/go.mod index c2ca9583df5..ebafb3d2757 100644 --- a/tools/src/controller-gen/go.mod +++ b/tools/src/controller-gen/go.mod @@ -1,6 +1,6 @@ module local -go 1.20 +go 1.21 require sigs.k8s.io/controller-tools v0.13.0 diff --git a/tools/src/crd-ref-docs/go.mod b/tools/src/crd-ref-docs/go.mod index 6b561c71ab7..6a27606ad34 100644 --- a/tools/src/crd-ref-docs/go.mod +++ b/tools/src/crd-ref-docs/go.mod @@ -1,6 +1,6 @@ module local -go 1.20 +go 1.21 require github.com/elastic/crd-ref-docs v0.0.9 diff --git a/tools/src/golangci-lint/go.mod b/tools/src/golangci-lint/go.mod index 0f4db103723..35588a57d89 100644 --- a/tools/src/golangci-lint/go.mod +++ b/tools/src/golangci-lint/go.mod @@ -1,6 +1,6 @@ module local -go 1.20 +go 1.21 require github.com/golangci/golangci-lint v1.55.1 diff --git a/tools/src/helm-docs/go.mod b/tools/src/helm-docs/go.mod index 82d55d2d43f..682bddcdc09 100644 --- a/tools/src/helm-docs/go.mod +++ b/tools/src/helm-docs/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway/tools/src/helm-docs -go 1.20 +go 1.21 require github.com/norwoodj/helm-docs v1.11.3 diff --git a/tools/src/kind/go.mod b/tools/src/kind/go.mod index eaf6166439a..160b8d84b52 100644 --- a/tools/src/kind/go.mod +++ b/tools/src/kind/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway/tools/src/kind -go 1.20 +go 1.21 require sigs.k8s.io/kind v0.20.0 diff --git a/tools/src/protoc-gen-go-grpc/go.mod b/tools/src/protoc-gen-go-grpc/go.mod index 7d3884774c6..079bab201a9 100644 --- a/tools/src/protoc-gen-go-grpc/go.mod +++ b/tools/src/protoc-gen-go-grpc/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway/tools/src/protoc-gen-go-grpc -go 1.20 +go 1.21 require google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 diff --git a/tools/src/protoc-gen-go/go.mod b/tools/src/protoc-gen-go/go.mod index 112de585840..5cbba95aa00 100644 --- a/tools/src/protoc-gen-go/go.mod +++ b/tools/src/protoc-gen-go/go.mod @@ -1,5 +1,5 @@ module github.com/envoyproxy/gateway/tools/src/protoc-gen-go -go 1.20 +go 1.21 require google.golang.org/protobuf v1.30.0 diff --git a/tools/src/setup-envtest/go.mod b/tools/src/setup-envtest/go.mod index 99b4fd7a633..7c22047aa6d 100644 --- a/tools/src/setup-envtest/go.mod +++ b/tools/src/setup-envtest/go.mod @@ -1,6 +1,6 @@ module local -go 1.20 +go 1.21 require sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20220706173534-cd0058ad295c From 6d532c12fd655f0820bf71b3f310c09b0f0bddc5 Mon Sep 17 00:00:00 2001 From: zirain Date: Tue, 31 Oct 2023 22:46:55 -0500 Subject: [PATCH 39/55] conformance: Enable HTTPRouteBackendProtocolH2C conformance test (#2136) * nit Signed-off-by: zirain * build Cluster depends on route type and service appProtocol Signed-off-by: zirain * enable HTTPRouteBackendProtocolH2C conformance test Signed-off-by: zirain * lint Signed-off-by: zirain * fix Signed-off-by: zirain * address comment Signed-off-by: zirain * move to package internal/ir Signed-off-by: zirain --------- Signed-off-by: zirain --- internal/gatewayapi/route.go | 30 +++++++++++++++++-- ...ndtrafficpolicy-with-loadbalancer.out.yaml | 2 ++ ...ckendtrafficpolicy-with-ratelimit.out.yaml | 2 ++ ...route-with-valid-extension-filter.out.yaml | 1 + ...-namespace-with-allowed-httproute.out.yaml | 1 + ...her-namespace-allowed-by-refgrant.out.yaml | 1 + ...ith-tls-terminate-and-passthrough.out.yaml | 2 ++ ...ith-same-algorithm-different-fqdn.out.yaml | 1 + ...-valid-multiple-tls-configuration.out.yaml | 1 + ...ener-with-valid-tls-configuration.out.yaml | 1 + ...with-preexisting-status-condition.out.yaml | 1 + ...-listener-with-multiple-tcproutes.out.yaml | 1 + ...-listener-with-multiple-udproutes.out.yaml | 1 + ...teway-with-stale-status-condition.out.yaml | 1 + ...listeners-on-same-tcp-or-tls-port.out.yaml | 1 + ...th-two-listeners-on-same-udp-port.out.yaml | 1 + ...isteners-with-multiple-httproutes.out.yaml | 4 +++ ...-with-same-port-http-tcp-protocol.out.yaml | 2 ++ ...-with-same-port-http-udp-protocol.out.yaml | 2 ++ ...s-with-tcproutes-with-sectionname.out.yaml | 2 ++ ...ith-tcproutes-without-sectionname.out.yaml | 2 ++ ...s-with-udproutes-with-sectionname.out.yaml | 2 ++ ...ith-udproutes-without-sectionname.out.yaml | 2 ++ .../grpcroute-with-header-match.out.yaml | 1 + ...ute-with-method-and-service-match.out.yaml | 2 ++ .../grpcroute-with-method-match.out.yaml | 2 ++ ...oute-with-request-header-modifier.out.yaml | 1 + .../grpcroute-with-service-match.out.yaml | 2 ++ ...way-with-more-different-listeners.out.yaml | 8 +++++ ...ng-to-gateway-with-more-listeners.out.yaml | 8 +++++ ...wo-listeners-with-different-ports.out.yaml | 2 ++ ...ing-to-gateway-with-two-listeners.out.yaml | 2 ++ .../httproute-attaching-to-gateway.out.yaml | 1 + ...taching-to-listener-matching-port.out.yaml | 1 + ...ner-on-gateway-with-two-listeners.out.yaml | 1 + ...ner-with-serviceimport-backendref.out.yaml | 1 + .../httproute-attaching-to-listener.out.yaml | 1 + ...httproute-backend-request-timeout.out.yaml | 1 + .../httproute-request-timeout.out.yaml | 1 + ...-multiple-backends-and-no-weights.out.yaml | 3 ++ ...ith-multiple-backends-and-weights.out.yaml | 3 ++ ...her-namespace-allowed-by-refgrant.out.yaml | 1 + ...her-namespace-allowed-by-refgrant.out.yaml | 1 + .../httproute-with-empty-matches.out.yaml | 1 + ...er-duplicate-add-multiple-filters.out.yaml | 1 + ...with-header-filter-duplicate-adds.out.yaml | 1 + ...duplicate-remove-multiple-filters.out.yaml | 1 + ...h-header-filter-duplicate-removes.out.yaml | 1 + ...header-filter-empty-header-values.out.yaml | 1 + ...ute-with-header-filter-no-headers.out.yaml | 1 + ...tproute-with-header-filter-remove.out.yaml | 1 + ...ute-with-mirror-filter-duplicates.out.yaml | 3 ++ ...route-with-mirror-filter-multiple.out.yaml | 3 ++ ...ith-mirror-filter-service-no-port.out.yaml | 1 + ...h-mirror-filter-service-not-found.out.yaml | 1 + .../httproute-with-mirror-filter.out.yaml | 2 ++ ...-with-response-header-filter-adds.out.yaml | 1 + ...er-duplicate-add-multiple-filters.out.yaml | 1 + ...onse-header-filter-duplicate-adds.out.yaml | 1 + ...duplicate-remove-multiple-filters.out.yaml | 1 + ...e-header-filter-duplicate-removes.out.yaml | 1 + ...header-filter-empty-header-values.out.yaml | 1 + ...response-header-filter-no-headers.out.yaml | 1 + ...ith-response-header-filter-remove.out.yaml | 1 + ...single-rule-with-exact-path-match.out.yaml | 1 + ...ingle-rule-with-http-method-match.out.yaml | 1 + ...h-single-rule-with-multiple-rules.out.yaml | 3 ++ ...h-prefix-and-exact-header-matches.out.yaml | 1 + ...e-invalid-backend-refs-no-service.out.yaml | 1 + ...to-gateway-with-wildcard-hostname.out.yaml | 1 + ...to-gateway-with-wildcard-hostname.out.yaml | 2 ++ ...ite-filter-full-path-replace-http.out.yaml | 1 + ...te-filter-hostname-prefix-replace.out.yaml | 1 + ...e-with-urlrewrite-filter-hostname.out.yaml | 1 + ...ewrite-filter-invalid-filter-type.out.yaml | 1 + ...ewrite-filter-prefix-replace-http.out.yaml | 1 + ...ng-to-gateway-with-unset-hostname.out.yaml | 1 + .../httproutes-with-multiple-matches.out.yaml | 7 +++++ ...multiple-gateways-multiple-routes.out.yaml | 2 ++ .../securitypolicy-with-cors.out.yaml | 2 ++ .../testdata/securitypolicy-with-jwt.out.yaml | 2 ++ ...teway-with-listener-tls-terminate.out.yaml | 1 + .../tlsroute-attaching-to-gateway.out.yaml | 1 + .../testdata/tlsroute-multiple.out.yaml | 2 ++ ...her-namespace-allowed-by-refgrant.out.yaml | 1 + .../tlsroute-with-empty-hostname.out.yaml | 1 + ...oute-with-empty-listener-hostname.out.yaml | 1 + internal/ir/protocol.go | 27 +++++++++++++++++ internal/ir/xds.go | 10 +++---- internal/xds/translator/accesslog.go | 2 +- internal/xds/translator/cluster.go | 10 ++++++- internal/xds/translator/cluster_test.go | 1 - internal/xds/translator/jwt_authn.go | 1 - internal/xds/translator/ratelimit.go | 3 +- .../testdata/in/xds-ir/http2-route.yaml | 1 + internal/xds/translator/tracing.go | 2 +- internal/xds/translator/translator.go | 19 ------------ test/conformance/conformance_test.go | 1 - .../experimental_conformance_test.go | 1 - 99 files changed, 212 insertions(+), 35 deletions(-) create mode 100644 internal/ir/protocol.go diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 4edc6cce86c..c4feee9f3ed 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -11,7 +11,7 @@ import ( "time" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/discovery/v1" + discoveryv1 "k8s.io/api/discovery/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a1 "sigs.k8s.io/gateway-api/apis/v1alpha2" @@ -1005,6 +1005,7 @@ func (t *Translator) processDestination(backendRef gwapiv1.BackendRef, } var endpoints []*ir.DestinationEndpoint + protocol := inspectAppProtocolByRouteKind(routeType) switch KindDerefOr(backendRef.Kind, KindService) { case KindServiceImport: serviceImport := resources.GetServiceImport(backendNamespace, string(backendRef.Name)) @@ -1037,12 +1038,18 @@ func (t *Translator) processDestination(backendRef gwapiv1.BackendRef, } } + // support HTTPRouteBackendProtocolH2C + if servicePort.AppProtocol != nil && + *servicePort.AppProtocol == "kubernetes.io/h2c" { + protocol = ir.HTTP2 + } + // Route to endpoints by default if !t.EndpointRoutingDisabled { endpointSlices := resources.GetEndpointSlicesForBackend(backendNamespace, string(backendRef.Name), KindDerefOr(backendRef.Kind, KindService)) endpoints = getIREndpointsFromEndpointSlice(endpointSlices, servicePort.Name, servicePort.Protocol) } else { - // Fall back to Service CluserIP routing + // Fall back to Service ClusterIP routing ep := ir.NewDestEndpoint( service.Spec.ClusterIP, uint32(*backendRef.Port)) @@ -1052,11 +1059,28 @@ func (t *Translator) processDestination(backendRef gwapiv1.BackendRef, ds = &ir.DestinationSetting{ Weight: &weight, + Protocol: protocol, Endpoints: endpoints, } return ds, weight } +func inspectAppProtocolByRouteKind(kind gwapiv1.Kind) ir.AppProtocol { + switch kind { + case KindUDPRoute: + return ir.UDP + case KindHTTPRoute: + return ir.HTTP + case KindTCPRoute: + return ir.TCP + case KindGRPCRoute: + return ir.GRPC + case KindTLSRoute: + return ir.HTTPS + } + return ir.TCP +} + // processAllowedListenersForParentRefs finds out if the route attaches to one of our // Gateways' listeners, and if so, gets the list of listeners that allow it to // attach for each parentRef. @@ -1127,7 +1151,7 @@ func (t *Translator) processAllowedListenersForParentRefs(routeContext RouteCont return relevantRoute } -func getIREndpointsFromEndpointSlice(endpointSlices []*v1.EndpointSlice, portName string, portProtocol corev1.Protocol) []*ir.DestinationEndpoint { +func getIREndpointsFromEndpointSlice(endpointSlices []*discoveryv1.EndpointSlice, portName string, portProtocol corev1.Protocol) []*ir.DestinationEndpoint { endpoints := []*ir.DestinationEndpoint{} for _, endpointSlice := range endpointSlices { for _, endpoint := range endpointSlice.Endpoints { diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml index a8c1817427c..b6be965c840 100755 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml @@ -248,6 +248,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' loadBalancer: @@ -274,6 +275,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io loadBalancer: diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit.out.yaml index 1903b43a593..0e4723e95a9 100755 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit.out.yaml @@ -266,6 +266,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/-1/* @@ -302,6 +303,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/extensions/httproute-with-valid-extension-filter.out.yaml b/internal/gatewayapi/testdata/extensions/httproute-with-valid-extension-filter.out.yaml index d01e792dd71..e8dac2910d8 100644 --- a/internal/gatewayapi/testdata/extensions/httproute-with-valid-extension-filter.out.yaml +++ b/internal/gatewayapi/testdata/extensions/httproute-with-valid-extension-filter.out.yaml @@ -122,6 +122,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 extensionRefs: - object: diff --git a/internal/gatewayapi/testdata/gateway-allows-same-namespace-with-allowed-httproute.out.yaml b/internal/gatewayapi/testdata/gateway-allows-same-namespace-with-allowed-httproute.out.yaml index 25c3cce6796..c039814f78a 100644 --- a/internal/gatewayapi/testdata/gateway-allows-same-namespace-with-allowed-httproute.out.yaml +++ b/internal/gatewayapi/testdata/gateway-allows-same-namespace-with-allowed-httproute.out.yaml @@ -111,6 +111,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/envoy-gateway/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml index 851bdc81538..8af7e3a482e 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml @@ -118,6 +118,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml index 125a1519bac..3c16278e7d3 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml @@ -184,6 +184,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo.bar.com name: httproute/default/httproute-1/rule/0/match/0/foo_bar_com @@ -203,6 +204,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTPS weight: 1 name: envoy-gateway/gateway-1/tls-passthrough/tlsroute-1 port: 10090 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml index 806ed34a6b6..d4a11d1f117 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml @@ -120,6 +120,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml index 07a1de64cb4..7fd1fa8d757 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml @@ -120,6 +120,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml index 337937ea290..256f5fa5750 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml @@ -117,6 +117,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/gateway-with-preexisting-status-condition.out.yaml b/internal/gatewayapi/testdata/gateway-with-preexisting-status-condition.out.yaml index 7f3e382bf42..d5a4ceb4895 100644 --- a/internal/gatewayapi/testdata/gateway-with-preexisting-status-condition.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-preexisting-status-condition.out.yaml @@ -111,6 +111,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml index a88038eae96..74ac5e6d3ca 100644 --- a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml @@ -128,6 +128,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8163 + protocol: TCP weight: 1 name: envoy-gateway/gateway-1/tcp/tcproute-1 port: 10162 diff --git a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml index 754dae0c4dc..b0410c25dce 100644 --- a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml @@ -128,6 +128,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8162 + protocol: UDP weight: 1 name: envoy-gateway/gateway-1/udp/udproute-1 port: 10162 diff --git a/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml b/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml index cc331a9ec1d..7d8d30b12c1 100644 --- a/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml @@ -117,6 +117,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml index 9f6f8957295..298f66ec3c3 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml @@ -126,6 +126,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8163 + protocol: TCP weight: 1 name: envoy-gateway/gateway-1/tcp1/tcproute-1 port: 10162 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml index 4b312da21d8..7a24c09c837 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml @@ -124,6 +124,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8162 + protocol: UDP weight: 1 name: envoy-gateway/gateway-1/udp1/udproute-1 port: 10162 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-multiple-httproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-multiple-httproutes.out.yaml index d7f5bbc33e2..5da2538be94 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-multiple-httproutes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-multiple-httproutes.out.yaml @@ -180,6 +180,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo.com name: httproute/default/httproute-2/rule/0/match/0/foo_com @@ -196,6 +197,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo.com name: httproute/default/httproute-1/rule/0/match/0/foo_com @@ -219,6 +221,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar.com name: httproute/default/httproute-2/rule/0/match/0/bar_com @@ -235,6 +238,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar.com name: httproute/default/httproute-1/rule/0/match/0/bar_com diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml index da39c8b00ef..79634a36482 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml @@ -175,6 +175,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* @@ -190,6 +191,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8163 + protocol: TCP weight: 1 name: envoy-gateway/gateway-1/tcp/tcproute-1 port: 10080 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml index d59e161199d..7805c70ac38 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml @@ -175,6 +175,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* @@ -190,6 +191,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8162 + protocol: UDP weight: 1 name: envoy-gateway/gateway-1/udp/udproute-1 port: 10080 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml index 49acc6c8452..df1b7a0ae3d 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml @@ -163,6 +163,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8163 + protocol: TCP weight: 1 name: envoy-gateway/gateway-1/tcp1/tcproute-1 port: 10162 @@ -174,6 +175,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8163 + protocol: TCP weight: 1 name: envoy-gateway/gateway-1/tcp2/tcproute-2 port: 10163 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml index 759e45901db..0168d322afa 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml @@ -159,6 +159,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8163 + protocol: TCP weight: 1 name: envoy-gateway/gateway-1/tcp1/tcproute-1 port: 10161 @@ -170,6 +171,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8163 + protocol: TCP weight: 1 name: envoy-gateway/gateway-1/tcp2/tcproute-1 port: 10162 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-with-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-with-sectionname.out.yaml index a5a304ba208..a0cdded06ba 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-with-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-with-sectionname.out.yaml @@ -163,6 +163,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8162 + protocol: UDP weight: 1 name: envoy-gateway/gateway-1/udp1/udproute-1 port: 10162 @@ -173,6 +174,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8162 + protocol: UDP weight: 1 name: envoy-gateway/gateway-1/udp2/udproute-2 port: 10163 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml index 692388c6498..30aa11dd95d 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml @@ -159,6 +159,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8162 + protocol: UDP weight: 1 name: envoy-gateway/gateway-1/udp1/udproute-1 port: 10161 @@ -169,6 +170,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8162 + protocol: UDP weight: 1 name: envoy-gateway/gateway-1/udp2/udproute-1 port: 10162 diff --git a/internal/gatewayapi/testdata/grpcroute-with-header-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-header-match.out.yaml index 59d139d01c1..f0068b645d8 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-header-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-header-match.out.yaml @@ -115,6 +115,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 headerMatches: - distinct: false diff --git a/internal/gatewayapi/testdata/grpcroute-with-method-and-service-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-method-and-service-match.out.yaml index ee66e91bc17..1da89fcadb9 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-method-and-service-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-method-and-service-match.out.yaml @@ -119,6 +119,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/0/* @@ -135,6 +136,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/1/* diff --git a/internal/gatewayapi/testdata/grpcroute-with-method-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-method-match.out.yaml index b7fc079c14f..5177fb3c8fc 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-method-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-method-match.out.yaml @@ -117,6 +117,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/1/* @@ -133,6 +134,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 headerMatches: - distinct: false diff --git a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml index 1891581612e..e11ecaa5f72 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml @@ -120,6 +120,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/-1/* diff --git a/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml index 55e3230098b..3cdb86680df 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml @@ -117,6 +117,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/0/* @@ -133,6 +134,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/1/* diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-different-listeners.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-different-listeners.out.yaml index d30026097ab..d355e36099d 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-different-listeners.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-different-listeners.out.yaml @@ -350,6 +350,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo.com name: httproute/default/httproute-1/rule/0/match/0/foo_com @@ -373,6 +374,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar.com name: httproute/default/httproute-1/rule/0/match/0/bar_com @@ -396,6 +398,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo1.com name: httproute/default/httproute-1/rule/0/match/0/foo1_com @@ -419,6 +422,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar1.com name: httproute/default/httproute-1/rule/0/match/0/bar1_com @@ -442,6 +446,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo2.com name: httproute/default/httproute-1/rule/0/match/0/foo2_com @@ -465,6 +470,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar2.com name: httproute/default/httproute-1/rule/0/match/0/bar2_com @@ -488,6 +494,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo3.com name: httproute/default/httproute-1/rule/0/match/0/foo3_com @@ -511,6 +518,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar3.com name: httproute/default/httproute-1/rule/0/match/0/bar3_com diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-listeners.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-listeners.out.yaml index de694b38c8c..6022df48ce9 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-listeners.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-listeners.out.yaml @@ -322,6 +322,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo.com name: httproute/default/httproute-1/rule/0/match/0/foo_com @@ -345,6 +346,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar.com name: httproute/default/httproute-1/rule/0/match/0/bar_com @@ -368,6 +370,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo1.com name: httproute/default/httproute-1/rule/0/match/0/foo1_com @@ -391,6 +394,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar1.com name: httproute/default/httproute-1/rule/0/match/0/bar1_com @@ -414,6 +418,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo2.com name: httproute/default/httproute-1/rule/0/match/0/foo2_com @@ -437,6 +442,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar2.com name: httproute/default/httproute-1/rule/0/match/0/bar2_com @@ -460,6 +466,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo3.com name: httproute/default/httproute-1/rule/0/match/0/foo3_com @@ -483,6 +490,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar3.com name: httproute/default/httproute-1/rule/0/match/0/bar3_com diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml index 737d43da668..bf3911172f2 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml @@ -150,6 +150,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* @@ -173,6 +174,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners.out.yaml index e88edaa93ac..bb65228cd75 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners.out.yaml @@ -142,6 +142,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: foo.com name: httproute/default/httproute-1/rule/0/match/0/foo_com @@ -165,6 +166,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar.com name: httproute/default/httproute-1/rule/0/match/0/bar_com diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway.out.yaml index ae14d6cbe63..7f7a8f3e1d2 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway.out.yaml @@ -111,6 +111,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-matching-port.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-matching-port.out.yaml index a8d9a02048b..6b4b54e6652 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-matching-port.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-matching-port.out.yaml @@ -115,6 +115,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-on-gateway-with-two-listeners.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-on-gateway-with-two-listeners.out.yaml index dddac198b29..c80b1d0fc47 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-on-gateway-with-two-listeners.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-on-gateway-with-two-listeners.out.yaml @@ -150,6 +150,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: bar.com name: httproute/default/httproute-1/rule/0/match/0/bar_com diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref.out.yaml index f5334296b70..8dd36eaab4a 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref.out.yaml @@ -115,6 +115,7 @@ xdsIR: - endpoints: - host: 8.8.8.8 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener.out.yaml index aae08dee870..292fa7c579e 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener.out.yaml @@ -113,6 +113,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml b/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml index d910e6e5442..e8a69536bcd 100755 --- a/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml +++ b/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml @@ -115,6 +115,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml b/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml index 8e55e85f2be..784af59968c 100644 --- a/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml +++ b/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml @@ -115,6 +115,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-no-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-no-weights.out.yaml index d7fc6c8c81c..0a5d688c520 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-no-weights.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-no-weights.out.yaml @@ -115,14 +115,17 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml index 06e52bfe474..b9914097e1c 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml @@ -118,14 +118,17 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 2 - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 3 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/httproute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml index c9c5a58e59d..feb27921697 100644 --- a/internal/gatewayapi/testdata/httproute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml @@ -113,6 +113,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-with-backendref-serviceimport-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/httproute-with-backendref-serviceimport-in-other-namespace-allowed-by-refgrant.out.yaml index 20ed4f04dbb..ce891f3e31a 100644 --- a/internal/gatewayapi/testdata/httproute-with-backendref-serviceimport-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-backendref-serviceimport-in-other-namespace-allowed-by-refgrant.out.yaml @@ -115,6 +115,7 @@ xdsIR: - endpoints: - host: 8.8.8.8 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-with-empty-matches.out.yaml b/internal/gatewayapi/testdata/httproute-with-empty-matches.out.yaml index 14f190acbc5..77b8f9ed8d0 100644 --- a/internal/gatewayapi/testdata/httproute-with-empty-matches.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-empty-matches.out.yaml @@ -110,6 +110,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/-1/* diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml index b186106f0ce..eaf4f97f422 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml @@ -141,6 +141,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml index 55a7d36259c..d95b214ddbf 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml @@ -157,6 +157,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-remove-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-remove-multiple-filters.out.yaml index 7f12824c553..18f1c0832a5 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-remove-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-remove-multiple-filters.out.yaml @@ -127,6 +127,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-removes.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-removes.out.yaml index a466c593e7a..d8f6fb86074 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-removes.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-removes.out.yaml @@ -122,6 +122,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml index 2e4b11c24cb..3d7bcf38534 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml @@ -132,6 +132,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-no-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-no-headers.out.yaml index d2d65c9dd62..e8ded08b7a7 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-no-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-no-headers.out.yaml @@ -119,6 +119,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-remove.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-remove.out.yaml index 2ae92bdd504..f8f8387c8b0 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-remove.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-remove.out.yaml @@ -123,6 +123,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-duplicates.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-duplicates.out.yaml index afa9f1c4524..ebd06bcda6b 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-duplicates.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-duplicates.out.yaml @@ -129,6 +129,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io mirrors: @@ -137,12 +138,14 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 - name: httproute/default/httproute-1/rule/0-mirror-1 settings: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml index d5aa80f0bd1..70b570f89f7 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml @@ -151,6 +151,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io mirrors: @@ -159,12 +160,14 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 - name: httproute/default/httproute-1/rule/0-mirror-2 settings: - endpoints: - host: 7.6.5.4 port: 8080 + protocol: HTTP weight: 1 name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml index 85b30ec48e6..5c4d788a2e6 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml @@ -123,6 +123,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml index 2858e31d5aa..1dd25e0427f 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml @@ -123,6 +123,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter.out.yaml index 6d64d583a12..e3355ceb10c 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter.out.yaml @@ -123,6 +123,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io mirrors: @@ -131,6 +132,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml index d376bb2bd31..fa69c95125d 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml @@ -153,6 +153,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml index 082da467faa..c6cd70c426e 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml @@ -141,6 +141,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml index 7387da265c8..7c8fdc5b531 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml @@ -157,6 +157,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-remove-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-remove-multiple-filters.out.yaml index 5050624b40e..447fac2d3be 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-remove-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-remove-multiple-filters.out.yaml @@ -127,6 +127,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-removes.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-removes.out.yaml index a6d34ce0944..5b623cd6ba8 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-removes.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-removes.out.yaml @@ -122,6 +122,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml index dce73fb7d96..328798f4ac2 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml @@ -132,6 +132,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-headers.out.yaml index 80d939f8009..f0b1cd0d639 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-headers.out.yaml @@ -119,6 +119,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-remove.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-remove.out.yaml index e1d73c90422..6d52a258a0e 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-remove.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-remove.out.yaml @@ -123,6 +123,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-exact-path-match.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-exact-path-match.out.yaml index 3de870613b9..5c98a914fd0 100644 --- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-exact-path-match.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-exact-path-match.out.yaml @@ -112,6 +112,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-http-method-match.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-http-method-match.out.yaml index fdb845ae1d0..1e2121fd72d 100644 --- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-http-method-match.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-http-method-match.out.yaml @@ -110,6 +110,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 headerMatches: - distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml index c5e10904d8e..b7fb0e5c1bb 100644 --- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml @@ -142,6 +142,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 headerMatches: - distinct: false @@ -166,6 +167,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/1/match/0/* @@ -182,6 +184,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 headerMatches: - distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-path-prefix-and-exact-header-matches.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-path-prefix-and-exact-header-matches.out.yaml index 4bb51c36abf..b82e6dca274 100644 --- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-path-prefix-and-exact-header-matches.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-path-prefix-and-exact-header-matches.out.yaml @@ -116,6 +116,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 headerMatches: - distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml b/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml index cd095768ea3..c2f5181aff0 100644 --- a/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml @@ -116,6 +116,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-with-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml index 8654dbf94b4..16f154f19c6 100644 --- a/internal/gatewayapi/testdata/httproute-with-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml @@ -114,6 +114,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-two-specific-hostnames-attaching-to-gateway-with-wildcard-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-two-specific-hostnames-attaching-to-gateway-with-wildcard-hostname.out.yaml index f89e3718881..17b2fc20b95 100644 --- a/internal/gatewayapi/testdata/httproute-with-two-specific-hostnames-attaching-to-gateway-with-wildcard-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-two-specific-hostnames-attaching-to-gateway-with-wildcard-hostname.out.yaml @@ -115,6 +115,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io @@ -131,6 +132,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: whales.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/whales_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-full-path-replace-http.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-full-path-replace-http.out.yaml index a216ec0d08e..b1cefeec922 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-full-path-replace-http.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-full-path-replace-http.out.yaml @@ -122,6 +122,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname-prefix-replace.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname-prefix-replace.out.yaml index 1758895c365..0cdf34621e4 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname-prefix-replace.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname-prefix-replace.out.yaml @@ -123,6 +123,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname.out.yaml index c89bf6ad9e6..84e6ef65a36 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname.out.yaml @@ -120,6 +120,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-filter-type.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-filter-type.out.yaml index 8b3354f1a3b..129286419c3 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-filter-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-filter-type.out.yaml @@ -120,6 +120,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-prefix-replace-http.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-prefix-replace-http.out.yaml index a77717cbd76..c0a7f60f73a 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-prefix-replace-http.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-prefix-replace-http.out.yaml @@ -122,6 +122,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproute-with-wildcard-hostname-attaching-to-gateway-with-unset-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-wildcard-hostname-attaching-to-gateway-with-unset-hostname.out.yaml index 6f9a6e0f893..35c8b7ae01c 100644 --- a/internal/gatewayapi/testdata/httproute-with-wildcard-hostname-attaching-to-gateway-with-unset-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-wildcard-hostname-attaching-to-gateway-with-unset-hostname.out.yaml @@ -113,6 +113,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*.envoyproxy.io' name: httproute/default/httproute-1/rule/0/match/0/*_envoyproxy_io diff --git a/internal/gatewayapi/testdata/httproutes-with-multiple-matches.out.yaml b/internal/gatewayapi/testdata/httproutes-with-multiple-matches.out.yaml index 83b255739cf..5b495b41e03 100644 --- a/internal/gatewayapi/testdata/httproutes-with-multiple-matches.out.yaml +++ b/internal/gatewayapi/testdata/httproutes-with-multiple-matches.out.yaml @@ -298,6 +298,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: example.com name: httproute/envoy-gateway/httproute-2/rule/0/match/0/example_com @@ -318,6 +319,7 @@ xdsIR: - endpoints: - host: 8.8.8.8 port: 8080 + protocol: HTTP weight: 1 hostname: example.com name: httproute/envoy-gateway/httproute-3/rule/0/match/0/example_com @@ -334,6 +336,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 headerMatches: - distinct: false @@ -354,6 +357,7 @@ xdsIR: - endpoints: - host: 8.8.8.8 port: 8080 + protocol: HTTP weight: 1 hostname: example.net name: httproute/envoy-gateway/httproute-5/rule/0/match/0/example_net @@ -370,6 +374,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*.com' name: httproute/envoy-gateway/httproute-1/rule/0/match/0/*_com @@ -386,6 +391,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*.net' name: httproute/envoy-gateway/httproute-1/rule/0/match/0/*_net @@ -402,6 +408,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: '*' name: httproute/envoy-gateway/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml b/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml index b7a57690426..3074568ba9e 100755 --- a/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml +++ b/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml @@ -235,6 +235,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io @@ -264,6 +265,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: example.com name: httproute/default/httproute-2/rule/0/match/0/example_com diff --git a/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml index 0a2b0cbb239..9e2fc0e1fb6 100755 --- a/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml @@ -292,6 +292,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/-1/* @@ -334,6 +335,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml index 8acf1b66a51..c14252d3ef1 100755 --- a/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml @@ -273,6 +273,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: GRPC weight: 1 hostname: '*' jwt: @@ -317,6 +318,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io jwt: diff --git a/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml b/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml index 20df52b004f..aea8b733cab 100644 --- a/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml +++ b/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml @@ -103,6 +103,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: TCP weight: 1 name: envoy-gateway/gateway-1/tls/tcproute-1 port: 10090 diff --git a/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml b/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml index 8e45df442d5..af83c0f97df 100644 --- a/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml @@ -100,6 +100,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTPS weight: 1 name: envoy-gateway/gateway-1/tls/tlsroute-1 port: 10090 diff --git a/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml b/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml index 77b25d4495f..bf5d7a8b744 100644 --- a/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml @@ -134,6 +134,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTPS weight: 1 name: envoy-gateway/gateway-1/tls/tlsroute-1 port: 10091 @@ -148,6 +149,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTPS weight: 1 name: envoy-gateway/gateway-1/tls/tlsroute-2 port: 10091 diff --git a/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml index 4264efe0bef..014d9dff690 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml @@ -101,6 +101,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTPS weight: 1 name: envoy-gateway/gateway-1/tls/tlsroute-1 port: 10090 diff --git a/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml index cb9f727850e..19779d07c21 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml @@ -99,6 +99,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTPS weight: 1 name: envoy-gateway/gateway-1/tls/tlsroute-1 port: 10091 diff --git a/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml index 414c6b8e574..bd87196bc86 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml @@ -101,6 +101,7 @@ xdsIR: - endpoints: - host: 7.7.7.7 port: 8080 + protocol: HTTPS weight: 1 name: envoy-gateway/gateway-1/tls/tlsroute-1 port: 10091 diff --git a/internal/ir/protocol.go b/internal/ir/protocol.go new file mode 100644 index 00000000000..805443921b2 --- /dev/null +++ b/internal/ir/protocol.go @@ -0,0 +1,27 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package ir + +type AppProtocol string + +const ( + // GRPC declares that the port carries gRPC traffic. + GRPC AppProtocol = "GRPC" + // GRPCWeb declares that the port carries gRPC traffic. + GRPCWeb AppProtocol = "GRPC-Web" + // HTTP declares that the port carries HTTP/1.1 traffic. + // Note that HTTP/1.0 or earlier may not be supported by the proxy. + HTTP AppProtocol = "HTTP" + // HTTP2 declares that the port carries HTTP/2 traffic. + HTTP2 AppProtocol = "HTTP2" + // HTTPS declares that the port carries HTTPS traffic. + HTTPS AppProtocol = "HTTPS" + // TCP declares the port uses TCP. + // This is the default protocol for a service port. + TCP AppProtocol = "TCP" + // UDP declares that the port uses UDP. + UDP AppProtocol = "UDP" +) diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 262a3891ff5..9411edba70d 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -13,7 +13,6 @@ import ( "github.com/tetratelabs/multierror" "golang.org/x/exp/slices" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -172,7 +171,8 @@ type HTTPListener struct { TLS []*TLSListenerConfig `json:"tls,omitempty" yaml:"tls,omitempty"` // Routes associated with HTTP traffic to the service. Routes []*HTTPRoute `json:"routes,omitempty" yaml:"routes,omitempty"` - // IsHTTP2 is set if the upstream client as well as the downstream server are configured to serve HTTP2 traffic. + // IsHTTP2 is set if the listener is configured to serve HTTP2 traffic, + // grpc-web and grpc-stats are also enabled if this is set. IsHTTP2 bool `json:"isHTTP2" yaml:"isHTTP2"` // TCPKeepalive configuration for the listener TCPKeepalive *TCPKeepalive `json:"tcpKeepalive,omitempty" yaml:"tcpKeepalive,omitempty"` @@ -467,7 +467,6 @@ func (r RouteDestination) Validate() error { } return errs - } // DestinationSetting holds the settings associated with the destination @@ -475,7 +474,9 @@ func (r RouteDestination) Validate() error { type DestinationSetting struct { // Weight associated with this destination. // Note: Weight is not used in TCP/UDP route. - Weight *uint32 `json:"weight,omitempty" yaml:"weight,omitempty"` + Weight *uint32 `json:"weight,omitempty" yaml:"weight,omitempty"` + // Protocol associated with this destination/port. + Protocol AppProtocol `json:"protocol" yaml:"protocol"` Endpoints []*DestinationEndpoint `json:"endpoints,omitempty" yaml:"endpoints,omitempty"` } @@ -489,7 +490,6 @@ func (d DestinationSetting) Validate() error { } return errs - } // DestinationEndpoint holds the endpoint details associated with the destination diff --git a/internal/xds/translator/accesslog.go b/internal/xds/translator/accesslog.go index 25b627e4b81..0fa06c9a211 100644 --- a/internal/xds/translator/accesslog.go +++ b/internal/xds/translator/accesslog.go @@ -243,13 +243,13 @@ func processClusterForAccessLog(tCtx *types.ResourceVersionTable, al *ir.AccessL ds := &ir.DestinationSetting{ Weight: ptr.To(uint32(1)), + Protocol: ir.GRPC, Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(otel.Host, otel.Port)}, } if err := addXdsCluster(tCtx, &xdsClusterArgs{ name: clusterName, settings: []*ir.DestinationSetting{ds}, tSocket: nil, - protocol: HTTP2, endpointType: DefaultEndpointType, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 0b30c07176c..a5be54e6d70 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -60,7 +60,15 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { cluster.RespectDnsTtl = true } - if args.protocol == HTTP2 { + isHTTP2 := false + for _, ds := range args.settings { + if ds.Protocol == ir.GRPC || + ds.Protocol == ir.HTTP2 { + isHTTP2 = true + break + } + } + if isHTTP2 { cluster.TypedExtensionProtocolOptions = buildTypedExtensionProtocolOptions() } diff --git a/internal/xds/translator/cluster_test.go b/internal/xds/translator/cluster_test.go index 30235b6d4d6..b7a024e6cf5 100644 --- a/internal/xds/translator/cluster_test.go +++ b/internal/xds/translator/cluster_test.go @@ -31,7 +31,6 @@ func TestBuildXdsCluster(t *testing.T) { args := &xdsClusterArgs{ name: bootstrapXdsCluster.Name, tSocket: bootstrapXdsCluster.TransportSocket, - protocol: HTTP2, endpointType: DefaultEndpointType, } dynamicXdsCluster := buildXdsCluster(args) diff --git a/internal/xds/translator/jwt_authn.go b/internal/xds/translator/jwt_authn.go index 7003bcac3fb..34bf2841e48 100644 --- a/internal/xds/translator/jwt_authn.go +++ b/internal/xds/translator/jwt_authn.go @@ -268,7 +268,6 @@ func createJWKSClusters(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRoute name: jwks.name, settings: []*ir.DestinationSetting{ds}, tSocket: tSocket, - protocol: DefaultProtocol, endpointType: epType, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err diff --git a/internal/xds/translator/ratelimit.go b/internal/xds/translator/ratelimit.go index 6a347904079..427c6bf7ec5 100644 --- a/internal/xds/translator/ratelimit.go +++ b/internal/xds/translator/ratelimit.go @@ -8,6 +8,7 @@ package translator import ( "bytes" "errors" + "net/url" "strconv" "strings" @@ -432,6 +433,7 @@ func (t *Translator) createRateLimitServiceCluster(tCtx *types.ResourceVersionTa host, port := t.getRateLimitServiceGrpcHostPort() ds := &ir.DestinationSetting{ Weight: ptr.To(uint32(1)), + Protocol: ir.GRPC, Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(host, uint32(port))}, } @@ -444,7 +446,6 @@ func (t *Translator) createRateLimitServiceCluster(tCtx *types.ResourceVersionTa name: clusterName, settings: []*ir.DestinationSetting{ds}, tSocket: tSocket, - protocol: HTTP2, endpointType: DefaultEndpointType, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err diff --git a/internal/xds/translator/testdata/in/xds-ir/http2-route.yaml b/internal/xds/translator/testdata/in/xds-ir/http2-route.yaml index ea4db20ccc9..2a61570f0ec 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http2-route.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http2-route.yaml @@ -24,3 +24,4 @@ http: - endpoints: - host: "1.2.3.4" port: 50000 + protocol: GRPC diff --git a/internal/xds/translator/tracing.go b/internal/xds/translator/tracing.go index 53a7c46a885..78127f283b3 100644 --- a/internal/xds/translator/tracing.go +++ b/internal/xds/translator/tracing.go @@ -125,13 +125,13 @@ func processClusterForTracing(tCtx *types.ResourceVersionTable, tracing *ir.Trac ds := &ir.DestinationSetting{ Weight: ptr.To(uint32(1)), + Protocol: ir.GRPC, Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(tracing.Provider.Host, uint32(tracing.Provider.Port))}, } if err := addXdsCluster(tCtx, &xdsClusterArgs{ name: clusterName, settings: []*ir.DestinationSetting{ds}, tSocket: nil, - protocol: HTTP2, endpointType: DefaultEndpointType, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 82fd0937aef..e65e8cac08a 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -153,11 +153,6 @@ func (t *Translator) processHTTPListenerXdsTranslation(tCtx *types.ResourceVersi } } - protocol := DefaultProtocol - if httpListener.IsHTTP2 { - protocol = HTTP2 - } - // store virtual hosts by domain vHosts := map[string]*routev3.VirtualHost{} // keep track of order by using a list as well as the map @@ -215,7 +210,6 @@ func (t *Translator) processHTTPListenerXdsTranslation(tCtx *types.ResourceVersi name: httpRoute.Destination.Name, settings: httpRoute.Destination.Settings, tSocket: nil, - protocol: protocol, endpointType: Static, loadBalancer: httpRoute.LoadBalancer, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { @@ -229,7 +223,6 @@ func (t *Translator) processHTTPListenerXdsTranslation(tCtx *types.ResourceVersi name: mirrorDest.Name, settings: mirrorDest.Settings, tSocket: nil, - protocol: protocol, endpointType: Static, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err @@ -276,7 +269,6 @@ func processTCPListenerXdsTranslation(tCtx *types.ResourceVersionTable, tcpListe name: tcpListener.Destination.Name, settings: tcpListener.Destination.Settings, tSocket: nil, - protocol: DefaultProtocol, endpointType: Static, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err @@ -313,7 +305,6 @@ func processUDPListenerXdsTranslation(tCtx *types.ResourceVersionTable, udpListe name: udpListener.Destination.Name, settings: udpListener.Destination.Settings, tSocket: nil, - protocol: DefaultProtocol, endpointType: Static, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err @@ -442,22 +433,12 @@ type xdsClusterArgs struct { name string settings []*ir.DestinationSetting tSocket *corev3.TransportSocket - protocol ProtocolType endpointType EndpointType loadBalancer *ir.LoadBalancer } -type ProtocolType int type EndpointType int -const ( - DefaultProtocol ProtocolType = iota - TCP - UDP - HTTP - HTTP2 -) - const ( DefaultEndpointType EndpointType = iota Static diff --git a/test/conformance/conformance_test.go b/test/conformance/conformance_test.go index 0e08a5a1ad1..da88413075e 100644 --- a/test/conformance/conformance_test.go +++ b/test/conformance/conformance_test.go @@ -50,7 +50,6 @@ func TestGatewayAPIConformance(t *testing.T) { SkipTests: []string{ tests.GatewayStaticAddresses.ShortName, tests.GatewayWithAttachedRoutes.ShortName, - tests.HTTPRouteBackendProtocolH2C.ShortName, }, ExemptFeatures: suite.MeshCoreFeatures, }) diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index a6a308cbbce..c5eae8f2dba 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -99,7 +99,6 @@ func experimentalConformance(t *testing.T) { SkipTests: []string{ tests.GatewayStaticAddresses.ShortName, tests.GatewayWithAttachedRoutes.ShortName, - tests.HTTPRouteBackendProtocolH2C.ShortName, }, ExemptFeatures: suite.MeshCoreFeatures, }, From 93a12e7fc697882186c1efb88ebc0aedc6c648e8 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Tue, 31 Oct 2023 23:20:41 -0700 Subject: [PATCH 40/55] Fix attachedRoutes computation (#2085) * Fix attachedRoutes computation * Fixes: https://github.com/envoyproxy/gateway/issues/2077 * Fixes: https://github.com/envoyproxy/gateway/issues/1916 Signed-off-by: Arko Dasgupta * make testdata Signed-off-by: Arko Dasgupta --------- Signed-off-by: Arko Dasgupta --- .../out/rejected-http-route.route.yaml | 4 +- internal/gatewayapi/route.go | 58 +++++++------------ ...th-extension-filter-invalid-group.out.yaml | 2 +- ...ith-non-matching-extension-filter.out.yaml | 2 +- ...with-unsupported-extension-filter.out.yaml | 2 +- ...valid-allowed-namespaces-selector.out.yaml | 4 +- ...with-invalid-allowed-routes-group.out.yaml | 4 +- ...allowed-routes-kind-and-supported.out.yaml | 4 +- ...-with-invalid-allowed-routes-kind.out.yaml | 4 +- ...th-invalid-allowed-tls-route-kind.out.yaml | 4 +- ...nvalid-multiple-tls-configuration.out.yaml | 2 +- ...id-tls-configuration-invalid-mode.out.yaml | 2 +- ...configuration-no-certificate-refs.out.yaml | 2 +- ...ion-no-valid-certificate-for-fqdn.out.yaml | 2 +- ...nfiguration-secret-does-not-exist.out.yaml | 2 +- ...uration-secret-in-other-namespace.out.yaml | 2 +- ...configuration-secret-is-not-valid.out.yaml | 2 +- ...ssing-allowed-namespaces-selector.out.yaml | 4 +- ...route-with-mismatch-port-protocol.out.yaml | 2 +- ...h-tcproute-with-multiple-backends.out.yaml | 2 +- ...with-tcproute-with-multiple-rules.out.yaml | 2 +- ...route-with-mismatch-port-protocol.out.yaml | 2 +- ...h-udproute-with-multiple-backends.out.yaml | 2 +- ...with-udproute-with-multiple-rules.out.yaml | 2 +- ...istener-with-unsupported-protocol.out.yaml | 4 +- ...-listener-with-multiple-tcproutes.out.yaml | 2 +- ...-listener-with-multiple-udproutes.out.yaml | 2 +- ...listeners-on-same-tcp-or-tls-port.out.yaml | 2 +- ...th-two-listeners-on-same-udp-port.out.yaml | 2 +- ...d-tlsroute-same-hostname-and-port.out.yaml | 4 +- ...eners-with-same-port-and-hostname.out.yaml | 4 +- ...me-port-and-incompatible-protocol.out.yaml | 4 +- ...ith-tcproutes-without-sectionname.out.yaml | 4 +- ...ith-udproutes-without-sectionname.out.yaml | 4 +- ...-with-header-filter-empty-headers.out.yaml | 2 +- ...ith-header-filter-invalid-headers.out.yaml | 2 +- ...th-header-filter-no-valid-headers.out.yaml | 2 +- ...to-gateway-with-wildcard-hostname.out.yaml | 2 +- ...direct-filter-invalid-filter-type.out.yaml | 2 +- ...th-redirect-filter-invalid-scheme.out.yaml | 2 +- ...th-redirect-filter-invalid-status.out.yaml | 2 +- ...ponse-header-filter-empty-headers.out.yaml | 2 +- ...nse-header-filter-invalid-headers.out.yaml | 2 +- ...se-header-filter-no-valid-headers.out.yaml | 2 +- ...rlrewrite-filter-invalid-hostname.out.yaml | 2 +- ...e-filter-invalid-multiple-filters.out.yaml | 2 +- ...lrewrite-filter-invalid-path-type.out.yaml | 2 +- ...th-urlrewrite-filter-invalid-path.out.yaml | 2 +- ...th-urlrewrite-filter-missing-path.out.yaml | 2 +- ...attaching-to-gateway-with-no-mode.out.yaml | 2 +- ...er-both-passthrough-and-cert-data.out.yaml | 2 +- test/conformance/conformance_test.go | 1 - .../experimental_conformance_test.go | 1 - 53 files changed, 85 insertions(+), 101 deletions(-) diff --git a/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml b/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml index 1cf2dc126c2..c578d14aef5 100644 --- a/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml +++ b/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml @@ -67,8 +67,8 @@ httpRoutes: parents: - conditions: - lastTransitionTime: null - message: There are no ready listeners for this parent ref - reason: NoReadyListeners + message: No listeners included by this parent ref allowed this attachment. + reason: NotAllowedByListeners status: "False" type: Accepted - lastTransitionTime: null diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index c4feee9f3ed..fc79ddb790c 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -572,12 +572,6 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route } irListener.Routes = append(irListener.Routes, perHostRoutes...) } - // Theoretically there should only be one parent ref per - // Route that attaches to a given Listener, so fine to just increment here, but we - // might want to check to ensure we're not double-counting. - if len(routeRoutes) > 0 { - listener.IncrementAttachedRoutes() - } } return hasHostnameIntersection @@ -680,12 +674,6 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour gwXdsIR := xdsIR[irKey] gwXdsIR.TCP = append(gwXdsIR.TCP, irListener) - // Theoretically there should only be one parent ref per - // Route that attaches to a given Listener, so fine to just increment here, but we - // might want to check to ensure we're not double-counting. - if len(irListener.Destination.Settings) > 0 { - listener.IncrementAttachedRoutes() - } } if !hasHostnameIntersection { @@ -792,7 +780,7 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour accepted := false for _, listener := range parentRef.listeners { // only one route is allowed for a UDP listener - if listener.AttachedRoutes() > 0 { + if listener.AttachedRoutes() > 1 { continue } if !listener.IsReady() { @@ -817,12 +805,6 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour gwXdsIR := xdsIR[irKey] gwXdsIR.UDP = append(gwXdsIR.UDP, irListener) - // Theoretically there should only be one parent ref per - // Route that attaches to a given Listener, so fine to just increment here, but we - // might want to check to ensure we're not double-counting. - if len(irListener.Destination.Settings) > 0 { - listener.IncrementAttachedRoutes() - } } // If no negative conditions have been set, the route is considered "Accepted=True". @@ -929,7 +911,7 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour accepted := false for _, listener := range parentRef.listeners { // only one route is allowed for a TCP listener - if listener.AttachedRoutes() > 0 { + if listener.AttachedRoutes() > 1 { continue } if !listener.IsReady() { @@ -954,12 +936,6 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour gwXdsIR := xdsIR[irKey] gwXdsIR.TCP = append(gwXdsIR.TCP, irListener) - // Theoretically there should only be one parent ref per - // Route that attaches to a given Listener, so fine to just increment here, but we - // might want to check to ensure we're not double-counting. - if len(irListener.Destination.Settings) > 0 { - listener.IncrementAttachedRoutes() - } } // If no negative conditions have been set, the route is considered "Accepted=True". @@ -1110,16 +1086,6 @@ func (t *Translator) processAllowedListenersForParentRefs(routeContext RouteCont continue } - if !HasReadyListener(selectedListeners) { - parentRefCtx.SetCondition(routeContext, - gwapiv1.RouteConditionAccepted, - metav1.ConditionFalse, - "NoReadyListeners", - "There are no ready listeners for this parent ref", - ) - continue - } - var allowedListeners []*ListenerContext for _, listener := range selectedListeners { acceptedKind := GetRouteType(routeContext) @@ -1139,6 +1105,26 @@ func (t *Translator) processAllowedListenersForParentRefs(routeContext RouteCont continue } + // Its safe to increment AttachedRoutes since we've found a valid parentRef + // and the listener allows this Route kind + + // Theoretically there should only be one parent ref per + // Route that attaches to a given Listener, so fine to just increment here, but we + // might want to check to ensure we're not double-counting. + for _, listener := range allowedListeners { + listener.IncrementAttachedRoutes() + } + + if !HasReadyListener(selectedListeners) { + parentRefCtx.SetCondition(routeContext, + gwapiv1.RouteConditionAccepted, + metav1.ConditionFalse, + "NoReadyListeners", + "There are no ready listeners for this parent ref", + ) + continue + } + parentRefCtx.SetListeners(allowedListeners...) parentRefCtx.SetCondition(routeContext, diff --git a/internal/gatewayapi/testdata/extensions/httproute-with-extension-filter-invalid-group.out.yaml b/internal/gatewayapi/testdata/extensions/httproute-with-extension-filter-invalid-group.out.yaml index 2828bf08166..07b9b2ebd37 100644 --- a/internal/gatewayapi/testdata/extensions/httproute-with-extension-filter-invalid-group.out.yaml +++ b/internal/gatewayapi/testdata/extensions/httproute-with-extension-filter-invalid-group.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/extensions/httproute-with-non-matching-extension-filter.out.yaml b/internal/gatewayapi/testdata/extensions/httproute-with-non-matching-extension-filter.out.yaml index d9271e30fc9..cabc3be656a 100644 --- a/internal/gatewayapi/testdata/extensions/httproute-with-non-matching-extension-filter.out.yaml +++ b/internal/gatewayapi/testdata/extensions/httproute-with-non-matching-extension-filter.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/extensions/httproute-with-unsupported-extension-filter.out.yaml b/internal/gatewayapi/testdata/extensions/httproute-with-unsupported-extension-filter.out.yaml index 5f8e8829df6..6aa7961381b 100644 --- a/internal/gatewayapi/testdata/extensions/httproute-with-unsupported-extension-filter.out.yaml +++ b/internal/gatewayapi/testdata/extensions/httproute-with-unsupported-extension-filter.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-namespaces-selector.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-namespaces-selector.out.yaml index d360fbafe44..815c262ebd9 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-namespaces-selector.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-namespaces-selector.out.yaml @@ -64,8 +64,8 @@ httpRoutes: parents: - conditions: - lastTransitionTime: null - message: There are no ready listeners for this parent ref - reason: NoReadyListeners + message: No listeners included by this parent ref allowed this attachment. + reason: NotAllowedByListeners status: "False" type: Accepted - lastTransitionTime: null diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-group.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-group.out.yaml index 1bd59a4c7c2..272e1e59d1d 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-group.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-group.out.yaml @@ -55,8 +55,8 @@ httpRoutes: parents: - conditions: - lastTransitionTime: null - message: There are no ready listeners for this parent ref - reason: NoReadyListeners + message: No listeners included by this parent ref allowed this attachment. + reason: NotAllowedByListeners status: "False" type: Accepted - lastTransitionTime: null diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind-and-supported.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind-and-supported.out.yaml index 03568e1828b..abb272c5906 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind-and-supported.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind-and-supported.out.yaml @@ -57,8 +57,8 @@ httpRoutes: parents: - conditions: - lastTransitionTime: null - message: There are no ready listeners for this parent ref - reason: NoReadyListeners + message: No listeners included by this parent ref allowed this attachment. + reason: NotAllowedByListeners status: "False" type: Accepted - lastTransitionTime: null diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind.out.yaml index 0854ce26a7d..26d322683a2 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind.out.yaml @@ -55,8 +55,8 @@ httpRoutes: parents: - conditions: - lastTransitionTime: null - message: There are no ready listeners for this parent ref - reason: NoReadyListeners + message: No listeners included by this parent ref allowed this attachment. + reason: NotAllowedByListeners status: "False" type: Accepted - lastTransitionTime: null diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-tls-route-kind.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-tls-route-kind.out.yaml index d6a010af299..9d4732d0c8f 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-tls-route-kind.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-tls-route-kind.out.yaml @@ -65,8 +65,8 @@ tlsRoutes: parents: - conditions: - lastTransitionTime: null - message: There are no ready listeners for this parent ref - reason: NoReadyListeners + message: No listeners included by this parent ref allowed this attachment. + reason: NotAllowedByListeners status: "False" type: Accepted - lastTransitionTime: null diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml index 7217e4191af..c9bae2909cc 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml @@ -28,7 +28,7 @@ gateways: mode: Terminate status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Secret envoy-gateway/tls-secret-ecdsa-2 public key algorithm must diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-invalid-mode.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-invalid-mode.out.yaml index 7db3c46cef1..70682af8625 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-invalid-mode.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-invalid-mode.out.yaml @@ -23,7 +23,7 @@ gateways: mode: Passthrough status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: TLS Passthrough mode is not supported, TLS mode must be Terminate. diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-certificate-refs.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-certificate-refs.out.yaml index 654ea7d841e..159e8c72d9c 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-certificate-refs.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-certificate-refs.out.yaml @@ -18,7 +18,7 @@ gateways: mode: Terminate status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Listener must have at least 1 TLS certificate ref diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-valid-certificate-for-fqdn.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-valid-certificate-for-fqdn.out.yaml index deb3363ef43..aa5914796dd 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-valid-certificate-for-fqdn.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-valid-certificate-for-fqdn.out.yaml @@ -23,7 +23,7 @@ gateways: mode: Terminate status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Secret envoy-gateway/tls-secret-1 must contain valid tls.crt and diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml index b7e09ffc5e6..ad32e3bdaf2 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml @@ -22,7 +22,7 @@ gateways: mode: Terminate status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Secret envoy-gateway/tls-secret-1 does not exist. diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml index ac0bea42b99..688333bf458 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml @@ -23,7 +23,7 @@ gateways: mode: Terminate status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Certificate ref to secret default/tls-secret-1 not permitted by any diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml index 3e8ca57f335..3223d24b870 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml @@ -22,7 +22,7 @@ gateways: mode: Terminate status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Secret envoy-gateway/tls-secret-1 must contain tls.crt and tls.key. diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-missing-allowed-namespaces-selector.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-missing-allowed-namespaces-selector.out.yaml index 9e7040d42cf..92069b626a0 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-missing-allowed-namespaces-selector.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-missing-allowed-namespaces-selector.out.yaml @@ -57,8 +57,8 @@ httpRoutes: parents: - conditions: - lastTransitionTime: null - message: There are no ready listeners for this parent ref - reason: NoReadyListeners + message: No listeners included by this parent ref allowed this attachment. + reason: NotAllowedByListeners status: "False" type: Accepted - lastTransitionTime: null diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml index 76f634d295a..b3adde9cae1 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: TCP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml index 5ca44bf64d0..010f8b93234 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: TCP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-rules.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-rules.out.yaml index b24190c9e08..074594d2e87 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-rules.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-rules.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: TCP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml index 518de1b91fa..543cc4143a9 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: UDP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-backends.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-backends.out.yaml index f52d4f1a720..7c438f3b264 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-backends.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-backends.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: UDP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-rules.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-rules.out.yaml index c024a1cfa91..04160fa4e4d 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-rules.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-rules.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: UDP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-unsupported-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-unsupported-protocol.out.yaml index 7e24746ae1d..b13be2100ce 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-unsupported-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-unsupported-protocol.out.yaml @@ -57,8 +57,8 @@ httpRoutes: parents: - conditions: - lastTransitionTime: null - message: There are no ready listeners for this parent ref - reason: NoReadyListeners + message: No listeners included by this parent ref allowed this attachment. + reason: NotAllowedByListeners status: "False" type: Accepted - lastTransitionTime: null diff --git a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml index 74ac5e6d3ca..58a4352f725 100644 --- a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: TCP status: listeners: - - attachedRoutes: 1 + - attachedRoutes: 2 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml index b0410c25dce..e82622c8665 100644 --- a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: UDP status: listeners: - - attachedRoutes: 1 + - attachedRoutes: 2 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml index 298f66ec3c3..3937ab6d28a 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml @@ -43,7 +43,7 @@ gateways: supportedKinds: - group: gateway.networking.k8s.io kind: TCPRoute - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Only one TCP/TLS listener is allowed in a given port diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml index 7a24c09c837..39cdeb84c4d 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml @@ -43,7 +43,7 @@ gateways: supportedKinds: - group: gateway.networking.k8s.io kind: UDPRoute - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Only one UDP listener is allowed in a given port diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-http-and-tlsroute-same-hostname-and-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-http-and-tlsroute-same-hostname-and-port.out.yaml index dda0a7c4e74..5667423dfce 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-http-and-tlsroute-same-hostname-and-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-http-and-tlsroute-same-hostname-and-port.out.yaml @@ -26,7 +26,7 @@ gateways: mode: Passthrough status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: All listeners for a given port must use a unique hostname @@ -49,7 +49,7 @@ gateways: kind: HTTPRoute - group: gateway.networking.k8s.io kind: GRPCRoute - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: All listeners for a given port must use a unique hostname diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-hostname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-hostname.out.yaml index c7db7a21465..5ef4071203b 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-hostname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-hostname.out.yaml @@ -24,7 +24,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: All listeners for a given port must use a unique hostname @@ -47,7 +47,7 @@ gateways: kind: HTTPRoute - group: gateway.networking.k8s.io kind: GRPCRoute - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: All listeners for a given port must use a unique hostname diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.out.yaml index 7ec1823a77e..381b05384f0 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.out.yaml @@ -24,7 +24,7 @@ gateways: protocol: HTTPS status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: All listeners for a given port must use a compatible protocol @@ -47,7 +47,7 @@ gateways: kind: HTTPRoute - group: gateway.networking.k8s.io kind: GRPCRoute - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: All listeners for a given port must use a compatible protocol diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml index 0168d322afa..c31ac5dc002 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml @@ -22,7 +22,7 @@ gateways: protocol: TCP status: listeners: - - attachedRoutes: 1 + - attachedRoutes: 2 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane @@ -43,7 +43,7 @@ gateways: supportedKinds: - group: gateway.networking.k8s.io kind: TCPRoute - - attachedRoutes: 1 + - attachedRoutes: 2 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml index 30aa11dd95d..cd65d8df583 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml @@ -22,7 +22,7 @@ gateways: protocol: UDP status: listeners: - - attachedRoutes: 1 + - attachedRoutes: 2 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane @@ -43,7 +43,7 @@ gateways: supportedKinds: - group: gateway.networking.k8s.io kind: UDPRoute - - attachedRoutes: 1 + - attachedRoutes: 2 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-empty-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-empty-headers.out.yaml index 9d79d3a3475..a4a5974005a 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-empty-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-empty-headers.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.out.yaml index 14cb1d167ef..d9467efdb75 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-no-valid-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-no-valid-headers.out.yaml index b32d9c0a122..5936881f5c5 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-no-valid-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-no-valid-headers.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-non-matching-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-non-matching-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml index 14f9cf7dacc..922220aa0a0 100644 --- a/internal/gatewayapi/testdata/httproute-with-non-matching-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-non-matching-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-filter-type.out.yaml b/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-filter-type.out.yaml index b551b071c98..c74ed5a3f53 100644 --- a/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-filter-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-filter-type.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-scheme.out.yaml b/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-scheme.out.yaml index ce331c461d9..4a5305be5d9 100644 --- a/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-scheme.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-scheme.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-status.out.yaml b/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-status.out.yaml index 08792fc2676..af22cb4bf50 100644 --- a/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-status.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-redirect-filter-invalid-status.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-headers.out.yaml index 1635b111757..7d6662a0708 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-headers.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.out.yaml index 77ff80ec20d..e319b1caee8 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-valid-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-valid-headers.out.yaml index e18af4f074e..4c77af97993 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-valid-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-valid-headers.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-hostname.out.yaml index 4368e3326aa..007a3ef1e54 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-hostname.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-multiple-filters.out.yaml index 4860707ed5a..d774cf7d858 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-multiple-filters.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-path-type.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-path-type.out.yaml index 3ac9cd2e136..c42b3ccaffb 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-path-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-path-type.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-path.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-path.out.yaml index 69dfe210917..d2f50fb22d0 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-path.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-path.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-missing-path.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-missing-path.out.yaml index df69cdec644..1afb98e60a7 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-missing-path.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-missing-path.out.yaml @@ -17,7 +17,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane diff --git a/internal/gatewayapi/testdata/tlsroute-not-attaching-to-gateway-with-no-mode.out.yaml b/internal/gatewayapi/testdata/tlsroute-not-attaching-to-gateway-with-no-mode.out.yaml index 2fac08a9c5e..a6855fec83d 100644 --- a/internal/gatewayapi/testdata/tlsroute-not-attaching-to-gateway-with-no-mode.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-not-attaching-to-gateway-with-no-mode.out.yaml @@ -16,7 +16,7 @@ gateways: protocol: TLS status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Listener must have TLS set when protocol is TLS. diff --git a/internal/gatewayapi/testdata/tlsroute-with-listener-both-passthrough-and-cert-data.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-listener-both-passthrough-and-cert-data.out.yaml index 0e48f934a10..3f70d651a8c 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-listener-both-passthrough-and-cert-data.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-listener-both-passthrough-and-cert-data.out.yaml @@ -23,7 +23,7 @@ gateways: mode: Passthrough status: listeners: - - attachedRoutes: 0 + - attachedRoutes: 1 conditions: - lastTransitionTime: null message: Listener must not have TLS certificate refs set for TLS mode Passthrough. diff --git a/test/conformance/conformance_test.go b/test/conformance/conformance_test.go index da88413075e..149909e2ce4 100644 --- a/test/conformance/conformance_test.go +++ b/test/conformance/conformance_test.go @@ -49,7 +49,6 @@ func TestGatewayAPIConformance(t *testing.T) { SupportedFeatures: suite.AllFeatures, SkipTests: []string{ tests.GatewayStaticAddresses.ShortName, - tests.GatewayWithAttachedRoutes.ShortName, }, ExemptFeatures: suite.MeshCoreFeatures, }) diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index c5eae8f2dba..348f44a3a4d 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -98,7 +98,6 @@ func experimentalConformance(t *testing.T) { SupportedFeatures: suite.AllFeatures, SkipTests: []string{ tests.GatewayStaticAddresses.ShortName, - tests.GatewayWithAttachedRoutes.ShortName, }, ExemptFeatures: suite.MeshCoreFeatures, }, From 77bcb3ce1396648f630a614379fa85e28873f484 Mon Sep 17 00:00:00 2001 From: tmsnan Date: Wed, 1 Nov 2023 15:59:25 +0800 Subject: [PATCH 41/55] fix comments in loadbalancer api (#2145) Signed-off-by: zhaonan --- api/v1alpha1/loadbalancer_types.go | 2 +- .../gateway.envoyproxy.io_backendtrafficpolicies.yaml | 4 ++-- site/content/en/latest/api/extension_types.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go index b4e36a342a5..9bf2d48702d 100644 --- a/api/v1alpha1/loadbalancer_types.go +++ b/api/v1alpha1/loadbalancer_types.go @@ -11,7 +11,7 @@ package v1alpha1 // +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? has(self.consistentHash) : !has(self.consistentHash)",message="If LoadBalancer type is consistentHash, consistentHash field needs to be set." type LoadBalancer struct { // Type decides the type of Load Balancer policy. - // Valid RateLimitType values are + // Valid LoadBalancerType values are // "ConsistentHash", // "LeastRequest", // "Random", diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 3d1edb778cc..b096eeb4588 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -63,8 +63,8 @@ spec: type: object type: description: Type decides the type of Load Balancer policy. Valid - RateLimitType values are "ConsistentHash", "LeastRequest", "Random", - "RoundRobin", + LoadBalancerType values are "ConsistentHash", "LeastRequest", + "Random", "RoundRobin", enum: - ConsistentHash - LeastRequest diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 881d1e6b594..08b53e29c85 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -1032,7 +1032,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `type` _[LoadBalancerType](#loadbalancertype)_ | Type decides the type of Load Balancer policy. Valid RateLimitType values are "ConsistentHash", "LeastRequest", "Random", "RoundRobin", | +| `type` _[LoadBalancerType](#loadbalancertype)_ | Type decides the type of Load Balancer policy. Valid LoadBalancerType values are "ConsistentHash", "LeastRequest", "Random", "RoundRobin", | | `consistentHash` _[ConsistentHash](#consistenthash)_ | ConsistentHash defines the configuration when the load balancer type is set to ConsistentHash | From defed574484e2708933d5f911b8bfc35e7ac8ee2 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Wed, 1 Nov 2023 15:59:59 +0800 Subject: [PATCH 42/55] fix(docs): incorrect quickstart links (#2146) Signed-off-by: bitliu --- site/content/en/latest/user/cors.md | 6 +++--- site/content/en/latest/user/customize-envoyproxy.md | 2 +- site/content/en/latest/user/envoy-patch-policy.md | 2 +- site/content/en/latest/user/gateway-api-metrics.md | 2 +- site/content/en/latest/user/grafana-integration.md | 2 +- site/content/en/latest/user/http-request-headers.md | 2 +- site/content/en/latest/user/http-response-headers.md | 2 +- site/content/en/latest/user/http-traffic-splitting.md | 2 +- site/content/en/latest/user/http-urlrewrite.md | 2 +- site/content/en/latest/user/jwt-authentication.md | 6 +++--- site/content/en/latest/user/proxy-observability.md | 2 +- site/content/en/latest/user/rate-limit.md | 2 +- site/content/en/latest/user/secure-gateways.md | 8 ++++---- site/content/en/latest/user/tls-cert-manager.md | 2 +- site/content/en/latest/user/tls-passthrough.md | 4 ++-- site/content/en/latest/user/tls-termination.md | 2 +- site/content/en/latest/user/udp-routing.md | 2 +- site/content/en/v0.2.0/user/http-request-headers.md | 2 +- site/content/en/v0.2.0/user/http-traffic-splitting.md | 2 +- site/content/en/v0.2.0/user/secure-gateways.md | 4 ++-- site/content/en/v0.2.0/user/tls-passthrough.md | 4 ++-- site/content/en/v0.3.0/user/authn.md | 6 +++--- site/content/en/v0.3.0/user/http-request-headers.md | 2 +- site/content/en/v0.3.0/user/http-response-headers.md | 2 +- site/content/en/v0.3.0/user/http-traffic-splitting.md | 2 +- site/content/en/v0.3.0/user/http-urlrewrite.md | 2 +- site/content/en/v0.3.0/user/rate-limit.md | 2 +- site/content/en/v0.3.0/user/secure-gateways.md | 4 ++-- site/content/en/v0.3.0/user/tls-passthrough.md | 4 ++-- site/content/en/v0.3.0/user/udp-routing.md | 2 +- site/content/en/v0.4.0/user/authn.md | 6 +++--- site/content/en/v0.4.0/user/customize-envoyproxy.md | 2 +- site/content/en/v0.4.0/user/http-request-headers.md | 2 +- site/content/en/v0.4.0/user/http-response-headers.md | 2 +- site/content/en/v0.4.0/user/http-traffic-splitting.md | 2 +- site/content/en/v0.4.0/user/http-urlrewrite.md | 2 +- site/content/en/v0.4.0/user/rate-limit.md | 2 +- site/content/en/v0.4.0/user/secure-gateways.md | 8 ++++---- site/content/en/v0.4.0/user/tls-passthrough.md | 4 ++-- site/content/en/v0.4.0/user/udp-routing.md | 2 +- site/content/en/v0.5.0/user/authn.md | 6 +++--- site/content/en/v0.5.0/user/customize-envoyproxy.md | 2 +- site/content/en/v0.5.0/user/envoy-patch-policy.md | 2 +- site/content/en/v0.5.0/user/http-request-headers.md | 2 +- site/content/en/v0.5.0/user/http-response-headers.md | 2 +- site/content/en/v0.5.0/user/http-traffic-splitting.md | 2 +- site/content/en/v0.5.0/user/http-urlrewrite.md | 2 +- site/content/en/v0.5.0/user/proxy-observability.md | 2 +- site/content/en/v0.5.0/user/rate-limit.md | 2 +- site/content/en/v0.5.0/user/secure-gateways.md | 8 ++++---- site/content/en/v0.5.0/user/tls-cert-manager.md | 2 +- site/content/en/v0.5.0/user/tls-passthrough.md | 4 ++-- site/content/en/v0.5.0/user/tls-termination.md | 2 +- site/content/en/v0.5.0/user/udp-routing.md | 2 +- 54 files changed, 80 insertions(+), 80 deletions(-) diff --git a/site/content/en/latest/user/cors.md b/site/content/en/latest/user/cors.md index c8192c62864..b86a983a7a9 100644 --- a/site/content/en/latest/user/cors.md +++ b/site/content/en/latest/user/cors.md @@ -11,7 +11,7 @@ This instantiated resource can be linked to a [Gateway][Gateway], [HTTPRoute][HT ## Prerequisites -Follow the steps from the [Quickstart](quickstart.md) guide to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) guide to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Configuration @@ -53,7 +53,7 @@ kubectl get securitypolicy/cors-example -o yaml ## Testing -Ensure the `GATEWAY_HOST` environment variable from the [Quickstart](quickstart.md) guide is set. If not, follow the +Ensure the `GATEWAY_HOST` environment variable from the [Quickstart](../quickstart) guide is set. If not, follow the Quickstart instructions to set the variable. ```shell @@ -103,7 +103,7 @@ its configuration. It won't deny any requests. The browsers are responsible for ## Clean-Up -Follow the steps from the [Quickstart](quickstart.md) guide to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) guide to uninstall Envoy Gateway and the example manifest. Delete the SecurityPolicy: diff --git a/site/content/en/latest/user/customize-envoyproxy.md b/site/content/en/latest/user/customize-envoyproxy.md index ef894817ea6..b0ece5dd2be 100644 --- a/site/content/en/latest/user/customize-envoyproxy.md +++ b/site/content/en/latest/user/customize-envoyproxy.md @@ -8,7 +8,7 @@ Service. To learn more about GatewayClass and ParametersRef, please refer to [Ga ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Add GatewayClass ParametersRef diff --git a/site/content/en/latest/user/envoy-patch-policy.md b/site/content/en/latest/user/envoy-patch-policy.md index cd9fee24dfc..e531e584792 100644 --- a/site/content/en/latest/user/envoy-patch-policy.md +++ b/site/content/en/latest/user/envoy-patch-policy.md @@ -22,7 +22,7 @@ not exposed by Envoy Gateway APIs today. ### Prerequisites -* Follow the steps from the [Quickstart](quickstart.md) guide to install Envoy Gateway and the example manifest. +* Follow the steps from the [Quickstart](../quickstart) guide to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ### Enable EnvoyPatchPolicy diff --git a/site/content/en/latest/user/gateway-api-metrics.md b/site/content/en/latest/user/gateway-api-metrics.md index 5331145b050..d2f93f32da6 100644 --- a/site/content/en/latest/user/gateway-api-metrics.md +++ b/site/content/en/latest/user/gateway-api-metrics.md @@ -7,7 +7,7 @@ The project also provides example dashboard for visualising the metrics using Gr ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. Run the following commands to install the metrics stack, with the Gateway API State Metrics configuration, on your kubernetes cluster: diff --git a/site/content/en/latest/user/grafana-integration.md b/site/content/en/latest/user/grafana-integration.md index 4002d02633f..01010dd8009 100644 --- a/site/content/en/latest/user/grafana-integration.md +++ b/site/content/en/latest/user/grafana-integration.md @@ -7,7 +7,7 @@ This guide shows you how to visualise the metrics exposed to prometheus using gr ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../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 from the [Proxy Observability](proxy-observability.md#Metrics) to enable prometheus metrics. diff --git a/site/content/en/latest/user/http-request-headers.md b/site/content/en/latest/user/http-request-headers.md index 17fe3b87bcb..0dbdbe13d3b 100644 --- a/site/content/en/latest/user/http-request-headers.md +++ b/site/content/en/latest/user/http-request-headers.md @@ -14,7 +14,7 @@ client. ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Adding Request Headers diff --git a/site/content/en/latest/user/http-response-headers.md b/site/content/en/latest/user/http-response-headers.md index 4a27728003d..9a0c3e38386 100644 --- a/site/content/en/latest/user/http-response-headers.md +++ b/site/content/en/latest/user/http-response-headers.md @@ -12,7 +12,7 @@ upstream service. ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Adding Response Headers diff --git a/site/content/en/latest/user/http-traffic-splitting.md b/site/content/en/latest/user/http-traffic-splitting.md index 94f021b5aec..960adbcc2ea 100644 --- a/site/content/en/latest/user/http-traffic-splitting.md +++ b/site/content/en/latest/user/http-traffic-splitting.md @@ -8,7 +8,7 @@ with status code `500` for all requests that would have been sent to that backen ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Single backendRef diff --git a/site/content/en/latest/user/http-urlrewrite.md b/site/content/en/latest/user/http-urlrewrite.md index fb68ae88322..60c0bebeeef 100644 --- a/site/content/en/latest/user/http-urlrewrite.md +++ b/site/content/en/latest/user/http-urlrewrite.md @@ -7,7 +7,7 @@ used on a Route rule. This MUST NOT be used on the same Route rule as a HTTPRequ ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Rewrite URL Prefix Path diff --git a/site/content/en/latest/user/jwt-authentication.md b/site/content/en/latest/user/jwt-authentication.md index 1b6bfe0b5a6..36663f35fd2 100644 --- a/site/content/en/latest/user/jwt-authentication.md +++ b/site/content/en/latest/user/jwt-authentication.md @@ -11,7 +11,7 @@ This instantiated resource can be linked to a [Gateway][Gateway], [HTTPRoute][HT ## Prerequisites -Follow the steps from the [Quickstart](quickstart.md) guide to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) guide to install Envoy Gateway and the example manifest. For GRPC - follow the steps from the [GRPC Routing](grpc-routing.md) example. Before proceeding, you should be able to query the example backend using HTTP or GRPC. @@ -71,7 +71,7 @@ kubectl get securitypolicy/jwt-example -o yaml ## Testing -Ensure the `GATEWAY_HOST` environment variable from the [Quickstart](quickstart.md) guide is set. If not, follow the +Ensure the `GATEWAY_HOST` environment variable from the [Quickstart](../quickstart) guide is set. If not, follow the Quickstart instructions to set the variable. ```shell @@ -150,7 +150,7 @@ You should see the below response ## Clean-Up -Follow the steps from the [Quickstart](quickstart.md) guide to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) guide to uninstall Envoy Gateway and the example manifest. Delete the SecurityPolicy: diff --git a/site/content/en/latest/user/proxy-observability.md b/site/content/en/latest/user/proxy-observability.md index 5afd1064b8d..f9d8f2d5a0d 100644 --- a/site/content/en/latest/user/proxy-observability.md +++ b/site/content/en/latest/user/proxy-observability.md @@ -7,7 +7,7 @@ This guide show you how to config proxy observability, includes metrics, logs, a ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. [FluentBit](https://fluentbit.io/) is used to collect logs from the EnvoyProxy instances and forward them to Loki. Install FluentBit: diff --git a/site/content/en/latest/user/rate-limit.md b/site/content/en/latest/user/rate-limit.md index e8a38ac7740..7b997e60226 100644 --- a/site/content/en/latest/user/rate-limit.md +++ b/site/content/en/latest/user/rate-limit.md @@ -21,7 +21,7 @@ can be linked to a [Gateway][], [HTTPRoute][] or [GRPCRoute][] resource. ### Install Envoy Gateway -* Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the HTTPRoute example manifest. +* Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the HTTPRoute example manifest. Before proceeding, you should be able to query the example backend using HTTP. ### Install Redis diff --git a/site/content/en/latest/user/secure-gateways.md b/site/content/en/latest/user/secure-gateways.md index c2b91f0b937..dba8d3a972b 100644 --- a/site/content/en/latest/user/secure-gateways.md +++ b/site/content/en/latest/user/secure-gateways.md @@ -11,7 +11,7 @@ testing and demonstration purposes only. ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## TLS Certificates @@ -242,7 +242,7 @@ Lastly, test connectivity using the above [Testing section](#testing). ## Clean-Up -Follow the steps from the [Quickstart Guide](quickstart.md) to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the Secrets: @@ -257,7 +257,7 @@ This section gives a walkthrough to generate RSA and ECDSA derived certificates ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../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](secure-gateways.md#tls-certificates) section in the guide to generate self-signed RSA derived Server certificate and private key, and configure those in the Gateway listener configuration to terminate HTTPS traffic. @@ -369,7 +369,7 @@ This sections gives a walkthrough to generate multiple certificates correspondin ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../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](secure-gateways.md#tls-certificates) section in the guide 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/site/content/en/latest/user/tls-cert-manager.md b/site/content/en/latest/user/tls-cert-manager.md index b47d80ca5d1..2fe8112f1b5 100644 --- a/site/content/en/latest/user/tls-cert-manager.md +++ b/site/content/en/latest/user/tls-cert-manager.md @@ -18,7 +18,7 @@ Changing to the Let's Encrypt production environment is straight-forward after t ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Deploying cert-manager diff --git a/site/content/en/latest/user/tls-passthrough.md b/site/content/en/latest/user/tls-passthrough.md index 4cef2eace8a..34af20e5dce 100644 --- a/site/content/en/latest/user/tls-passthrough.md +++ b/site/content/en/latest/user/tls-passthrough.md @@ -12,7 +12,7 @@ to terminate the TLS connection, while the Gateway routes the requests to the ap ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## TLS Certificates @@ -106,7 +106,7 @@ curl -v -HHost:passthrough.example.com --resolve "passthrough.example.com:6443:$ ## Clean-Up -Follow the steps from the [Quickstart Guide](quickstart.md) to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the Secret: diff --git a/site/content/en/latest/user/tls-termination.md b/site/content/en/latest/user/tls-termination.md index eaae97ec9fd..eb0d2d6932c 100644 --- a/site/content/en/latest/user/tls-termination.md +++ b/site/content/en/latest/user/tls-termination.md @@ -10,7 +10,7 @@ This guide will walk through the steps required to configure TLS Terminate mode ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway. ## TLS Certificates Generate the certificates and keys used by the Gateway to terminate client TLS connections. diff --git a/site/content/en/latest/user/udp-routing.md b/site/content/en/latest/user/udp-routing.md index 17ba65e0f22..73a03c8aac0 100644 --- a/site/content/en/latest/user/udp-routing.md +++ b/site/content/en/latest/user/udp-routing.md @@ -137,7 +137,7 @@ _udp.foo.bar.com. 0 IN SRV 0 0 42376 . ## Clean-Up -Follow the steps from the [Quickstart Guide](quickstart.md) to uninstall Envoy Gateway. +Follow the steps from the [Quickstart Guide](../quickstart) to uninstall Envoy Gateway. Delete the CoreDNS example manifest and the UDPRoute: diff --git a/site/content/en/v0.2.0/user/http-request-headers.md b/site/content/en/v0.2.0/user/http-request-headers.md index cc801d28ddc..1166f0bb668 100644 --- a/site/content/en/v0.2.0/user/http-request-headers.md +++ b/site/content/en/v0.2.0/user/http-request-headers.md @@ -14,7 +14,7 @@ client. ## Prerequisites -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Adding Request Headers diff --git a/site/content/en/v0.2.0/user/http-traffic-splitting.md b/site/content/en/v0.2.0/user/http-traffic-splitting.md index 421a4fa0546..e15320c02d2 100644 --- a/site/content/en/v0.2.0/user/http-traffic-splitting.md +++ b/site/content/en/v0.2.0/user/http-traffic-splitting.md @@ -8,7 +8,7 @@ with status code `500` for all requests that would have been sent to that backen ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## Single backendRef diff --git a/site/content/en/v0.2.0/user/secure-gateways.md b/site/content/en/v0.2.0/user/secure-gateways.md index a7cb5d05acc..21f845ebf3c 100644 --- a/site/content/en/v0.2.0/user/secure-gateways.md +++ b/site/content/en/v0.2.0/user/secure-gateways.md @@ -11,7 +11,7 @@ testing and demonstration purposes only. ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## TLS Certificates @@ -242,7 +242,7 @@ Lastly, test connectivity using the above [Testing section](#testing). ## Clean-Up -Follow the steps from the [Quickstart Guide](quickstart.md) to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the Secrets: diff --git a/site/content/en/v0.2.0/user/tls-passthrough.md b/site/content/en/v0.2.0/user/tls-passthrough.md index 73efa8d32dd..7a8a197cec2 100644 --- a/site/content/en/v0.2.0/user/tls-passthrough.md +++ b/site/content/en/v0.2.0/user/tls-passthrough.md @@ -12,7 +12,7 @@ to terminate the TLS connection, while the Gateway routes the requests to the ap ## Installation -Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. ## TLS Certificates @@ -106,7 +106,7 @@ curl -v -HHost:passthrough.example.com --resolve "passthrough.example.com:6443:$ ## Clean-Up -Follow the steps from the [Quickstart Guide](quickstart.md) to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart Guide](../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the Secret: diff --git a/site/content/en/v0.3.0/user/authn.md b/site/content/en/v0.3.0/user/authn.md index aedf5952273..312e4103b9b 100644 --- a/site/content/en/v0.3.0/user/authn.md +++ b/site/content/en/v0.3.0/user/authn.md @@ -8,7 +8,7 @@ supports validating a JWT from an HTTP header, e.g. `Authorization: Bearer Date: Wed, 1 Nov 2023 21:47:59 +0800 Subject: [PATCH 43/55] fix: null pointer when CORS maxAge is not specified (#2133) fix nullpointer Signed-off-by: huabing zhao Signed-off-by: Huabing Zhao --- internal/xds/translator/cors.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/xds/translator/cors.go b/internal/xds/translator/cors.go index b070b7fb54a..14ce8232dca 100644 --- a/internal/xds/translator/cors.go +++ b/internal/xds/translator/cors.go @@ -126,7 +126,9 @@ func patchRouteWithCORSConfig(route *routev3.Route, irRoute *ir.HTTPRoute) error allowMethods = strings.Join(irRoute.CORS.AllowMethods, ", ") allowHeaders = strings.Join(irRoute.CORS.AllowHeaders, ", ") exposeHeaders = strings.Join(irRoute.CORS.ExposeHeaders, ", ") - maxAge = strconv.Itoa(int(irRoute.CORS.MaxAge.Seconds())) + if irRoute.CORS.MaxAge != nil { + maxAge = strconv.Itoa(int(irRoute.CORS.MaxAge.Seconds())) + } routeCfgProto := &corsv3.CorsPolicy{ AllowOriginStringMatch: allowOrigins, From 58bf2c2335d43fc62eca5e0ff5fd82909407b2f0 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Wed, 1 Nov 2023 16:30:50 -0700 Subject: [PATCH 44/55] Prep v0.6 release (#2152) * Prep v0.6 release * Update VERSION * update docs for v0.6 * point website to v0.6 by default * Add Release Notes * Add Release Announcement Signed-off-by: Arko Dasgupta --- VERSION | 2 +- release-notes/v0.6.0.yaml | 75 + site/content/en/_index.md | 4 +- site/content/en/blog/releases/v0.6.md | 82 + site/content/en/v0.6.0/_index.md | 21 + site/content/en/v0.6.0/api/_index.md | 5 + site/content/en/v0.6.0/api/extension_types.md | 1706 +++++++++++++++++ .../en/v0.6.0/contributions/CODEOWNERS.md | 19 + .../v0.6.0/contributions/CODE_OF_CONDUCT.md | 6 + .../en/v0.6.0/contributions/CONTRIBUTING.md | 190 ++ .../en/v0.6.0/contributions/DEVELOP.md | 163 ++ site/content/en/v0.6.0/contributions/DOCS.md | 69 + .../en/v0.6.0/contributions/RELEASING.md | 252 +++ .../content/en/v0.6.0/contributions/_index.md | 5 + .../en/v0.6.0/contributions/roadmap.md | 96 + site/content/en/v0.6.0/design/_index.md | 5 + site/content/en/v0.6.0/design/accesslog.md | 237 +++ .../v0.6.0/design/backend-traffic-policy.md | 155 ++ site/content/en/v0.6.0/design/bootstrap.md | 381 ++++ .../en/v0.6.0/design/client-traffic-policy.md | 114 ++ site/content/en/v0.6.0/design/config-api.md | 353 ++++ site/content/en/v0.6.0/design/eg-metrics.md | 225 +++ site/content/en/v0.6.0/design/egctl.md | 59 + .../en/v0.6.0/design/envoy-patch-policy.md | 176 ++ .../v0.6.0/design/extending-envoy-gateway.md | 327 ++++ .../en/v0.6.0/design/gatewayapi-translator.md | 253 +++ site/content/en/v0.6.0/design/goals.md | 91 + .../en/v0.6.0/design/local-envoy-gateway.md | 52 + site/content/en/v0.6.0/design/metrics.md | 112 ++ site/content/en/v0.6.0/design/pprof.md | 70 + site/content/en/v0.6.0/design/rate-limit.md | 419 ++++ .../en/v0.6.0/design/security-policy.md | 115 ++ .../content/en/v0.6.0/design/system-design.md | 174 ++ .../en/v0.6.0/design/tcp-udp-design.md | 49 + site/content/en/v0.6.0/design/tracing.md | 161 ++ site/content/en/v0.6.0/design/watching.md | 120 ++ site/content/en/v0.6.0/install/_index.md | 5 + site/content/en/v0.6.0/install/api.md | 57 + .../en/v0.6.0/install/install-egctl.md | 57 + .../content/en/v0.6.0/install/install-helm.md | 144 ++ .../content/en/v0.6.0/install/install-yaml.md | 39 + site/content/en/v0.6.0/user/_index.md | 5 + site/content/en/v0.6.0/user/cors.md | 122 ++ .../en/v0.6.0/user/customize-envoyproxy.md | 322 ++++ .../content/en/v0.6.0/user/deployment-mode.md | 400 ++++ site/content/en/v0.6.0/user/egctl.md | 742 +++++++ .../en/v0.6.0/user/envoy-patch-policy.md | 202 ++ .../content/en/v0.6.0/user/gateway-address.md | 69 + .../en/v0.6.0/user/gateway-api-metrics.md | 54 + .../en/v0.6.0/user/gatewayapi-support.md | 118 ++ .../en/v0.6.0/user/grafana-integration.md | 65 + site/content/en/v0.6.0/user/grpc-routing.md | 204 ++ site/content/en/v0.6.0/user/http-redirect.md | 129 ++ .../en/v0.6.0/user/http-request-headers.md | 285 +++ .../en/v0.6.0/user/http-request-mirroring.md | 250 +++ .../en/v0.6.0/user/http-response-headers.md | 283 +++ site/content/en/v0.6.0/user/http-routing.md | 137 ++ .../en/v0.6.0/user/http-traffic-splitting.md | 313 +++ .../content/en/v0.6.0/user/http-urlrewrite.md | 297 +++ .../en/v0.6.0/user/jwt-authentication.md | 170 ++ .../en/v0.6.0/user/multicluster-service.md | 86 + .../en/v0.6.0/user/proxy-observability.md | 134 ++ site/content/en/v0.6.0/user/quickstart.md | 103 + site/content/en/v0.6.0/user/rate-limit.md | 829 ++++++++ .../content/en/v0.6.0/user/secure-gateways.md | 455 +++++ site/content/en/v0.6.0/user/tcp-routing.md | 304 +++ .../en/v0.6.0/user/tls-cert-manager.md | 434 +++++ .../content/en/v0.6.0/user/tls-passthrough.md | 119 ++ .../content/en/v0.6.0/user/tls-termination.md | 85 + site/content/en/v0.6.0/user/udp-routing.md | 156 ++ site/hugo.toml | 5 +- 71 files changed, 13518 insertions(+), 4 deletions(-) create mode 100644 release-notes/v0.6.0.yaml create mode 100644 site/content/en/blog/releases/v0.6.md create mode 100644 site/content/en/v0.6.0/_index.md create mode 100644 site/content/en/v0.6.0/api/_index.md create mode 100644 site/content/en/v0.6.0/api/extension_types.md create mode 100644 site/content/en/v0.6.0/contributions/CODEOWNERS.md create mode 100644 site/content/en/v0.6.0/contributions/CODE_OF_CONDUCT.md create mode 100644 site/content/en/v0.6.0/contributions/CONTRIBUTING.md create mode 100644 site/content/en/v0.6.0/contributions/DEVELOP.md create mode 100644 site/content/en/v0.6.0/contributions/DOCS.md create mode 100644 site/content/en/v0.6.0/contributions/RELEASING.md create mode 100644 site/content/en/v0.6.0/contributions/_index.md create mode 100644 site/content/en/v0.6.0/contributions/roadmap.md create mode 100644 site/content/en/v0.6.0/design/_index.md create mode 100644 site/content/en/v0.6.0/design/accesslog.md create mode 100644 site/content/en/v0.6.0/design/backend-traffic-policy.md create mode 100644 site/content/en/v0.6.0/design/bootstrap.md create mode 100644 site/content/en/v0.6.0/design/client-traffic-policy.md create mode 100644 site/content/en/v0.6.0/design/config-api.md create mode 100644 site/content/en/v0.6.0/design/eg-metrics.md create mode 100644 site/content/en/v0.6.0/design/egctl.md create mode 100644 site/content/en/v0.6.0/design/envoy-patch-policy.md create mode 100644 site/content/en/v0.6.0/design/extending-envoy-gateway.md create mode 100644 site/content/en/v0.6.0/design/gatewayapi-translator.md create mode 100644 site/content/en/v0.6.0/design/goals.md create mode 100644 site/content/en/v0.6.0/design/local-envoy-gateway.md create mode 100644 site/content/en/v0.6.0/design/metrics.md create mode 100644 site/content/en/v0.6.0/design/pprof.md create mode 100644 site/content/en/v0.6.0/design/rate-limit.md create mode 100644 site/content/en/v0.6.0/design/security-policy.md create mode 100644 site/content/en/v0.6.0/design/system-design.md create mode 100644 site/content/en/v0.6.0/design/tcp-udp-design.md create mode 100644 site/content/en/v0.6.0/design/tracing.md create mode 100644 site/content/en/v0.6.0/design/watching.md create mode 100644 site/content/en/v0.6.0/install/_index.md create mode 100644 site/content/en/v0.6.0/install/api.md create mode 100644 site/content/en/v0.6.0/install/install-egctl.md create mode 100644 site/content/en/v0.6.0/install/install-helm.md create mode 100644 site/content/en/v0.6.0/install/install-yaml.md create mode 100644 site/content/en/v0.6.0/user/_index.md create mode 100644 site/content/en/v0.6.0/user/cors.md create mode 100644 site/content/en/v0.6.0/user/customize-envoyproxy.md create mode 100644 site/content/en/v0.6.0/user/deployment-mode.md create mode 100644 site/content/en/v0.6.0/user/egctl.md create mode 100644 site/content/en/v0.6.0/user/envoy-patch-policy.md create mode 100644 site/content/en/v0.6.0/user/gateway-address.md create mode 100644 site/content/en/v0.6.0/user/gateway-api-metrics.md create mode 100644 site/content/en/v0.6.0/user/gatewayapi-support.md create mode 100644 site/content/en/v0.6.0/user/grafana-integration.md create mode 100644 site/content/en/v0.6.0/user/grpc-routing.md create mode 100644 site/content/en/v0.6.0/user/http-redirect.md create mode 100644 site/content/en/v0.6.0/user/http-request-headers.md create mode 100644 site/content/en/v0.6.0/user/http-request-mirroring.md create mode 100644 site/content/en/v0.6.0/user/http-response-headers.md create mode 100644 site/content/en/v0.6.0/user/http-routing.md create mode 100644 site/content/en/v0.6.0/user/http-traffic-splitting.md create mode 100644 site/content/en/v0.6.0/user/http-urlrewrite.md create mode 100644 site/content/en/v0.6.0/user/jwt-authentication.md create mode 100644 site/content/en/v0.6.0/user/multicluster-service.md create mode 100644 site/content/en/v0.6.0/user/proxy-observability.md create mode 100644 site/content/en/v0.6.0/user/quickstart.md create mode 100644 site/content/en/v0.6.0/user/rate-limit.md create mode 100644 site/content/en/v0.6.0/user/secure-gateways.md create mode 100644 site/content/en/v0.6.0/user/tcp-routing.md create mode 100644 site/content/en/v0.6.0/user/tls-cert-manager.md create mode 100644 site/content/en/v0.6.0/user/tls-passthrough.md create mode 100644 site/content/en/v0.6.0/user/tls-termination.md create mode 100644 site/content/en/v0.6.0/user/udp-routing.md diff --git a/VERSION b/VERSION index 01b366027cd..60f63432822 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.6.0-rc.1 +v0.6.0 diff --git a/release-notes/v0.6.0.yaml b/release-notes/v0.6.0.yaml new file mode 100644 index 00000000000..d370027a0a5 --- /dev/null +++ b/release-notes/v0.6.0.yaml @@ -0,0 +1,75 @@ +date: Nov 1, 2023 + +changes: + - area: documentation + change: | + Introduced a new website based on Hugo + Added Grafana dashboards and integration docs for EnvoyProxy metrics + Added Grafana integration docs for Gateway API metrics + + - area: installation + change: | + Updated EnvoyProxy image to be a distroless variant. + Removed resources around kube-rbac-proxy + + + - area: api + change: | + Upgraded to Gateway API v1.0.0 + Added the ClientTrafficPolicy CRD with Keep Alive Support + Added the BackendTrafficPolicy CRD with RateLimit and LoadBalancer Support + Added the SecurityPolicy CRD with CORS and JWT Support + Added EnvoyGateway Metrics with Prometheus and OpenTelemetry support + Added Support for InitContainers in EnvoyProxy CRD + Added Support for LoadBalancerIP in EnvoyProxy CRD + Added Support for AllocateLoadBalancerNodePorts in EnvoyProxy CRD + Added Support for LoadBalancerClass in EnvoyProxy CRD + Added Support for selecting EnvoyProxy stats to be generated + Added Support for enabling EnvoyProxy Virtual Host metrics + Added Support for Merging Gateway resources onto the same infrastructure + + breaking-change: | + Removed the AuthenticationFilter CRD + Removed the RateLimitFilter CRD + Moved EnvoyProxy CRD from `config.gateway.envoyproxy.io` to `gateway.envoyproxy.io` + Enabled EnvoyProxy Prometheus Endpoint by default with an option to disable it + Updated the Bootstrap field within the EnvoyProxy CRD with an additional value + field to specify bootstrap config + + - area: conformance + change: | + Added Support for HTTPRouteBackendProtocolH2C Test + Added Support for HTTPRouteBackendProtocolWebSocket Test + Added Support for HTTPRouteRequestMultipleMirrors Test + Added Support for HTTPRouteTimeoutRequest Test + Added Support for HTTPRouteTimeoutBackendRequest Test + Added Support for HTTPRouteRedirectPortAndScheme Test + + - area: watchable + change: | + Improved caching of resource by implementing a compare function agnostic of resource order + + - area: translator + change: | + Added support for routing to EndpointSlice endpoints + Added support for HTTPRoute Timeouts + Added support for multiple RequestMirror filters per HTTPRoute rule + Use / instead of - in IR Route Names + Added Support to ignore ports in Host header + + - area: providers + change: | + Added the generationChangedPredicate to most resources to limit resource reconiliation + Improved reconiliation by using the same enqueue request for all resources + Added support for reconciling ServiceImport CRD + Added support for selectively watching resources based on Namespace Selector + + - area: xds + change: | + Fixed Layered Runtime warnings + Upgraded to the latest version of go-control-plane that fixed xDS Resource ordering issues for ADS. + Added HTTP2 Keep Alives to the xds connection + + - area: cli + change: | + Added Support for egctl stats command diff --git a/site/content/en/_index.md b/site/content/en/_index.md index 06ea406b2b1..e724ec80a57 100644 --- a/site/content/en/_index.md +++ b/site/content/en/_index.md @@ -3,10 +3,10 @@ title: Envoy Gateway --- {{< blocks/cover title="Welcome to Envoy Gateway!" image_anchor="top" height="full" >}} - + GET STARTED - + CONTRIBUTING

Manages Envoy Proxy as a Standalone or Kubernetes-based Application Gateway

diff --git a/site/content/en/blog/releases/v0.6.md b/site/content/en/blog/releases/v0.6.md new file mode 100644 index 00000000000..987862d2100 --- /dev/null +++ b/site/content/en/blog/releases/v0.6.md @@ -0,0 +1,82 @@ +--- +title: Announcing Envoy Gateway v0.6 +subtitle: Major Update +linktitle: Release v0.6 +description: Envoy Gateway v0.6 release announcement. +publishdate: 2023-11-01 +release: v0.6.0 +skip_list: true +--- + +We are pleased to announce the release of Envoy Gateway v0.6! + +This is the fifth functional release of Envoy Gateway. We would like to thank the entire Envoy Gateway community for +helping publish the release. + +| [Release Notes][] | [Docs][docs] | [Compatibility Matrix][matrix] | [Download][] | +|-------------------|--------------|--------------------------------|--------------| + +## What's New + +The release adds a ton of features and functionality. Here are some highlights: + +### Gateway API + ++ Upgraded to Gateway API v1.0 ++ Added support for HTTPRoute Timeouts + +### Add Control Plane Proxy Telemetry + ++ Added Support for Metrics Telemetry + +### Add Support for directly configuring xDS + ++ Added Support for the EnvoyPatchPolicy API + +### ClientTrafficPolicy + ++ Added Support for configuring Downstream Keep Alives + +### BackendTrafficPolicy + ++ Added Support for configuring Rate limiting ++ Added Support for configuring load balancing + +### SecurityPolicy + ++ Added Support for configuring JWT ++ Added Support for configuring CORS + + +### API Updates + ++ Added support for selectively watching resources based on Namespace Selector ++ Added EnvoyGateway Metrics with Prometheus and OpenTelemetry support ++ Added Support for InitContainers in EnvoyProxy CRD ++ Added Support for LoadBalancerIP in EnvoyProxy CRD ++ Added Support for AllocateLoadBalancerNodePorts in EnvoyProxy CRD ++ Added Support for LoadBalancerClass in EnvoyProxy CRD ++ Added Support for selecting EnvoyProxy stats to be generated ++ Added Support for enabling EnvoyProxy Virtual Host metrics ++ Added Support for Merging Gateway resources onto the same infrastructure + +### CLI + ++ Added `egctl stats` command + +### Kubernetes Provider + ++ Improved reconiliation by using the same enqueue request for all resources ++ Added support for reconciling ServiceImport CRD + +### Breaking changes + ++ Removed RateLimitFilter, and replaced it with BackendTrafficPolicy ++ Removed AuthenticationFilter, and replaced it with SecurityPolicy ++ Moved the EnvoyProxy CRD from `config.gateway.envoyproxy.io` to `gateway.envoyproxy.io` ++ Converted the `bootstrap` field within `EnvoyProxy` into a struct to support merge operations. + +[Release Notes]: https://github.com/envoyproxy/gateway/blob/main/release-notes/v0.6.0.yaml +[matrix]: https://gateway.envoyproxy.io/v0.6.0/intro/compatibility.html +[docs]: https://gateway.envoyproxy.io/v0.6.0/index.html +[Download]: https://github.com/envoyproxy/gateway/releases/tag/v0.6.0 diff --git a/site/content/en/v0.6.0/_index.md b/site/content/en/v0.6.0/_index.md new file mode 100644 index 00000000000..567b43bfe36 --- /dev/null +++ b/site/content/en/v0.6.0/_index.md @@ -0,0 +1,21 @@ ++++ +title = "Welcome to Envoy Gateway" +linktitle = "Documentation" +description = "Envoy Gateway Documents" + +[[cascade]] +type = "docs" ++++ + +{{% alert title="Note" color="primary" %}} + +This project is under **active** development. Many features are not complete. We would love for you to [Get Involved](contributions/)! + +{{% /alert %}} + +Envoy Gateway is an open source project for managing [Envoy Proxy](https://www.envoyproxy.io/) as a standalone or Kubernetes-based application +gateway. [Gateway API](https://gateway-api.sigs.k8s.io/) resources are used to dynamically provision and configure the managed Envoy Proxies. + +![architecture](/img/traffic.png) + +## Ready to get started? diff --git a/site/content/en/v0.6.0/api/_index.md b/site/content/en/v0.6.0/api/_index.md new file mode 100644 index 00000000000..396d9ffcefc --- /dev/null +++ b/site/content/en/v0.6.0/api/_index.md @@ -0,0 +1,5 @@ +--- +title: "API" +description: This section includes APIs of Envoy Gateway. +weight: 80 +--- diff --git a/site/content/en/v0.6.0/api/extension_types.md b/site/content/en/v0.6.0/api/extension_types.md new file mode 100644 index 00000000000..08b53e29c85 --- /dev/null +++ b/site/content/en/v0.6.0/api/extension_types.md @@ -0,0 +1,1706 @@ ++++ +title = "API Reference" ++++ + + +## Packages +- [gateway.envoyproxy.io/v1alpha1](#gatewayenvoyproxyiov1alpha1) + + +## gateway.envoyproxy.io/v1alpha1 + +Package v1alpha1 contains API schema definitions for the gateway.envoyproxy.io +API group. + + +### Resource Types +- [BackendTrafficPolicy](#backendtrafficpolicy) +- [BackendTrafficPolicyList](#backendtrafficpolicylist) +- [ClientTrafficPolicy](#clienttrafficpolicy) +- [ClientTrafficPolicyList](#clienttrafficpolicylist) +- [EnvoyGateway](#envoygateway) +- [EnvoyPatchPolicy](#envoypatchpolicy) +- [EnvoyPatchPolicyList](#envoypatchpolicylist) +- [EnvoyProxy](#envoyproxy) +- [SecurityPolicy](#securitypolicy) +- [SecurityPolicyList](#securitypolicylist) + + + +#### BackendTrafficPolicy + + + +BackendTrafficPolicy allows the user to configure the behavior of the connection between the downstream client and Envoy Proxy listener. + +_Appears in:_ +- [BackendTrafficPolicyList](#backendtrafficpolicylist) + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `BackendTrafficPolicy` +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` _[BackendTrafficPolicySpec](#backendtrafficpolicyspec)_ | spec defines the desired state of BackendTrafficPolicy. | + + +#### BackendTrafficPolicyList + + + +BackendTrafficPolicyList contains a list of BackendTrafficPolicy resources. + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `BackendTrafficPolicyList` +| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` _[BackendTrafficPolicy](#backendtrafficpolicy) array_ | | + + +#### BackendTrafficPolicySpec + + + +spec defines the desired state of BackendTrafficPolicy. + +_Appears in:_ +- [BackendTrafficPolicy](#backendtrafficpolicy) + +| Field | Description | +| --- | --- | +| `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | targetRef is the name of the resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. | +| `rateLimit` _[RateLimitSpec](#ratelimitspec)_ | RateLimit allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. | +| `loadBalancer` _[LoadBalancer](#loadbalancer)_ | LoadBalancer policy to apply when routing traffic from the gateway to the backend endpoints | + + + + +#### BootstrapType + +_Underlying type:_ `string` + +BootstrapType defines the types of bootstrap supported by Envoy Gateway. + +_Appears in:_ +- [ProxyBootstrap](#proxybootstrap) + + + +#### CORS + + + +CORS defines the configuration for Cross-Origin Resource Sharing (CORS). + +_Appears in:_ +- [SecurityPolicySpec](#securitypolicyspec) + +| Field | Description | +| --- | --- | +| `allowOrigins` _[StringMatch](#stringmatch) array_ | AllowOrigins defines the origins that are allowed to make requests. | +| `allowMethods` _string array_ | AllowMethods defines the methods that are allowed to make requests. | +| `allowHeaders` _string array_ | AllowHeaders defines the headers that are allowed to be sent with requests. | +| `exposeHeaders` _string array_ | ExposeHeaders defines the headers that can be exposed in the responses. | +| `maxAge` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | MaxAge defines how long the results of a preflight request can be cached. | + + +#### ClaimToHeader + + + +ClaimToHeader defines a configuration to convert JWT claims into HTTP headers + +_Appears in:_ +- [JWTProvider](#jwtprovider) + +| Field | Description | +| --- | --- | +| `header` _string_ | Header defines the name of the HTTP request header that the JWT Claim will be saved into. | +| `claim` _string_ | Claim is the JWT Claim that should be saved into the header : it can be a nested claim of type (eg. "claim.nested.key", "sub"). The nested claim name must use dot "." to separate the JSON name path. | + + +#### ClientTrafficPolicy + + + +ClientTrafficPolicy allows the user to configure the behavior of the connection between the downstream client and Envoy Proxy listener. + +_Appears in:_ +- [ClientTrafficPolicyList](#clienttrafficpolicylist) + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `ClientTrafficPolicy` +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` _[ClientTrafficPolicySpec](#clienttrafficpolicyspec)_ | Spec defines the desired state of ClientTrafficPolicy. | + + +#### ClientTrafficPolicyList + + + +ClientTrafficPolicyList contains a list of ClientTrafficPolicy resources. + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `ClientTrafficPolicyList` +| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` _[ClientTrafficPolicy](#clienttrafficpolicy) array_ | | + + +#### ClientTrafficPolicySpec + + + +ClientTrafficPolicySpec defines the desired state of ClientTrafficPolicy. + +_Appears in:_ +- [ClientTrafficPolicy](#clienttrafficpolicy) + +| Field | Description | +| --- | --- | +| `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. TargetRef | +| `tcpKeepalive` _[TCPKeepalive](#tcpkeepalive)_ | TcpKeepalive settings associated with the downstream client connection. If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives. Disabled by default. | + + + + +#### ConsistentHash + + + +ConsistentHash defines the configuration related to the consistent hash load balancer policy + +_Appears in:_ +- [LoadBalancer](#loadbalancer) + +| Field | Description | +| --- | --- | +| `type` _[ConsistentHashType](#consistenthashtype)_ | | + + +#### ConsistentHashType + +_Underlying type:_ `string` + +ConsistentHashType defines the type of input to hash on. + +_Appears in:_ +- [ConsistentHash](#consistenthash) + + + +#### CustomTag + + + + + +_Appears in:_ +- [ProxyTracing](#proxytracing) + +| Field | Description | +| --- | --- | +| `type` _[CustomTagType](#customtagtype)_ | Type defines the type of custom tag. | +| `literal` _[LiteralCustomTag](#literalcustomtag)_ | Literal adds hard-coded value to each span. It's required when the type is "Literal". | +| `environment` _[EnvironmentCustomTag](#environmentcustomtag)_ | Environment adds value from environment variable to each span. It's required when the type is "Environment". | +| `requestHeader` _[RequestHeaderCustomTag](#requestheadercustomtag)_ | RequestHeader adds value from request header to each span. It's required when the type is "RequestHeader". | + + +#### CustomTagType + +_Underlying type:_ `string` + + + +_Appears in:_ +- [CustomTag](#customtag) + + + +#### EnvironmentCustomTag + + + +EnvironmentCustomTag adds value from environment variable to each span. + +_Appears in:_ +- [CustomTag](#customtag) + +| Field | Description | +| --- | --- | +| `name` _string_ | Name defines the name of the environment variable which to extract the value from. | +| `defaultValue` _string_ | DefaultValue defines the default value to use if the environment variable is not set. | + + +#### EnvoyGateway + + + +EnvoyGateway is the schema for the envoygateways API. + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `EnvoyGateway` +| `gateway` _[Gateway](#gateway)_ | Gateway defines desired Gateway API specific configuration. If unset, default configuration parameters will apply. | +| `provider` _[EnvoyGatewayProvider](#envoygatewayprovider)_ | Provider defines the desired provider and provider-specific configuration. If unspecified, the Kubernetes provider is used with default configuration parameters. | +| `logging` _[EnvoyGatewayLogging](#envoygatewaylogging)_ | Logging defines logging parameters for Envoy Gateway. | +| `admin` _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | Admin defines the desired admin related abilities. If unspecified, the Admin is used with default configuration parameters. | +| `telemetry` _[EnvoyGatewayTelemetry](#envoygatewaytelemetry)_ | Telemetry defines the desired control plane telemetry related abilities. If unspecified, the telemetry is used with default configuration. | +| `rateLimit` _[RateLimit](#ratelimit)_ | RateLimit defines the configuration associated with the Rate Limit service deployed by Envoy Gateway required to implement the Global Rate limiting functionality. The specific rate limit service used here is the reference implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit. This configuration is unneeded for "Local" rate limiting. | +| `extensionManager` _[ExtensionManager](#extensionmanager)_ | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. | +| `extensionApis` _[ExtensionAPISettings](#extensionapisettings)_ | ExtensionAPIs defines the settings related to specific Gateway API Extensions implemented by Envoy Gateway | + + +#### EnvoyGatewayAdmin + + + +EnvoyGatewayAdmin defines the Envoy Gateway Admin configuration. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `address` _[EnvoyGatewayAdminAddress](#envoygatewayadminaddress)_ | Address defines the address of Envoy Gateway Admin Server. | +| `enableDumpConfig` _boolean_ | EnableDumpConfig defines if enable dump config in Envoy Gateway logs. | +| `enablePprof` _boolean_ | EnablePprof defines if enable pprof in Envoy Gateway Admin Server. | + + +#### EnvoyGatewayAdminAddress + + + +EnvoyGatewayAdminAddress defines the Envoy Gateway Admin Address configuration. + +_Appears in:_ +- [EnvoyGatewayAdmin](#envoygatewayadmin) + +| Field | Description | +| --- | --- | +| `port` _integer_ | Port defines the port the admin server is exposed on. | +| `host` _string_ | Host defines the admin server hostname. | + + +#### EnvoyGatewayCustomProvider + + + +EnvoyGatewayCustomProvider defines configuration for the Custom provider. + +_Appears in:_ +- [EnvoyGatewayProvider](#envoygatewayprovider) + +| Field | Description | +| --- | --- | +| `resource` _[EnvoyGatewayResourceProvider](#envoygatewayresourceprovider)_ | Resource defines the desired resource provider. This provider is used to specify the provider to be used to retrieve the resource configurations such as Gateway API resources | +| `infrastructure` _[EnvoyGatewayInfrastructureProvider](#envoygatewayinfrastructureprovider)_ | Infrastructure defines the desired infrastructure provider. This provider is used to specify the provider to be used to provide an environment to deploy the out resources like the Envoy Proxy data plane. | + + +#### EnvoyGatewayFileResourceProvider + + + +EnvoyGatewayFileResourceProvider defines configuration for the File Resource provider. + +_Appears in:_ +- [EnvoyGatewayResourceProvider](#envoygatewayresourceprovider) + +| Field | Description | +| --- | --- | +| `paths` _string array_ | Paths are the paths to a directory or file containing the resource configuration. Recursive sub directories are not currently supported. | + + +#### EnvoyGatewayHostInfrastructureProvider + + + +EnvoyGatewayHostInfrastructureProvider defines configuration for the Host Infrastructure provider. + +_Appears in:_ +- [EnvoyGatewayInfrastructureProvider](#envoygatewayinfrastructureprovider) + + + +#### EnvoyGatewayInfrastructureProvider + + + +EnvoyGatewayInfrastructureProvider defines configuration for the Custom Infrastructure provider. + +_Appears in:_ +- [EnvoyGatewayCustomProvider](#envoygatewaycustomprovider) + +| Field | Description | +| --- | --- | +| `type` _[InfrastructureProviderType](#infrastructureprovidertype)_ | Type is the type of infrastructure providers to use. Supported types are "Host". | +| `host` _[EnvoyGatewayHostInfrastructureProvider](#envoygatewayhostinfrastructureprovider)_ | Host defines the configuration of the Host provider. Host provides runtime deployment of the data plane as a child process on the host environment. | + + +#### EnvoyGatewayKubernetesProvider + + + +EnvoyGatewayKubernetesProvider defines configuration for the Kubernetes provider. + +_Appears in:_ +- [EnvoyGatewayProvider](#envoygatewayprovider) + +| Field | Description | +| --- | --- | +| `rateLimitDeployment` _[KubernetesDeploymentSpec](#kubernetesdeploymentspec)_ | RateLimitDeployment defines the desired state of the Envoy ratelimit deployment resource. If unspecified, default settings for the managed Envoy ratelimit deployment resource are applied. | +| `watch` _[KubernetesWatchMode](#kuberneteswatchmode)_ | Watch holds configuration of which input resources should be watched and reconciled. | +| `deploy` _[KubernetesDeployMode](#kubernetesdeploymode)_ | Deploy holds configuration of how output managed resources such as the Envoy Proxy data plane should be deployed | +| `overwrite_control_plane_certs` _boolean_ | OverwriteControlPlaneCerts updates the secrets containing the control plane certs, when set. | + + +#### EnvoyGatewayLogComponent + +_Underlying type:_ `string` + +EnvoyGatewayLogComponent defines a component that supports a configured logging level. + +_Appears in:_ +- [EnvoyGatewayLogging](#envoygatewaylogging) + + + +#### EnvoyGatewayLogging + + + +EnvoyGatewayLogging defines logging for Envoy Gateway. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `level` _object (keys:[EnvoyGatewayLogComponent](#envoygatewaylogcomponent), values:[LogLevel](#loglevel))_ | Level is the logging level. If unspecified, defaults to "info". EnvoyGatewayLogComponent options: default/provider/gateway-api/xds-translator/xds-server/infrastructure/global-ratelimit. LogLevel options: debug/info/error/warn. | + + +#### EnvoyGatewayMetricSink + + + +EnvoyGatewayMetricSink defines control plane metric sinks where metrics are sent to. + +_Appears in:_ +- [EnvoyGatewayMetrics](#envoygatewaymetrics) + +| Field | Description | +| --- | --- | +| `type` _[MetricSinkType](#metricsinktype)_ | Type defines the metric sink type. EG control plane currently supports OpenTelemetry. | +| `openTelemetry` _[EnvoyGatewayOpenTelemetrySink](#envoygatewayopentelemetrysink)_ | OpenTelemetry defines the configuration for OpenTelemetry sink. It's required if the sink type is OpenTelemetry. | + + +#### EnvoyGatewayMetrics + + + +EnvoyGatewayMetrics defines control plane push/pull metrics configurations. + +_Appears in:_ +- [EnvoyGatewayTelemetry](#envoygatewaytelemetry) + +| Field | Description | +| --- | --- | +| `sinks` _[EnvoyGatewayMetricSink](#envoygatewaymetricsink) array_ | Sinks defines the metric sinks where metrics are sent to. | +| `prometheus` _[EnvoyGatewayPrometheusProvider](#envoygatewayprometheusprovider)_ | Prometheus defines the configuration for prometheus endpoint. | + + +#### EnvoyGatewayOpenTelemetrySink + + + + + +_Appears in:_ +- [EnvoyGatewayMetricSink](#envoygatewaymetricsink) + +| Field | Description | +| --- | --- | +| `host` _string_ | Host define the sink service hostname. | +| `protocol` _string_ | Protocol define the sink service protocol. | +| `port` _integer_ | Port defines the port the sink service is exposed on. | + + +#### EnvoyGatewayPrometheusProvider + + + +EnvoyGatewayPrometheusProvider will expose prometheus endpoint in pull mode. + +_Appears in:_ +- [EnvoyGatewayMetrics](#envoygatewaymetrics) + +| Field | Description | +| --- | --- | +| `disable` _boolean_ | Disable defines if disables the prometheus metrics in pull mode. | + + +#### EnvoyGatewayProvider + + + +EnvoyGatewayProvider defines the desired configuration of a provider. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `type` _[ProviderType](#providertype)_ | Type is the type of provider to use. Supported types are "Kubernetes". | +| `kubernetes` _[EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider)_ | Kubernetes defines the configuration of the Kubernetes provider. Kubernetes provides runtime configuration via the Kubernetes API. | +| `custom` _[EnvoyGatewayCustomProvider](#envoygatewaycustomprovider)_ | Custom defines the configuration for the Custom provider. This provider allows you to define a specific resource provider and a infrastructure provider. | + + +#### EnvoyGatewayResourceProvider + + + +EnvoyGatewayResourceProvider defines configuration for the Custom Resource provider. + +_Appears in:_ +- [EnvoyGatewayCustomProvider](#envoygatewaycustomprovider) + +| Field | Description | +| --- | --- | +| `type` _[ResourceProviderType](#resourceprovidertype)_ | Type is the type of resource provider to use. Supported types are "File". | +| `file` _[EnvoyGatewayFileResourceProvider](#envoygatewayfileresourceprovider)_ | File defines the configuration of the File provider. File provides runtime configuration defined by one or more files. | + + +#### EnvoyGatewaySpec + + + +EnvoyGatewaySpec defines the desired state of Envoy Gateway. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) + +| Field | Description | +| --- | --- | +| `gateway` _[Gateway](#gateway)_ | Gateway defines desired Gateway API specific configuration. If unset, default configuration parameters will apply. | +| `provider` _[EnvoyGatewayProvider](#envoygatewayprovider)_ | Provider defines the desired provider and provider-specific configuration. If unspecified, the Kubernetes provider is used with default configuration parameters. | +| `logging` _[EnvoyGatewayLogging](#envoygatewaylogging)_ | Logging defines logging parameters for Envoy Gateway. | +| `admin` _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | Admin defines the desired admin related abilities. If unspecified, the Admin is used with default configuration parameters. | +| `telemetry` _[EnvoyGatewayTelemetry](#envoygatewaytelemetry)_ | Telemetry defines the desired control plane telemetry related abilities. If unspecified, the telemetry is used with default configuration. | +| `rateLimit` _[RateLimit](#ratelimit)_ | RateLimit defines the configuration associated with the Rate Limit service deployed by Envoy Gateway required to implement the Global Rate limiting functionality. The specific rate limit service used here is the reference implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit. This configuration is unneeded for "Local" rate limiting. | +| `extensionManager` _[ExtensionManager](#extensionmanager)_ | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. | +| `extensionApis` _[ExtensionAPISettings](#extensionapisettings)_ | ExtensionAPIs defines the settings related to specific Gateway API Extensions implemented by Envoy Gateway | + + +#### EnvoyGatewayTelemetry + + + +EnvoyGatewayTelemetry defines telemetry configurations for envoy gateway control plane. Control plane will focus on metrics observability telemetry and tracing telemetry later. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `metrics` _[EnvoyGatewayMetrics](#envoygatewaymetrics)_ | Metrics defines metrics configuration for envoy gateway. | + + +#### EnvoyJSONPatchConfig + + + +EnvoyJSONPatchConfig defines the configuration for patching a Envoy xDS Resource using JSONPatch semantic + +_Appears in:_ +- [EnvoyPatchPolicySpec](#envoypatchpolicyspec) + +| Field | Description | +| --- | --- | +| `type` _[EnvoyResourceType](#envoyresourcetype)_ | Type is the typed URL of the Envoy xDS Resource | +| `name` _string_ | Name is the name of the resource | +| `operation` _[JSONPatchOperation](#jsonpatchoperation)_ | Patch defines the JSON Patch Operation | + + +#### EnvoyPatchPolicy + + + +EnvoyPatchPolicy allows the user to modify the generated Envoy xDS resources by Envoy Gateway using this patch API + +_Appears in:_ +- [EnvoyPatchPolicyList](#envoypatchpolicylist) + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `EnvoyPatchPolicy` +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` _[EnvoyPatchPolicySpec](#envoypatchpolicyspec)_ | Spec defines the desired state of EnvoyPatchPolicy. | + + +#### EnvoyPatchPolicyList + + + +EnvoyPatchPolicyList contains a list of EnvoyPatchPolicy resources. + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `EnvoyPatchPolicyList` +| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` _[EnvoyPatchPolicy](#envoypatchpolicy) array_ | | + + +#### EnvoyPatchPolicySpec + + + +EnvoyPatchPolicySpec defines the desired state of EnvoyPatchPolicy. + +_Appears in:_ +- [EnvoyPatchPolicy](#envoypatchpolicy) + +| Field | Description | +| --- | --- | +| `type` _[EnvoyPatchType](#envoypatchtype)_ | Type decides the type of patch. Valid EnvoyPatchType values are "JSONPatch". | +| `jsonPatches` _[EnvoyJSONPatchConfig](#envoyjsonpatchconfig) array_ | JSONPatch defines the JSONPatch configuration. | +| `targetRef` _[PolicyTargetReference](#policytargetreference)_ | TargetRef is the name of the Gateway API resource this policy is being attached to. Currently only attaching to Gateway is supported This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway TargetRef | +| `priority` _integer_ | Priority of the EnvoyPatchPolicy. If multiple EnvoyPatchPolicies are applied to the same TargetRef, they will be applied in the ascending order of the priority i.e. int32.min has the highest priority and int32.max has the lowest priority. Defaults to 0. | + + + + +#### EnvoyPatchType + +_Underlying type:_ `string` + +EnvoyPatchType specifies the types of Envoy patching mechanisms. + +_Appears in:_ +- [EnvoyPatchPolicySpec](#envoypatchpolicyspec) + + + +#### EnvoyProxy + + + +EnvoyProxy is the schema for the envoyproxies API. + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `EnvoyProxy` +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` _[EnvoyProxySpec](#envoyproxyspec)_ | EnvoyProxySpec defines the desired state of EnvoyProxy. | + + +#### EnvoyProxyKubernetesProvider + + + +EnvoyProxyKubernetesProvider defines configuration for the Kubernetes resource provider. + +_Appears in:_ +- [EnvoyProxyProvider](#envoyproxyprovider) + +| Field | Description | +| --- | --- | +| `envoyDeployment` _[KubernetesDeploymentSpec](#kubernetesdeploymentspec)_ | EnvoyDeployment defines the desired state of the Envoy deployment resource. If unspecified, default settings for the managed Envoy deployment resource are applied. | +| `envoyService` _[KubernetesServiceSpec](#kubernetesservicespec)_ | EnvoyService defines the desired state of the Envoy service resource. If unspecified, default settings for the managed Envoy service resource are applied. | + + +#### EnvoyProxyProvider + + + +EnvoyProxyProvider defines the desired state of a resource provider. + +_Appears in:_ +- [EnvoyProxySpec](#envoyproxyspec) + +| Field | Description | +| --- | --- | +| `type` _[ProviderType](#providertype)_ | Type is the type of resource provider to use. A resource provider provides infrastructure resources for running the data plane, e.g. Envoy proxy, and optional auxiliary control planes. Supported types are "Kubernetes". | +| `kubernetes` _[EnvoyProxyKubernetesProvider](#envoyproxykubernetesprovider)_ | Kubernetes defines the desired state of the Kubernetes resource provider. Kubernetes provides infrastructure resources for running the data plane, e.g. Envoy proxy. If unspecified and type is "Kubernetes", default settings for managed Kubernetes resources are applied. | + + +#### EnvoyProxySpec + + + +EnvoyProxySpec defines the desired state of EnvoyProxy. + +_Appears in:_ +- [EnvoyProxy](#envoyproxy) + +| Field | Description | +| --- | --- | +| `provider` _[EnvoyProxyProvider](#envoyproxyprovider)_ | Provider defines the desired resource provider and provider-specific configuration. If unspecified, the "Kubernetes" resource provider is used with default configuration parameters. | +| `logging` _[ProxyLogging](#proxylogging)_ | Logging defines logging parameters for managed proxies. | +| `telemetry` _[ProxyTelemetry](#proxytelemetry)_ | Telemetry defines telemetry parameters for managed proxies. | +| `bootstrap` _[ProxyBootstrap](#proxybootstrap)_ | Bootstrap defines the Envoy Bootstrap as a YAML string. Visit https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/bootstrap/v3/bootstrap.proto#envoy-v3-api-msg-config-bootstrap-v3-bootstrap to learn more about the syntax. If set, this is the Bootstrap configuration used for the managed Envoy Proxy fleet instead of the default Bootstrap configuration set by Envoy Gateway. Some fields within the Bootstrap that are required to communicate with the xDS Server (Envoy Gateway) and receive xDS resources from it are not configurable and will result in the `EnvoyProxy` resource being rejected. Backward compatibility across minor versions is not guaranteed. We strongly recommend using `egctl x translate` to generate a `EnvoyProxy` resource with the `Bootstrap` field set to the default Bootstrap configuration used. You can edit this configuration, and rerun `egctl x translate` to ensure there are no validation errors. | +| `concurrency` _integer_ | Concurrency defines the number of worker threads to run. If unset, it defaults to the number of cpuset threads on the platform. | +| `mergeGateways` _boolean_ | 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. | + + + + +#### EnvoyResourceType + +_Underlying type:_ `string` + +EnvoyResourceType specifies the type URL of the Envoy resource. + +_Appears in:_ +- [EnvoyJSONPatchConfig](#envoyjsonpatchconfig) + + + +#### ExtensionAPISettings + + + +ExtensionAPISettings defines the settings specific to Gateway API Extensions. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `enableEnvoyPatchPolicy` _boolean_ | EnableEnvoyPatchPolicy enables Envoy Gateway to reconcile and implement the EnvoyPatchPolicy resources. | + + +#### ExtensionHooks + + + +ExtensionHooks defines extension hooks across all supported runners + +_Appears in:_ +- [ExtensionManager](#extensionmanager) + +| Field | Description | +| --- | --- | +| `xdsTranslator` _[XDSTranslatorHooks](#xdstranslatorhooks)_ | XDSTranslator defines all the supported extension hooks for the xds-translator runner | + + +#### ExtensionManager + + + +ExtensionManager defines the configuration for registering an extension manager to the Envoy Gateway control plane. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `resources` _[GroupVersionKind](#groupversionkind) array_ | Resources defines the set of K8s resources the extension will handle. | +| `hooks` _[ExtensionHooks](#extensionhooks)_ | Hooks defines the set of hooks the extension supports | +| `service` _[ExtensionService](#extensionservice)_ | Service defines the configuration of the extension service that the Envoy Gateway Control Plane will call through extension hooks. | + + +#### ExtensionService + + + +ExtensionService defines the configuration for connecting to a registered extension service. + +_Appears in:_ +- [ExtensionManager](#extensionmanager) + +| Field | Description | +| --- | --- | +| `host` _string_ | Host define the extension service hostname. | +| `port` _integer_ | Port defines the port the extension service is exposed on. | +| `tls` _[ExtensionTLS](#extensiontls)_ | TLS defines TLS configuration for communication between Envoy Gateway and the extension service. | + + +#### ExtensionTLS + + + +ExtensionTLS defines the TLS configuration when connecting to an extension service + +_Appears in:_ +- [ExtensionService](#extensionservice) + +| Field | Description | +| --- | --- | +| `certificateRef` _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | CertificateRef contains a references to objects (Kubernetes objects or otherwise) that contains a TLS certificate and private keys. These certificates are used to establish a TLS handshake to the extension server. + CertificateRef can only reference a Kubernetes Secret at this time. | + + +#### FileEnvoyProxyAccessLog + + + + + +_Appears in:_ +- [ProxyAccessLogSink](#proxyaccesslogsink) + +| Field | Description | +| --- | --- | +| `path` _string_ | Path defines the file path used to expose envoy access log(e.g. /dev/stdout). | + + +#### Gateway + + + +Gateway defines the desired Gateway API configuration of Envoy Gateway. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `controllerName` _string_ | ControllerName defines the name of the Gateway API controller. If unspecified, defaults to "gateway.envoyproxy.io/gatewayclass-controller". See the following for additional details: https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1.GatewayClass | + + +#### GlobalRateLimit + + + +GlobalRateLimit defines global rate limit configuration. + +_Appears in:_ +- [RateLimitSpec](#ratelimitspec) + +| Field | Description | +| --- | --- | +| `rules` _[RateLimitRule](#ratelimitrule) array_ | Rules are a list of RateLimit selectors and limits. Each rule and its associated limit is applied in a mutually exclusive way i.e. if multiple rules get selected, each of their associated limits get applied, so a single traffic request might increase the rate limit counters for multiple rules if selected. | + + +#### GroupVersionKind + + + +GroupVersionKind unambiguously identifies a Kind. It can be converted to k8s.io/apimachinery/pkg/runtime/schema.GroupVersionKind + +_Appears in:_ +- [ExtensionManager](#extensionmanager) + +| Field | Description | +| --- | --- | +| `group` _string_ | | +| `version` _string_ | | +| `kind` _string_ | | + + +#### HeaderMatch + + + +HeaderMatch defines the match attributes within the HTTP Headers of the request. + +_Appears in:_ +- [RateLimitSelectCondition](#ratelimitselectcondition) + + + +#### InfrastructureProviderType + +_Underlying type:_ `string` + +InfrastructureProviderType defines the types of custom infrastructure providers supported by Envoy Gateway. + +_Appears in:_ +- [EnvoyGatewayInfrastructureProvider](#envoygatewayinfrastructureprovider) + + + +#### JSONPatchOperation + + + +JSONPatchOperation defines the JSON Patch Operation as defined in https://datatracker.ietf.org/doc/html/rfc6902 + +_Appears in:_ +- [EnvoyJSONPatchConfig](#envoyjsonpatchconfig) + +| Field | Description | +| --- | --- | +| `op` _[JSONPatchOperationType](#jsonpatchoperationtype)_ | Op is the type of operation to perform | +| `path` _string_ | Path is the location of the target document/field where the operation will be performed Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. | +| `value` _[JSON](#json)_ | Value is the new value of the path location. | + + +#### JSONPatchOperationType + +_Underlying type:_ `string` + +JSONPatchOperationType specifies the JSON Patch operations that can be performed. + +_Appears in:_ +- [JSONPatchOperation](#jsonpatchoperation) + + + +#### JWT + + + +JWT defines the configuration for JSON Web Token (JWT) authentication. + +_Appears in:_ +- [SecurityPolicySpec](#securitypolicyspec) + +| Field | Description | +| --- | --- | +| `providers` _[JWTProvider](#jwtprovider) array_ | Providers defines the JSON Web Token (JWT) authentication provider type. + When multiple JWT providers are specified, the JWT is considered valid if any of the providers successfully validate the JWT. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. | + + +#### JWTProvider + + + +JWTProvider defines how a JSON Web Token (JWT) can be verified. + +_Appears in:_ +- [JWT](#jwt) + +| Field | Description | +| --- | --- | +| `name` _string_ | Name defines a unique name for the JWT provider. A name can have a variety of forms, including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. | +| `issuer` _string_ | Issuer is the principal that issued the JWT and takes the form of a URL or email address. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 for URL format and https://rfc-editor.org/rfc/rfc5322.html for email format. If not provided, the JWT issuer is not checked. | +| `audiences` _string array_ | Audiences is a list of JWT audiences allowed access. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.3. If not provided, JWT audiences are not checked. | +| `remoteJWKS` _[RemoteJWKS](#remotejwks)_ | RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. | +| `claimToHeaders` _[ClaimToHeader](#claimtoheader) array_ | ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers For examples, following config: The claim must be of type; string, int, double, bool. Array type claims are not supported | + + +#### KubernetesContainerSpec + + + +KubernetesContainerSpec defines the desired state of the Kubernetes container resource. + +_Appears in:_ +- [KubernetesDeploymentSpec](#kubernetesdeploymentspec) + +| Field | Description | +| --- | --- | +| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#envvar-v1-core) array_ | List of environment variables to set in the container. | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#resourcerequirements-v1-core)_ | Resources required by this container. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | +| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#securitycontext-v1-core)_ | SecurityContext defines the security options the container should be run with. If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ | +| `image` _string_ | Image specifies the EnvoyProxy container image to be used, instead of the default image. | +| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volumemount-v1-core) array_ | VolumeMounts are volumes to mount into the container's filesystem. Cannot be updated. | + + +#### KubernetesDeployMode + + + +KubernetesDeployMode holds configuration for how to deploy managed resources such as the Envoy Proxy data plane fleet. + +_Appears in:_ +- [EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider) + + + +#### KubernetesDeploymentSpec + + + +KubernetesDeploymentSpec defines the desired state of the Kubernetes deployment resource. + +_Appears in:_ +- [EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider) +- [EnvoyProxyKubernetesProvider](#envoyproxykubernetesprovider) + +| Field | Description | +| --- | --- | +| `replicas` _integer_ | Replicas is the number of desired pods. Defaults to 1. | +| `strategy` _[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#deploymentstrategy-v1-apps)_ | The deployment strategy to use to replace existing pods with new ones. | +| `pod` _[KubernetesPodSpec](#kubernetespodspec)_ | Pod defines the desired specification of pod. | +| `container` _[KubernetesContainerSpec](#kubernetescontainerspec)_ | Container defines the desired specification of main container. | +| `initContainers` _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#container-v1-core) array_ | List of initialization containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ | + + +#### KubernetesPodSpec + + + +KubernetesPodSpec defines the desired state of the Kubernetes pod resource. + +_Appears in:_ +- [KubernetesDeploymentSpec](#kubernetesdeploymentspec) + +| Field | Description | +| --- | --- | +| `annotations` _object (keys:string, values:string)_ | Annotations are the annotations that should be appended to the pods. By default, no pod annotations are appended. | +| `labels` _object (keys:string, values:string)_ | Labels are the additional labels that should be tagged to the pods. By default, no additional pod labels are tagged. | +| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#podsecuritycontext-v1-core)_ | SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#affinity-v1-core)_ | If specified, the pod's scheduling constraints. | +| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#toleration-v1-core) array_ | If specified, the pod's tolerations. | +| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volume-v1-core) array_ | Volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes | + + +#### KubernetesServiceSpec + + + +KubernetesServiceSpec defines the desired state of the Kubernetes service resource. + +_Appears in:_ +- [EnvoyProxyKubernetesProvider](#envoyproxykubernetesprovider) + +| Field | Description | +| --- | --- | +| `annotations` _object (keys:string, values:string)_ | Annotations that should be appended to the service. By default, no annotations are appended. | +| `type` _[ServiceType](#servicetype)_ | Type determines how the Service is exposed. Defaults to LoadBalancer. Valid options are ClusterIP, LoadBalancer and NodePort. "LoadBalancer" means a service will be exposed via an external load balancer (if the cloud provider supports it). "ClusterIP" means a service will only be accessible inside the cluster, via the cluster IP. "NodePort" means a service will be exposed on a static Port on all Nodes of the cluster. | +| `loadBalancerClass` _string_ | LoadBalancerClass, when specified, allows for choosing the LoadBalancer provider implementation if more than one are available or is otherwise expected to be specified | +| `allocateLoadBalancerNodePorts` _boolean_ | AllocateLoadBalancerNodePorts defines if NodePorts will be automatically allocated for services with type LoadBalancer. Default is "true". It may be set to "false" if the cluster load-balancer does not rely on NodePorts. If the caller requests specific NodePorts (by specifying a value), those requests will be respected, regardless of this field. This field may only be set for services with type LoadBalancer and will be cleared if the type is changed to any other type. | +| `loadBalancerIP` _string_ | LoadBalancerIP defines the IP Address of the underlying load balancer service. This field may be ignored if the load balancer provider does not support this feature. This field has been deprecated in Kubernetes, but it is still used for setting the IP Address in some cloud providers such as GCP. | + + +#### KubernetesWatchMode + + + +KubernetesWatchMode holds the configuration for which input resources to watch and reconcile. + +_Appears in:_ +- [EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider) + +| Field | Description | +| --- | --- | +| `Type` _[KubernetesWatchModeType](#kuberneteswatchmodetype)_ | Type indicates what watch mode to use. KubernetesWatchModeTypeNamespaces and KubernetesWatchModeTypeNamespaceSelectors are currently supported By default, when this field is unset or empty, Envoy Gateway will watch for input namespaced resources from all namespaces. | +| `Namespaces` _string array_ | Namespaces holds the list of namespaces that Envoy Gateway will watch for namespaced scoped resources such as Gateway, HTTPRoute and Service. Note that Envoy Gateway will continue to reconcile relevant cluster scoped resources such as GatewayClass that it is linked to. Precisely one of Namespaces and NamespaceSelectors must be set | +| `namespaces` _string array_ | NamespaceSelectors holds a list of labels that namespaces have to have in order to be watched. Note this doesn't set the informer to watch the namespaces with the given labels. Informer still watches all namespaces. But the events for objects whois namespce have no given labels will be filtered out. Precisely one of Namespaces and NamespaceSelectors must be set | + + +#### KubernetesWatchModeType + +_Underlying type:_ `string` + +KubernetesWatchModeType defines the type of KubernetesWatchMode + +_Appears in:_ +- [KubernetesWatchMode](#kuberneteswatchmode) + + + +#### LiteralCustomTag + + + +LiteralCustomTag adds hard-coded value to each span. + +_Appears in:_ +- [CustomTag](#customtag) + +| Field | Description | +| --- | --- | +| `value` _string_ | Value defines the hard-coded value to add to each span. | + + +#### LoadBalancer + + + +LoadBalancer defines the load balancer policy to be applied. + +_Appears in:_ +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) + +| Field | Description | +| --- | --- | +| `type` _[LoadBalancerType](#loadbalancertype)_ | Type decides the type of Load Balancer policy. Valid LoadBalancerType values are "ConsistentHash", "LeastRequest", "Random", "RoundRobin", | +| `consistentHash` _[ConsistentHash](#consistenthash)_ | ConsistentHash defines the configuration when the load balancer type is set to ConsistentHash | + + +#### LoadBalancerType + +_Underlying type:_ `string` + +LoadBalancerType specifies the types of LoadBalancer. + +_Appears in:_ +- [LoadBalancer](#loadbalancer) + + + +#### LogLevel + +_Underlying type:_ `string` + +LogLevel defines a log level for Envoy Gateway and EnvoyProxy system logs. + +_Appears in:_ +- [EnvoyGatewayLogging](#envoygatewaylogging) +- [ProxyLogging](#proxylogging) + + + +#### Match + + + +Match defines the stats match configuration. + +_Appears in:_ +- [ProxyMetrics](#proxymetrics) + +| Field | Description | +| --- | --- | +| `type` _[MatcherType](#matchertype)_ | MatcherType defines the stats matcher type | +| `value` _string_ | | + + +#### MatchType + +_Underlying type:_ `string` + +MatchType specifies the semantics of how a string value should be compared. Valid MatchType values are "Exact", "Prefix", "Suffix", "RegularExpression". + +_Appears in:_ +- [StringMatch](#stringmatch) + + + +#### MatcherType + +_Underlying type:_ `string` + + + +_Appears in:_ +- [Match](#match) + + + +#### MetricSinkType + +_Underlying type:_ `string` + + + +_Appears in:_ +- [EnvoyGatewayMetricSink](#envoygatewaymetricsink) +- [ProxyMetricSink](#proxymetricsink) + + + +#### OpenTelemetryEnvoyProxyAccessLog + + + +TODO: consider reuse ExtensionService? + +_Appears in:_ +- [ProxyAccessLogSink](#proxyaccesslogsink) + +| Field | Description | +| --- | --- | +| `host` _string_ | Host define the extension service hostname. | +| `port` _integer_ | Port defines the port the extension service is exposed on. | +| `resources` _object (keys:string, values:string)_ | Resources is a set of labels that describe the source of a log entry, including envoy node info. It's recommended to follow [semantic conventions](https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/). | + + +#### ProviderType + +_Underlying type:_ `string` + +ProviderType defines the types of providers supported by Envoy Gateway. + +_Appears in:_ +- [EnvoyGatewayProvider](#envoygatewayprovider) +- [EnvoyProxyProvider](#envoyproxyprovider) + + + +#### ProxyAccessLog + + + + + +_Appears in:_ +- [ProxyTelemetry](#proxytelemetry) + +| Field | Description | +| --- | --- | +| `disable` _boolean_ | Disable disables access logging for managed proxies if set to true. | +| `settings` _[ProxyAccessLogSetting](#proxyaccesslogsetting) array_ | Settings defines accesslog settings for managed proxies. If unspecified, will send default format to stdout. | + + +#### ProxyAccessLogFormat + + + +ProxyAccessLogFormat defines the format of accesslog. By default accesslogs are written to standard output. + +_Appears in:_ +- [ProxyAccessLogSetting](#proxyaccesslogsetting) + +| Field | Description | +| --- | --- | +| `type` _[ProxyAccessLogFormatType](#proxyaccesslogformattype)_ | Type defines the type of accesslog format. | +| `text` _string_ | Text defines the text accesslog format, following Envoy accesslog formatting, It's required when the format type is "Text". Envoy [command operators](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators) may be used in the format. The [format string documentation](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#config-access-log-format-strings) provides more information. | +| `json` _object (keys:string, values:string)_ | JSON is additional attributes that describe the specific event occurrence. Structured format for the envoy access logs. Envoy [command operators](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators) can be used as values for fields within the Struct. It's required when the format type is "JSON". | + + +#### ProxyAccessLogFormatType + +_Underlying type:_ `string` + + + +_Appears in:_ +- [ProxyAccessLogFormat](#proxyaccesslogformat) + + + +#### ProxyAccessLogSetting + + + + + +_Appears in:_ +- [ProxyAccessLog](#proxyaccesslog) + +| Field | Description | +| --- | --- | +| `format` _[ProxyAccessLogFormat](#proxyaccesslogformat)_ | Format defines the format of accesslog. | +| `sinks` _[ProxyAccessLogSink](#proxyaccesslogsink) array_ | Sinks defines the sinks of accesslog. | + + +#### ProxyAccessLogSink + + + + + +_Appears in:_ +- [ProxyAccessLogSetting](#proxyaccesslogsetting) + +| Field | Description | +| --- | --- | +| `type` _[ProxyAccessLogSinkType](#proxyaccesslogsinktype)_ | Type defines the type of accesslog sink. | +| `file` _[FileEnvoyProxyAccessLog](#fileenvoyproxyaccesslog)_ | File defines the file accesslog sink. | +| `openTelemetry` _[OpenTelemetryEnvoyProxyAccessLog](#opentelemetryenvoyproxyaccesslog)_ | OpenTelemetry defines the OpenTelemetry accesslog sink. | + + +#### ProxyAccessLogSinkType + +_Underlying type:_ `string` + + + +_Appears in:_ +- [ProxyAccessLogSink](#proxyaccesslogsink) + + + +#### ProxyBootstrap + + + +ProxyBootstrap defines Envoy Bootstrap configuration. + +_Appears in:_ +- [EnvoyProxySpec](#envoyproxyspec) + +| Field | Description | +| --- | --- | +| `type` _[BootstrapType](#bootstraptype)_ | Type is the type of the bootstrap configuration, it should be either Replace or Merge. If unspecified, it defaults to Replace. | +| `value` _string_ | Value is a YAML string of the bootstrap. | + + +#### ProxyLogComponent + +_Underlying type:_ `string` + +ProxyLogComponent defines a component that supports a configured logging level. + +_Appears in:_ +- [ProxyLogging](#proxylogging) + + + +#### ProxyLogging + + + +ProxyLogging defines logging parameters for managed proxies. + +_Appears in:_ +- [EnvoyProxySpec](#envoyproxyspec) + +| Field | Description | +| --- | --- | +| `level` _object (keys:[ProxyLogComponent](#proxylogcomponent), values:[LogLevel](#loglevel))_ | Level is a map of logging level per component, where the component is the key and the log level is the value. If unspecified, defaults to "default: warn". | + + +#### ProxyMetricSink + + + + + +_Appears in:_ +- [ProxyMetrics](#proxymetrics) + +| Field | Description | +| --- | --- | +| `type` _[MetricSinkType](#metricsinktype)_ | Type defines the metric sink type. EG currently only supports OpenTelemetry. | +| `openTelemetry` _[ProxyOpenTelemetrySink](#proxyopentelemetrysink)_ | OpenTelemetry defines the configuration for OpenTelemetry sink. It's required if the sink type is OpenTelemetry. | + + +#### ProxyMetrics + + + + + +_Appears in:_ +- [ProxyTelemetry](#proxytelemetry) + +| Field | Description | +| --- | --- | +| `prometheus` _[ProxyPrometheusProvider](#proxyprometheusprovider)_ | Prometheus defines the configuration for Admin endpoint `/stats/prometheus`. | +| `sinks` _[ProxyMetricSink](#proxymetricsink) array_ | Sinks defines the metric sinks where metrics are sent to. | +| `matches` _[Match](#match) array_ | Matches defines configuration for selecting specific metrics instead of generating all metrics stats that are enabled by default. This helps reduce CPU and memory overhead in Envoy, but eliminating some stats may after critical functionality. Here are the stats that we strongly recommend not disabling: `cluster_manager.warming_clusters`, `cluster..membership_total`,`cluster..membership_healthy`, `cluster..membership_degraded`,reference https://github.com/envoyproxy/envoy/issues/9856, https://github.com/envoyproxy/envoy/issues/14610 | +| `enableVirtualHostStats` _boolean_ | EnableVirtualHostStats enables envoy stat metrics for virtual hosts. | + + +#### ProxyOpenTelemetrySink + + + + + +_Appears in:_ +- [ProxyMetricSink](#proxymetricsink) + +| Field | Description | +| --- | --- | +| `host` _string_ | Host define the service hostname. | +| `port` _integer_ | Port defines the port the service is exposed on. | + + +#### ProxyPrometheusProvider + + + + + +_Appears in:_ +- [ProxyMetrics](#proxymetrics) + +| Field | Description | +| --- | --- | +| `disable` _boolean_ | Disable the Prometheus endpoint. | + + +#### ProxyTelemetry + + + + + +_Appears in:_ +- [EnvoyProxySpec](#envoyproxyspec) + +| Field | Description | +| --- | --- | +| `accessLog` _[ProxyAccessLog](#proxyaccesslog)_ | AccessLogs defines accesslog parameters for managed proxies. If unspecified, will send default format to stdout. | +| `tracing` _[ProxyTracing](#proxytracing)_ | Tracing defines tracing configuration for managed proxies. If unspecified, will not send tracing data. | +| `metrics` _[ProxyMetrics](#proxymetrics)_ | Metrics defines metrics configuration for managed proxies. | + + +#### ProxyTracing + + + + + +_Appears in:_ +- [ProxyTelemetry](#proxytelemetry) + +| Field | Description | +| --- | --- | +| `samplingRate` _integer_ | SamplingRate controls the rate at which traffic will be selected for tracing if no prior sampling decision has been made. Defaults to 100, valid values [0-100]. 100 indicates 100% sampling. | +| `customTags` _object (keys:string, values:[CustomTag](#customtag))_ | CustomTags defines the custom tags to add to each span. If provider is kubernetes, pod name and namespace are added by default. | +| `provider` _[TracingProvider](#tracingprovider)_ | Provider defines the tracing provider. Only OpenTelemetry is supported currently. | + + +#### RateLimit + + + +RateLimit defines the configuration associated with the Rate Limit Service used for Global Rate Limiting. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `backend` _[RateLimitDatabaseBackend](#ratelimitdatabasebackend)_ | Backend holds the configuration associated with the database backend used by the rate limit service to store state associated with global ratelimiting. | +| `timeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | Timeout specifies the timeout period for the proxy to access the ratelimit server If not set, timeout is 20ms. | +| `failClosed` _boolean_ | FailClosed is a switch used to control the flow of traffic when the response from the ratelimit server cannot be obtained. If FailClosed is false, let the traffic pass, otherwise, don't let the traffic pass and return 500. If not set, FailClosed is False. | + + +#### RateLimitDatabaseBackend + + + +RateLimitDatabaseBackend defines the configuration associated with the database backend used by the rate limit service. + +_Appears in:_ +- [RateLimit](#ratelimit) + +| Field | Description | +| --- | --- | +| `type` _[RateLimitDatabaseBackendType](#ratelimitdatabasebackendtype)_ | Type is the type of database backend to use. Supported types are: * Redis: Connects to a Redis database. | +| `redis` _[RateLimitRedisSettings](#ratelimitredissettings)_ | Redis defines the settings needed to connect to a Redis database. | + + +#### RateLimitDatabaseBackendType + +_Underlying type:_ `string` + +RateLimitDatabaseBackendType specifies the types of database backend to be used by the rate limit service. + +_Appears in:_ +- [RateLimitDatabaseBackend](#ratelimitdatabasebackend) + + + +#### RateLimitRedisSettings + + + +RateLimitRedisSettings defines the configuration for connecting to redis database. + +_Appears in:_ +- [RateLimitDatabaseBackend](#ratelimitdatabasebackend) + +| Field | Description | +| --- | --- | +| `url` _string_ | URL of the Redis Database. | +| `tls` _[RedisTLSSettings](#redistlssettings)_ | TLS defines TLS configuration for connecting to redis database. | + + +#### RateLimitRule + + + +RateLimitRule defines the semantics for matching attributes from the incoming requests, and setting limits for them. + +_Appears in:_ +- [GlobalRateLimit](#globalratelimit) + +| Field | Description | +| --- | --- | +| `clientSelectors` _[RateLimitSelectCondition](#ratelimitselectcondition) array_ | ClientSelectors holds the list of select conditions to select specific clients using attributes from the traffic flow. All individual select conditions must hold True for this rule and its limit to be applied. If this field is empty, it is equivalent to True, and the limit is applied. | +| `limit` _[RateLimitValue](#ratelimitvalue)_ | Limit holds the rate limit values. This limit is applied for traffic flows when the selectors compute to True, causing the request to be counted towards the limit. The limit is enforced and the request is ratelimited, i.e. a response with 429 HTTP status code is sent back to the client when the selected requests have reached the limit. | + + +#### RateLimitSelectCondition + + + +RateLimitSelectCondition specifies the attributes within the traffic flow that can be used to select a subset of clients to be ratelimited. All the individual conditions must hold True for the overall condition to hold True. + +_Appears in:_ +- [RateLimitRule](#ratelimitrule) + +| Field | Description | +| --- | --- | +| `headers` _[HeaderMatch](#headermatch) array_ | Headers is a list of request headers to match. Multiple header values are ANDed together, meaning, a request MUST match all the specified headers. | +| `sourceCIDR` _[SourceMatch](#sourcematch)_ | SourceCIDR is the client IP Address range to match on. | + + +#### RateLimitSpec + + + +RateLimitSpec defines the desired state of RateLimitSpec. + +_Appears in:_ +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) + +| Field | Description | +| --- | --- | +| `type` _[RateLimitType](#ratelimittype)_ | Type decides the scope for the RateLimits. Valid RateLimitType values are "Global". | +| `global` _[GlobalRateLimit](#globalratelimit)_ | Global defines global rate limit configuration. | + + +#### RateLimitType + +_Underlying type:_ `string` + +RateLimitType specifies the types of RateLimiting. + +_Appears in:_ +- [RateLimitSpec](#ratelimitspec) + + + +#### RateLimitUnit + +_Underlying type:_ `string` + +RateLimitUnit specifies the intervals for setting rate limits. Valid RateLimitUnit values are "Second", "Minute", "Hour", and "Day". + +_Appears in:_ +- [RateLimitValue](#ratelimitvalue) + + + +#### RateLimitValue + + + +RateLimitValue defines the limits for rate limiting. + +_Appears in:_ +- [RateLimitRule](#ratelimitrule) + +| Field | Description | +| --- | --- | +| `requests` _integer_ | | +| `unit` _[RateLimitUnit](#ratelimitunit)_ | | + + +#### RedisTLSSettings + + + +RedisTLSSettings defines the TLS configuration for connecting to redis database. + +_Appears in:_ +- [RateLimitRedisSettings](#ratelimitredissettings) + +| Field | Description | +| --- | --- | +| `certificateRef` _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | CertificateRef defines the client certificate reference for TLS connections. Currently only a Kubernetes Secret of type TLS is supported. | + + +#### RemoteJWKS + + + +RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. + +_Appears in:_ +- [JWTProvider](#jwtprovider) + +| Field | Description | +| --- | --- | +| `uri` _string_ | URI is the HTTPS URI to fetch the JWKS. Envoy's system trust bundle is used to validate the server certificate. | + + +#### RequestHeaderCustomTag + + + +RequestHeaderCustomTag adds value from request header to each span. + +_Appears in:_ +- [CustomTag](#customtag) + +| Field | Description | +| --- | --- | +| `name` _string_ | Name defines the name of the request header which to extract the value from. | +| `defaultValue` _string_ | DefaultValue defines the default value to use if the request header is not set. | + + +#### ResourceProviderType + +_Underlying type:_ `string` + +ResourceProviderType defines the types of custom resource providers supported by Envoy Gateway. + +_Appears in:_ +- [EnvoyGatewayResourceProvider](#envoygatewayresourceprovider) + + + +#### SecurityPolicy + + + +SecurityPolicy allows the user to configure various security settings for a Gateway. + +_Appears in:_ +- [SecurityPolicyList](#securitypolicylist) + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `SecurityPolicy` +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` _[SecurityPolicySpec](#securitypolicyspec)_ | Spec defines the desired state of SecurityPolicy. | + + +#### SecurityPolicyList + + + +SecurityPolicyList contains a list of SecurityPolicy resources. + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` +| `kind` _string_ | `SecurityPolicyList` +| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` _[SecurityPolicy](#securitypolicy) array_ | | + + +#### SecurityPolicySpec + + + +SecurityPolicySpec defines the desired state of SecurityPolicy. + +_Appears in:_ +- [SecurityPolicy](#securitypolicy) + +| Field | Description | +| --- | --- | +| `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. TargetRef | +| `cors` _[CORS](#cors)_ | CORS defines the configuration for Cross-Origin Resource Sharing (CORS). | +| `jwt` _[JWT](#jwt)_ | JWT defines the configuration for JSON Web Token (JWT) authentication. | + + + + +#### ServiceType + +_Underlying type:_ `string` + +ServiceType string describes ingress methods for a service + +_Appears in:_ +- [KubernetesServiceSpec](#kubernetesservicespec) + + + +#### SourceMatch + + + + + +_Appears in:_ +- [RateLimitSelectCondition](#ratelimitselectcondition) + + + +#### StringMatch + + + +StringMatch defines how to match any strings. This is a general purpose match condition that can be used by other EG APIs that need to match against a string. + +_Appears in:_ +- [CORS](#cors) + +| Field | Description | +| --- | --- | +| `type` _[MatchType](#matchtype)_ | Type specifies how to match against a string. | +| `value` _string_ | Value specifies the string value that the match must have. | + + +#### TCPKeepalive + + + +TCPKeepalive define the TCP Keepalive configuration. + +_Appears in:_ +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Description | +| --- | --- | +| `probes` _integer_ | The total number of unacknowledged probes to send before deciding the connection is dead. Defaults to 9. | +| `idleTime` _Duration_ | The duration a connection needs to be idle before keep-alive probes start being sent. The duration format is Defaults to `7200s`. | +| `interval` _Duration_ | The duration between keep-alive probes. Defaults to `75s`. | + + +#### TracingProvider + + + + + +_Appears in:_ +- [ProxyTracing](#proxytracing) + +| Field | Description | +| --- | --- | +| `type` _[TracingProviderType](#tracingprovidertype)_ | Type defines the tracing provider type. EG currently only supports OpenTelemetry. | +| `host` _string_ | Host define the provider service hostname. | +| `port` _integer_ | Port defines the port the provider service is exposed on. | + + +#### TracingProviderType + +_Underlying type:_ `string` + + + +_Appears in:_ +- [TracingProvider](#tracingprovider) + + + +#### XDSTranslatorHook + +_Underlying type:_ `string` + +XDSTranslatorHook defines the types of hooks that an Envoy Gateway extension may support for the xds-translator + +_Appears in:_ +- [XDSTranslatorHooks](#xdstranslatorhooks) + + + +#### XDSTranslatorHooks + + + +XDSTranslatorHooks contains all the pre and post hooks for the xds-translator runner. + +_Appears in:_ +- [ExtensionHooks](#extensionhooks) + +| Field | Description | +| --- | --- | +| `pre` _[XDSTranslatorHook](#xdstranslatorhook) array_ | | +| `post` _[XDSTranslatorHook](#xdstranslatorhook) array_ | | + + diff --git a/site/content/en/v0.6.0/contributions/CODEOWNERS.md b/site/content/en/v0.6.0/contributions/CODEOWNERS.md new file mode 100644 index 00000000000..63b751abde5 --- /dev/null +++ b/site/content/en/v0.6.0/contributions/CODEOWNERS.md @@ -0,0 +1,19 @@ +--- +title: "Maintainers" +description: "This section includes Maintainers of Envoy Gateway." +--- + +## The following maintainers, listed in alphabetical order, own everything + +- @AliceProxy +- @arkodg +- @Xunzhuo +- @zirain +- @qicz + +## Emeritus Maintainers + +- @danehans +- @alexgervais +- @skriss +- @youngnick diff --git a/site/content/en/v0.6.0/contributions/CODE_OF_CONDUCT.md b/site/content/en/v0.6.0/contributions/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..e19da050dff --- /dev/null +++ b/site/content/en/v0.6.0/contributions/CODE_OF_CONDUCT.md @@ -0,0 +1,6 @@ +--- +title: "Code of Conduct" +description: "This section includes Code of Conduct of Envoy Gateway." +--- + +Envoy Gateway follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). diff --git a/site/content/en/v0.6.0/contributions/CONTRIBUTING.md b/site/content/en/v0.6.0/contributions/CONTRIBUTING.md new file mode 100644 index 00000000000..f94b2c940e9 --- /dev/null +++ b/site/content/en/v0.6.0/contributions/CONTRIBUTING.md @@ -0,0 +1,190 @@ +--- +title: "Contributing" +description: "This section tells how to contribute to Envoy Gateway." +weight: 3 +--- + +We welcome contributions from the community. Please carefully review the [project goals](/about) +and following guidelines to streamline your contributions. + +## Communication + +* Before starting work on a major feature, please contact us via GitHub or Slack. We will ensure no + one else is working on it and ask you to open a GitHub issue. +* A "major feature" is defined as any change that is > 100 LOC altered (not including tests), or + changes any user-facing behavior. We will use the GitHub issue to discuss the feature and come to + agreement. This is to prevent your time being wasted, as well as ours. The GitHub review process + for major features is also important so that [affiliations with commit access](../codeowners) can + come to agreement on the design. If it's appropriate to write a design document, the document must + be hosted either in the GitHub issue, or linked to from the issue and hosted in a world-readable + location. +* Small patches and bug fixes don't need prior communication. + +## Inclusivity + +The Envoy Gateway community has an explicit goal to be inclusive to all. As such, all PRs must adhere +to the following guidelines for all code, APIs, and documentation: + +* The following words and phrases are not allowed: + * *Whitelist*: use allowlist instead. + * *Blacklist*: use denylist or blocklist instead. + * *Master*: use primary instead. + * *Slave*: use secondary or replica instead. +* Documentation should be written in an inclusive style. The [Google developer + documentation](https://developers.google.com/style/inclusive-documentation) contains an excellent + reference on this topic. +* The above policy is not considered definitive and may be amended in the future as industry best + practices evolve. Additional comments on this topic may be provided by maintainers during code + review. + +## Submitting a PR + +* Fork the repo. +* Hack +* DCO sign-off each commit. This can be done with `git commit -s`. +* Submit your PR. +* Tests will automatically run for you. +* We will **not** merge any PR that is not passing tests. +* PRs are expected to have 100% test coverage for added code. This can be verified with a coverage + build. If your PR cannot have 100% coverage for some reason please clearly explain why when you + open it. +* Any PR that changes user-facing behavior **must** have associated documentation in the [docs](https://github.com/envoyproxy/gateway/tree/main/site) folder of the repo as + well as the [changelog](/blog/releases). +* All code comments and documentation are expected to have proper English grammar and punctuation. + If you are not a fluent English speaker (or a bad writer ;-)) please let us know and we will try + to find some help but there are no guarantees. +* Your PR title should be descriptive, and generally start with type that contains a subsystem name with `()` if necessary + and summary followed by a colon. format `chore/docs/feat/fix/refactor/style/test: summary`. + Examples: + * "docs: fix grammar error" + * "feat(translator): add new feature" + * "fix: fix xx bug" + * "chore: change ci & build tools etc" +* Your PR commit message will be used as the commit message when your PR is merged. You should + update this field if your PR diverges during review. +* Your PR description should have details on what the PR does. If it fixes an existing issue it + should end with "Fixes #XXX". +* If your PR is co-authored or based on an earlier PR from another contributor, + please attribute them with `Co-authored-by: name `. See + GitHub's [multiple author + guidance](https://help.github.com/en/github/committing-changes-to-your-project/creating-a-commit-with-multiple-authors) + for further details. +* When all tests are passing and all other conditions described herein are satisfied, a maintainer + will be assigned to review and merge the PR. +* Once you submit a PR, *please do not rebase it*. It's much easier to review if subsequent commits + are new commits and/or merges. We squash and merge so the number of commits you have in the PR + doesn't matter. +* We expect that once a PR is opened, it will be actively worked on until it is merged or closed. + We reserve the right to close PRs that are not making progress. This is generally defined as no + changes for 7 days. Obviously PRs that are closed due to lack of activity can be reopened later. + Closing stale PRs helps us to keep on top of all the work currently in flight. + +## Maintainer PR Review Policy + +* See [CODEOWNERS.md](../codeowners) for the current list of maintainers. +* A maintainer representing a different affiliation from the PR owner is required to review and + approve the PR. +* When the project matures, it is expected that a "domain expert" for the code the PR touches should + review the PR. This person does not require commit access, just domain knowledge. +* The above rules may be waived for PRs which only update docs or comments, or trivial changes to + tests and tools (where trivial is decided by the maintainer in question). +* If there is a question on who should review a PR please discuss in Slack. +* Anyone is welcome to review any PR that they want, whether they are a maintainer or not. +* Please make sure that the PR title, commit message, and description are updated if the PR changes + significantly during review. +* Please **clean up the title and body** before merging. By default, GitHub fills the squash merge + title with the original title, and the commit body with every individual commit from the PR. + The maintainer doing the merge should make sure the title follows the guidelines above and should + overwrite the body with the original commit message from the PR (cleaning it up if necessary) + while preserving the PR author's final DCO sign-off. + +## Decision making + +This is a new and complex project, and we need to make a lot of decisions very quickly. +To this end, we've settled on this process for making (possibly contentious) decisions: + +* For decisions that need a record, we create an issue. +* In that issue, we discuss opinions, then a maintainer can call for a vote in a comment. +* Maintainers can cast binding votes on that comment by reacting or replying in another comment. +* Non-maintainer community members are welcome to cast non-binding votes by either of these methods. +* Voting will be resolved by simple majority. +* In the event of deadlocks, the question will be put to steering instead. + +## DCO: Sign your work + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as an open-source patch. The rules are pretty simple: if you +can certify the below (from +[developercertificate.org](https://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign-off when creating the git commit via `git commit -s`. + +If you want this to be automatic you can set up some aliases: + +```bash +git config --add alias.amend "commit -s --amend" +git config --add alias.c "commit -s" +``` + +## Fixing DCO + +If your PR fails the DCO check, it's necessary to fix the entire commit history in the PR. Best +practice is to [squash](https://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) +the commit history to a single commit, append the DCO sign-off as described above, and [force +push](https://git-scm.com/docs/git-push#git-push---force). For example, if you have 2 commits in +your history: + +```bash +git rebase -i HEAD^^ +(interactive squash + DCO append) +git push origin -f +``` + +Note, that in general rewriting history in this way is a hindrance to the review process and this +should only be done to correct a DCO mistake. diff --git a/site/content/en/v0.6.0/contributions/DEVELOP.md b/site/content/en/v0.6.0/contributions/DEVELOP.md new file mode 100644 index 00000000000..6f82c4a411f --- /dev/null +++ b/site/content/en/v0.6.0/contributions/DEVELOP.md @@ -0,0 +1,163 @@ +--- +title: "Developer Guide" +description: "This section tells how to develop Envoy Gateway." +weight: 2 +--- + +Envoy Gateway is built using a [make][]-based build system. Our CI is based on [Github Actions][] using [workflows][]. + +## Prerequisites + +### go + +* Version: 1.20 +* Installation Guide: https://go.dev/doc/install + +### make + +* Recommended Version: 4.0 or later +* Installation Guide: https://www.gnu.org/software/make + +### docker + +* Optional when you want to build a Docker image or run `make` inside Docker. +* Recommended Version: 20.10.16 +* Installation Guide: https://docs.docker.com/engine/install + +### python3 + +* Need a `python3` program +* Must have a functioning `venv` module; this is part of the standard + library, but some distributions (such as Debian and Ubuntu) replace + it with a stub and require you to install a `python3-venv` package + separately. + +## Quickstart + +* Run `make help` to see all the available targets to build, test and run Envoy Gateway. + +### Building + +* Run `make build` to build all the binaries. +* Run `make build BINS="envoy-gateway"` to build the Envoy Gateway binary. +* Run `make build BINS="egctl"` to build the egctl binary. + +__Note:__ The binaries get generated in the `bin/$OS/$ARCH` directory, for example, `bin/linux/amd64/`. + +### Testing + +* Run `make test` to run the golang tests. + +* Run `make testdata` to generate the golden YAML testdata files. + +### Running Linters + +* Run `make lint` to make sure your code passes all the linter checks. +__Note:__ The `golangci-lint` configuration resides [here](https://github.com/envoyproxy/gateway/blob/main/tools/linter/golangci-lint/.golangci.yml). + +### Building and Pushing the Image + +* Run `IMAGE=docker.io/you/gateway-dev make image` to build the docker image. +* Run `IMAGE=docker.io/you/gateway-dev make push-multiarch` to build and push the multi-arch docker image. + +__Note:__ Replace `IMAGE` with your registry's image name. + +### Deploying Envoy Gateway for Test/Dev + +* Run `make create-cluster` to create a [Kind][] cluster. + +#### Option 1: Use the Latest [gateway-dev][] Image + +* Run `TAG=latest make kube-deploy` to deploy Envoy Gateway in the Kind cluster using the latest image. Replace `latest` + to use a different image tag. + +#### Option 2: Use a Custom Image + +* Run `make kube-install-image` to build an image from the tip of your current branch and load it in the Kind cluster. +* Run `IMAGE_PULL_POLICY=IfNotPresent make kube-deploy` to install Envoy Gateway into the Kind cluster using your custom image. + +### Deploying Envoy Gateway in Kubernetes + +* Run `TAG=latest make kube-deploy` to deploy Envoy Gateway using the latest image into a Kubernetes cluster (linked to + the current kube context). Preface the command with `IMAGE` or replace `TAG` to use a different Envoy Gateway image or + tag. +* Run `make kube-undeploy` to uninstall Envoy Gateway from the cluster. + +__Note:__ Envoy Gateway is tested against Kubernetes v1.24.0. + +### Demo Setup + +* Run `make kube-demo` to deploy a demo backend service, gatewayclass, gateway and httproute resource +(similar to steps outlined in the [Quickstart][] docs) and test the configuration. +* Run `make kube-demo-undeploy` to delete the resources created by the `make kube-demo` command. + +### Run Gateway API Conformance Tests + +The commands below deploy Envoy Gateway to a Kubernetes cluster and run the Gateway API conformance tests. Refer to the +Gateway API [conformance homepage][] to learn more about the tests. If Envoy Gateway is already installed, run +`TAG=latest make run-conformance` to run the conformance tests. + +#### On a Linux Host + +* Run `TAG=latest make conformance` to create a Kind cluster, install Envoy Gateway using the latest [gateway-dev][] + image, and run Gateway API conformance tests. + +#### On a Mac Host + +Since Mac doesn't support [directly exposing][] the Docker network to the Mac host, use one of the following +workarounds to run conformance tests: + +* Deploy your own Kubernetes cluster or use Docker Desktop with [Kubernetes support][] and then run + `TAG=latest make kube-deploy run-conformance`. This will install Envoy Gateway using the latest [gateway-dev][] image + to the Kubernetes cluster using the current kubectl context and run the conformance tests. Use `make kube-undeploy` to + uninstall Envoy Gateway. +* Install and run [Docker Mac Net Connect][mac_connect] and then run `TAG=latest make conformance`. + +__Note:__ Preface commands with `IMAGE` or replace `TAG` to use a different Envoy Gateway image or tag. If `TAG` +is unspecified, the short SHA of your current branch is used. + +### Debugging the Envoy Config + +An easy way to view the envoy config that Envoy Gateway is using is to port-forward to the admin interface port +(currently `19000`) on the Envoy deployment that corresponds to a Gateway so that it can be accessed locally. + +Get the name of the Envoy deployment. The following example is for Gateway `eg` in the `default` namespace: + +```shell +export ENVOY_DEPLOYMENT=$(kubectl get deploy -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}') +``` + +Port forward the admin interface port: + +```shell +kubectl port-forward deploy/${ENVOY_DEPLOYMENT} -n envoy-gateway-system 19000:19000 +``` + +Now you are able to view the running Envoy configuration by navigating to `127.0.0.1:19000/config_dump`. + +There are many other endpoints on the [Envoy admin interface][] that may be helpful when debugging. + +### JWT Testing + +An example [JSON Web Token (JWT)][jwt] and [JSON Web Key Set (JWKS)][jwks] are used for the [request authentication][] +user guide. The JWT was created by the [JWT Debugger][], using the `RS256` algorithm. The public key from the JWTs +verify signature was copied to [JWK Creator][] for generating the JWK. The JWK Creator was configured with matching +settings, i.e. `Signing` public key use and the `RS256` algorithm. The generated JWK was wrapped in a JWKS structure +and is hosted in the repo. + +[Quickstart]: https://github.com/envoyproxy/gateway/blob/main/docs/latest/user/quickstart.md +[make]: https://www.gnu.org/software/make/ +[Github Actions]: https://docs.github.com/en/actions +[workflows]: https://github.com/envoyproxy/gateway/tree/main/.github/workflows +[Kind]: https://kind.sigs.k8s.io/ +[conformance homepage]: https://gateway-api.sigs.k8s.io/concepts/conformance/ +[directly exposing]: https://kind.sigs.k8s.io/docs/user/loadbalancer/ +[Kubernetes support]: https://docs.docker.com/desktop/kubernetes/ +[gateway-dev]: https://hub.docker.com/r/envoyproxy/gateway-dev/tags +[mac_connect]: https://github.com/chipmk/docker-mac-net-connect +[Envoy admin interface]: https://www.envoyproxy.io/docs/envoy/latest/operations/admin#operations-admin-interface +[jwt]: https://tools.ietf.org/html/rfc7519 +[jwks]: https://tools.ietf.org/html/rfc7517 +[request authentication]: https://gateway.envoyproxy.io/latest/user/authn.html +[JWT Debugger]: https://jwt.io/ +[JWK Creator]: https://russelldavies.github.io/jwk-creator/ diff --git a/site/content/en/v0.6.0/contributions/DOCS.md b/site/content/en/v0.6.0/contributions/DOCS.md new file mode 100644 index 00000000000..ae19953a8b5 --- /dev/null +++ b/site/content/en/v0.6.0/contributions/DOCS.md @@ -0,0 +1,69 @@ +--- +title: "Working on Envoy Gateway Docs" +description: "This section tells the development of + Envoy Gateway Documents." +--- + +{{% alert title="Note" color="warning" %}} +We migrated from ***Sphinx*** to ***Hugo*** for Envoy Gateway Documents. + +Read blog: [Welcome to new website!](/blog/2023/10/08/welcome-to-new-website/) +{{% /alert %}} + +The documentation for the Envoy Gateway lives in the `site/content/en` directory. Any +individual document can be written using [Markdown]. + +## Documentation Structure + +We supported the versioned Docs now, the directory name under docs represents +the version of docs. The root of the latest site is in `site/content/en/latest`. +This is probably where to start if you're trying to understand how things fit together. + +Note that the new contents should be added to `site/content/en/latest` and will be cut off at +the next release. The contents under `site/content/en/v0.5.0` are auto-generated, +and usually do not need to make changes to them, unless if you find the current release pages have +some incorrect contents. If so, you should send a PR to update contents both of `site/content/en/latest` +and `site/content/en/v0.5.0`. + +You can access the website which represents the current release in default, +and you can access the website which contains the latest version changes in +[Here][latest-website] or at the footer of the pages. + +## Documentation Workflow + +To work with the docs, just edit Markdown files in `site/content/en/latest`, +then run + +```bash +make docs +``` + +This will create `site/public` with the built HTML pages. You can preview it +by running: + +``` shell +make docs-serve +``` + +If you want to generate a new release version of the docs, like `v0.6.0`, then run + +```bash +make docs-release TAG=v0.6.0 +``` + +This will update the VERSION file at the project root, which records current release version, +and it will be used in the pages version context and binary version output. Also, this will generate +new dir `site/content/en/v0.6.0`, which contains docs at v0.6.0 and updates artifact links to `v0.6.0` +in all files under `site/content/en/v0.6.0/user`, like `quickstart.md`, `http-routing.md` and etc. + +## Publishing Docs + +Whenever docs are pushed to `main`, CI will publish the built docs to GitHub +Pages. For more details, see `.github/workflows/docs.yaml`. + +## Reference + +Go to [Hugo](https://gohugo.io) and [Docsy](https://www.docsy.dev/docs) to learn more. + +[Markdown]: https://daringfireball.net/projects/markdown/syntax +[latest-website]: /latest diff --git a/site/content/en/v0.6.0/contributions/RELEASING.md b/site/content/en/v0.6.0/contributions/RELEASING.md new file mode 100644 index 00000000000..f81d5be457d --- /dev/null +++ b/site/content/en/v0.6.0/contributions/RELEASING.md @@ -0,0 +1,252 @@ +--- +title: "Release Process" +description: "This section tells the release process of Envoy Gateway." +--- + +This document guides maintainers through the process of creating an Envoy Gateway release. + +- [Release Candidate](#release-candidate) +- [Minor Release](#minor-release) +- [Announce the Release](#announce-the-release) + +## Release Candidate + +The following steps should be used for creating a release candidate. + +### Prerequisites + +- Permissions to push to the Envoy Gateway repository. + +Set environment variables for use in subsequent steps: + +```shell +export MAJOR_VERSION=0 +export MINOR_VERSION=3 +export RELEASE_CANDIDATE_NUMBER=1 +export GITHUB_REMOTE=origin +``` + +1. Clone the repo, checkout the `main` branch, ensure it’s up-to-date, and your local branch is clean. +2. Create a topic branch for adding the release notes and updating the [VERSION][] file with the release version. Refer to previous [release notes][] and [VERSION][] for additional details. +3. Sign, commit, and push your changes to your fork. +4. Submit a [Pull Request][] to merge the changes into the `main` branch. Do not proceed until your PR has merged and + the [Build and Test][] has successfully completed. +5. Create a new release branch from `main`. The release branch should be named + `release/v${MAJOR_VERSION}.${MINOR_VERSION}`, e.g. `release/v0.3`. + + ```shell + git checkout -b release/v${MAJOR_VERSION}.${MINOR_VERSION} + ``` + +6. Push the branch to the Envoy Gateway repo. + + ```shell + git push ${GITHUB_REMOTE} release/v${MAJOR_VERSION}.${MINOR_VERSION} + ``` + +7. Create a topic branch for updating the Envoy proxy image and Envoy Ratelimit image to the tag supported by the release. Reference [PR #2098][] + for additional details on updating the image tag. +8. Sign, commit, and push your changes to your fork. +9. Submit a [Pull Request][] to merge the changes into the `release/v${MAJOR_VERSION}.${MINOR_VERSION}` branch. Do not + proceed until your PR has merged into the release branch and the [Build and Test][] has completed for your PR. +10. Ensure your release branch is up-to-date and tag the head of your release branch with the release candidate number. + + ```shell + git tag -a v${MAJOR_VERSION}.${MINOR_VERSION}.0-rc.${RELEASE_CANDIDATE_NUMBER} -m 'Envoy Gateway v${MAJOR_VERSION}.${MINOR_VERSION}.0-rc.${RELEASE_CANDIDATE_NUMBER} Release Candidate' + ``` + +11. Push the tag to the Envoy Gateway repository. + + ```shell + git push ${GITHUB_REMOTE} v${MAJOR_VERSION}.${MINOR_VERSION}.0-rc.${RELEASE_CANDIDATE_NUMBER} + ``` + +12. This will trigger the [release GitHub action][] that generates the release, release artifacts, etc. +13. Confirm that the [release workflow][] completed successfully. +14. Confirm that the Envoy Gateway [image][] with the correct release tag was published to Docker Hub. +15. Confirm that the [release][] was created. +16. Note that the [Quickstart Guide][] references are __not__ updated for release candidates. However, test + the quickstart steps using the release candidate by manually updating the links. +17. [Generate][] the GitHub changelog. +18. Ensure you check the "This is a pre-release" checkbox when editing the GitHub release. +19. If you find any bugs in this process, please create an issue. + +### Setup cherry picker action + +After release branch cut, RM (Release Manager) should add job [cherrypick action](../../../.github/workflows/cherrypick.yaml) for target release. + +Configuration looks like following: + +```yaml + cherry_pick_release_v0_4: + runs-on: ubuntu-latest + name: Cherry pick into release-v0.4 + if: ${{ contains(github.event.pull_request.labels.*.name, 'cherrypick/release-v0.4') && github.event.pull_request.merged == true }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Cherry pick into release/v0.4 + uses: carloscastrojumo/github-cherry-pick-action@v1.0.9 + with: + branch: release/v0.4 + title: "[release/v0.4] {old_title}" + body: "Cherry picking #{old_pull_request_id} onto release/v0.4" + labels: | + cherrypick/release-v0.4 + # put release manager here + reviewers: | + AliceProxy +``` + +Replace `v0.4` with real branch name, and `AliceProxy` with the real name of RM. + +## Minor Release + +The following steps should be used for creating a minor release. + +### Prerequisites + +- Permissions to push to the Envoy Gateway repository. +- A release branch that has been cut from the corresponding release candidate. Refer to the + [Release Candidate](#release-candidate) section for additional details on cutting a release candidate. + +Set environment variables for use in subsequent steps: + +```shell +export MAJOR_VERSION=0 +export MINOR_VERSION=3 +export GITHUB_REMOTE=origin +``` + +1. Clone the repo, checkout the `main` branch, ensure it’s up-to-date, and your local branch is clean. +2. Create a topic branch for adding the release notes, release announcement, and versioned release docs. + + 1. Create the release notes. Reference previous [release notes][] for additional details. __Note:__ The release + notes should be an accumulation of the release candidate release notes and any changes since the release + candidate. + 2. Create a release announcement. Refer to [PR #635] as an example release announcement. + 3. Include the release in the compatibility matrix. Refer to [PR #1002] as an example. + 4. Generate the versioned release docs: + + ``` shell + make docs-release TAG=v${MAJOR_VERSION}.${MINOR_VERSION}.0 + ``` + + 5. Update the `Get Started` and `Contributing` button referred link in `site/content/en/_index.md`: + + ```shell + + Get Started + + + Contributing + + ``` + + 6. Uodate the `Documentation` referred link on the menu in `site/hugo.toml`: + + ```shell + [[menu.main]] + name = "Documentation" + weight = -101 + pre = "" + url = "/v0.5.0" + ``` + +3. Sign, commit, and push your changes to your fork. +4. Submit a [Pull Request][] to merge the changes into the `main` branch. Do not proceed until all your PRs have merged + and the [Build and Test][] has completed for your final PR. + +5. Checkout the release branch. + + ```shell + git checkout -b release/v${MAJOR_VERSION}.${MINOR_VERSION} $GITHUB_REMOTE/release/v${MAJOR_VERSION}.${MINOR_VERSION} + ``` + +6. If the tip of the release branch does not match the tip of `main`, perform the following: + + 1. Create a topic branch from the release branch. + 2. Cherry-pick the commits from `main` that differ from the release branch. + 3. Run tests locally, e.g. `make lint`. + 4. Sign, commit, and push your topic branch to your Envoy Gateway fork. + 5. Submit a PR to merge the topic from of your fork into the Envoy Gateway release branch. + 6. Do not proceed until the PR has merged and CI passes for the merged PR. + 7. If you are still on your topic branch, change to the release branch: + + ```shell + git checkout release/v${MAJOR_VERSION}.${MINOR_VERSION} + ``` + + 8. Ensure your local release branch is up-to-date: + + ```shell + git pull $GITHUB_REMOTE release/v${MAJOR_VERSION}.${MINOR_VERSION} + ``` + +7. Tag the head of your release branch with the release tag. For example: + + ```shell + git tag -a v${MAJOR_VERSION}.${MINOR_VERSION}.0 -m 'Envoy Gateway v${MAJOR_VERSION}.${MINOR_VERSION}.0 Release' + ``` + + __Note:__ The tag version differs from the release branch by including the `.0` patch version. + +8. Push the tag to the Envoy Gateway repository. + + ```shell + git push origin v${MAJOR_VERSION}.${MINOR_VERSION}.0 + ``` + +9. This will trigger the [release GitHub action][] that generates the release, release artifacts, etc. +10. Confirm that the [release workflow][] completed successfully. +11. Confirm that the Envoy Gateway [image][] with the correct release tag was published to Docker Hub. +12. Confirm that the [release][] was created. +13. Confirm that the steps in the [Quickstart Guide][] work as expected. +14. [Generate][] the GitHub changelog and include the following text at the beginning of the release page: + + ```console + # Release Announcement + + Check out the [v${MAJOR_VERSION}.${MINOR_VERSION} release announcement] + (https://gateway.envoyproxy.io/releases/v${MAJOR_VERSION}.${MINOR_VERSION}.html) to learn more about the release. + ``` + +If you find any bugs in this process, please create an issue. + +## Announce the Release + +It's important that the world knows about the release. Use the following steps to announce the release. + +1. Set the release information in the Envoy Gateway Slack channel. For example: + + ```shell + Envoy Gateway v${MAJOR_VERSION}.${MINOR_VERSION} has been released: https://github.com/envoyproxy/gateway/releases/tag/v${MAJOR_VERSION}.${MINOR_VERSION}.0 + ``` + +2. Send a message to the Envoy Gateway Slack channel. For example: + + ```shell + On behalf of the entire Envoy Gateway community, I am pleased to announce the release of Envoy Gateway + v${MAJOR_VERSION}.${MINOR_VERSION}. A big thank you to all the contributors that made this release possible. + Refer to the official v${MAJOR_VERSION}.${MINOR_VERSION} announcement for release details and the project docs + to start using Envoy Gateway. + ... + ``` + + Link to the GitHub release and release announcement page that highlights the release. + +[release notes]: https://github.com/envoyproxy/gateway/tree/main/release-notes +[Pull Request]: https://github.com/envoyproxy/gateway/pulls +[Quickstart Guide]: https://github.com/envoyproxy/gateway/blob/main/docs/user/quickstart.md +[Build and Test]: https://github.com/envoyproxy/gateway/blob/main/.github/workflows/build_and_test.yaml +[release GitHub action]: https://github.com/envoyproxy/gateway/blob/main/.github/workflows/release.yaml +[release workflow]: https://github.com/envoyproxy/gateway/actions/workflows/release.yaml +[image]: https://hub.docker.com/r/envoyproxy/gateway/tags +[release]: https://github.com/envoyproxy/gateway/releases +[Generate]: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes +[PR #635]: https://github.com/envoyproxy/gateway/pull/635 +[PR #2098]: https://github.com/envoyproxy/gateway/pull/2098 +[PR #1002]: https://github.com/envoyproxy/gateway/pull/1002 +[VERSION]: https://github.com/envoyproxy/gateway/blob/main/VERSION diff --git a/site/content/en/v0.6.0/contributions/_index.md b/site/content/en/v0.6.0/contributions/_index.md new file mode 100644 index 00000000000..3255d996472 --- /dev/null +++ b/site/content/en/v0.6.0/contributions/_index.md @@ -0,0 +1,5 @@ +--- +title: Get Involved +description: "This section includes contents related to **Contributions**" +weight: 100 +--- diff --git a/site/content/en/v0.6.0/contributions/roadmap.md b/site/content/en/v0.6.0/contributions/roadmap.md new file mode 100644 index 00000000000..955af2a9623 --- /dev/null +++ b/site/content/en/v0.6.0/contributions/roadmap.md @@ -0,0 +1,96 @@ +--- +title: "Roadmap" +weight: -1 +description: "This section records the roadmap of Envoy Gateway." +--- + +This document serves as a high-level reference for Envoy Gateway users and contributors to understand the direction of +the project. + +## Contributing to the Roadmap + +- To add a feature to the roadmap, create an [issue][issue] or join a [community meeting][meeting] to discuss your use + case. If your feature is accepted, a maintainer will assign your issue to a [release milestone][milestones] and update + this document accordingly. +- To help with an existing roadmap item, comment on or assign yourself to the associated issue. +- If a roadmap item doesn't have an issue, create one, assign yourself to the issue, and reference this document. A + maintainer will submit a [pull request][PR] to add the feature to the roadmap. __Note:__ The feature should be + discussed in an issue or a community meeting before implementing it. + +If you don't know where to start contributing, help is needed to reduce technical, automation, and documentation debt. +Look for issues with the `help wanted` label to get started. + +## Details + +Roadmap features and timelines may change based on feedback, community contributions, etc. If you depend on a specific +roadmap item, you're encouraged to attend a community meeting to discuss the details, or help us deliver the feature by +contributing to the project. + +`Last Updated: April 2023` + +### [v0.2.0][v0.2.0]: Establish a Solid Foundation + +- Complete the core Envoy Gateway implementation- [Issue #60][60]. +- Establish initial testing, e2e, integration, etc- [Issue #64][64]. +- Establish user and developer project documentation- [Issue #17][17]. +- Achieve Gateway API conformance (e.g. routing, LB, Header transformation, etc.)- [Issue #65][65]. +- Setup a CI/CD pipeline- [Issue #63][63]. + +### [v0.3.0][v0.3.0]: Drive Advanced Features through Extension Mechanisms + +- Support extended Gateway API fields [Issue #707][707]. +- Support experimental Gateway APIs such as TCPRoute [Issue #643][643], UDPRoute [Issue #641][641] and GRPCRoute [Issue #642][642]. +- Establish guidelines for leveragaing Gateway API extensions [Issue #675][675]. +- Rate Limiting [Issue #670][670]. +- Authentication [Issue #336][336]. + +### [v0.4.0][v0.4.0]: Customizing Envoy Gateway + +- Extending Envoy Gateway control plane [Issue #20][20] +- Helm based installation for Envoy Gateway [Issue #650][650] +- Customizing managed Envoy Proxy Kubernetes resource fields [Issue #648][648] +- Configuring xDS Bootstrap [Issue #31][31] + +### [v0.5.0][v0.5.0]: Observability and Scale + +- Observability for data plane [Issue #699][699]. +- Allow users to configure xDS Resources [Issue #24][24]. + +### [v0.6.0][v0.6.0]: Preparation for GA + +- Observability for control plane [Issue #700][700]. +- Compute and document Envoy Gateway performance [Issue #1365][1365]. +- Add TrafficPolicy APIs for advanced features [Issue #1492][1492]. +- Envoy Gateway meets readiness criteria [Issue #1160][1160]. + +[issue]: https://github.com/envoyproxy/gateway/issues +[meeting]: https://docs.google.com/document/d/1leqwsHX8N-XxNEyTflYjRur462ukFxd19Rnk3Uzy55I/edit?usp=sharing +[pr]: https://github.com/envoyproxy/gateway/compare +[milestones]: https://github.com/envoyproxy/gateway/milestones +[v0.2.0]: https://github.com/envoyproxy/gateway/milestone/1 +[v0.3.0]: https://github.com/envoyproxy/gateway/milestone/7 +[v0.4.0]: https://github.com/envoyproxy/gateway/milestone/12 +[v0.5.0]: https://github.com/envoyproxy/gateway/milestone/13 +[v0.6.0]: https://github.com/envoyproxy/gateway/milestone/15 +[17]: https://github.com/envoyproxy/gateway/issues/17 +[20]: https://github.com/envoyproxy/gateway/issues/20 +[24]: https://github.com/envoyproxy/gateway/issues/24 +[31]: https://github.com/envoyproxy/gateway/issues/31 +[60]: https://github.com/envoyproxy/gateway/issues/60 +[63]: https://github.com/envoyproxy/gateway/issues/63 +[64]: https://github.com/envoyproxy/gateway/issues/64 +[65]: https://github.com/envoyproxy/gateway/issues/65 +[336]: https://github.com/envoyproxy/gateway/issues/336 +[641]: https://github.com/envoyproxy/gateway/issues/641 +[642]: https://github.com/envoyproxy/gateway/issues/642 +[648]: https://github.com/envoyproxy/gateway/issues/648 +[650]: https://github.com/envoyproxy/gateway/issues/650 +[643]: https://github.com/envoyproxy/gateway/issues/643 +[670]: https://github.com/envoyproxy/gateway/issues/670 +[675]: https://github.com/envoyproxy/gateway/issues/675 +[699]: https://github.com/envoyproxy/gateway/issues/699 +[700]: https://github.com/envoyproxy/gateway/issues/700 +[707]: https://github.com/envoyproxy/gateway/issues/707 +[1160]: https://github.com/envoyproxy/gateway/issues/1160 +[1365]: https://github.com/envoyproxy/gateway/issues/1365 +[1492]: https://github.com/envoyproxy/gateway/issues/1492 diff --git a/site/content/en/v0.6.0/design/_index.md b/site/content/en/v0.6.0/design/_index.md new file mode 100644 index 00000000000..2820db4c216 --- /dev/null +++ b/site/content/en/v0.6.0/design/_index.md @@ -0,0 +1,5 @@ +--- +title: "Design" +weight: 1 +description: This section includes Designs of Envoy Gateway. +--- diff --git a/site/content/en/v0.6.0/design/accesslog.md b/site/content/en/v0.6.0/design/accesslog.md new file mode 100644 index 00000000000..cb72f05fe43 --- /dev/null +++ b/site/content/en/v0.6.0/design/accesslog.md @@ -0,0 +1,237 @@ +--- +title: "Observability: Accesslog" +--- + +## Overview + +Envoy supports extensible accesslog to different sinks, File, gRPC etc. Envoy supports customizable access log formats using predefined fields as well as arbitrary HTTP request and response headers. Envoy supports several built-in access log filters and extension filters that are registered at runtime. + +Envoy Gateway leverages [Gateway API](https://gateway-api.sigs.k8s.io/) for configuring managed Envoy proxies. Gateway API defines core, extended, and implementation-specific API [support levels](https://gateway-api.sigs.k8s.io/concepts/conformance/?h=extended#2-support-levels) for implementers such as Envoy Gateway to expose features. Since accesslog is not covered by `Core` or `Extended` APIs, EG should provide an easy to config access log formats and sinks per `EnvoyProxy`. + +## Goals + +- Support send accesslog to `File` or `OpenTelemetry` backend +- TODO: Support access log filters base on [CEL](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/access_loggers/filters/cel/v3/cel.proto#extension-envoy-access-loggers-extension-filters-cel) expression + +## Non-Goals + +- Support non-CEL filters, e.g. `status_code_filter`, `response_flag_filter` +- Support [HttpGrpcAccessLogConfig](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/access_loggers/grpc/v3/als.proto#extensions-access-loggers-grpc-v3-httpgrpcaccesslogconfig) or [TcpGrpcAccessLogConfig](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/access_loggers/grpc/v3/als.proto#extensions-access-loggers-grpc-v3-tcpgrpcaccesslogconfig) + +## Use-Cases + +- Configure accesslog for a `EnvoyProxy` to `File` +- Configure accesslog for a `EnvoyProxy` to `OpenTelemetry` backend +- Configure multi accesslog providers for a `EnvoyProxy` + +### ProxyAccessLog API Type + +```golang mdox-exec="sed '1,7d' api/config/v1alpha1/accesslogging_types.go" +type ProxyAccessLog struct { + // Disable disables access logging for managed proxies if set to true. + Disable bool `json:"disable,omitempty"` + // Settings defines accesslog settings for managed proxies. + // If unspecified, will send default format to stdout. + // +optional + Settings []ProxyAccessLogSetting `json:"settings,omitempty"` +} + +type ProxyAccessLogSetting struct { + // Format defines the format of accesslog. + Format ProxyAccessLogFormat `json:"format"` + // Sinks defines the sinks of accesslog. + // +kubebuilder:validation:MinItems=1 + Sinks []ProxyAccessLogSink `json:"sinks"` +} + +type ProxyAccessLogFormatType string + +const ( + // ProxyAccessLogFormatTypeText defines the text accesslog format. + ProxyAccessLogFormatTypeText ProxyAccessLogFormatType = "Text" + // ProxyAccessLogFormatTypeJSON defines the JSON accesslog format. + ProxyAccessLogFormatTypeJSON ProxyAccessLogFormatType = "JSON" + // TODO: support format type "mix" in the future. +) + +// ProxyAccessLogFormat defines the format of accesslog. +// +union +type ProxyAccessLogFormat struct { + // Type defines the type of accesslog format. + // +kubebuilder:validation:Enum=Text;JSON + // +unionDiscriminator + Type ProxyAccessLogFormatType `json:"type,omitempty"` + // Text defines the text accesslog format, following Envoy accesslog formatting, + // empty value results in proxy's default access log format. + // It's required when the format type is "Text". + // Envoy [command operators](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators) may be used in the format. + // The [format string documentation](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#config-access-log-format-strings) provides more information. + // +optional + Text *string `json:"text,omitempty"` + // JSON is additional attributes that describe the specific event occurrence. + // Structured format for the envoy access logs. Envoy [command operators](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators) + // can be used as values for fields within the Struct. + // It's required when the format type is "JSON". + // +optional + JSON map[string]string `json:"json,omitempty"` +} + +type ProxyAccessLogSinkType string + +const ( + // ProxyAccessLogSinkTypeFile defines the file accesslog sink. + ProxyAccessLogSinkTypeFile ProxyAccessLogSinkType = "File" + // ProxyAccessLogSinkTypeOpenTelemetry defines the OpenTelemetry accesslog sink. + ProxyAccessLogSinkTypeOpenTelemetry ProxyAccessLogSinkType = "OpenTelemetry" +) + +type ProxyAccessLogSink struct { + // Type defines the type of accesslog sink. + // +kubebuilder:validation:Enum=File;OpenTelemetry + Type ProxyAccessLogSinkType `json:"type,omitempty"` + // File defines the file accesslog sink. + // +optional + File *FileEnvoyProxyAccessLog `json:"file,omitempty"` + // OpenTelemetry defines the OpenTelemetry accesslog sink. + // +optional + OpenTelemetry *OpenTelemetryEnvoyProxyAccessLog `json:"openTelemetry,omitempty"` +} + +type FileEnvoyProxyAccessLog struct { + // Path defines the file path used to expose envoy access log(e.g. /dev/stdout). + // Empty value disables accesslog. + Path string `json:"path,omitempty"` +} + +// TODO: consider reuse ExtensionService? +type OpenTelemetryEnvoyProxyAccessLog struct { + // Host define the extension service hostname. + Host string `json:"host"` + // Port defines the port the extension service is exposed on. + // + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=4317 + Port int32 `json:"port,omitempty"` + // Resources is a set of labels that describe the source of a log entry, including envoy node info. + // It's recommended to follow [semantic conventions](https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/). + // +optional + Resources map[string]string `json:"resources,omitempty"` + + // TODO: support more OpenTelemetry accesslog options(e.g. TLS, auth etc.) in the future. +} +``` + +### Example + +- The following is an example to disable access log. + +```yaml mdox-exec="sed '1,12d' examples/kubernetes/accesslog/disable-accesslog.yaml" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: disable-accesslog + namespace: envoy-gateway-system +spec: + telemetry: + accessLog: + disable: true +``` + +- The following is an example with text format access log. + +```yaml mdox-exec="sed '1,12d' examples/kubernetes/accesslog/text-accesslog.yaml" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: text-access-logging + namespace: envoy-gateway-system +spec: + telemetry: + accessLog: + settings: + - format: + type: Text + text: | + [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%" + sinks: + - type: File + file: + path: /dev/stdout +``` + +- The following is an example with json format access log. + +```yaml mdox-exec="sed '1,12d' examples/kubernetes/accesslog/json-accesslog.yaml" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: json-access-logging + namespace: envoy-gateway-system +spec: + telemetry: + accessLog: + settings: + - format: + type: JSON + json: + status: "%RESPONSE_CODE%" + message: "%LOCAL_REPLY_BODY%" + sinks: + - type: File + file: + path: /dev/stdout +``` + +- The following is an example with OpenTelemetry format access log. + +```yaml mdox-exec="sed '1,12d' examples/kubernetes/accesslog/otel-accesslog.yaml" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: otel-access-logging + namespace: envoy-gateway-system +spec: + telemetry: + accessLog: + settings: + - format: + type: Text + text: | + [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%" + sinks: + - type: OpenTelemetry + openTelemetry: + host: otel-collector.monitoring.svc.cluster.local + port: 4317 + resources: + k8s.cluster.name: "cluster-1" +``` + +- The following is an example of sending same format to different sinks. + +```yaml mdox-exec="sed '1,12d' examples/kubernetes/accesslog/multi-sinks.yaml" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: multi-sinks + namespace: envoy-gateway-system +spec: + telemetry: + accessLog: + settings: + - format: + type: Text + text: | + [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%" + sinks: + - type: File + file: + path: /dev/stdout + - type: OpenTelemetry + openTelemetry: + host: otel-collector.monitoring.svc.cluster.local + port: 4317 + resources: + k8s.cluster.name: "cluster-1" +``` diff --git a/site/content/en/v0.6.0/design/backend-traffic-policy.md b/site/content/en/v0.6.0/design/backend-traffic-policy.md new file mode 100644 index 00000000000..3cc0709b946 --- /dev/null +++ b/site/content/en/v0.6.0/design/backend-traffic-policy.md @@ -0,0 +1,155 @@ +--- +title: "BackendTrafficPolicy" +--- + +## Overview + +This design document introduces the `BackendTrafficPolicy` API allowing users to configure +the behavior for how the Envoy Proxy server communicates with upstream backend services/endpoints. + +## Goals + +- Add an API definition to hold settings for configuring behavior of the connection between the backend services +and Envoy Proxy listener. + +## Non Goals + +- Define the API configuration fields in this API. + +## Implementation + +`BackendTrafficPolicy` is an implied hierarchy type API that can be used to extend [Gateway API][]. +It can target either a `Gateway`, or an xRoute (`HTTPRoute`/`GRPCRoute`/etc.). When targeting a `Gateway`, +it will apply the configured settings within ght `BackendTrafficPolicy` to all children xRoute resources of that `Gateway`. +If a `BackendTrafficPolicy` targets an xRoute and a different `BackendTrafficPolicy` targets the `Gateway` that route belongs to, +then the configuration from the policy that is targeting the xRoute resource will win in a conflict. + +### Example + +Here is an example highlighting how a user can configure this API. + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: GatewayClass +metadata: + name: eg +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: eg + namespace: default +spec: + gatewayClassName: eg + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: ipv4-route + namespace: default +spec: + parentRefs: + - name: eg + hostnames: + - "www.foo.example.com" + rules: + - backendRefs: + - group: "" + kind: Service + name: ipv4-service + port: 3000 + weight: 1 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: ipv6-route + namespace: default +spec: + parentRefs: + - name: eg + hostnames: + - "www.bar.example.com" + rules: + - backendRefs: + - group: "" + kind: Service + name: ipv6-service + port: 3000 + weight: 1 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: default-ipv-policy + namespace: default +spec: + protocols: + enableIPv6: false + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: eg + namespace: default +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: ipv6-support-policy + namespace: default +spec: + protocols: + enableIPv6: true + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: ipv6-route + namespace: default +``` + +## Features / API Fields + +Here is a list of some features that can be included in this API. Note that this list is not exhaustive. + +- Protocol configuration +- Circuit breaking +- Retries +- Keep alive probes +- Health checking +- Load balancing + +## Design Decisions + +- This API will only support a single `targetRef` and can bind to only a `Gateway` or xRoute (`HTTPRoute`/`GRPCRoute`/etc.) resource. +- This API resource MUST be part of same namespace as the resource it targets. +- There can be only be ONE policy resource attached to a specific `Listener` (section) within a `Gateway` +- If the policy targets a resource but cannot attach to it, this information should be reflected +in the Policy Status field using the `Conflicted=True` condition. +- If multiple polices target the same resource, the oldest resource (based on creation timestamp) will +attach to the Gateway Listeners, the others will not. +- If Policy A has a `targetRef` that includes a `sectionName` i.e. +it targets a specific Listener within a `Gateway` and Policy B has a `targetRef` that targets the same +entire Gateway then + - Policy A will be applied/attached to the specific Listener defined in the `targetRef.SectionName` + - Policy B will be applied to the remaining Listeners within the Gateway. Policy B will have an additional + status condition `Overridden=True`. + +## Alternatives + +- The project can indefintely wait for these configuration parameters to be part of the [Gateway API][]. + +[Gateway API]: https://gateway-api.sigs.k8s.io/ diff --git a/site/content/en/v0.6.0/design/bootstrap.md b/site/content/en/v0.6.0/design/bootstrap.md new file mode 100644 index 00000000000..4475710ad5d --- /dev/null +++ b/site/content/en/v0.6.0/design/bootstrap.md @@ -0,0 +1,381 @@ +--- +title: "Bootstrap Design" +--- + +## Overview + +[Issue 31][] specifies the need for allowing advanced users to specify their custom +Envoy Bootstrap configuration rather than using the default Bootstrap configuration +defined in Envoy Gateway. This allows advanced users to extend Envoy Gateway and +support their custom use cases such setting up tracing and stats configuration +that is not supported by Envoy Gateway. + +## Goals + +* Define an API field to allow a user to specify a custom Bootstrap +* Provide tooling to allow the user to generate the default Bootstrap configuration + as well as validate their custom Bootstrap. + +## Non Goals + +* Allow user to configure only a section of the Bootstrap + +## API + +Leverage the existing [EnvoyProxy][] resource which can be attached to the [GatewayClass][] using +the [parametersRef][] field, and define a `Bootstrap` field within the resource. If this field is set, +the value is used as the Bootstrap configuration for all managed Envoy Proxies created by Envoy Gateway. + +```go +// EnvoyProxySpec defines the desired state of EnvoyProxy. +type EnvoyProxySpec struct { + ...... + // Bootstrap defines the Envoy Bootstrap as a YAML string. + // Visit https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/bootstrap/v3/bootstrap.proto#envoy-v3-api-msg-config-bootstrap-v3-bootstrap + // to learn more about the syntax. + // If set, this is the Bootstrap configuration used for the managed Envoy Proxy fleet instead of the default Bootstrap configuration + // set by Envoy Gateway. + // Some fields within the Bootstrap that are required to communicate with the xDS Server (Envoy Gateway) and receive xDS resources + // from it are not configurable and will result in the `EnvoyProxy` resource being rejected. + // Backward compatibility across minor versions is not guaranteed. + // We strongly recommend using `egctl x translate` to generate a `EnvoyProxy` resource with the `Bootstrap` field set to the default + // Bootstrap configuration used. You can edit this configuration, and rerun `egctl x translate` to ensure there are no validation errors. + // + // +optional + Bootstrap *string `json:"bootstrap,omitempty"` +} +``` + +## Tooling + +A CLI tool `egctl x translate` will be provided to the user to help generate a working Bootstrap configuration. +Here is an example where a user inputs a `GatewayClass` and the CLI generates the `EnvoyProxy` resource with the `Bootstrap` field populated. + +``` +cat < /etc/envoy-gateway/config.yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +provider: + type: Kubernetes + kubernetes: {} +EOF +``` + +This configuration will cause Envoy Gateway to use the Kubernetes provider with default configuration parameters. + +The Kubernetes provider can be configured using the `provider` field. For example, the `foo` field can be set to "bar": + +```yaml +$ cat << EOF > /etc/envoy-gateway/config.yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +provider: + type: Kubernetes + kubernetes: + foo: bar +EOF +``` + +__Note:__ The Provider API from the Kubernetes package is currently undefined and `foo: bar` is provided for +illustration purposes only. + +The same API structure is followed for each supported provider. The following example causes Envoy Gateway to use the +File provider: + +```yaml +$ cat << EOF > /etc/envoy-gateway/config.yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +provider: + type: File + file: + foo: bar +EOF +``` + +__Note:__ The Provider API from the File package is currently undefined and `foo: bar` is provided for illustration +purposes only. + +Gateway API-related configuration is expressed through the `gateway` field. If unspecified, Envoy Gateway will use +default configuration parameters for `gateway`. The following example causes the [GatewayClass][gc] controller to +manage GatewayClasses with controllerName `foo` instead of the default `gateway.envoyproxy.io/gatewayclass-controller`: + +```yaml +$ cat << EOF > /etc/envoy-gateway/config.yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +gateway: + controllerName: foo +EOF +``` + +With any of the above configuration examples, Envoy Gateway can be started without any additional arguments: + +```shell +$ ./envoy-gateway +``` + +## Data Plane API + +The data plane is configured dynamically through Kubernetes resources, primarily [Gateway API][gw_api] objects. +Optionally, the data plane infrastructure can be configured by referencing a [custom resource (CR)][cr] through +`spec.parametersRef` of the managed GatewayClass. The `EnvoyProxy` API defines the data plane infrastructure +configuration and is represented as the CR referenced by the managed GatewayClass. Key points of this API are: + +* If unreferenced by `gatewayclass.spec.parametersRef`, default parameters will be used to configure the data plane + infrastructure, e.g. expose Envoy network endpoints using a LoadBalancer service. +* Envoy Gateway will follow Gateway API [recommendations][gc] regarding updates to the EnvoyProxy CR: + > It is recommended that this resource be used as a template for Gateways. This means that a Gateway is based on the + > state of the GatewayClass at the time it was created and changes to the GatewayClass or associated parameters are + > not propagated down to existing Gateways. + +The initial `EnvoyProxy` API: + +```go +// gateway/api/config/v1alpha1/envoyproxy.go + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EnvoyProxy is the Schema for the envoyproxies API. +type EnvoyProxy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec EnvoyProxySpec `json:"spec,omitempty"` + Status EnvoyProxyStatus `json:"status,omitempty"` +} + +// EnvoyProxySpec defines the desired state of Envoy Proxy infrastructure +// configuration. +type EnvoyProxySpec struct { + // Undefined by this design spec. +} + +// EnvoyProxyStatus defines the observed state of EnvoyProxy. +type EnvoyProxyStatus struct { + // Undefined by this design spec. +} +``` + +The EnvoyProxySpec and EnvoyProxyStatus fields will be defined in the future as proxy infrastructure configuration use +cases are better understood. + +### Data Plane Configuration + +GatewayClass and Gateway resources define the data plane infrastructure. Note that all examples assume Envoy Gateway is +running with the Kubernetes provider. + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: GatewayClass +metadata: + name: example-class +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: example-gateway +spec: + gatewayClassName: example-class + listeners: + - name: http + protocol: HTTP + port: 80 +``` + +Since the GatewayClass does not define `spec.parametersRef`, the data plane is provisioned using default configuration +parameters. The Envoy proxies will be configured with a http listener and a Kubernetes LoadBalancer service listening +on port 80. + +The following example will configure the data plane to use a ClusterIP service instead of the default LoadBalancer +service: + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: GatewayClass +metadata: + name: example-class +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parametersRef: + name: example-config + group: gateway.envoyproxy.io + kind: EnvoyProxy +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: example-gateway +spec: + gatewayClassName: example-class + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: example-config +spec: + networkPublishing: + type: ClusterIPService +``` + +__Note:__ The NetworkPublishing API is currently undefined and is provided here for illustration purposes only. + +[issue_51]: https://github.com/envoyproxy/gateway/issues/51 +[design_doc]: https://github.com/envoyproxy/gateway/blob/main/docs/design/SYSTEM_DESIGN.md +[gw_api]: https://gateway-api.sigs.k8s.io/ +[gc]: https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.GatewayClass +[cr]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ +[union]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#unions diff --git a/site/content/en/v0.6.0/design/eg-metrics.md b/site/content/en/v0.6.0/design/eg-metrics.md new file mode 100644 index 00000000000..60b93840852 --- /dev/null +++ b/site/content/en/v0.6.0/design/eg-metrics.md @@ -0,0 +1,225 @@ +--- +date: 2023-10-10 +title: "Control Plane Observability: Metrics" +--- + +This document aims to cover all aspects of envoy gateway control plane metrics observability. + +{{% alert title="Note" color="secondary" %}} +**Data plane** observability (while important) is outside of scope for this document. For dataplane observability, refer to [here](../metrics). +{{% /alert %}} + +## Current State + +At present, the Envoy Gateway control plane provides logs and controller-runtime metrics, without traces. Logs are managed through our proprietary library (`internal/logging`, a shim to `zap`) and are written to `/dev/stdout`. + +## Goals + +Our objectives include: + ++ Supporting **PULL** mode for Prometheus metrics and exposing these metrics on the admin address. ++ Supporting **PUSH** mode for Prometheus metrics, thereby sending metrics to the Open Telemetry Stats sink via gRPC or HTTP. + +## Non-Goals + +Our non-goals include: + ++ Supporting other stats sinks. + +## Use-Cases + +The use-cases include: + ++ Exposing Prometheus metrics in the Envoy Gateway Control Plane. ++ Pushing Envoy Gateway Control Plane metrics via the Open Telemetry Sink. + +## Design + +### Standards + +Our metrics, will be built upon the [OpenTelemetry](https://opentelemetry.io/) standards. All metrics will be configured via the [OpenTelemetry SDK](https://opentelemetry.io/docs/specs/otel/metrics/sdk/), which offers neutral libraries that can be connected to various backends. + +This approach allows the Envoy Gateway code to concentrate on the crucial aspect - generating the metrics - and delegate all other tasks to systems designed for telemetry ingestion. + +### Attributes + +OpenTelemetry defines a set of [Semantic Conventions](https://opentelemetry.io/docs/concepts/semantic-conventions/), including [Kubernetes specific ones](https://opentelemetry.io/docs/specs/otel/resource/semantic_conventions/k8s/). + +These attributes can be expressed in logs (as keys of structured logs), traces (as attributes), and metrics (as labels). + +We aim to use attributes consistently where applicable. Where possible, these should adhere to codified Semantic Conventions; when not possible, they should maintain consistency across the project. + +### Extensibility + +Envoy Gateway supports both **PULL/PUSH** mode metrics, with Metrics exported via Prometheus by default. + +Additionally, Envoy Gateway can export metrics using both the [OTEL gRPC metrics exporter](https://opentelemetry.io/docs/specs/otel/metrics/sdk_exporters/otlp/#general) and [OTEL HTTP metrics exporter](https://opentelemetry.io/docs/specs/otel/metrics/sdk_exporters/otlp/#general), which pushes metrics by grpc/http to a remote OTEL collector. + +Users can extend these in two ways: + +#### Downstream Collection + +Based on the exported data, other tools can collect, process, and export telemetry as needed. Some examples include: + ++ Metrics in **PULL** mode: The OTEL collector can scrape Prometheus and export to X. ++ Metrics in **PUSH** mode: The OTEL collector can receive OTEL gRPC/HTTP exporter metrics and export to X. + +While the examples above involve OTEL collectors, there are numerous other systems available. + +#### Vendor extensions + +The OTEL libraries allow for the registration of Providers/Handlers. While we will offer the default ones (PULL via Prometheus, PUSH via OTEL HTTP metrics exporter) mentioned in Envoy Gateway's extensibility, we can easily allow custom builds of Envoy Gateway to plug in alternatives if the default options don't meet their needs. + +For instance, users may prefer to write metrics over the OTLP gRPC metrics exporter instead of the HTTP metrics exporter. This is perfectly acceptable -- and almost impossible to prevent. The OTEL has ways to register their providers/exporters, and Envoy Gateway can ensure its usage is such that it's not overly difficult to swap out a different provider/exporter. + +### Stability + +Observability is, in essence, a user-facing API. Its primary purpose is to be consumed - by both humans and tooling. Therefore, having well-defined guarantees around their formats is crucial. + +Please note that this refers only to the contents of the telemetry - what we emit, the names of things, semantics, etc. Other settings like Prometheus vs OTLP, JSON vs plaintext, logging levels, etc., are not considered. + +I propose the following: + +#### Metrics + +Metrics offer the greatest potential for providing guarantees. They often directly influence alerts and dashboards, making changes highly impactful. This contrasts with traces and logs, which are often used for ad-hoc analysis, where minor changes to information can be easily understood by a human. + +Moreover, there is precedent for this: [Kubernetes Metrics Lifecycle](https://kubernetes.io/docs/concepts/cluster-administration/system-metrics/#metric-lifecycle) has well-defined processes, and Envoy Gateway's dataplane (Envoy Proxy) metrics are de facto stable. + +Currently, all Envoy Gateway metrics lack defined stability. I suggest we categorize all existing metrics as either: + ++ ***Deprecated***: a metric that is intended to be phased out. ++ ***Experimental***: a metric that is off by default. ++ ***Alpha***: a metric that is on by default. + +We should aim to promote a core set of metrics to **Stable** within a few releases. + +## Envoy Gateway API Types + +New APIs will be added to Envoy Gateway config, which are used to manage Control Plane Telemetry bootstrap configs. + +### EnvoyGatewayTelemetry + +``` go +// EnvoyGatewayTelemetry defines telemetry configurations for envoy gateway control plane. +// Control plane will focus on metrics observability telemetry and tracing telemetry later. +type EnvoyGatewayTelemetry struct { + // Metrics defines metrics configuration for envoy gateway. + Metrics *EnvoyGatewayMetrics `json:"metrics,omitempty"` +} +``` + +### EnvoyGatewayMetrics + +> Prometheus will be exposed on 0.0.0.0:19001, which is not supported to be configured yet. + +``` go +// EnvoyGatewayMetrics defines control plane push/pull metrics configurations. +type EnvoyGatewayMetrics struct { + // Sinks defines the metric sinks where metrics are sent to. + Sinks []EnvoyGatewayMetricSink `json:"sinks,omitempty"` + // Prometheus defines the configuration for prometheus endpoint. + Prometheus *EnvoyGatewayPrometheusProvider `json:"prometheus,omitempty"` +} + +// EnvoyGatewayMetricSink defines control plane +// metric sinks where metrics are sent to. +type EnvoyGatewayMetricSink struct { + // Type defines the metric sink type. + // EG control plane currently supports OpenTelemetry. + // +kubebuilder:validation:Enum=OpenTelemetry + // +kubebuilder:default=OpenTelemetry + Type MetricSinkType `json:"type"` + // OpenTelemetry defines the configuration for OpenTelemetry sink. + // It's required if the sink type is OpenTelemetry. + OpenTelemetry *EnvoyGatewayOpenTelemetrySink `json:"openTelemetry,omitempty"` +} + +type EnvoyGatewayOpenTelemetrySink struct { + // Host define the sink service hostname. + Host string `json:"host"` + // Protocol define the sink service protocol. + // +kubebuilder:validation:Enum=grpc;http + Protocol string `json:"protocol"` + // Port defines the port the sink service is exposed on. + // + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=4317 + Port int32 `json:"port,omitempty"` +} + +// EnvoyGatewayPrometheusProvider will expose prometheus endpoint in pull mode. +type EnvoyGatewayPrometheusProvider struct { + // Disable defines if disables the prometheus metrics in pull mode. + // + Disable bool `json:"disable,omitempty"` +} + +``` + +#### Example + ++ The following is an example to disable prometheus metric. + +``` yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +logging: + level: null + default: info +provider: + type: Kubernetes +telemetry: + metrics: + prometheus: + disable: true +``` + ++ The following is an example to send metric via Open Telemetry sink to OTEL gRPC Collector. + +``` yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +logging: + level: null + default: info +provider: + type: Kubernetes +telemetry: + metrics: + sinks: + - type: OpenTelemetry + openTelemetry: + host: otel-collector.monitoring.svc.cluster.local + port: 4317 + protocol: grpc +``` + ++ The following is an example to disable prometheus metric and send metric via Open Telemetry sink to OTEL HTTP Collector at the same time. + +``` yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +logging: + level: null + default: info +provider: + type: Kubernetes +telemetry: + metrics: + prometheus: + disable: false + sinks: + - type: OpenTelemetry + openTelemetry: + host: otel-collector.monitoring.svc.cluster.local + port: 4318 + protocol: http +``` diff --git a/site/content/en/v0.6.0/design/egctl.md b/site/content/en/v0.6.0/design/egctl.md new file mode 100644 index 00000000000..0f67d99f100 --- /dev/null +++ b/site/content/en/v0.6.0/design/egctl.md @@ -0,0 +1,59 @@ +--- +title: "egctl Design" +--- + +## Motivation + +EG should provide a command line tool with following capabilities: + +- Collect configuration from envoy proxy and gateway +- Analyse system configuration to diagnose any issues in envoy gateway + +This tool is named `egctl`. + +## Syntax + +Use the following syntax to run `egctl` commands from your terminal window: + +```console +egctl [command] [entity] [name] [flags] +``` + +where `command`, `name`, and `flags` are: + +* `command`: Specifies the operation that you want to perform on one or more resources, + for example `config`, `version`. + +* `entity`: Specifies the entity the operation is being performed on such as `envoy-proxy` or `envoy-gateway`. + +* `name`: Specifies the name of the specified instance. + +* `flags`: Specifies optional flags. For example, you can use the `-c` or `--config` flags to specify the values for installing. + +If you need help, run `egctl help` from the terminal window. + +## Operation + +The following table includes short descriptions and the general syntax for all the `egctl` operations: + +| Operation | Syntax | Description | +| --------------| -------------------------------- | -------------------------------------------------------------------------------------| +| `version` | `egctl version` | Prints out build version information. | +| `config` | `egctl config ENTITY` | Retrieve information about proxy configuration from envoy proxy and gateway | +| `analyze` | `egctl analyze` | Analyze EG configuration and print validation messages | +| `experimental`| `egctl experimental` | Subcommand for experimental features. These do not guarantee backwards compatibility | + +## Examples + +Use the following set of examples to help you familiarize yourself with running the commonly used `egctl` operations: + +```console +# Retrieve all information about proxy configuration from envoy +egctl config envoy-proxy all + +# Retrieve listener information about proxy configuration from envoy +egctl config envoy-proxy listener + +# Retrieve information about envoy gateway +egctl config envoy-gateway +``` diff --git a/site/content/en/v0.6.0/design/envoy-patch-policy.md b/site/content/en/v0.6.0/design/envoy-patch-policy.md new file mode 100644 index 00000000000..d34937d05ef --- /dev/null +++ b/site/content/en/v0.6.0/design/envoy-patch-policy.md @@ -0,0 +1,176 @@ +--- +title: "EnvoyPatchPolicy" +--- + +## Overview + +This design introduces the `EnvoyPatchPolicy` API allowing users to modify the generated Envoy xDS Configuration +that Envoy Gateway generates before sending it to Envoy Proxy. + +Envoy Gateway allows users to configure networking and security intent using the +upstream [Gateway API][] as well as implementation specific [Extension APIs][] defined in this project +to provide a more batteries included experience for application developers. +* These APIs are an abstracted version of the underlying Envoy xDS API to provide a better user experience for the application developer, exposing and setting only a subset of the fields for a specific feature, sometimes in a opinionated way (e.g [RateLimit][]) +* These APIs do not expose all the features capabilities that Envoy has either because these features are desired but the API +is not defined yet or the project cannot support such an extensive list of features. +To alleviate this problem, and provide an interim solution for a small section of advanced users who are well versed in +Envoy xDS API and its capabilities, this API is being introduced. + +## Goals +* Add an API allowing users to modify the generated xDS Configuration + +## Non Goals +* Support multiple patch mechanisims + +## Implementation +`EnvoyPatchPolicy` is a [Direct Policy Attachment][] type API that can be used to extend [Gateway API][] +Modifications to the generated xDS configuration can be provided as a JSON Patch which is defined in +[RFC 6902][]. This patching mechanism has been adopted in [Kubernetes][] as well as [Kustomize][] to update +resource objects. + +### Example +Here is an example highlighting how a user can configure global ratelimiting using an external rate limit service using this API. + +``` +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: GatewayClass +metadata: + name: eg +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: eg + namespace: default +spec: + gatewayClassName: eg + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: backend + namespace: default +spec: + parentRefs: + - name: eg + hostnames: + - "www.example.com" + rules: + - backendRefs: + - group: "" + kind: Service + name: backend + port: 3000 + weight: 1 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyPatchPolicy +metadata: + name: ratelimit-patch-policy + namespace: default +spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: eg + namespace: default + type: JSONPatch + jsonPatches: + - type: "type.googleapis.com/envoy.config.listener.v3.Listener" + # The listener name is of the form // + name: default/eg/http + operation: + op: add + path: "/default_filter_chain/filters/0/typed_config/http_filters/0" + value: + name: "envoy.filters.http.ratelimit" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit" + domain: "eag-ratelimit" + failure_mode_deny: true + timeout: 1s + rate_limit_service: + grpc_service: + envoy_grpc: + cluster_name: rate-limit-cluster + transport_api_version: V3 + - type: "type.googleapis.com/envoy.config.route.v3.RouteConfiguration" + # The route name is of the form // + name: default/eg/http + operation: + op: add + path: "/virtual_hosts/0/rate_limits" + value: + - actions: + - remote_address: {} + - type: "type.googleapis.com/envoy.config.cluster.v3.Cluster" + name: rate-limit-cluster + operation: + op: add + path: "" + value: + name: rate-limit-cluster + type: STRICT_DNS + connect_timeout: 10s + lb_policy: ROUND_ROBIN + http2_protocol_options: {} + load_assignment: + cluster_name: rate-limit-cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: ratelimit.svc.cluster.local + port_value: 8081 +``` + + +## Verification +* Offline - Leverage [egctl x translate][] to ensure that the `EnvoyPatchPolicy` can be successfully applied and the desired +output xDS is created. +* Runtime - Use the `Status` field within `EnvoyPatchPolicy` to highlight whether the patch was applied successfully or not. + +## State of the World +* Istio - Supports the [EnvoyFilter][] API which allows users to customize the output xDS using patches and proto based merge +semantics. + +## Design Decisions +* This API will only support a single `targetRef` and can bind to only a `Gateway` resource. This simplifies reasoning of how +patches will work. +* This API will always be an experimental API and cannot be graduated into a stable API because Envoy Gateway cannot garuntee + * that the naming scheme for the generated resources names will not change across releases + * that the underlying Envoy Proxy API will not change across releases +* This API needs to be explicitly enabled using the [EnvoyGateway][] API + +## Open Questions +* Should the value only support JSON or YAML as well (which is a JSON superset) ? + +## Alternatives +* Users can customize the Envoy [Bootstrap configuration using EnvoyProxy API][] and provide static xDS configuration. +* Users can extend functionality by [Extending the Control Plane][] and adding gRPC hooks to modify the generated xDS configuration. + + + +[Direct Policy Attachment]: https://gateway-api.sigs.k8s.io/references/policy-attachment/#direct-policy-attachment +[RFC 6902]: https://datatracker.ietf.org/doc/html/rfc6902 +[Gateway API]: https://gateway-api.sigs.k8s.io/ +[Kubernetes]: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ +[Kustomize]: https://github.com/kubernetes-sigs/kustomize/blob/master/examples/jsonpatch.md +[Extension APIs]: https://gateway.envoyproxy.io/latest/api/extension_types.html +[RateLimit]: https://gateway.envoyproxy.io/latest/user/rate-limit.html +[EnvoyGateway]: https://gateway.envoyproxy.io/latest/api/config_types.html#envoygateway +[Extending the Control Plane]: https://gateway.envoyproxy.io/latest/design/extending-envoy-gateway.html +[EnvoyFilter]: https://istio.io/latest/docs/reference/config/networking/envoy-filter +[egctl x translate]: https://gateway.envoyproxy.io/latest/user/egctl.html#egctl-experimental-translate +[Bootstrap configuration using EnvoyProxy API]: https://gateway.envoyproxy.io/latest/user/customize-envoyproxy.html#customize-envoyproxy-bootstrap-config diff --git a/site/content/en/v0.6.0/design/extending-envoy-gateway.md b/site/content/en/v0.6.0/design/extending-envoy-gateway.md new file mode 100644 index 00000000000..d4f36cc7a4a --- /dev/null +++ b/site/content/en/v0.6.0/design/extending-envoy-gateway.md @@ -0,0 +1,327 @@ +--- +title: "Envoy Gateway Extensions Design" +--- + +As outlined in the [official goals][] for the Envoy Gateway project, one of the main goals is to "provide a common foundation for vendors to build value-added products +without having to re-engineer fundamental interactions". Development of the Envoy Gateway project has been focused on developing the core features for the project and +Kubernetes Gateway API conformance. This system focuses on the “common foundation for vendors” component by introducing a way for vendors to extend Envoy Gateway. + +To meaningfully extend Envoy Gateway and provide additional features, Extensions need to be able to introduce their own custom resources and have a high level of control +over the configuration generated by Envoy Gateway. Simply applying some static xDS configuration patches or relying on the existing Gateway API resources are both insufficient on their own +as means to add larger features that require dynamic user-configuration. + +As an example, an extension developer may wish to provide their own out-of-the-box authentication filters that require configuration from the end-user. This is a scenario where the ability to introduce +custom resources and attach them to [HTTPRoute][]s as an [ExtensionRef][] is necessary. Providing the same feature through a series of xDS patch resources would be too cumbersome for many end-users that want to avoid +that level of complexity when managing their clusters. + +## Goals + +- Provide a foundation for extending the Envoy Gateway control plane +- Allow Extension Developers to introduce their own custom resources for extending the Gateway-API via [ExtensionRefs][], [policyAttachments][] (future) and [backendRefs][] (future). +- Extension developers should **NOT** have to maintain a custom fork of Envoy Gateway +- Provide a system for extending Envoy Gateway which allows extension projects to ship updates independent of Envoy Gateway's release schedule +- Modify the generated Envoy xDS config +- Setup a foundation for the initial iteration of Extending Envoy Gateway +- Allow an Extension to hook into the infra manager pipeline (future) + +## Non-Goals + +- The initial design does not capture every hook that Envoy Gateway will eventually support. +- Extend [Gateway API Policy Attachments][]. At some point, these will be addressed using this extension system, but the initial implementation omits these. +- Support multiple extensions at the same time. Due to the fact that extensions will be modifying xDS resources after they are generated, handling the order of extension execution for each individual hook point is a challenge. Additionally, there is no +real way to prevent one extension from overwriting or breaking modifications to xDS resources that were made by another extension that was executed first. + +## Overview + +Envoy Gateway can be extended by vendors by means of an extension server developed by the vendor and deployed alongside Envoy Gateway. +An extension server can make use of one or more pre/post hooks inside Envoy Gateway before and after its major components (translator, etc.) to allow the extension to modify the data going into or coming out of these components. +An extension can be created external to Envoy Gateway as its own Kubernetes deployment or loaded as a sidecar. gRPC is used for the calls between Envoy Gateway and an extension. In the hook call, Envoy Gateway sends data as well +as context information to the extension and expects a reply with a modified version of the data that was sent to the extension. Since extensions fundamentally alter the logic and data that Envoy Gateway provides, Extension projects assume responsibility for any bugs and issues +they create as a direct result of their modification of Envoy Gateway. + +## Diagram + +![Architecture](/img/extension-example.png) + +## Registering Extensions in Envoy Gateway + +Information about the extension that Envoy Gateway needs to load is configured in the Envoy Gateway config. + +An example configuration: + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +extensionManager: + resources: + - group: example.myextension.io + version: v2 + kind: OAuth2Filter + hooks: + xdsTranslator: + post: + - Route + - VirtualHost + - HTTPListener + - Translation + service: + host: my-extension.example + port: 443 + tls: + certificateRef: + name: my-secret + namespace: default +``` + +An extension must supply connection information in the `extension.service` field so that Envoy Gateway can communicate with the extension. The `tls` configuration is optional. + +If the extension wants Envoy Gateway to watch resources for it then the extension must configure the optional `extension.resources` field and supply a list of: + +- `group`: the API group of the resource +- `version`: the API version of the resource +- `kind`: the Kind of resource + +The extension can configure the `extensionManager.hooks` field to specify which hook points it would like to support. If a given hook is not listed here then it will not be executed even +if the extension is configured properly. This allows extension developers to only opt-in to the hook points they want to make use of. + +This configuration is required to be provided at bootstrap and modifying the registered extension during runtime is not currently supported. +Envoy Gateway will keep track of the registered extension and its API `groups` and `kinds` when processing Gateway API resources. + +## Extending Gateway API and the Data Plane + +Envoy Gateway manages [Envoy][] deployments, which act as the data plane that handles actual user traffic. Users configure the data plane using the K8s Gateway API resources which Envoy +Gateway converts into [Envoy specific configuration (xDS)][] to send over to Envoy. + +Gateway API offers [ExtensionRef filters][] and [Policy Attachments][] as extension points for implementers to use. Envoy Gateway extends the Gateway API using these extension points to provide support for [rate limiting][] +and [authentication][] native to the project. The initial design of Envoy Gateway extensions will primarily focus on ExtensionRef filters so that extension developers can reference their own resources as HTTP Filters in the same way +that Envoy Gateway has native support for rate limiting and authentication filters. + +When Envoy Gateway encounters an [HTTPRoute][] or [GRPCRoute][] that has an `ExtensionRef` `filter` with a `group` and `kind` that Envoy Gateway does not support, it will first +check the registered extension to determine if it supports the referenced object before considering it a configuration error. + +This allows users to be able to reference additional filters provided by their Envoy Gateway Extension, in their `HTTPRoute`s / `GRPCRoute`s: + +```yaml +apiVersion: example.myextension.io/v1alpha1 +kind: OAuth2Filter +metadata: + name: oauth2-filter +spec: + ... + +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: example +spec: + parentRefs: + - name: eg + hostnames: + - www.example.com + rules: + - clientSelectors: + - path: + type: PathPrefix + value: / + filters: + - type: ExtensionRef + extensionRef: + group: example.myextension.io + kind: OAuth2Filter + name: oauth2-filter + backendRefs: + - name: backend + port: 3000 +``` + +In order to enable the usage of new resources introduced by an extension for translation and xDS modification, Envoy Gateway provides hook points within the translation pipeline, where it calls out to the extension service registered in the [EnvoyGateway config][] +if they specify an `group` that matches the `group` of an `ExtensionRef` filter. The extension will then be able to modify the xDS that Envoy Gateway generated and send back the +modified configuration. If an extension is not registered or if the registered extension does not specify support for the `group` of an `ExtensionRef` filter then Envoy Gateway will treat it as an unknown resource +and provide an error to the user. + +**Note:** Currently (as of [v1beta1][]) Gateway API does not provide a means to specify the namespace or version of an object referenced as an `ExtensionRef`. The extension mechanism will assume that +the namespace of any `ExtensionRef` is the same as the namespace of the `HTTPRoute` or `GRPCRoute` it is attached to rather than treating the `name` field of an `ExtensionRef` as a `name.namespace` string. +If Gateway API adds support for these fields then the design of the Envoy Gateway extensions will be updated to support them. + +## Watching New Resources + +Envoy Gateway will dynamically create new watches on resources introduced by the registered Extension. It does so by using the [controller-runtime][] to create new watches on [Unstructured][] resources that match the `version`s, `group`s, and `kind`s that the +registered extension configured. When communicating with an extension, Envoy Gateway sends these Unstructured resources over to the extension. This eliminates the need for the extension to create its own watches which would have a strong chance of creating race conditions and reconciliation loops when resources change. When an extension receives the Unstructured resources from Envoy Gateway it can perform its own type validation on them. Currently we make the simplifying assumption that the registered extension's `Kinds` are filters referenced by `extensionRef` in `HTTPRouteFilter`s . Support for Policy attachments will be introduced at a later time. + +## xDS Hooks API + +Envoy Gateway supports the following hooks as the initial foundation of the Extension system. Additional hooks can be developed using this extension system at a later point as new use-cases and needs are discovered. The primary iteration of the extension hooks +focuses solely on the modification of xDS resources. + +### Route Modification Hook + +The [Route][] level Hook provides a way for extensions to modify a route generated by Envoy Gateway before it is finalized. +Doing so allows extensions to configure/modify route fields configured by Envoy Gateway and also to configure the +Route's TypedPerFilterConfig which may be desirable to do things such as pass settings and information to ext_authz filters. +The Post Route Modify hook also passes a list of Unstructured data for the externalRefs owned by the extension on the HTTPRoute that created this xDS route +This hook is always executed when an extension is loaded that has added `Route` to the `EnvoyProxy.extensionManager.hooks.xdsTranslator.post`, and only on Routes which were generated from an HTTPRoute that uses extension resources as externalRef filters. + +```go +// PostRouteModifyRequest sends a Route that was generated by Envoy Gateway along with context information to an extension so that the Route can be modified +message PostRouteModifyRequest { + envoy.config.route.v3.Route route = 1; + PostRouteExtensionContext post_route_context = 2; +} + +// RouteExtensionContext provides resources introduced by an extension and watched by Envoy Gateway +// additional context information can be added to this message as more use-cases are discovered +message PostRouteExtensionContext { + // Resources introduced by the extension that were used as extensionRefs in an HTTPRoute/GRPCRoute + repeated ExtensionResource extension_resources = 1; + + // hostnames are the fully qualified domain names attached to the HTTPRoute + repeated string hostnames = 2; +} + +// ExtensionResource stores the data for a K8s API object referenced in an HTTPRouteFilter +// extensionRef. It is constructed from an unstructured.Unstructured marshalled to JSON. An extension +// can marshal the bytes from this resource back into an unstructured.Unstructured and then +// perform type checking to obtain the resource. +message ExtensionResource { + bytes unstructured_bytes = 1; +} + +// PostRouteModifyResponse is the expected response from an extension and contains a modified version of the Route that was sent +// If an extension returns a nil Route then it will not be modified +message PostRouteModifyResponse { + envoy.config.route.v3.Route route = 1; +} +``` + +### VirtualHost Modification Hook + +The [VirtualHost][] Hook provides a way for extensions to modify a VirtualHost generated by Envoy Gateway before it is finalized. +An extension can also make use of this hook to generate and insert entirely new Routes not generated by Envoy Gateway. +This hook is always executed when an extension is loaded that has added `VirtualHost` to the `EnvoyProxy.extensionManager.hooks.xdsTranslator.post`. +An extension may return nil to not make any changes to the VirtualHost. + +```protobuf +// PostVirtualHostModifyRequest sends a VirtualHost that was generated by Envoy Gateway along with context information to an extension so that the VirtualHost can be modified +message PostVirtualHostModifyRequest { + envoy.config.route.v3.VirtualHost virtual_host = 1; + PostVirtualHostExtensionContext post_virtual_host_context = 2; +} + +// Empty for now but we can add fields to the context as use-cases are discovered without +// breaking any clients that use the API +// additional context information can be added to this message as more use-cases are discovered +message PostVirtualHostExtensionContext {} + +// PostVirtualHostModifyResponse is the expected response from an extension and contains a modified version of the VirtualHost that was sent +// If an extension returns a nil Virtual Host then it will not be modified +message PostVirtualHostModifyResponse { + envoy.config.route.v3.VirtualHost virtual_host = 1; +} +``` + +### HTTP Listener Modification Hook + +The HTTP [Listener][] modification hook is the broadest xDS modification Hook available and allows an extension to make changes to a Listener generated by Envoy Gateway before it is finalized. +This hook is always executed when an extension is loaded that has added `HTTPListener` to the `EnvoyProxy.extensionManager.hooks.xdsTranslator.post`. An extension may return nil +in order to not make any changes to the Listener. + +```protobuf +// PostVirtualHostModifyRequest sends a Listener that was generated by Envoy Gateway along with context information to an extension so that the Listener can be modified +message PostHTTPListenerModifyRequest { + envoy.config.listener.v3.Listener listener = 1; + PostHTTPListenerExtensionContext post_listener_context = 2; +} + +// Empty for now but we can add fields to the context as use-cases are discovered without +// breaking any clients that use the API +// additional context information can be added to this message as more use-cases are discovered +message PostHTTPListenerExtensionContext {} + +// PostHTTPListenerModifyResponse is the expected response from an extension and contains a modified version of the Listener that was sent +// If an extension returns a nil Listener then it will not be modified +message PostHTTPListenerModifyResponse { + envoy.config.listener.v3.Listener listener = 1; +} +``` + +### Post xDS Translation Modify Hook + +The Post Translate Modify hook allows an extension to modify the clusters and secrets in the xDS config. +This allows for inserting clusters that may change along with extension specific configuration to be dynamically created rather than +using custom bootstrap config which would be sufficient for clusters that are static and not prone to have their configurations changed. +An example of how this may be used is to inject a cluster that will be used by an ext_authz http filter created by the extension. +The list of clusters and secrets returned by the extension are used as the final list of all clusters and secrets +This hook is always executed when an extension is loaded that has added `Translation` to the `EnvoyProxy.extensionManager.hooks.xdsTranslator.post`. + +```protobuf +// PostTranslateModifyRequest currently sends only clusters and secrets to an extension. +// The extension is free to add/modify/remove the resources it received. +message PostTranslateModifyRequest { + PostTranslateExtensionContext post_translate_context = 1; + repeated envoy.config.cluster.v3.Cluster clusters = 2; + repeated envoy.extensions.transport_sockets.tls.v3.Secret secrets = 3; +} + +// PostTranslateModifyResponse is the expected response from an extension and contains +// the full list of xDS clusters and secrets to be used for the xDS config. +message PostTranslateModifyResponse { + repeated envoy.config.cluster.v3.Cluster clusters = 1; + repeated envoy.extensions.transport_sockets.tls.v3.Secret secrets = 2; +} +``` + +### Extension Service + +Currently, an extension must implement all of the following hooks although it may return the input(s) it received +if no modification of the resource is desired. A future expansion of the extension hooks will allow an Extension to specify +with config which Hooks it would like to "subscribe" to and which Hooks it does not wish to support. These specific Hooks were chosen +in order to provide extensions with the ability to have both broad and specific control over xDS resources and to minimize the amount of data being sent. + +```protobuf +service EnvoyGatewayExtension { + rpc PostRouteModify (PostRouteModifyRequest) returns (PostRouteModifyResponse) {}; + rpc PostVirtualHostModify(PostVirtualHostModifyRequest) returns (PostVirtualHostModifyResponse) {}; + rpc PostHTTPListenerModify(PostHTTPListenerModifyRequest) returns (PostHTTPListenerModifyResponse) {}; + rpc PostTranslateModify(PostTranslateModifyRequest) returns (PostTranslateModifyResponse) {}; +} +``` + +## Design Decisions + +- Envoy Gateway watches new custom resources introduced by a loaded extension and passes the resources back to the extension when they are used. + - This decision was made to solve the problem about how resources introduced by an extension get watched. If an extension server watches its own resources then it would need some way to trigger an Envoy Gateway reconfigure when a resource that Envoy Gateway is not watching gets updated. Having Envoy Gateway watch all resources removes any concern about creating race confitions or reconcile loops that would result from Envoy Gateway and the extension server both having so much separate state that needs to be synchronized. +- The Extension Server takes ownership of producing the correct xDS configuration in the hook responses +- The Extension Server will be responsible for ensuring the performance of the hook processing time +- The Post xDS level gRPC hooks all currently send a context field even though it contains nothing for several hooks. These fields exist so that they can be updadated in the future to pass +additional information to extensions as new use-cases and needs are discovered. +- The initial design supplies the scaffolding for both "pre xDS" and "post xDS" hooks. Only the post hooks are currently implemented which operate on xDS resources after they have been generated. +The pre hooks will be implemented at a later date along with one or more hooks in the infra manager. The infra manager level hook(s) will exist to power use-cases such as dynamically creating Deployments/Services for the extension the +whenever Envoy Gateway creates an instance of Envoy Proxy. An extension developer might want to take advantage of this functionality to inject a new authorization service as a sidecar on the Envoy Proxy deployment for reduced latency. +- Multiple extensions are not be supported at the same time. Preventing conflict between multiple extensions that are mangling xDS resources is too difficult to ensure compatibility with and is likely to only generate issues. + +## Known Challenges + +Extending Envoy Gateway by using an external extension server which makes use of hook points in Envoy Gateway does comes with a few trade-offs. One known trade-off is the impact of the time that it takes for the hook calls to be executed. Since an extension would make use of hook points in Envoy Gateway that use gRPC for communication, the time it takes to perform these requests could become a concern for some extension developers. One way to minimize the request time of the hook calls is to load the extension server as a sidecar to Envoy Gateway to minimize the impact of networking on the hook calls. + +[official goals]: https://github.com/envoyproxy/gateway/blob/main/GOALS.md#extensibility +[ExtensionRef filters]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.LocalObjectReference +[ExtensionRef]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.LocalObjectReference +[ExtensionRefs]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.LocalObjectReference +[backendRefs]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.BackendObjectReference +[Gateway API Policy attachments]: https://gateway-api.sigs.k8s.io/references/policy-attachment/?h=policy +[Policy Attachments]: https://gateway-api.sigs.k8s.io/references/policy-attachment/?h=policy +[policyAttachments]: https://gateway-api.sigs.k8s.io/references/policy-attachment/?h=policy +[Envoy]: https://www.envoyproxy.io/ +[Envoy specific configuration (xDS)]: https://www.envoyproxy.io/docs/envoy/v1.25.1/configuration/configuration +[v1beta1]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io%2fv1beta1 +[rate limiting]: https://gateway.envoyproxy.io/v0.3.0/user/rate-limit.html +[authentication]: https://gateway.envoyproxy.io/v0.3.0/user/authn.html +[HTTPRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRoute +[GRPCRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute +[EnvoyGateway config]: https://gateway.envoyproxy.io/v0.3.0/api/config_types.html#envoygateway +[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime +[Unstructured]: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured +[Listener]: https://www.envoyproxy.io/docs/envoy/v1.23.0/api-v3/config/listener/v3/listener.proto#config-listener-v3-listener +[VirtualHost]: https://www.envoyproxy.io/docs/envoy/v1.23.0/api-v3/config/route/v3/route_components.proto#config-route-v3-virtualhost +[Route]: https://www.envoyproxy.io/docs/envoy/v1.23.0/api-v3/config/route/v3/route_components.proto#config-route-v3-route diff --git a/site/content/en/v0.6.0/design/gatewayapi-translator.md b/site/content/en/v0.6.0/design/gatewayapi-translator.md new file mode 100644 index 00000000000..b83ed82588d --- /dev/null +++ b/site/content/en/v0.6.0/design/gatewayapi-translator.md @@ -0,0 +1,253 @@ +--- +title: "Gateway API Translator Design" +weight: 4 +--- + +The Gateway API translates external resources, e.g. GatewayClass, from the configured Provider to the Intermediate +Representation (IR). + +## Assumptions + +Initially target core conformance features only, to be followed by extended conformance features. + +## Inputs and Outputs + +The main inputs to the Gateway API translator are: + +- GatewayClass, Gateway, HTTPRoute, TLSRoute, Service, ReferenceGrant, Namespace, and Secret resources. + +__Note:__ ReferenceGrant is not fully implemented as of v0.2. + +The outputs of the Gateway API translator are: + +- Xds and Infra Internal Representations (IRs). +- Status updates for GatewayClass, Gateways, HTTPRoutes + +## Listener Compatibility + +Envoy Gateway follows Gateway API listener compatibility spec: +> Each listener in a Gateway must have a unique combination of Hostname, Port, and Protocol. An implementation MAY group +> Listeners by Port and then collapse each group of Listeners into a single Listener if the implementation determines +> that the Listeners in the group are “compatible”. + +__Note:__ Envoy Gateway does not collapse listeners across multiple Gateways. + +### Listener Compatibility Examples + +#### Example 1: Gateway with compatible Listeners (same port & protocol, different hostnames) + +```yaml +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1beta1 +metadata: + name: gateway-1 + namespace: envoy-gateway +spec: + gatewayClassName: envoy-gateway + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + hostname: "*.envoygateway.io" + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + hostname: whales.envoygateway.io +``` + +#### Example 2: Gateway with compatible Listeners (same port & protocol, one hostname specified, one not) + +```yaml +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1beta1 +metadata: + name: gateway-1 + namespace: envoy-gateway +spec: + gatewayClassName: envoy-gateway + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + hostname: "*.envoygateway.io" + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +``` + +#### Example 3: Gateway with incompatible Listeners (same port, protocol and hostname) + +```yaml +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1beta1 +metadata: + name: gateway-1 + namespace: envoy-gateway +spec: + gatewayClassName: envoy-gateway + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + hostname: whales.envoygateway.io + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + hostname: whales.envoygateway.io +``` + +#### Example 4: Gateway with incompatible Listeners (neither specify a hostname) + +```yaml +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1beta1 +metadata: + name: gateway-1 + namespace: envoy-gateway +spec: + gatewayClassName: envoy-gateway + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +``` + +## Computing Status + +Gateway API specifies a rich set of status fields & conditions for each resource. To achieve conformance, Envoy Gateway +must compute the appropriate status fields and conditions for managed resources. + +Status is computed and set for: + +- The managed GatewayClass (`gatewayclass.status.conditions`). +- Each managed Gateway, based on its Listeners' status (`gateway.status.conditions`). For the Kubernetes provider, the + Envoy Deployment and Service status are also included to calculate Gateway status. +- Listeners for each Gateway (`gateway.status.listeners`). +- The ParentRef for each Route (`route.status.parents`). + +The Gateway API translator is responsible for calculating status conditions while translating Gateway API resources to +the IR and publishing status over the [message bus][]. The Status Manager subscribes to these status messages and +updates the resource status using the configured provider. For example, the Status Manager uses a Kubernetes client to +update resource status on the Kubernetes API server. + +## Outline + +The following roughly outlines the translation process. Each step may produce (1) IR; and (2) status updates on Gateway +API resources. + +1. Process Gateway Listeners + - Validate unique hostnames, ports, and protocols. + - Validate and compute supported kinds. + - Validate allowed namespaces (validate selector if specified). + - Validate TLS fields if specified, including resolving referenced Secrets. + +2. Process HTTPRoutes + - foreach route rule: + - compute matches + - [core] path exact, path prefix + - [core] header exact + - [extended] query param exact + - [extended] HTTP method + - compute filters + - [core] request header modifier (set/add/remove) + - [core] request redirect (hostname, statuscode) + - [extended] request mirror + - compute backends + - [core] Kubernetes services + - foreach route parent ref: + - get matching listeners (check Gateway, section name, listener validation status, listener allowed routes, hostname intersection) + - foreach matching listener: + - foreach hostname intersection with route: + - add each computed route rule to host + +## Context Structs + +To help store, access and manipulate information as it's processed during the translation process, a set of context +structs are used. These structs wrap a given Gateway API type, and add additional fields and methods to support +processing. + +`GatewayContext` wraps a Gateway and provides helper methods for setting conditions, accessing Listeners, etc. + +```go +type GatewayContext struct { + // The managed Gateway + *v1beta1.Gateway + + // A list of Gateway ListenerContexts. + listeners []*ListenerContext +} +``` + +`ListenerContext` wraps a Listener and provides helper methods for setting conditions and other status information on +the associated Gateway. + +```go +type ListenerContext struct { + // The Gateway listener. + *v1beta1.Listener + + // The Gateway this Listener belongs to. + gateway *v1beta1.Gateway + + // An index used for managing this listener in the list of Gateway listeners. + listenerStatusIdx int + + // Only Routes in namespaces selected by the selector may be attached + // to the Gateway this listener belongs to. + namespaceSelector labels.Selector + + // The TLS Secret for this Listener, if applicable. + tlsSecret *v1.Secret +} +``` + +`RouteContext` represents a generic Route object (HTTPRoute, TLSRoute, etc.) that can reference Gateway objects. + +```go +type RouteContext interface { + client.Object + + // GetRouteType returns the Kind of the Route object, HTTPRoute, + // TLSRoute, TCPRoute, UDPRoute etc. + GetRouteType() string + + // GetHostnames returns the hosts targeted by the Route object. + GetHostnames() []string + + // GetParentReferences returns the ParentReference of the Route object. + GetParentReferences() []v1beta1.ParentReference + + // GetRouteParentContext returns RouteParentContext by using the Route + // objects' ParentReference. + GetRouteParentContext(forParentRef v1beta1.ParentReference) *RouteParentContext +} +``` + +[message bus]: watching.md diff --git a/site/content/en/v0.6.0/design/goals.md b/site/content/en/v0.6.0/design/goals.md new file mode 100644 index 00000000000..fd38b2004c6 --- /dev/null +++ b/site/content/en/v0.6.0/design/goals.md @@ -0,0 +1,91 @@ +--- +title: "Goals" +weight: 1 +--- + +The high-level goal of the Envoy Gateway project is to attract more users to Envoy by lowering barriers to adoption +through expressive, extensible, role-oriented APIs that support a multitude of ingress and L7/L4 traffic routing +use cases; and provide a common foundation for vendors to build value-added products without having to re-engineer +fundamental interactions. + +## Objectives + +### Expressive API + +The Envoy Gateway project will expose a simple and expressive API, with defaults set for many capabilities. + +The API will be the Kubernetes-native [Gateway API][], plus Envoy-specific extensions and extension points. This +expressive and familiar API will make Envoy accessible to more users, especially application developers, and make Envoy +a stronger option for "getting started" as compared to other proxies. Application developers will use the API out of +the box without needing to understand in-depth concepts of Envoy Proxy or use OSS wrappers. The API will use familiar +nouns that [users](#personas) understand. + +The core full-featured Envoy xDS APIs will remain available for those who need more capability and for those who +add functionality on top of Envoy Gateway, such as commercial API gateway products. + +This expressive API will not be implemented by Envoy Proxy, but rather an officially supported translation layer +on top. + +### Batteries included + +Envoy Gateway will simplify how Envoy is deployed and managed, allowing application developers to focus on +delivering core business value. + +The project plans to include additional infrastructure components required by users to fulfill their Ingress and API +gateway needs: It will handle Envoy infrastructure provisioning (e.g. Kubernetes Service, Deployment, et cetera), and +possibly infrastructure provisioning of related sidecar services. It will include sensible defaults with the ability to +override. It will include channels for improving ops by exposing status through API conditions and Kubernetes status +sub-resources. + +Making an application accessible needs to be a trivial task for any developer. Similarly, infrastructure administrators +will enjoy a simplified management model that doesn't require extensive knowledge of the solution's architecture to +operate. + +### All environments + +Envoy Gateway will support running natively in Kubernetes environments as well as non-Kubernetes deployments. + +Initially, Kubernetes will receive the most focus, with the aim of having Envoy Gateway become the de facto +standard for Kubernetes ingress supporting the [Gateway API][]. +Additional goals include multi-cluster support and various runtime environments. + +### Extensibility + +Vendors will have the ability to provide value-added products built on the Envoy Gateway foundation. + +It will remain easy for end-users to leverage common Envoy Proxy extension points such as providing an implementation +for authentication methods and rate-limiting. For advanced use cases, users will have the ability to use the full power +of xDS. + +Since a general-purpose API cannot address all use cases, Envoy Gateway will provide additional extension points +for flexibility. As such, Envoy Gateway will form the base of vendor-provided managed control plane solutions, +allowing vendors to shift to a higher management plane layer. + +## Non-objectives + +### Cannibalize vendor models + +Vendors need to have the ability to drive commercial value, so the goal is not to cannibalize any existing vendor +monetization model, though some vendors may be affected by it. + +### Disrupt current Envoy usage patterns + +Envoy Gateway is purely an additive convenience layer and is not meant to disrupt any usage pattern of any user +with Envoy Proxy, xDS, or go-control-plane. + +## Personas + +_In order of priority_ + +### 1. Application developer + +The application developer spends the majority of their time developing business logic code. They require the ability to +manage access to their application. + +### 2. Infrastructure administrators + +The infrastructure administrators are responsible for the installation, maintenance, and operation of +API gateways appliances in infrastructure, such as CRDs, roles, service accounts, certificates, etc. +Infrastructure administrators support the needs of application developers by managing instances of Envoy Gateway. + +[Gateway API]: https://gateway-api.sigs.k8s.io/ diff --git a/site/content/en/v0.6.0/design/local-envoy-gateway.md b/site/content/en/v0.6.0/design/local-envoy-gateway.md new file mode 100644 index 00000000000..aad0dc5f6f2 --- /dev/null +++ b/site/content/en/v0.6.0/design/local-envoy-gateway.md @@ -0,0 +1,52 @@ +--- +title: "Running Envoy Gateway locally" +--- + +## Overview + +Today, Envoy Gateway runs only on Kubernetes. This is an ideal solution +when the applications are running in Kubernetes. +However there might be cases when the applications are running on the host which would +require Envoy Gateway to run locally. + +## Goals + +* Define an API to allow Envoy Gateway to retrieve configuration while running locally. +* Define an API to allow Envoy Gateway to deploy the managed Envoy Proxy fleet on the host +machine. + +## Non Goals + +* Support multiple ways to retrieve configuration while running locally. +* Support multiple ways to deploy the Envoy Proxy fleet locally on the host. + +## API + +* The `provider` field within the `EnvoyGateway` configuration only supports +`Kubernetes` today which provides two features - the ability to retrieve +resources from the Kubernetes API Server as well as deploy the managed +Envoy Proxy fleet on Kubernetes. +* This document proposes adding a new top level `provider` type called `Custom` +with two fields called `resource` and `infrastructure` to allow the user to configure +the sub providers for providing resource configuration and an infrastructure to deploy +the Envoy Proxy data plane in. +* A `File` resource provider will be introduced to enable retrieveing configuration locally +by reading from the configuration from a file. +* A `Host` infrastructure provider will be introduced to allow Envoy Gateway to spawn a +Envoy Proxy child process on the host. + +Here is an example configuration + +``` +provider: + type: Custom + custom: + resource: + type: File + file: + paths: + - "config.yaml" + infrastructure: + type: Host + host: {} +``` diff --git a/site/content/en/v0.6.0/design/metrics.md b/site/content/en/v0.6.0/design/metrics.md new file mode 100644 index 00000000000..c87b23ad4e5 --- /dev/null +++ b/site/content/en/v0.6.0/design/metrics.md @@ -0,0 +1,112 @@ +--- +title: "Observability: Metrics" +--- + +## Overview + +Envoy provide robust platform for metrics, Envoy support three different kinds of stats: counter, gauges, histograms. + +Envoy enables prometheus format output via the `/stats/prometheus` [admin endpoint](https://www.envoyproxy.io/docs/envoy/latest/operations/admin). + +Envoy support different kinds of sinks, but EG will only support [Open Telemetry sink](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/stat_sinks/open_telemetry/v3/open_telemetry.proto). + +Envoy Gateway leverages [Gateway API](https://gateway-api.sigs.k8s.io/) for configuring managed Envoy proxies. Gateway API defines core, extended, and implementation-specific API [support levels](https://gateway-api.sigs.k8s.io/concepts/conformance/?h=extended#2-support-levels) for implementers such as Envoy Gateway to expose features. Since metrics is not covered by `Core` or `Extended` APIs, EG should provide an easy to config metrics per `EnvoyProxy`. + +## Goals + +- Support expose metrics in prometheus way(reuse probe port). +- Support Open Telemetry stats sink. + +## Non-Goals + +- Support other stats sink. + +## Use-Cases + +- Enable prometheus metric by default +- Disable prometheus metric +- Push metrics via Open Telemetry Sink +- TODO: Customize histogram buckets of target metric +- TODO: Support stats matcher + +### ProxyMetric API Type + +```golang mdox-exec="sed '1,7d' api/v1alpha1/metric_types.go" +type ProxyMetrics struct { + // Prometheus defines the configuration for Admin endpoint `/stats/prometheus`. + Prometheus *PrometheusProvider `json:"prometheus,omitempty"` + // Sinks defines the metric sinks where metrics are sent to. + Sinks []MetricSink `json:"sinks,omitempty"` +} + +type MetricSinkType string + +const ( + MetricSinkTypeOpenTelemetry MetricSinkType = "OpenTelemetry" +) + +type MetricSink struct { + // Type defines the metric sink type. + // EG currently only supports OpenTelemetry. + // +kubebuilder:validation:Enum=OpenTelemetry + // +kubebuilder:default=OpenTelemetry + Type MetricSinkType `json:"type"` + // OpenTelemetry defines the configuration for OpenTelemetry sink. + // It's required if the sink type is OpenTelemetry. + OpenTelemetry *OpenTelemetrySink `json:"openTelemetry,omitempty"` +} + +type OpenTelemetrySink struct { + // Host define the service hostname. + Host string `json:"host"` + // Port defines the port the service is exposed on. + // + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=65535 + // +kubebuilder:default=4317 + Port int32 `json:"port,omitempty"` + + // TODO: add support for customizing OpenTelemetry sink in https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/stat_sinks/open_telemetry/v3/open_telemetry.proto#envoy-v3-api-msg-extensions-stat-sinks-open-telemetry-v3-sinkconfig +} + +type PrometheusProvider struct { + // Disable the Prometheus endpoint. + Disable bool `json:"disable,omitempty"` +} +``` + +### Example + +1. The following is an example to disable prometheus metric. + +```yaml mdox-exec="sed '1,12d' examples/kubernetes/metric/disable-prometheus.yaml" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: prometheus + namespace: envoy-gateway-system +spec: + telemetry: + metrics: + prometheus: + disable: true +``` + +1. The following is an example to send metric via Open Telemetry sink. + +```yaml mdox-exec="sed '1,12d' examples/kubernetes/metric/otel-sink.yaml" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: otel-sink + namespace: envoy-gateway-system +spec: + telemetry: + metrics: + sinks: + - type: OpenTelemetry + openTelemetry: + host: otel-collector.monitoring.svc.cluster.local + port: 4317 +``` diff --git a/site/content/en/v0.6.0/design/pprof.md b/site/content/en/v0.6.0/design/pprof.md new file mode 100644 index 00000000000..e2dd3082b26 --- /dev/null +++ b/site/content/en/v0.6.0/design/pprof.md @@ -0,0 +1,70 @@ +--- +title: "Debug support in Envoy Gateway" +--- + +## Overview + +Envoy Gateway exposes endpoints at `localhost:19000/debug/pprof` to run Golang profiles to aid in live debugging. + +The endpoints are equivalent to those found in the http/pprof package. `/debug/pprof/` returns an HTML page listing the available profiles. + +## Goals + +* Add admin server to Envoy Gateway control plane, separated with admin server. +* Add pprof support to Envoy Gateway control plane. +* Define an API to allow Envoy Gateway to custom admin server configuration. +* Define an API to allow Envoy Gateway to open envoy gateway config dump in logs. + +The following are the different types of profiles end-user can run: + +PROFILE | FUNCTION +-- | -- +/debug/pprof/allocs | Returns a sampling of all past memory allocations. +/debug/pprof/block | Returns stack traces of goroutines that led to blocking on synchronization primitives. +/debug/pprof/cmdline | Returns the command line that was invoked by the current program. +/debug/pprof/goroutine | Returns stack traces of all current goroutines. +/debug/pprof/heap | Returns a sampling of memory allocations of live objects. +/debug/pprof/mutex | Returns stack traces of goroutines holding contended mutexes. +/debug/pprof/profile | Returns pprof-formatted cpu profile. You can specify the duration using the seconds GET parameter. The default duration is 30 seconds. +/debug/pprof/symbol | Returns the program counters listed in the request. +/debug/pprof/threadcreate | Returns stack traces that led to creation of new OS threads. +/debug/pprof/trace | Returns the execution trace in binary form. You can specify the duration using the seconds GET parameter. The default duration is 1 second. + +## Non Goals + +## API + +* Add `admin` field in EnvoyGateway config. +* Add `address` field under `admin` field. +* Add `port` and `host` under `address` field. +* Add `enableDumpConfig` field under `admin field. +* Add `enablePprof` field under `admin field. + +Here is an example configuration to open admin server and enable Pprof: + +``` yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +gateway: + controllerName: "gateway.envoyproxy.io/gatewayclass-controller" +kind: EnvoyGateway +provider: + type: "Kubernetes" +admin: + enablePprof: true + address: + host: 127.0.0.1 + port: 19000 +``` + +Here is an example configuration to open envoy gateway config dump in logs: + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +gateway: + controllerName: "gateway.envoyproxy.io/gatewayclass-controller" +kind: EnvoyGateway +provider: + type: "Kubernetes" +admin: + enableDumpConfig: true +``` diff --git a/site/content/en/v0.6.0/design/rate-limit.md b/site/content/en/v0.6.0/design/rate-limit.md new file mode 100644 index 00000000000..e35d44c8239 --- /dev/null +++ b/site/content/en/v0.6.0/design/rate-limit.md @@ -0,0 +1,419 @@ +--- +title: "Rate Limit Design" +--- + +## Overview + +Rate limit is a feature that allows the user to limit the number of incoming requests +to a predefined value based on attributes within the traffic flow. + +Here are some reasons why a user may want to implements Rate limits + +* To prevent malicious activity such as DDoS attacks. +* To prevent applications and its resources (such as a database) from getting overloaded. +* To create API limits based on user entitlements. + +## Scope Types + +The rate limit type here describes the scope of rate limits. + +* Global - In this case, the rate limit is common across all the instances of Envoy proxies +where its applied i.e. if the data plane has 2 replicas of Envoy running, and the rate limit is +10 requests/second, this limit is common and will be hit if 5 requests pass through the first replica +and 5 requests pass through the second replica within the same second. + +* Local - In this case, the rate limits are specific to each instance/replica of Envoy running. +Note - This is not part of the initial design and will be added as a future enhancement. + +## Match Types + +### Rate limit a specific traffic flow + +* Here is an example of a ratelimit implemented by the application developer to limit a specific user +by matching on a custom `x-user-id` header with a value set to `one` + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: RateLimitFilter +metadata: + name: ratelimit-specific-user +spec: + type: Global + global: + rules: + - clientSelectors: + - headers: + - name: x-user-id + value: one + limit: + requests: 10 + unit: Hour +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: example +spec: + parentRefs: + - name: eg + hostnames: + - www.example.com + rules: + - matches: + - path: + type: PathPrefix + value: /foo + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: RateLimitFilter + name: ratelimit-specific-user + backendRefs: + - name: backend + port: 3000 +``` + +### Rate limit all traffic flows + +* Here is an example of a rate limit implemented by the application developer that limits the total requests made +to a specific route to safeguard health of internal application components. In this case, no specific `headers` match +is specified, and the rate limit is applied to all traffic flows accepted by this `HTTPRoute`. + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: RateLimitFilter +metadata: + name: ratelimit-all-requests +spec: + type: Global + global: + rules: + - limit: + requests: 1000 + unit: Second +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: example +spec: + parentRefs: + - name: eg + hostnames: + - www.example.com + rules: + - matches: + - path: + type: PathPrefix + value: /foo + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: RateLimitFilter + name: ratelimit-all-requests + backendRefs: + - name: backend + port: 3000 +``` + +### Rate limit per distinct value + +* Here is an example of a rate limit implemented by the application developer to limit any unique user +by matching on a custom `x-user-id` header. Here, user A (recognised from the traffic flow using the header +`x-user-id` and value `a`) will be rate limited at 10 requests/hour and so will user B +(recognised from the traffic flow using the header `x-user-id` and value `b`). + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: RateLimitFilter +metadata: + name: ratelimit-per-user +spec: + type: Global + global: + rules: + - clientSelectors: + - headers: + - type: Distinct + name: x-user-id + limit: + requests: 10 + unit: Hour +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: example +spec: + parentRefs: + - name: eg + hostnames: + - www.example.com + rules: + - matches: + - path: + type: PathPrefix + value: /foo + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: RateLimitFilter + name: ratelimit-per-user + backendRefs: + - name: backend + port: 3000 +``` + +### Rate limit per source IP + +* Here is an example of a rate limit implemented by the application developer that limits the total requests made +to a specific route by matching on source IP. In this case, requests from `x.x.x.x` will be rate limited at 10 requests/hour. + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: RateLimitFilter +metadata: + name: ratelimit-per-ip +spec: + type: Global + global: + rules: + - clientSelectors: + - sourceIP: x.x.x.x/32 + limit: + requests: 10 + unit: Hour +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: example +spec: + parentRefs: + - name: eg + hostnames: + - www.example.com + rules: + - matches: + - path: + type: PathPrefix + value: /foo + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: RateLimitFilter + name: ratelimit-per-user + backendRefs: + - name: backend + port: 3000 +``` + +### Rate limit based on JWT claims + +* Here is an example of rate limit implemented by the application developer that limits the total requests made +to a specific route by matching on the jwt claim. In this case, requests with jwt claim information of `{"name":"John Doe"}` +will be rate limited at 10 requests/hour. + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: jwt-example +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: eg + jwt: + providers: + - name: example + remoteJWKS: + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json + claimToHeaders: + - claim: name + header: custom-request-header +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: RateLimitFilter +metadata: + name: ratelimit-specific-user +spec: + type: Global + global: + rules: + - clientSelectors: + - headers: + - name: custom-request-header + value: John Doe + limit: + requests: 10 + unit: Hour +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: example +spec: + parentRefs: + - name: eg + hostnames: + - "www.example.com" + rules: + - backendRefs: + - group: "" + kind: Service + name: backend + port: 3000 + weight: 1 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: RateLimitFilter + name: ratelimit-specific-user + matches: + - path: + type: PathPrefix + value: /foo +``` + + +## Multiple RateLimitFilters, rules and clientSelectors +* Users can create multiple `RateLimitFilter`s and apply it to the same `HTTPRoute`. In such a case each +`RateLimitFilter` will be applied to the route and matched (and limited) in a mutually exclusive way, independent of each other. +* Rate limits are applied for each `RateLimitFilter` `rule` when ALL the conditions under `clientSelectors` hold true. + +Here's an example highlighting this - + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: RateLimitFilter +metadata: + name: ratelimit-all-safeguard-app +spec: + type: Global + global: + rules: + - limit: + requests: 100 + unit: Second +--- + +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: RateLimitFilter +metadata: + name: ratelimit-per-user +spec: + type: Global + global: + rules: + - clientSelectors: + - headers: + - type: Distinct + name: x-user-id + limit: + requests: 1000 + unit: Hour +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: example +spec: + parentRefs: + - name: eg + hostnames: + - www.example.com + rules: + - matches: + - path: + type: PathPrefix + value: /foo + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: RateLimitFilter + name: ratelimit-per-user + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: RateLimitFilter + name: ratelimit-all-safeguard-app + backendRefs: + - name: backend + port: 3000 +``` + +* The user has created two `RateLimitFilter`s and has attached it to a `HTTPRoute` - one(`ratelimit-all-safeguard-app`) to +ensure that the backend does not get overwhelmed with requests, any excess requests are rate limited irrespective of +the attributes within the traffic flow, and another(`ratelimit-per-user`) to rate limit each distinct user client +who can be differentiated using the `x-user-id` header, to ensure that each client does not make exessive requests to the backend. +* If user `baz` (identified with the header and value of `x-user-id: baz`) sends 90 requests within the first second, and +user `bar` sends 11 more requests during that same interval of 1 second, and user `bar` sends the 101th request within that second, +the rule defined in `ratelimit-all-safeguard-app` gets activated and Envoy Gateway will ratelimit the request sent by `bar` (and any other +request sent within that 1 second). After 1 second, the rate limit counter associated with the `ratelimit-all-safeguard-app` rule +is reset and again evaluated. +* If user `bar` also ends up sending 90 more requests within the hour, summing up `bar`'s total request count to 101, the rate limit rule +defined within `ratelimit-per-user` will get activated, and `bar`'s requests will be rate limited again until the hour interval ends. +* Within the same above hour, if `baz` sends 991 more requests, summing up `baz`'s total request count to 1001, the rate limit rule defined +within `ratelimit-per-user` will get activated for `baz`, and `baz`'s requests will also be rate limited until the hour interval ends. + +## Design Decisions + +* The initial design uses an Extension filter to apply the Rate Limit functionality on a specific [HTTPRoute][]. +This was preferred over the [PolicyAttachment][] extension mechanism, because it is unclear whether Rate Limit +will be required to be enforced or overridden by the platform administrator or not. +* The RateLimitFilter can only be applied as a filter to a [HTTPRouteRule][], applying it across all backends within a [HTTPRoute][] +and cannot be applied a filter within a [HTTPBackendRef][] for a specific backend. +* The [HTTPRoute][] API has a [matches][] field within each [rule][] to select a specific traffic flow to be routed to +the destination backend. The RateLimitFilter API that can be attached to an HTTPRoute via an [extensionRef][] filter, +also has a `clientSelectors` field within each `rule` to select attributes within the traffic flow to rate limit specific clients. +The two levels of selectors/matches allow for flexibility and aim to hold match information specific to its use, allowing the author/owner +of each configuration to be different. It also allows the `clientSelectors` field within the RateLimitFilter to be enhanced with other matchable +attribute such as [IP subnet][] in the future that are not relevant in the [HTTPRoute][] API. + +## Implementation Details + +### Global Rate limiting + +* [Global rate limiting][] in Envoy Proxy can be achieved using the following - + * [Actions][] can be configured per [xDS Route][]. + * If the match criteria defined within these actions is met for a specific HTTP Request, a set of key value pairs called [descriptors][] + defined within the above actions is sent to a remote [rate limit service][], whose configuration (such as the URL for the rate limit service) is defined + using a [rate limit filter][]. + * Based on information received by the rate limit service and its programmed configuration, a decision is computed, whether to rate limit + the HTTP Request or not, and is sent back to Envoy, which enforces this decision on the data plane. +* Envoy Gateway will leverage this Envoy Proxy feature by - + * Translating the user facing RateLimitFilter API into Rate limit [Actions][] as well as Rate limit service configuration to implement + the desired API intent. + * Envoy Gateway will use the existing [reference implementation][] of the rate limit service. + * The Infrastructure administrator will need to enable the rate limit service using new settings that will be defined in the [EnvoyGateway][] config API. + * The xDS IR will be enhanced to hold the user facing rate limit intent. + * The xDS Translator will be enhanced to translate the rate limit field within the xDS IR into Rate limit [Actions][] as well as instantiate the [rate limit filter][]. + * A new runner called `rate-limit` will be added that subscribes to the xDS IR messages and translates it into a new Rate Limit Infra IR which contains + the [rate limit service configuration][] as well as other information needed to deploy the rate limit service. + * The infrastructure service will be enhanced to subscribe to the Rate Limit Infra IR and deploy a provider specific rate limit service runnable entity. + * A Status field within the RateLimitFilter API will be added to reflect whether the specific configuration was programmed correctly in these multiple locations or not. + +[PolicyAttachment]: https://gateway-api.sigs.k8s.io/references/policy-attachment/ +[HTTPRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRoute +[HTTPRouteRule]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteRule +[HTTPBackendRef]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io%2fv1beta1.HTTPBackendRef +[matches]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteMatch +[rule]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteMatch +[extensionRef]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilterType +[IP subnet]: https://en.wikipedia.org/wiki/Subnetwork +[Actions]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-ratelimit-action +[descriptors]: https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/rate_limit_filter.html?highlight=descriptor#example-1 +[Global rate limiting]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/other_features/global_rate_limiting +[xDS Route]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-routeaction +[rate limit filter]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ratelimit/v3/rate_limit.proto#envoy-v3-api-msg-extensions-filters-http-ratelimit-v3-ratelimit +[rate limit service]: https://www.envoyproxy.io/docs/envoy/latest/configuration/other_features/rate_limit#config-rate-limit-service +[reference implementation]: https://github.com/envoyproxy/ratelimit +[EnvoyGateway]: https://github.com/envoyproxy/gateway/blob/main/api/config/v1alpha1/envoygateway_types.go +[rate limit service configuration]: https://github.com/envoyproxy/ratelimit#configuration diff --git a/site/content/en/v0.6.0/design/security-policy.md b/site/content/en/v0.6.0/design/security-policy.md new file mode 100644 index 00000000000..b7413b92ad0 --- /dev/null +++ b/site/content/en/v0.6.0/design/security-policy.md @@ -0,0 +1,115 @@ +--- +title: "SecurityPolicy " +--- + +## Overview + +This design document introduces the `SecurityPolicy` API allowing system administrators to configure +authentication and authorization policies to the traffic entering the gateway. + +## Goals +* Add an API definition to hold settings for configuring authentication and authorization rules +on the traffic entering the gateway. + +## Non Goals +* Define the API configuration fields in this API. + +## Implementation +`SecurityPolicy` is a [Policy Attachment][] type API that can be used to extend [Gateway API][] +to define authentication and authorization rules.. + +### Example +Here is an example highlighting how a user can configure this API. + +``` +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: GatewayClass +metadata: + name: eg +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: eg + namespace: default +spec: + gatewayClassName: eg + listeners: + - name: https + protocol: HTTPS + port: 443 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: backend + namespace: default +spec: + parentRefs: + - name: eg + hostnames: + - "www.example.com" + rules: + - backendRefs: + - group: "" + kind: Service + name: backend + port: 3000 + weight: 1 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: jwt-authn-policy + namespace: default +spec: + jwt: + providers: + - name: example + remoteJWKS: + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: eg + namespace: default +``` + +## Features / API Fields +Here is a list of features that can be included in this API +* JWT based authentication +* OIDC Authentication +* External Authorization +* Basic Auth +* API Key Auth +* CORS + +## Design Decisions +* This API will only support a single `targetRef` and can bind to a `Gateway` resource or a `HTTPRoute` or `GRPCRoute`. +* This API resource MUST be part of same namespace as the targetRef resource +* There can be only be ONE policy resource attached to a specific targetRef e.g. a `Listener` (section) within a `Gateway` +* If the policy targets a resource but cannot attach to it, this information should be reflected +in the Policy Status field using the `Conflicted=True` condition. +* If multiple polices target the same resource, the oldest resource (based on creation timestamp) will +attach to the Gateway Listeners, the others will not. +* If Policy A has a `targetRef` that includes a `sectionName` i.e. +it targets a specific Listener within a `Gateway` and Policy B has a `targetRef` that targets the same +entire Gateway then + * Policy A will be applied/attached to the specific Listener defined in the `targetRef.SectionName` + * Policy B will be applied to the remaining Listeners within the Gateway. Policy B will have an additional + status condition `Overridden=True`. +* A Policy targeting the most specific scope wins over a policy targeting a lesser specific scope. + i.e. A Policy targeting a xRoute (`HTTPRoute` or `GRPCRoute`) overrides a Policy targeting a Listener that is +this route's parentRef which in turn overrides a Policy targeting the Gateway the listener/section is a part of. + +## Alternatives +* The project can indefintely wait for these configuration parameters to be part of the [Gateway API]. + +[Policy Attachment]: https://gateway-api.sigs.k8s.io/references/policy-attachment +[Gateway API]: https://gateway-api.sigs.k8s.io/ diff --git a/site/content/en/v0.6.0/design/system-design.md b/site/content/en/v0.6.0/design/system-design.md new file mode 100644 index 00000000000..16123948ee7 --- /dev/null +++ b/site/content/en/v0.6.0/design/system-design.md @@ -0,0 +1,174 @@ +--- +title: "System Design" +weight: 2 +--- + +## Goals + +* Define the system components needed to satisfy the requirements of Envoy Gateway. + +## Non-Goals + +* Create a detailed design and interface specification for each system component. + +## Terminology + +* Control Plane- A collection of inter-related software components for providing application gateway and routing + functionality. The control plane is implemented by Envoy Gateway and provides services for managing the data plane. + These services are detailed in the [components](#components) section. +* Data Plane- Provides intelligent application-level traffic routing and is implemented as one or more Envoy proxies. + +## Architecture + +![Architecture](/img/architecture.png) + +## Configuration + +Envoy Gateway is configured statically at startup and the managed data plane is configured dynamically through +Kubernetes resources, primarily [Gateway API][gw_api] objects. + +### Static Configuration + +Static configuration is used to configure Envoy Gateway at startup, i.e. change the GatewayClass controllerName, +configure a Provider, etc. Currently, Envoy Gateway only supports configuration through a configuration file. If the +configuration file is not provided, Envoy Gateway starts-up with default configuration parameters. + +### Dynamic Configuration + +Dynamic configuration is based on the concept of a declaring the desired state of the data plane and using +reconciliation loops to drive the actual state toward the desired state. The desired state of the data plane is +defined as Kubernetes resources that provide the following services: + +* Infrastructure Management- Manage the data plane infrastructure, i.e. deploy, upgrade, etc. This configuration is + expressed through [GatewayClass][gc] and [Gateway][gw] resources. The `EnvoyProxy` [Custom Resource][cr] can be + referenced by `gatewayclass.spec.parametersRef` to modify data plane infrastructure default parameters, + e.g. expose Envoy network endpoints using a `ClusterIP` service instead of a `LoadBalancer` service. +* Traffic Routing- Define how to handle application-level requests to backend services. For example, route all HTTP + requests for "www.example.com" to a backend service running a web server. This configuration is expressed through + [HTTPRoute][hroute] and [TLSRoute][troute] resources that match, filter, and route traffic to a [backend][be]. + Although a backend can be any valid Kubernetes Group/Kind resource, Envoy Gateway only supports a [Service][svc] + reference. + +## Components + +Envoy Gateway is made up of several components that communicate in-process; how this communication happens is described +in the [Watching Components Design][wcd]. + +### Provider + +A Provider is an infrastructure component that Envoy Gateway calls to establish its runtime configuration, resolve +services, persist data, etc. As of v0.2, Kubernetes is the only implemented provider. A file provider is on the roadmap +via [Issue #37][]. Other providers can be added in the future as Envoy Gateway use cases are better understood. A +provider is configured at start up through Envoy Gateway's [static configuration](#static-configuration). + +#### Kubernetes Provider + +* Uses Kubernetes-style controllers to reconcile Kubernetes resources that comprise the + [dynamic configuration](#dynamic-configuration). +* Manages the data plane through Kubernetes API CRUD operations. +* Uses Kubernetes for Service discovery. +* Uses etcd (via Kubernetes API) to persist data. + +#### File Provider + +* Uses a file watcher to watch files in a directory that define the data plane configuration. +* Manages the data plane by calling internal APIs, e.g. `CreateDataPlane()`. +* Uses the host's DNS for Service discovery. +* If needed, the local filesystem is used to persist data. + +### Resource Watcher + +The Resource Watcher watches resources used to establish and maintain Envoy Gateway's dynamic configuration. The +mechanics for watching resources is provider-specific, e.g. informers, caches, etc. are used for the Kubernetes +provider. The Resource Watcher uses the configured provider for input and provides resources to the Resource Translator +as output. + +### Resource Translator + +The Resource Translator translates external resources, e.g. GatewayClass, from the Resource Watcher to the Intermediate +Representation (IR). It is responsible for: + +* Translating infrastructure-specific resources/fields from the Resource Watcher to the Infra IR. +* Translating proxy configuration resources/fields from the Resource Watcher to the xDS IR. + +__Note:__ The Resource Translator is implemented as the `Translator` API type in the `gatewayapi` package. + +### Intermediate Representation (IR) + +The Intermediate Representation defines internal data models that external resources are translated into. This allows +Envoy Gateway to be decoupled from the external resources used for dynamic configuration. The IR consists of an Infra IR +used as input for the Infra Manager and an xDS IR used as input for the xDS Translator. + +* Infra IR- Used as the internal definition of the managed data plane infrastructure. +* xDS IR- Used as the internal definition of the managed data plane xDS configuration. + +### xDS Translator + +The xDS Translator translates the xDS IR into xDS Resources that are consumed by the xDS server. + +### xDS Server + +The xDS Server is a xDS gRPC Server based on [Go Control Plane][go_cp]. Go Control Plane implements the Delta xDS Server +Protocol and is responsible for using xDS to configure the data plane. + +### Infra Manager + +The Infra Manager is a provider-specific component responsible for managing the following infrastructure: + +* Data Plane - Manages all the infrastructure required to run the managed Envoy proxies. For example, CRUD Deployment, + Service, etc. resources to run Envoy in a Kubernetes cluster. +* Auxiliary Control Planes - Optional infrastructure needed to implement application Gateway features that require + external integrations with the managed Envoy proxies. For example, [Global Rate Limiting][grl] requires provisioning + and configuring the [Envoy Rate Limit Service][rls] and the [Rate Limit filter][rlf]. Such features are exposed to + users through the [Custom Route Filters][crf] extension. + +The Infra Manager consumes the Infra IR as input to manage the data plane infrastructure. + +## Design Decisions + +* Envoy Gateway consumes one [GatewayClass][gc] by comparing its configured controller name with + `spec.controllerName` of a GatewayClass. If multiple GatewayClasses exist with the same `spec.controllerName`, Envoy + Gateway follows Gateway API [guidelines][gwapi_conflicts] to resolve the conflict. + `gatewayclass.spec.parametersRef` refers to the `EnvoyProxy` custom resource for configuring the managed proxy + infrastructure. If unspecified, default configuration parameters are used for the managed proxy infrastructure. +* Envoy Gateway manages [Gateways][gw] that reference its GatewayClass. + * A Gateway resource causes Envoy Gateway to provision managed Envoy proxy infrastructure. + * Envoy Gateway groups Listeners by Port and collapses each group of Listeners into a single Listener if the Listeners + in the group are compatible. Envoy Gateway considers Listeners to be compatible if all the following conditions are + met: + * Either each Listener within the group specifies the “HTTP” Protocol or each Listener within the group specifies + either the “HTTPS” or “TLS” Protocol. + * Each Listener within the group specifies a unique "Hostname". + * As a special case, one Listener within a group may omit "Hostname", in which case this Listener matches when no + other Listener matches. + * Envoy Gateway does __not__ merge listeners across multiple Gateways. +* Envoy Gateway follows Gateway API [guidelines][gwapi_conflicts] to resolve any conflicts. + * A Gateway `listener` corresponds to an Envoy proxy [Listener][listener]. +* An [HTTPRoute][hroute] resource corresponds to an Envoy proxy [Route][route]. + * Each [backendRef][be_ref] corresponds to an Envoy proxy [Cluster][cluster]. +* The goal is to make Envoy Gateway components extensible in the future. See the [roadmap][] for additional details. + +The draft for this document is [here][draft_design]. + +[gw_api]: https://gateway-api.sigs.k8s.io +[gc]: https://gateway-api.sigs.k8s.io/concepts/api-overview/#gatewayclass +[gw]: https://gateway-api.sigs.k8s.io/concepts/api-overview/#gateway +[hroute]: https://gateway-api.sigs.k8s.io/concepts/api-overview/#httproute +[troute]: https://gateway-api.sigs.k8s.io/concepts/api-overview/#tlsroute +[go_cp]: https://github.com/envoyproxy/go-control-plane +[grl]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/other_features/global_rate_limiting +[rls]: https://github.com/envoyproxy/ratelimit +[rlf]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ratelimit/v3/rate_limit.proto#envoy-v3-api-msg-extensions-filters-http-ratelimit-v3-ratelimit +[crf]: https://gateway-api.sigs.k8s.io/v1alpha2/api-types/httproute/#filters-optional +[gwapi_conflicts]: https://gateway-api.sigs.k8s.io/concepts/guidelines/#conflicts +[listener]: https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/listeners#config-listeners +[route]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-route +[be_ref]: https://gateway-api.sigs.k8s.io/v1alpha2/api-types/httproute/#backendrefs-optional +[cluster]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster +[draft_design]: https://docs.google.com/document/d/1riyTPPYuvNzIhBdrAX8dpfxTmcobWZDSYTTB5NeybuY/edit +[cr]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ +[be]: https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.BackendObjectReference +[svc]: https://kubernetes.io/docs/concepts/services-networking/service/ +[ wcd ]: ./watching.md +[Issue #37]: https://github.com/envoyproxy/gateway/issues/37 +[roadmap]: roadmap.md diff --git a/site/content/en/v0.6.0/design/tcp-udp-design.md b/site/content/en/v0.6.0/design/tcp-udp-design.md new file mode 100644 index 00000000000..f517e24feda --- /dev/null +++ b/site/content/en/v0.6.0/design/tcp-udp-design.md @@ -0,0 +1,49 @@ +--- +title: "TCP and UDP Proxy Design " +--- + +Even though most of the use cases for Envoy Gateway are at Layer-7, Envoy Gateway can also work at Layer-4 to proxy TCP +and UDP traffic. This document will explore the options we have when operating Envoy Gateway at Layer-4 and explain the +design decision. + +Envoy can work as a non-transparent proxy or a transparent proxy for both [TCP](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/other_features/ip_transparency#arch-overview-ip-transparency-original-src-listener) + and [UDP](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/udp/udp_proxy/v3/udp_proxy.proto#envoy-v3-api-msg-extensions-filters-udp-udp-proxy-v3-udpproxyconfig) +, so ideally, Envoy Gateway should also be able to work in these two modes: + +## Non-transparent Proxy Mode +For TCP, Envoy terminates the downstream connection, connects the upstream with its own IP address, and proxies the +TCP traffic from the downstream to the upstream. + +For UDP, Envoy receives UDP datagrams from the downstream, and uses its own IP address as the sender IP address when +proxying the UDP datagrams to the upstream. + +In this mode, the upstream will see Envoy's IP address and port. + +## Transparent Proxy Mode +For TCP, Envoy terminates the downstream connection, connects the upstream with the downstream IP address, and proxies +the TCP traffic from the downstream to the upstream. + +For UDP, Envoy receives UDP datagrams from the downstream, and uses the downstream IP address as the sender IP address +when proxying the UDP datagrams to the upstream. + +In this mode, the upstream will see the original downstream IP address and Envoy's mac address. + +Note: Even in transparent mode, the upstream can't see the port number of the downstream because Envoy doesn't forward +the port number. + +## The Implications of Transparent Proxy Mode + +### Escalated Privilege +Envoy needs to bind to the downstream IP when connecting to the upstream, which means Envoy requires escalated +CAP_NET_ADMIN privileges. This is often considered as a bad security practice and not allowed in some sensitive deployments. + +### Routing +The upstream can see the original source IP, but the original port number won't be passed, so the return +traffic from the upstream must be routed back to Envoy because only Envoy knows how to send the return traffic back +to the right port number of the downstream, which requires routing at the upstream side to be set up. +In a Kubernetes cluster, Envoy Gateway will have to carefully cooperate with CNI plugins to get the routing right. + +## The Design Decision (For Now) + +The implementation will only support proxying in non-transparent mode i.e. the backend will see the source IP and +port of the deployed Envoy instance instead of the client. diff --git a/site/content/en/v0.6.0/design/tracing.md b/site/content/en/v0.6.0/design/tracing.md new file mode 100644 index 00000000000..66f9454bc32 --- /dev/null +++ b/site/content/en/v0.6.0/design/tracing.md @@ -0,0 +1,161 @@ +--- +title: "Observability: Tracing" +--- + +## Overview + +Envoy supports extensible tracing to different sinks, Zipkin, OpenTelemetry etc. Overview of Envoy tracing can be found [here](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/observability/tracing). + +Envoy Gateway leverages [Gateway API](https://gateway-api.sigs.k8s.io/) for configuring managed Envoy proxies. Gateway API defines core, extended, and implementation-specific API [support levels](https://gateway-api.sigs.k8s.io/concepts/conformance/?h=extended#2-support-levels) for implementers such as Envoy Gateway to expose features. Since tracing is not covered by `Core` or `Extended` APIs, EG should provide an easy to config tracing per `EnvoyProxy`. + +Only OpenTelemetry sink can be configured currently, you can use [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) to export to other tracing backends. + +## Goals + +- Support send tracing to `OpenTelemetry` backend +- Support configurable sampling rate +- Support propagate tag from `Literal`, `Environment` and `Request Header` + +## Non-Goals + +- Support other tracing backend, e.g. `Zipkin`, `Jaeger` + +## Use-Cases + +- Configure accesslog for a `EnvoyProxy` to `File` + +### ProxyAccessLog API Type + +```golang mdox-exec="sed '1,7d' api/config/v1alpha1/tracing_types.go" +type ProxyTracing struct { + // SamplingRate controls the rate at which traffic will be + // selected for tracing if no prior sampling decision has been made. + // Defaults to 100, valid values [0-100]. 100 indicates 100% sampling. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=100 + // +kubebuilder:default=100 + // +optional + SamplingRate *uint32 `json:"samplingRate,omitempty"` + // CustomTags defines the custom tags to add to each span. + // If provider is kubernetes, pod name and namespace are added by default. + CustomTags map[string]CustomTag `json:"customTags,omitempty"` + // Provider defines the tracing provider. + // Only OpenTelemetry is supported currently. + Provider TracingProvider `json:"provider"` +} + +type TracingProviderType string + +const ( + TracingProviderTypeOpenTelemetry TracingProviderType = "OpenTelemetry" +) + +type TracingProvider struct { + // Type defines the tracing provider type. + // EG currently only supports OpenTelemetry. + // +kubebuilder:validation:Enum=OpenTelemetry + // +kubebuilder:default=OpenTelemetry + Type TracingProviderType `json:"type"` + // Host define the provider service hostname. + Host string `json:"host"` + // Port defines the port the provider service is exposed on. + // + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=4317 + Port int32 `json:"port,omitempty"` +} + +type CustomTagType string + +const ( + // CustomTagTypeLiteral adds hard-coded value to each span. + CustomTagTypeLiteral CustomTagType = "Literal" + // CustomTagTypeEnvironment adds value from environment variable to each span. + CustomTagTypeEnvironment CustomTagType = "Environment" + // CustomTagTypeRequestHeader adds value from request header to each span. + CustomTagTypeRequestHeader CustomTagType = "RequestHeader" +) + +type CustomTag struct { + // Type defines the type of custom tag. + // +kubebuilder:validation:Enum=Literal;Environment;RequestHeader + // +unionDiscriminator + // +kubebuilder:default=Literal + Type CustomTagType `json:"type"` + // Literal adds hard-coded value to each span. + // It's required when the type is "Literal". + Literal *LiteralCustomTag `json:"literal,omitempty"` + // Environment adds value from environment variable to each span. + // It's required when the type is "Environment". + Environment *EnvironmentCustomTag `json:"environment,omitempty"` + // RequestHeader adds value from request header to each span. + // It's required when the type is "RequestHeader". + RequestHeader *RequestHeaderCustomTag `json:"requestHeader,omitempty"` + + // TODO: add support for Metadata tags in the future. + // EG currently doesn't support metadata for route or cluster. +} + +// LiteralCustomTag adds hard-coded value to each span. +type LiteralCustomTag struct { + // Value defines the hard-coded value to add to each span. + Value string `json:"value"` +} + +// EnvironmentCustomTag adds value from environment variable to each span. +type EnvironmentCustomTag struct { + // Name defines the name of the environment variable which to extract the value from. + Name string `json:"name"` + // DefaultValue defines the default value to use if the environment variable is not set. + // +optional + DefaultValue *string `json:"defaultValue,omitempty"` +} + +// RequestHeaderCustomTag adds value from request header to each span. +type RequestHeaderCustomTag struct { + // Name defines the name of the request header which to extract the value from. + Name string `json:"name"` + // DefaultValue defines the default value to use if the request header is not set. + // +optional + DefaultValue *string `json:"defaultValue,omitempty"` +} +``` + +### Example + +1. The following is an example to config tracing. + +```yaml mdox-exec="sed '1,12d' examples/kubernetes/tracing/default.yaml" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: tracing + namespace: envoy-gateway-system +spec: + telemetry: + tracing: + # sample 100% of requests + samplingRate: 100 + provider: + host: otel-collector.monitoring.svc.cluster.local + port: 4317 + customTags: + # This is an example of using a literal as a tag value + key1: + type: Literal + literal: + value: "val1" + # This is an example of using an environment variable as a tag value + env1: + type: Environment + environment: + name: ENV1 + defaultValue: "-" + # This is an example of using a header value as a tag value + header1: + type: RequestHeader + requestHeader: + name: X-Header-1 + defaultValue: "-" +``` diff --git a/site/content/en/v0.6.0/design/watching.md b/site/content/en/v0.6.0/design/watching.md new file mode 100644 index 00000000000..5eabad7b3f9 --- /dev/null +++ b/site/content/en/v0.6.0/design/watching.md @@ -0,0 +1,120 @@ +--- +title: "Watching Components Design" +weight: 3 +--- + +Envoy Gateway is made up of several components that communicate in-process. Some of them (namely Providers) watch +external resources, and "publish" what they see for other components to consume; others watch what another publishes and +act on it (such as the resource translator watches what the providers publish, and then publishes its own results that +are watched by another component). Some of these internally published results are consumed by multiple components. + +To facilitate this communication use the [watchable][] library. The `watchable.Map` type is very similar to the +standard library's `sync.Map` type, but supports a `.Subscribe` (and `.SubscribeSubset`) method that promotes a pub/sub +pattern. + +## Pub + +Many of the things we communicate around are naturally named, either by a bare "name" string or by a "name"/"namespace" +tuple. And because `watchable.Map` is typed, it makes sense to have one map for each type of thing (very similar to if +we were using native Go `map`s). For example, a struct that might be written to by the Kubernetes provider, and read by +the IR translator: + + ```go + type ResourceTable struct { + // gateway classes are cluster-scoped; no namespace + GatewayClasses watchable.Map[string, *gwapiv1.GatewayClass] + + // gateways are namespace-scoped, so use a k8s.io/apimachinery/pkg/types.NamespacedName as the map key. + Gateways watchable.Map[types.NamespacedName, *gwapiv1.Gateway] + + HTTPRoutes watchable.Map[types.NamespacedName, *gwapiv1.HTTPRoute] + } + ``` + +The Kubernetes provider updates the table by calling `table.Thing.Store(name, val)` and `table.Thing.Delete(name)`; +updating a map key with a value that is deep-equal (usually `reflect.DeepEqual`, but you can implement your own `.Equal` +method) the current value is a no-op; it won't trigger an event for subscribers. This is handy so that the publisher +doesn't have as much state to keep track of; it doesn't need to know "did I already publish this thing", it can just +`.Store` its data and `watchable` will do the right thing. + +## Sub + +Meanwhile, the translator and other interested components subscribe to it with `table.Thing.Subscribe` (or +`table.Thing.SubscribeSubset` if they only care about a few "Thing"s). So the translator goroutine might look like: + + ```go + func(ctx context.Context) error { + for snapshot := range k8sTable.HTTPRoutes.Subscribe(ctx) { + fullState := irInput{ + GatewayClasses: k8sTable.GatewayClasses.LoadAll(), + Gateways: k8sTable.Gateways.LoadAll(), + HTTPRoutes: snapshot.State, + } + translate(irInput) + } + } + ``` + +Or, to watch multiple maps in the same loop: + + ```go + func worker(ctx context.Context) error { + classCh := k8sTable.GatewayClasses.Subscribe(ctx) + gwCh := k8sTable.Gateways.Subscribe(ctx) + routeCh := k8sTable.HTTPRoutes.Subscribe(ctx) + for ctx.Err() == nil { + var arg irInput + select { + case snapshot := <-classCh: + arg.GatewayClasses = snapshot.State + case snapshot := <-gwCh: + arg.Gateways = snapshot.State + case snapshot := <-routeCh: + arg.Routes = snapshot.State + } + if arg.GateWayClasses == nil { + arg.GatewayClasses = k8sTable.GateWayClasses.LoadAll() + } + if arg.GateWays == nil { + arg.Gateways = k8sTable.GateWays.LoadAll() + } + if arg.HTTPRoutes == nil { + arg.HTTPRoutes = k8sTable.HTTPRoutes.LoadAll() + } + translate(irInput) + } + } + ``` + +From the updates it gets from `.Subscribe`, it can get a full view of the map being subscribed to via `snapshot.State`; +but it must read the other maps explicitly. Like `sync.Map`, `watchable.Map`s are thread-safe; while `.Subscribe` is a +handy way to know when to run, `.Load` and friends can be used without subscribing. + +There can be any number of subscribers. For that matter, there can be any number of publishers `.Store`ing things, but +it's probably wise to just have one publisher for each map. + +The channel returned from `.Subscribe` **is immediately readable** with a snapshot of the map as it existed when +`.Subscribe` was called; and becomes readable again whenever `.Store` or `.Delete` mutates the map. If multiple +mutations happen between reads (or if mutations happen between `.Subscribe` and the first read), they are coalesced in +to one snapshot to be read; the `snapshot.State` is the most-recent full state, and `snapshot.Updates` is a listing of +each of the mutations that cause this snapshot to be different than the last-read one. This way subscribers don't need +to worry about a backlog accumulating if they can't keep up with the rate of changes from the publisher. + +If the map contains anything before `.Subscribe` is called, that very first read won't include `snapshot.Updates` +entries for those pre-existing items; if you are working with `snapshot.Update` instead of `snapshot.State`, then you +must add special handling for your first read. We have a utility function `./internal/message.HandleSubscription` to +help with this. + +## Other Notes + +The common pattern will likely be that the entrypoint that launches the goroutines for each component instantiates the +map, and passes them to the appropriate publishers and subscribers; same as if they were communicating via a dumb +`chan`. + +A limitation of `watchable.Map` is that in order to ensure safety between goroutines, it does require that value types +be deep-copiable; either by having a `DeepCopy` method, being a `proto.Message`, or by containing no reference types and +so can be deep-copied by naive assignment. Fortunately, we're using `controller-gen` anyway, and `controller-gen` can +generate `DeepCopy` methods for us: just stick a `// +k8s:deepcopy-gen=true` on the types that you want it to generate +methods for. + +[watchable]: https://pkg.go.dev/github.com/telepresenceio/watchable diff --git a/site/content/en/v0.6.0/install/_index.md b/site/content/en/v0.6.0/install/_index.md new file mode 100644 index 00000000000..b4c6f79c6fd --- /dev/null +++ b/site/content/en/v0.6.0/install/_index.md @@ -0,0 +1,5 @@ +--- +title: "Installation" +description: This section includes installation related contents of Envoy Gateway. +weight: 70 +--- diff --git a/site/content/en/v0.6.0/install/api.md b/site/content/en/v0.6.0/install/api.md new file mode 100644 index 00000000000..253d528bdfb --- /dev/null +++ b/site/content/en/v0.6.0/install/api.md @@ -0,0 +1,57 @@ ++++ +title = "gateway-helm" ++++ + + +![Version: v0.0.0-latest](https://img.shields.io/badge/Version-v0.0.0--latest-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square) + +The Helm chart for Envoy Gateway + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| envoy-gateway-steering-committee | | | +| envoy-gateway-maintainers | | | + +## Source Code + +* + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| certgen.job.annotations | object | `{}` | | +| certgen.job.ttlSecondsAfterFinished | int | `0` | | +| certgen.rbac.annotations | object | `{}` | | +| certgen.rbac.labels | object | `{}` | | +| config.envoyGateway.gateway.controllerName | string | `"gateway.envoyproxy.io/gatewayclass-controller"` | | +| config.envoyGateway.logging.level.default | string | `"info"` | | +| config.envoyGateway.provider.type | string | `"Kubernetes"` | | +| createNamespace | bool | `false` | | +| deployment.envoyGateway.cert.expiryDays | int | `365` | | +| deployment.envoyGateway.image.repository | string | `"${ImageRepository}"` | | +| deployment.envoyGateway.image.tag | string | `"${ImageTag}"` | | +| deployment.envoyGateway.imagePullPolicy | string | `"Always"` | | +| deployment.envoyGateway.resources.limits.cpu | string | `"500m"` | | +| deployment.envoyGateway.resources.limits.memory | string | `"1024Mi"` | | +| deployment.envoyGateway.resources.requests.cpu | string | `"100m"` | | +| deployment.envoyGateway.resources.requests.memory | string | `"256Mi"` | | +| deployment.pod.annotations | object | `{}` | | +| deployment.pod.labels | object | `{}` | | +| deployment.ports[0].name | string | `"grpc"` | | +| deployment.ports[0].port | int | `18000` | | +| deployment.ports[0].targetPort | int | `18000` | | +| deployment.ports[1].name | string | `"ratelimit"` | | +| deployment.ports[1].port | int | `18001` | | +| deployment.ports[1].targetPort | int | `18001` | | +| deployment.replicas | int | `1` | | +| envoyGatewayMetricsService.ports[0].name | string | `"http"` | | +| envoyGatewayMetricsService.ports[0].port | int | `19001` | | +| envoyGatewayMetricsService.ports[0].protocol | string | `"TCP"` | | +| envoyGatewayMetricsService.ports[0].targetPort | int | `19001` | | +| kubernetesClusterDomain | string | `"cluster.local"` | | + diff --git a/site/content/en/v0.6.0/install/install-egctl.md b/site/content/en/v0.6.0/install/install-egctl.md new file mode 100644 index 00000000000..637933bb290 --- /dev/null +++ b/site/content/en/v0.6.0/install/install-egctl.md @@ -0,0 +1,57 @@ +--- +title: "Install egctl" +weight: -80 +--- + +{{% alert title="What is egctl?" color="primary" %}} + +`egctl` is a command line tool to provide additional functionality for Envoy Gateway users. + +{{% /alert %}} + + +This guide shows how to install the egctl CLI. egctl can be installed either from source, or from pre-built binary releases. + +### From The Envoy Gateway Project + +The Envoy Gateway project provides two ways to fetch and install egctl. These are the official methods to get egctl releases. Installation through those methods can be found below the official methods. + +### From the Binary Releases + +Every [release](https://github.com/envoyproxy/gateway/releases) of egctl provides binary releases for a variety of OSes. These binary versions can be manually downloaded and installed. + +1. Download your [desired version](https://github.com/envoyproxy/gateway/releases) +2. Unpack it (tar -zxvf egctl_latest_linux_amd64.tar.gz) +3. Find the egctl binary in the unpacked directory, and move it to its desired destination (mv bin/linux/amd64/egctl /usr/local/bin/egctl) + +From there, you should be able to run: `egctl help`. + +### From Script + +`egctl` now has an installer script that will automatically grab the latest release version of egctl and install it locally. + +You can fetch that script, and then execute it locally. It's well documented so that you can read through it and understand what it is doing before you run it. + +```shell +curl -fsSL -o get-egctl.sh https://gateway.envoyproxy.io/get-egctl.sh + +chmod +x get-egctl.sh + +# get help info of the +bash get-egctl.sh --help + +# install the latest development version of egctl +bash VERSION=latest get-egctl.sh +``` + +Yes, you can just use the below command if you want to live on the edge. + +```shell +curl https://gateway.envoyproxy.io/get-egctl.sh | VERSION=latest bash +``` + +{{% alert title="Next Steps" color="warning" %}} + +You can refer to [User Guides](/latest/user/egctl) to more details about egctl. + +{{% /alert %}} diff --git a/site/content/en/v0.6.0/install/install-helm.md b/site/content/en/v0.6.0/install/install-helm.md new file mode 100644 index 00000000000..3f3c57e1db9 --- /dev/null +++ b/site/content/en/v0.6.0/install/install-helm.md @@ -0,0 +1,144 @@ ++++ +title = "Install with Helm" +weight = -100 ++++ + +[Helm](https://helm.sh) is a package manager for Kubernetes that automates the release and management of software on Kubernetes. + +Envoy Gateway can be installed via a Helm chart with a few simple steps, depending on if you are deploying for the first time, upgrading Envoy Gateway from an existing installation, or migrating from Envoy Gateway. + +## Before you begin + +{{% alert title="Compatibility Matrix" color="warning" %}} +Refer to the [Version Compatibility Matrix](/blog/2022/10/01/versions/) to learn more. +{{% /alert %}} + +The Envoy Gateway Helm chart is hosted by DockerHub. + +It is published at `oci://docker.io/envoyproxy/gateway-helm`. + +{{% alert title="Note" color="primary" %}} +We use `v0.0.0-latest` as the latest development version. + +You can visit [Envoy Gateway Helm Chart](https://hub.docker.com/r/envoyproxy/gateway-helm/tags) for more releases. +{{% /alert %}} + +## Install with Helm + +Envoy Gateway is typically deployed to Kubernetes from the command line. If you don't have Kubernetes, you should use `kind` to create one. + +{{% alert title="Developer Guide" color="primary" %}} +Refer to the [Developer Guide](/latest/contributions/develop) to learn more. +{{% /alert %}} + +Install the Gateway API CRDs and Envoy Gateway: + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespace +``` + +Wait for Envoy Gateway to become available: + +```shell +kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available +``` + +Install the GatewayClass, Gateway, HTTPRoute and example app: + +```shell +kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/latest/quickstart.yaml -n default +``` + +**Note**: [`quickstart.yaml`] defines that Envoy Gateway will listen for +traffic on port 80 on its globally-routable IP address, to make it easy to use +browsers to test Envoy Gateway. When Envoy Gateway sees that its Listener is +using a privileged port (<1024), it will map this internally to an +unprivileged port, so that Envoy Gateway doesn't need additional privileges. +It's important to be aware of this mapping, since you may need to take it into +consideration when debugging. + +[`quickstart.yaml`]: https://github.com/envoyproxy/gateway/releases/download/latest/quickstart.yaml + +## Helm chart customizations + +Some of the quick ways of using the helm install command for envoy gateway installation are below. + +### Increase the replicas + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespace --set deployment.replicas=2 +``` + +### Change the kubernetesClusterDomain name + +If you have installed your cluster with different domain name you can use below command. + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespace --set kubernetesClusterDomain= +``` + +**Note**: Above are some of the ways we can directly use for customization of our installation. But if you are looking for more complex changes [values.yaml](https://helm.sh/docs/chart_template_guide/values_files/) comes to rescue. + +### Using values.yaml file for complex installation + +```yaml +deployment: + envoyGateway: + resources: + limits: + cpu: 700m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + ports: + - name: grpc + port: 18005 + targetPort: 18000 + - name: ratelimit + port: 18006 + targetPort: 18001 + +config: + envoyGateway: + logging: + level: + default: debug +``` + +Here we have made three changes to our values.yaml file. Increase the resources limit for cpu to `700m`, changed the port for grpc to `18005` and for ratelimit to `18006` and also updated the logging level to `debug`. + +You can use the below command to install the envoy gateway using values.yaml file. + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespace -f values.yaml +``` + +{{% alert title="Helm Chart Values" color="primary" %}} +If you want to know all the available fields inside the values.yaml file, please see the [Helm Chart Values](../api). +{{% /alert %}} + +## Open Ports + +These are the ports used by Envoy Gateway and the managed Envoy Proxy. + +### Envoy Gateway + +| Envoy Gateway | Address | Port | Configurable | +|:----------------------:|:---------:|:------:| :------: | +| Xds EnvoyProxy Server | 0.0.0.0 | 18000 | No | +| Xds RateLimit Server | 0.0.0.0 | 18001 | No | +| Admin Server | 127.0.0.1 | 19000 | Yes | +| Metrics Server | 0.0.0.0 | 19001 | No | +| Health Check | 127.0.0.1 | 8081 | No | + +### EnvoyProxy + +| Envoy Proxy | Address | Port | +|:---------------------------------:|:-----------:| :-----: | +| Admin Server | 127.0.0.1 | 19000 | +| Heath Check | 0.0.0.0 | 19001 | + +{{% alert title="Next Steps" color="warning" %}} +Envoy Gateway should now be successfully installed and running, but in order to experience more abilities of Envoy Gateway, you can refer to [User Guides](../../user). +{{% /alert %}} diff --git a/site/content/en/v0.6.0/install/install-yaml.md b/site/content/en/v0.6.0/install/install-yaml.md new file mode 100644 index 00000000000..4b13529f000 --- /dev/null +++ b/site/content/en/v0.6.0/install/install-yaml.md @@ -0,0 +1,39 @@ ++++ +title = "Install with Kubernetes YAML" +weight = -99 ++++ + +In this guide, we'll walk you through installing Envoy Gateway in your Kubernetes cluster. + +The manual install process does not allow for as much control over configuration +as the [Helm install method](../install-helm), so if you need more control over your Envoy Gateway +installation, it is recommended that you use helm. + +## Before you begin + +Envoy Gateway is designed to run in Kubernetes for production. The most essential requirements are: + +* Kubernetes 1.25 or later +* The `kubectl` command-line tool + +{{% alert title="Compatibility Matrix" color="warning" %}} +Refer to the [Version Compatibility Matrix](/blog/2022/10/01/versions/) to learn more. +{{% /alert %}} + +## Install with YAML + +Envoy Gateway is typically deployed to Kubernetes from the command line. If you don't have Kubernetes, you should use `kind` to create one. + +{{% alert title="Developer Guide" color="primary" %}} +Refer to the [Developer Guide](/latest/contributions/develop) to learn more. +{{% /alert %}} + +1. In your terminal, run the following command: + + ```shell + kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/latest/install.yaml + ``` + +2. Next Steps + + Envoy Gateway should now be successfully installed and running, but in order to experience more abilities of Envoy Gateway, you can refer to [User Guides](/latest/user). diff --git a/site/content/en/v0.6.0/user/_index.md b/site/content/en/v0.6.0/user/_index.md new file mode 100644 index 00000000000..e413578a6ca --- /dev/null +++ b/site/content/en/v0.6.0/user/_index.md @@ -0,0 +1,5 @@ +--- +title: "User Guides" +weight: 2 +description: This section includes User Guides of Envoy Gateway. +--- diff --git a/site/content/en/v0.6.0/user/cors.md b/site/content/en/v0.6.0/user/cors.md new file mode 100644 index 00000000000..eaa92c874a9 --- /dev/null +++ b/site/content/en/v0.6.0/user/cors.md @@ -0,0 +1,122 @@ +--- +title: "CORS" +--- + +This guide provides instructions for configuring [Cross-Origin Resource Sharing (CORS)][cors] on Envoy Gateway. +CORS defines a way for client web applications that are loaded in one domain to interact with resources in a different +domain. + +Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure CORS. +This instantiated resource can be linked to a [Gateway][Gateway], [HTTPRoute][HTTPRoute] or [GRPCRoute][GRPCRoute] resource. + +## Prerequisites + +Follow the steps from the [Quickstart](../quickstart) guide to install Envoy Gateway and the example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +## Configuration + +The below example defines a SecurityPolicy that allows CORS requests from `www.foo.com`. + +```shell +cat < /dev/null +``` + +You should see the below response, indicating that the request from `http://www.foo.com` is allowed: + +```shell +< access-control-allow-origin: http://www.foo.com +< access-control-allow-methods: GET, POST +< access-control-allow-headers: x-header-1, x-header-2 +< access-control-max-age: 86400 +< access-control-expose-headers: x-header-3, x-header-4 +``` + +If you try to send a request from `http://www.bar.com`, you should see the below response: + +```shell +curl -H "Origin: http://www.bar.com" \ + -H "Host: www.example.com" \ + -H "Access-Control-Request-Method: GET" \ + -X OPTIONS -v -s \ + http://$GATEWAY_HOST \ + 1> /dev/null +``` + +You won't see any CORS headers in the response, indicating that the request from `http://www.bar.com` was not allowed. + +Note: CORS specification requires that the browsers to send a preflight request to the server to ask if it's allowed +to access the limited resource in another domains. The browsers are supposed to follow the response from the server to +determine whether to send the actual request or not. The CORS filter only response to the preflight requests according to +its configuration. It won't deny any requests. The browsers are responsible for enforcing the CORS policy. + +```shell + +## Clean-Up + +Follow the steps from the [Quickstart](../quickstart) guide to uninstall Envoy Gateway and the example manifest. + +Delete the SecurityPolicy: + +```shell +kubectl delete securitypolicy/cors-example +``` + +## Next Steps + +Checkout the [Developer Guide](../../contributions/develop/) to get involved in the project. + +[SecurityPolicy]: https://gateway.envoyproxy.io/v0.6.0/design/security-policy +[cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS +[Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway +[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute +[GRPCRoute]: https://gateway-api.sigs.k8s.io/api-types/grpcroute diff --git a/site/content/en/v0.6.0/user/customize-envoyproxy.md b/site/content/en/v0.6.0/user/customize-envoyproxy.md new file mode 100644 index 00000000000..e08e115ac7a --- /dev/null +++ b/site/content/en/v0.6.0/user/customize-envoyproxy.md @@ -0,0 +1,322 @@ +--- +title: "Customize EnvoyProxy" +--- + +Envoy Gateway provides an [EnvoyProxy][] CRD that can be linked to the ParametersRef +in GatewayClass, allowing cluster admins to customize the managed EnvoyProxy Deployment and +Service. To learn more about GatewayClass and ParametersRef, please refer to [Gateway API documentation][]. + +## Installation + +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +## Add GatewayClass ParametersRef + +First, you need to add ParametersRef in GatewayClass, and refer to EnvoyProxy Config: + +```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. + +## Customize EnvoyProxy Deployment Volumes or VolumeMounts + +You can customize the EnvoyProxy Deployment Volumes or VolumeMounts via EnvoyProxy Config like: + +```shell +cat < GET /get HTTP/1.1 +> Host: www.marketing.example.com +> User-Agent: curl/7.86.0 +> Accept: */* +> +Handling connection for 8888 +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< date: Thu, 20 Apr 2023 19:19:42 GMT +< content-length: 521 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +{ + "path": "/get", + "host": "www.marketing.example.com", + "method": "GET", + "proto": "HTTP/1.1", + "headers": { + "Accept": [ + "*/*" + ], + "User-Agent": [ + "curl/7.86.0" + ], + "X-Envoy-Expected-Rq-Timeout-Ms": [ + "15000" + ], + "X-Envoy-Internal": [ + "true" + ], + "X-Forwarded-For": [ + "10.1.0.157" + ], + "X-Forwarded-Proto": [ + "http" + ], + "X-Request-Id": [ + "c637977c-458a-48ae-92b3-f8c429849322" + ] + }, + "namespace": "marketing", + "ingress": "", + "service": "", + "pod": "backend-74888f465f-bcs8f" +* Connection #0 to host localhost left intact +``` + +* Lets deploy Envoy Gateway in the `product` namespace and also watch resources only in this namespace. + +``` +helm install --set config.envoyGateway.gateway.controllerName=gateway.envoyproxy.io/product-gatewayclass-controller --set config.envoyGateway.provider.kubernetes.watch.namespaces={product} eg-product oci://docker.io/envoyproxy/gateway-helm --version v0.6.0 -n product --create-namespace +``` + +Lets create a `GatewayClass` linked to the product team's Envoy Gateway controller, and as well other resources linked to it, so the `backend` application operated by this team can be exposed to external clients. + +```shell +cat < GET /get HTTP/1.1 +> Host: www.product.example.com +> User-Agent: curl/7.86.0 +> Accept: */* +> +Handling connection for 8889 +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< date: Thu, 20 Apr 2023 19:20:17 GMT +< content-length: 517 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +{ + "path": "/get", + "host": "www.product.example.com", + "method": "GET", + "proto": "HTTP/1.1", + "headers": { + "Accept": [ + "*/*" + ], + "User-Agent": [ + "curl/7.86.0" + ], + "X-Envoy-Expected-Rq-Timeout-Ms": [ + "15000" + ], + "X-Envoy-Internal": [ + "true" + ], + "X-Forwarded-For": [ + "10.1.0.156" + ], + "X-Forwarded-Proto": [ + "http" + ], + "X-Request-Id": [ + "39196453-2250-4331-b756-54003b2853c2" + ] + }, + "namespace": "product", + "ingress": "", + "service": "", + "pod": "backend-74888f465f-64fjs" +* Connection #0 to host localhost left intact +``` + +With the below command you can ensure that you are no able to access the marketing team's backend exposed using the `www.marketing.example.com` hostname +and the product team's data plane. + +```shell +curl --verbose --header "Host: www.marketing.example.com" http://localhost:8889/get +``` + +``` +* Trying 127.0.0.1:8889... +* Connected to localhost (127.0.0.1) port 8889 (#0) +> GET /get HTTP/1.1 +> Host: www.marketing.example.com +> User-Agent: curl/7.86.0 +> Accept: */* +> +Handling connection for 8889 +* Mark bundle as not supporting multiuse +< HTTP/1.1 404 Not Found +< date: Thu, 20 Apr 2023 19:22:13 GMT +< server: envoy +< content-length: 0 +< +* Connection #0 to host localhost left intact +``` diff --git a/site/content/en/v0.6.0/user/egctl.md b/site/content/en/v0.6.0/user/egctl.md new file mode 100644 index 00000000000..38daed73a4b --- /dev/null +++ b/site/content/en/v0.6.0/user/egctl.md @@ -0,0 +1,742 @@ +--- +title: "Use egctl" +--- + +`egctl` is a command line tool to provide additional functionality for Envoy Gateway users. + + + +## egctl experimental translate + +This subcommand allows users to translate from an input configuration type to an output configuration type. + +In the below example, we will translate the Kubernetes resources (including the Gateway API resources) into xDS +resources. + +```shell +cat <// + name: default/eg/http + operation: + op: add + path: "/default_filter_chain/filters/0/typed_config/local_reply_config" + value: + mappers: + - filter: + status_code_filter: + comparison: + op: EQ + value: + default_value: 404 + runtime_key: key_b + status_code: 406 + body: + inline_string: "could not find what you are looking for" +EOF +``` + +* Lets edit the HTTPRoute resource from the Quickstart to only match on paths with value `/get` + +``` +kubectl patch httproute backend --type=json --patch '[{ + "op": "add", + "path": "/spec/rules/0/matches/0/path/value", + "value": "/get", +}]' +``` + +* Lets test it out by specifying a path apart from `/get` + +``` +$ curl --header "Host: www.example.com" http://localhost:8888/find +Handling connection for 8888 +could not find what you are looking for +``` + +## Debugging + +### Runtime + +* The `Status` subresource should have information about the status of the resource. Make sure +`Accepted=True` and `Programmed=True` conditions are set to ensure that the policy has been +applied to Envoy Proxy. + +``` +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyPatchPolicy +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"gateway.envoyproxy.io/v1alpha1","kind":"EnvoyPatchPolicy","metadata":{"annotations":{},"name":"custom-response-patch-policy","namespace":"default"},"spec":{"jsonPatches":[{"name":"default/eg/http","operation":{"op":"add","path":"/default_filter_chain/filters/0/typed_config/local_reply_config","value":{"mappers":[{"body":{"inline_string":"could not find what you are looking for"},"filter":{"status_code_filter":{"comparison":{"op":"EQ","value":{"default_value":404}}}}}]}},"type":"type.googleapis.com/envoy.config.listener.v3.Listener"}],"priority":0,"targetRef":{"group":"gateway.networking.k8s.io","kind":"Gateway","name":"eg","namespace":"default"},"type":"JSONPatch"}} + creationTimestamp: "2023-07-31T21:47:53Z" + generation: 1 + name: custom-response-patch-policy + namespace: default + resourceVersion: "10265" + uid: a35bda6e-a0cc-46d7-a63a-cee765174bc3 +spec: + jsonPatches: + - name: default/eg/http + operation: + op: add + path: /default_filter_chain/filters/0/typed_config/local_reply_config + value: + mappers: + - body: + inline_string: could not find what you are looking for + filter: + status_code_filter: + comparison: + op: EQ + value: + default_value: 404 + type: type.googleapis.com/envoy.config.listener.v3.Listener + priority: 0 + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: eg + namespace: default + type: JSONPatch +status: + conditions: + - lastTransitionTime: "2023-07-31T21:48:19Z" + message: EnvoyPatchPolicy has been accepted. + observedGeneration: 1 + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: "2023-07-31T21:48:19Z" + message: successfully applied patches. + reason: Programmed + status: "True" + type: Programmed +``` + +### Offline + +* You can use [egctl x translate][] to validate the translated xds output. + +## Caveats + +This API will always be an unstable API and the same outcome cannot be garunteed +across versions for these reasons +* The Envoy Proxy API might deprecate and remove API fields +* Envoy Gateway might alter the xDS translation creating a different xDS output +such as changing the `name` field of resources. + +[EnvoyPatchPolicy]: https://gateway.envoyproxy.io/v0.6.0/api/extension_types.html#envoypatchpolicy +[EnvoyGateway]: https://gateway.envoyproxy.io/v0.6.0/api/config_types.html#envoygateway +[JSON Patch]: https://datatracker.ietf.org/doc/html/rfc6902 +[xDS]: https://www.envoyproxy.io/docs/envoy/v0.6.0/intro/arch_overview/operations/dynamic_configuration +[Local Reply Modification]: https://www.envoyproxy.io/docs/envoy/v0.6.0/configuration/http/http_conn_man/local_reply +[egctl x translate]: https://gateway.envoyproxy.io/v0.6.0/user/egctl.html#egctl-experimental-translate diff --git a/site/content/en/v0.6.0/user/gateway-address.md b/site/content/en/v0.6.0/user/gateway-address.md new file mode 100644 index 00000000000..bee4735c168 --- /dev/null +++ b/site/content/en/v0.6.0/user/gateway-address.md @@ -0,0 +1,69 @@ +--- +title: "Gateway Address" +--- + +The Gateway API provides an optional [Addresses][] field through which Envoy Gateway can set addresses for Envoy Proxy Service. The currently supported addresses are: + +- [External IPs](#External-IPs) + +## Installation + +Install Envoy Gateway: + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.6.0 -n envoy-gateway-system --create-namespace +``` + +Wait for Envoy Gateway to become available: + +```shell +kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available +``` + +## External IPs + +Using the addresses in `Gateway.Spec.Addresses` as the [External IPs][] of Envoy Proxy Service, this will __require__ the address to be of type `IPAddress`. + +Install the GatewayClass, Gateway from quickstart: + +```shell +kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v0.6.0/quickstart.yaml -n default +``` + +Set the address of the Gateway, the address settings here are for reference only: + +```shell +kubectl patch gateway eg --type=json --patch '[{ + "op": "add", + "path": "/spec/addresses", + "value": [{ + "type": "IPAddress", + "value": "1.2.3.4" + }] +}]' +``` + +Verify the Gateway status: + +```shell +kubectl get gateway + +NAME CLASS ADDRESS PROGRAMMED AGE +eg eg 1.2.3.4 True 14m +``` + +Verify the Envoy Proxy Service status: + +```shell +kubectl get service -n envoy-gateway-system + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +envoy-default-eg-64656661 LoadBalancer 10.96.236.219 1.2.3.4 80:31017/TCP 15m +envoy-gateway ClusterIP 10.96.192.76 18000/TCP 15m +envoy-gateway-metrics-service ClusterIP 10.96.124.73 8443/TCP 15m +``` + +__Note:__ If the `Gateway.Spec.Addresses` is explicitly set, it will be the only addresses that populates the Gateway status. + +[Addresses]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.GatewayAddress +[External IPs]: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips diff --git a/site/content/en/v0.6.0/user/gateway-api-metrics.md b/site/content/en/v0.6.0/user/gateway-api-metrics.md new file mode 100644 index 00000000000..d2f93f32da6 --- /dev/null +++ b/site/content/en/v0.6.0/user/gateway-api-metrics.md @@ -0,0 +1,54 @@ +--- +title: "Gateway API Metrics" +--- + +Resource metrics for Gateway API objects are available using the [Gateway API State Metrics](https://github.com/Kuadrant/gateway-api-state-metrics) project. +The project also provides example dashboard for visualising the metrics using Grafana, and example alerts using Prometheus & Alertmanager. + +## Prerequisites + +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +Run the following commands to install the metrics stack, with the Gateway API State Metrics configuration, on your kubernetes cluster: + +```shell +kubectl apply --server-side -f https://raw.githubusercontent.com/Kuadrant/gateway-api-state-metrics/main/config/examples/kube-prometheus/bundle_crd.yaml +kubectl apply -f https://raw.githubusercontent.com/Kuadrant/gateway-api-state-metrics/main/config/examples/kube-prometheus/bundle.yaml +``` + +## Metrics and Alerts + +To access the Prometheus UI, wait for the statefulset to be ready, then use the port-forward command: + +```shell +# This first command may fail if the statefulset has not been created yet. +# In that case, try again until you get a message like 'Waiting for 2 pods to be ready...' +# or 'statefulset rolling update complete 2 pods...' +kubectl -n monitoring rollout status --watch --timeout=5m statefulset/prometheus-k8s +kubectl -n monitoring port-forward service/prometheus-k8s 9090:9090 > /dev/null & +``` + +Navigate to [http://localhost:9090](http://localhost:9090). +Metrics can be queried from the 'Graph' tab e.g. `gatewayapi_gateway_created` +See the [Gateway API State Metrics README](https://github.com/Kuadrant/gateway-api-state-metrics/tree/main#metrics) for the full list of Gateway API metrics available. + +Alerts can be see in the 'Alerts' tab. +Gateway API specific alerts will be grouped under the 'gateway-api.rules' heading. + +***Note:*** Alerts are defined in a PrometheusRules custom resource in the 'monitoring' namespace. You can modify the alert rules by updating this resource. + +## Dashboards + +To view the dashboards in Grafana, wait for the deployment to be ready, then use the port-forward command: + +```shell +kubectl -n monitoring wait --timeout=5m deployment/grafana --for=condition=Available +kubectl -n monitoring port-forward service/grafana 3000:3000 > /dev/null & +``` + +Navigate to [http://localhost:3000](http://localhost:3000) and sign in with admin/admin. +The Gateway API State dashboards will be available in the 'Default' folder and tagged with 'gateway-api'. +See the [Gateway API State Metrics README](https://github.com/Kuadrant/gateway-api-state-metrics/tree/main#dashboards) for further information on available dashboards. + +***Note:*** Dashboards are loaded from configmaps. You can modify the dashboards in the Grafana UI, however you will need to export them from the UI and update the json in the configmaps to persist changes. diff --git a/site/content/en/v0.6.0/user/gatewayapi-support.md b/site/content/en/v0.6.0/user/gatewayapi-support.md new file mode 100644 index 00000000000..d9265fd139d --- /dev/null +++ b/site/content/en/v0.6.0/user/gatewayapi-support.md @@ -0,0 +1,118 @@ +--- +title: "Gateway API Support" +--- + +As mentioned in the [system design][] document, Envoy Gateway's managed data plane is configured dynamically through +Kubernetes resources, primarily [Gateway API][] objects. Envoy Gateway supports configuration using the following Gateway API resources. + +## GatewayClass + +A [GatewayClass][] represents a "class" of gateways, i.e. which Gateways should be managed by Envoy Gateway. +Envoy Gateway supports managing __a single__ GatewayClass resource that matches its configured `controllerName` and +follows Gateway API guidelines for [resolving conflicts][] when multiple GatewayClasses exist with a matching +`controllerName`. + +__Note:__ If specifying GatewayClass [parameters reference][], it must refer to an [EnvoyProxy][] resource. + +## Gateway + +When a [Gateway][] resource is created that references the managed GatewayClass, Envoy Gateway will create and manage a +new Envoy Proxy deployment. Gateway API resources that reference this Gateway will configure this managed Envoy Proxy +deployment. + +## HTTPRoute + +An [HTTPRoute][] configures routing of HTTP traffic through one or more Gateways. The following HTTPRoute filters are +supported by Envoy Gateway: + +- `requestHeaderModifier`: [RequestHeaderModifiers](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilter) + can be used to modify or add request headers before the request is proxied to its destination. +- `responseHeaderModifier`: [ResponseHeaderModifiers](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilter) + can be used to modify or add response headers before the response is sent back to the client. +- `requestMirror`: [RequestMirrors](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilter) + configure destinations where the requests should also be mirrored to. Responses to mirrored requests will be ignored. +- `requestRedirect`: [RequestRedirects](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilter) + configure policied for how requests that match the HTTPRoute should be modified and then redirected. +- `urlRewrite`: [UrlRewrites](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilter) + allow for modification of the request's hostname and path before it is proxied to its destination. +- `extensionRef`: [ExtensionRefs][] are used by Envoy Gateway to implement extended filters. Currently, Envoy Gateway + supports rate limiting and request authentication filters. For more information about these filters, refer to the + [rate limiting][] and [request authentication][] documentation. + +__Notes:__ +- The only [BackendRef][] kind supported by Envoy Gateway is a [Service][]. Routing traffic to other destinations such + as arbitrary URLs is not possible. +- The `filters` field within [HTTPBackendRef][] is not supported. + +## TCPRoute + +A [TCPRoute][] configures routing of raw TCP traffic through one or more Gateways. Traffic can be forwarded to the +desired BackendRefs based on a TCP port number. + +__Note:__ A TCPRoute only supports proxying in non-transparent mode, i.e. the backend will see the source IP and port of +the Envoy Proxy instance instead of the client. + +## UDPRoute + +A [UDPRoute][] configures routing of raw UDP traffic through one or more Gateways. Traffic can be forwarded to the +desired BackendRefs based on a UDP port number. + +__Note:__ Similar to TCPRoutes, UDPRoutes only support proxying in non-transparent mode i.e. the backend will see the +source IP and port of the Envoy Proxy instance instead of the client. + +## GRPCRoute + +A [GRPCRoute][] configures routing of [gRPC][] requests through one or more Gateways. They offer request matching by +hostname, gRPC service, gRPC method, or HTTP/2 Header. Envoy Gateway supports the following filters on GRPCRoutes to +provide additional traffic processing: + +- `requestHeaderModifier`: [RequestHeaderModifiers](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRouteFilter) + can be used to modify or add request headers before the request is proxied to its destination. +- `responseHeaderModifier`: [ResponseHeaderModifiers](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRouteFilter) + can be used to modify or add response headers before the response is sent back to the client. +- `requestMirror`: [RequestMirrors](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRouteFilter) + configure destinations where the requests should also be mirrored to. Responses to mirrored requests will be ignored. + +__Notes:__ +- The only [BackendRef][grpc-filter] kind supported by Envoy Gateway is a [Service][]. Routing traffic to other + destinations such as arbitrary URLs is not currently possible. +- The `filters` field within [HTTPBackendRef][] is not supported. + +## TLSRoute + +A [TLSRoute][] configures routing of TCP traffic through one or more Gateways. However, unlike TCPRoutes, TLSRoutes +can match against TLS-specific metadata. + +## ReferenceGrant + +A [ReferenceGrant][] is used to allow a resource to reference another resource in a different namespace. Normally an +HTTPRoute created in namespace `foo` is not allowed to reference a Service in namespace `bar`. A ReferenceGrant permits +these types of cross-namespace references. Envoy Gateway supports the following ReferenceGrant use-cases: + +- Allowing an HTTPRoute, GRPCRoute, TLSRoute, UDPRoute, or TCPRoute to reference a Service in a different namespace. +- Allowing an HTTPRoute's `requestMirror` filter to include a BackendRef that references a Service in a different + namespace. +- Allowing a Gateway's [SecretObjectReference][] to reference a secret in a different namespace. + +[system design]: https://gateway.envoyproxy.io/v0.6.0/design/system-design.html +[Gateway API]: https://gateway-api.sigs.k8s.io/ +[GatewayClass]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.GatewayClass +[parameters reference]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.ParametersReference +[Gateway]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.Gateway +[HTTPRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRoute +[Service]: https://kubernetes.io/docs/concepts/services-networking/service/ +[BackendRef]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.BackendRef +[HTTPBackendRef]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPBackendRef +[TCPRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute +[UDPRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.UDPRoute +[GRPCRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute +[gRPC]: https://grpc.io/ +[TLSRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TLSRoute +[ReferenceGrant]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io%2fv1beta1.ReferenceGrant +[SecretObjectReference]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.SecretObjectReference +[rate limiting]: https://gateway.envoyproxy.io/v0.6.0/user/rate-limit.html +[request authentication]: https://gateway.envoyproxy.io/v0.6.0/user/authn.html +[EnvoyProxy]: https://gateway.envoyproxy.io/v0.6.0/api/config_types.html#envoyproxy +[resolving conflicts]: https://gateway-api.sigs.k8s.io/concepts/guidelines/?h=conflict#conflicts +[ExtensionRefs]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilterType +[grpc-filter]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRouteFilter diff --git a/site/content/en/v0.6.0/user/grafana-integration.md b/site/content/en/v0.6.0/user/grafana-integration.md new file mode 100644 index 00000000000..07ec52b7257 --- /dev/null +++ b/site/content/en/v0.6.0/user/grafana-integration.md @@ -0,0 +1,65 @@ +--- +title: "Visualising metrics using Grafana" +--- + +Envoy Gateway provides support for exposing Envoy Proxy metrics to a Prometheus instance. +This guide shows you how to visualise the metrics exposed to prometheus using grafana. + +## Prerequisites + +Follow the steps from the [Quickstart Guide](../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 from the [Proxy Observability](proxy-observability.md#Metrics) to enable prometheus metrics. + +[Prometheus](https://prometheus.io) is used to scrape metrics from the Envoy Proxy instances. Install Prometheus: + +```shell +helm repo add prometheus-community https://prometheus-community.github.io/helm-charts +helm repo update +helm upgrade --install prometheus prometheus-community/prometheus -n monitoring --create-namespace +``` + +[Grafana](https://grafana.com/grafana/) is used to visualise the metrics exposed by the envoy proxy instances. +Install Grafana: + +```shell +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +helm upgrade --install grafana grafana/grafana -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/grafana/helm-values.yaml -n monitoring --create-namespace +``` + +Expose endpoints: + +```shell +GRAFANA_IP=$(kubectl get svc grafana -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +``` + +## Connecting Grafana with Prometheus datasource + +To visualise metrics from Prometheus, we have to connect Grafana with Prometheus. If you installed Grafana from the command +from prerequisites sections, the prometheus datasource should be already configured. + +You can also add the data source manually by following the instructions from [Grafana Docs](https://grafana.com/docs/grafana/v0.6.0/datasources/prometheus/configure-prometheus-data-source/). + +## Accessing Grafana + +You can access the Grafana instance by visiting `http://{GRAFANA_IP}`, derived in prerequisites. + +To log in to Grafana, use the credentials `admin:admin`. + +Envoy Gateway has examples of dashboard for you to get started: + +### [Envoy Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-global.json) + +![Envoy Global](/img/envoy-global-dashboard.png) + +### [Envoy Clusters](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-clusters.json) + +![Envoy Clusters](/img/envoy-clusters-dashboard.png) + +### [Envoy Pod Resources](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-pod-resource.json) + +![Envoy Pod Resources](/img/envoy-pod-resources-dashboard.png) + +You can load the above dashboards in your Grafana to get started. Please refer to Grafana docs for [importing dashboards](https://grafana.com/docs/grafana/v0.6.0/dashboards/manage-dashboards/#import-a-dashboard). diff --git a/site/content/en/v0.6.0/user/grpc-routing.md b/site/content/en/v0.6.0/user/grpc-routing.md new file mode 100644 index 00000000000..e365386036e --- /dev/null +++ b/site/content/en/v0.6.0/user/grpc-routing.md @@ -0,0 +1,204 @@ +--- +title: "GRPC Routing" +--- + +The [GRPCRoute][] resource allows users to configure gRPC routing by matching HTTP/2 traffic and forwarding it to backend gRPC servers. +To learn more about gRPC routing, refer to the [Gateway API documentation][]. + +## Prerequisites + +Install Envoy Gateway: + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.6.0 -n envoy-gateway-system --create-namespace +``` + +Wait for Envoy Gateway to become available: + +```shell +kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available +``` + +## Installation + +Install the gRPC routing example resources: + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/grpc-routing.yaml +``` + +The manifest installs a [GatewayClass][], [Gateway][], a Deployment, a Service, and a GRPCRoute resource. +The GatewayClass is a cluster-scoped resource that represents a class of Gateways that can be instantiated. + +__Note:__ Envoy Gateway is configured by default to manage a GatewayClass with +`controllerName: gateway.envoyproxy.io/gatewayclass-controller`. + +## Verification + +Check the status of the GatewayClass: + +```shell +kubectl get gc --selector=example=grpc-routing +``` + +The status should reflect "Accepted=True", indicating Envoy Gateway is managing the GatewayClass. + +A Gateway represents configuration of infrastructure. When a Gateway is created, [Envoy proxy][] infrastructure is +provisioned or configured by Envoy Gateway. The `gatewayClassName` defines the name of a GatewayClass used by this +Gateway. Check the status of the Gateway: + +```shell +kubectl get gateways --selector=example=grpc-routing +``` + +The status should reflect "Ready=True", indicating the Envoy proxy infrastructure has been provisioned. The status also +provides the address of the Gateway. This address is used later in the guide to test connectivity to proxied backend +services. + +Check the status of the GRPCRoute: + +```shell +kubectl get grpcroutes --selector=example=grpc-routing -o yaml +``` + +The status for the GRPCRoute should surface "Accepted=True" and a `parentRef` that references the example Gateway. +The `example-route` matches any traffic for "grpc-example.com" and forwards it to the "yages" Service. + +## Testing the Configuration + +Before testing GRPC routing to the `yages` backend, get the Gateway's address. + +```shell +export GATEWAY_HOST=$(kubectl get gateway/example-gateway -o jsonpath='{.status.addresses[0].value}') +``` + +Test GRPC routing to the `yages` backend using the [grpcurl][] command. + +```shell +grpcurl -plaintext -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping +``` + +You should see the below response + +```shell +{ + "text": "pong" +} +``` + +Envoy Gateway also supports [gRPC-Web][] requests for this configuration. The below `curl` command can be used to send a grpc-Web request with over HTTP/2. You should receive the same response seen in the previous command. + +The data in the body `AAAAAAA=` is a base64 encoded representation of an empty message (data length 0) that the Ping RPC accepts. + +```shell +curl --http2-prior-knowledge -s ${GATEWAY_HOST}:80/yages.Echo/Ping -H 'Host: grpc-example.com' -H 'Content-Type: application/grpc-web-text' -H 'Accept: application/grpc-web-text' -XPOST -d'AAAAAAA=' | base64 -d +``` + +## GRPCRoute Match +The `matches` field can be used to restrict the route to a specific set of requests based on GRPC's service and/or method names. +It supports two match types: `Exact` and `RegularExpression`. + +### Exact + +`Exact` match is the default match type. + +The following example shows how to match a request based on the service and method names for `grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo`, +as well as a match for all services with a method name `Ping` which matches `yages.Echo/Ping` in our deployment. + +```shell +cat < GET /get HTTP/1.1 +> Host: headers.example +> User-Agent: curl/7.81.0 +> Accept: */* +> add-header: something +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +... + "headers": { + "Accept": [ + "*/*" + ], + "Add-Header": [ + "something", + "foo" + ], +... +``` + +## Setting Request Headers + +Setting headers is similar to adding headers. If the request does not have the header configured by the filter, then it +will be added, but unlike [adding request headers](#adding-request-headers) which will append the value of the header if +the request already contains it, setting a header will cause the value to be replaced by the value configured in the +filter. + +```shell +cat < GET /get HTTP/1.1 +> Host: headers.example +> User-Agent: curl/7.81.0 +> Accept: */* +> add-header: something +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< + "headers": { + "Accept": [ + "*/*" + ], + "Set-Header": [ + "foo" + ], +... +``` + +## Removing Request Headers + +Headers can be removed from a request by simply supplying a list of header names. + +Setting headers is similar to adding headers. If the request does not have the header configured by the filter, then it +will be added, but unlike [adding request headers](#adding-request-headers) which will append the value of the header if +the request already contains it, setting a header will cause the value to be replaced by the value configured in the +filter. + +```shell +cat < GET /get HTTP/1.1 +> Host: headers.example +> User-Agent: curl/7.81.0 +> Accept: */* +> add-header: something +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< + + "headers": { + "Accept": [ + "*/*" + ], + "Add-Header": [ + "something" + ], +... +``` + +## Combining Filters + +Headers can be added/set/removed in a single filter on the same HTTPRoute and they will all perform as expected + +```shell +cat < GET /get HTTP/1.1 +> Host: backends.example +> User-Agent: curl/7.81.0 +> Accept: */* +> add-header: something +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +... + "namespace": "default", + "ingress": "", + "service": "", + "pod": "backend-79665566f5-s589f" +... +``` + +Check the logs of the pods and you will see that the original deployment and the new deployment each got a request: + +```shell +$ kubectl logs deploy/backend && kubectl logs deploy/backend-2 +... +Starting server, listening on port 3000 (http) +Echoing back request made to /get to client (10.42.0.10:41566) +Starting server, listening on port 3000 (http) +Echoing back request made to /get to client (10.42.0.10:45096) +``` + +## Multiple BackendRefs + +When an `HTTPRoute` has multiple `backendRefs` and an `HTTPRequestMirrorFilter`, traffic splitting will still behave the same as it normally would for the main `backendRefs` while the `backendRef` of the `HTTPRequestMirrorFilter` will continue receiving mirrored copies of the incoming requests. + +```shell +cat < GET /get HTTP/1.1 +> Host: headers.example +> User-Agent: curl/7.81.0 +> Accept: */* +> X-Echo-Set-Header: X-Foo: value1 +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< x-foo: value1 +< add-header: foo +< +... + "headers": { + "Accept": [ + "*/*" + ], + "X-Echo-Set-Header": [ + "X-Foo: value1" + ] +... +``` + +## Setting Response Headers + +Setting headers is similar to adding headers. If the response does not have the header configured by the filter, then it +will be added, but unlike [adding response headers](#adding-response-headers) which will append the value of the header +if the response already contains it, setting a header will cause the value to be replaced by the value configured in the +filter. + +```shell +cat < GET /get HTTP/1.1 +> Host: headers.example +> User-Agent: curl/7.81.0 +> Accept: */* +> X-Echo-Set-Header: set-header: value1 +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< set-header: foo +< + "headers": { + "Accept": [ + "*/*" + ], + "X-Echo-Set-Header": [ + "set-header": value1" + ] +... +``` + +## Removing Response Headers + +Headers can be removed from a response by simply supplying a list of header names. + +Setting headers is similar to adding headers. If the response does not have the header configured by the filter, then it +will be added, but unlike [adding response headers](#adding-response-headers) which will append the value of the header +if the response already contains it, setting a header will cause the value to be replaced by the value configured in the +filter. + +```shell +cat < GET /get HTTP/1.1 +> Host: headers.example +> User-Agent: curl/7.81.0 +> Accept: */* +> X-Echo-Set-Header: remove-header: value1 +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< + + "headers": { + "Accept": [ + "*/*" + ], + "X-Echo-Set-Header": [ + "remove-header": value1" + ] +... +``` + +## Combining Filters + +Headers can be added/set/removed in a single filter on the same HTTPRoute and they will all perform as expected + +```shell +cat < GET /get HTTP/1.1 +> Host: backends.example +> User-Agent: curl/7.81.0 +> Accept: */* +> add-header: something +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +... + "namespace": "default", + "ingress": "", + "service": "", + "pod": "backend-79665566f5-s589f" +... +``` + +## Multiple backendRefs + +If multiple backendRefs are configured, then traffic will be split between the backendRefs equally unless a weight is +configured. + +First, create a second instance of the example app from the quickstart: + +```shell +cat < GET /get HTTP/1.1 +> Host: backends.example +> User-Agent: curl/7.81.0 +> Accept: */* +> add-header: something +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +... + "namespace": "default", + "ingress": "", + "service": "", + "pod": "backend-75bcd4c969-lsxpz" +... +``` + +## Weighted backendRefs + +If multiple backendRefs are configured and an un-even traffic split between the backends is desired, then the `weight` +field can be used to control the weight of requests to each backend. If weight is not configured for a backendRef it is +assumed to be `1`. + +The [weight field in a backendRef][backendRefs] controls the distribution of the traffic split. The proportion of +requests to a single backendRef is calculated by dividing its `weight` by the sum of all backendRef weights in the +HTTPRoute. The weight is not a percentage and the sum of all weights does not need to add up to 100. + +The HTTPRoute below will configure the gateway to send 80% of the traffic to the backend service, and 20% to the +backend-2 service. + +```shell +cat < GET /get HTTP/1.1 +> Host: backends.example +> User-Agent: curl/7.81.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 500 Internal Server Error +< server: envoy +< content-length: 0 +< +``` + +[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute/ +[backendRefs]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.BackendRef diff --git a/site/content/en/v0.6.0/user/http-urlrewrite.md b/site/content/en/v0.6.0/user/http-urlrewrite.md new file mode 100644 index 00000000000..60c0bebeeef --- /dev/null +++ b/site/content/en/v0.6.0/user/http-urlrewrite.md @@ -0,0 +1,297 @@ +--- +title: "HTTP URL Rewrite" +--- + +[HTTPURLRewriteFilter][] defines a filter that modifies a request during forwarding. At most one of these filters may be +used on a Route rule. This MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter. + +## Prerequisites + +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +## Rewrite URL Prefix Path + +You can configure to rewrite the prefix in the url like below. In this example, any curls to +`http://${GATEWAY_HOST}/get/xxx` will be rewritten to `http://${GATEWAY_HOST}/replace/xxx`. + +```shell +cat < GET /get/origin/path HTTP/1.1 +> Host: path.rewrite.example +> User-Agent: curl/7.85.0 +> Accept: */* +> + +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< date: Wed, 21 Dec 2022 11:03:28 GMT +< content-length: 503 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +{ + "path": "/replace/origin/path", + "host": "path.rewrite.example", + "method": "GET", + "proto": "HTTP/1.1", + "headers": { + "Accept": [ + "*/*" + ], + "User-Agent": [ + "curl/7.85.0" + ], + "X-Envoy-Expected-Rq-Timeout-Ms": [ + "15000" + ], + "X-Envoy-Original-Path": [ + "/get/origin/path" + ], + "X-Forwarded-Proto": [ + "http" + ], + "X-Request-Id": [ + "fd84b842-9937-4fb5-83c7-61470d854b90" + ] + }, + "namespace": "default", + "ingress": "", + "service": "", + "pod": "backend-6fdd4b9bd8-8vlc5" +... +``` + +You can see that the `X-Envoy-Original-Path` is `/get/origin/path`, but the actual path is `/replace/origin/path`. + +## Rewrite URL Full Path + +You can configure to rewrite the fullpath in the url like below. In this example, any request sent to +`http://${GATEWAY_HOST}/get/origin/path/xxxx` will be rewritten to +`http://${GATEWAY_HOST}/force/replace/fullpath`. + +```shell +cat < GET /get/origin/path/extra HTTP/1.1 +> Host: path.rewrite.example +> User-Agent: curl/7.85.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< date: Wed, 21 Dec 2022 11:09:31 GMT +< content-length: 512 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +{ + "path": "/force/replace/fullpath", + "host": "path.rewrite.example", + "method": "GET", + "proto": "HTTP/1.1", + "headers": { + "Accept": [ + "*/*" + ], + "User-Agent": [ + "curl/7.85.0" + ], + "X-Envoy-Expected-Rq-Timeout-Ms": [ + "15000" + ], + "X-Envoy-Original-Path": [ + "/get/origin/path/extra" + ], + "X-Forwarded-Proto": [ + "http" + ], + "X-Request-Id": [ + "8ab774d6-9ffa-4faa-abbb-f45b0db00895" + ] + }, + "namespace": "default", + "ingress": "", + "service": "", + "pod": "backend-6fdd4b9bd8-8vlc5" +... +``` + +You can see that the `X-Envoy-Original-Path` is `/get/origin/path/extra`, but the actual path is +`/force/replace/fullpath`. + +## Rewrite Host Name + +You can configure to rewrite the hostname like below. In this example, any requests sent to +`http://${GATEWAY_HOST}/get` with `--header "Host: path.rewrite.example"` will rewrite host into `envoygateway.io`. + +```shell +cat < GET /get HTTP/1.1 +> Host: path.rewrite.example +> User-Agent: curl/7.85.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< date: Wed, 21 Dec 2022 11:15:15 GMT +< content-length: 481 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +{ + "path": "/get", + "host": "envoygateway.io", + "method": "GET", + "proto": "HTTP/1.1", + "headers": { + "Accept": [ + "*/*" + ], + "User-Agent": [ + "curl/7.85.0" + ], + "X-Envoy-Expected-Rq-Timeout-Ms": [ + "15000" + ], + "X-Forwarded-Host": [ + "path.rewrite.example" + ], + "X-Forwarded-Proto": [ + "http" + ], + "X-Request-Id": [ + "39aa447c-97b9-45a3-a675-9fb266ab1af0" + ] + }, + "namespace": "default", + "ingress": "", + "service": "", + "pod": "backend-6fdd4b9bd8-8vlc5" +... +``` + +You can see that the `X-Forwarded-Host` is `path.rewrite.example`, but the actual host is `envoygateway.io`. + +[HTTPURLRewriteFilter]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPURLRewriteFilter diff --git a/site/content/en/v0.6.0/user/jwt-authentication.md b/site/content/en/v0.6.0/user/jwt-authentication.md new file mode 100644 index 00000000000..213d75c5d09 --- /dev/null +++ b/site/content/en/v0.6.0/user/jwt-authentication.md @@ -0,0 +1,170 @@ +--- +title: "JWT Authentication" +--- + +This guide provides instructions for configuring [JSON Web Token (JWT)][jwt] authentication. JWT authentication checks +if an incoming request has a valid JWT before routing the request to a backend service. Currently, Envoy Gateway only +supports validating a JWT from an HTTP header, e.g. `Authorization: Bearer `. + +Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure JWT authentication. +This instantiated resource can be linked to a [Gateway][Gateway], [HTTPRoute][HTTPRoute] or [GRPCRoute][GRPCRoute] resource. + +## Prerequisites + +Follow the steps from the [Quickstart](../quickstart) guide to install Envoy Gateway and the example manifest. +For GRPC - follow the steps from the [GRPC Routing](grpc-routing.md) example. +Before proceeding, you should be able to query the example backend using HTTP or GRPC. + +## Configuration + +Allow requests with a valid JWT by creating an [SecurityPolicy][SecurityPolicy] and attaching it to the example +HTTPRoute or GRPCRoute. + +### HTTPRoute + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/jwt/jwt.yaml +``` + +Two HTTPRoute has been created, one for `/foo` and another for `/bar`. A SecurityPolicy has been created and targeted +HTTPRoute foo to authenticate requests for `/foo`. The HTTPRoute bar is not targeted by the SecurityPolicy and will allow +unauthenticated requests to `/bar`. + +Verify the HTTPRoute configuration and status: + +```shell +kubectl get httproute/foo -o yaml +kubectl get httproute/bar -o yaml +``` + +The SecurityPolicy is configured for JWT authentication and uses a single [JSON Web Key Set (JWKS)][jwks] +provider for authenticating the JWT. + +Verify the SecurityPolicy configuration: + +```shell +kubectl get securitypolicy/jwt-example -o yaml +``` + +### GRPCRoute + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/jwt/grpc-jwt.yaml +``` + +A SecurityPolicy has been created and targeted GRPCRoute yages to authenticate all requests for `yages` service.. + +Verify the GRPCRoute configuration and status: + +```shell +kubectl get grpcroute/yages -o yaml +``` + +The SecurityPolicy is configured for JWT authentication and uses a single [JSON Web Key Set (JWKS)][jwks] +provider for authenticating the JWT. + +Verify the SecurityPolicy configuration: + +```shell +kubectl get securitypolicy/jwt-example -o yaml +``` + +## Testing + +Ensure the `GATEWAY_HOST` environment variable from the [Quickstart](../quickstart) guide is set. If not, follow the +Quickstart instructions to set the variable. + +```shell +echo $GATEWAY_HOST +``` + +### HTTPRoute + +Verify that requests to `/foo` are denied without a JWT: + +```shell +curl -sS -o /dev/null -H "Host: www.example.com" -w "%{http_code}\n" http://$GATEWAY_HOST/foo +``` + +A `401` HTTP response code should be returned. + +Get the JWT used for testing request authentication: + +```shell +TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - +``` + +__Note:__ The above command decodes and returns the token's payload. You can replace `f2` with `f1` to view the token's +header. + +Verify that a request to `/foo` with a valid JWT is allowed: + +```shell +curl -sS -o /dev/null -H "Host: www.example.com" -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n" http://$GATEWAY_HOST/foo +``` + +A `200` HTTP response code should be returned. + +Verify that requests to `/bar` are allowed __without__ a JWT: + +```shell +curl -sS -o /dev/null -H "Host: www.example.com" -w "%{http_code}\n" http://$GATEWAY_HOST/bar +``` + +### GRPCRoute + +Verify that requests to `yages`service are denied without a JWT: + +```shell +grpcurl -plaintext -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping +``` + +You should see the below response + +```shell +Error invoking method "yages.Echo/Ping": rpc error: code = Unauthenticated desc = failed to query for service descriptor "yages.Echo": Jwt is missing +``` + +Get the JWT used for testing request authentication: + +```shell +TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - +``` + +__Note:__ The above command decodes and returns the token's payload. You can replace `f2` with `f1` to view the token's +header. + +Verify that a request to `yages` service with a valid JWT is allowed: + +```shell +grpcurl -plaintext -H "authorization: Bearer $TOKEN" -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping +``` + +You should see the below response + +```shell +{ + "text": "pong" +} +``` + +## Clean-Up + +Follow the steps from the [Quickstart](../quickstart) guide to uninstall Envoy Gateway and the example manifest. + +Delete the SecurityPolicy: + +```shell +kubectl delete securitypolicy/jwt-example +``` + +## Next Steps + +Checkout the [Developer Guide](../../contributions/develop/) to get involved in the project. + +[SecurityPolicy]: https://gateway.envoyproxy.io/v0.6.0/design/security-policy +[jwt]: https://tools.ietf.org/html/rfc7519 +[jwks]: https://tools.ietf.org/html/rfc7517 +[Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway +[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute +[GRPCRoute]: https://gateway-api.sigs.k8s.io/api-types/grpcroute diff --git a/site/content/en/v0.6.0/user/multicluster-service.md b/site/content/en/v0.6.0/user/multicluster-service.md new file mode 100644 index 00000000000..ca7580e0f8c --- /dev/null +++ b/site/content/en/v0.6.0/user/multicluster-service.md @@ -0,0 +1,86 @@ +--- +title: "Multicluster Service Routing" +--- + +The Multicluster Service API ServiceImport object can be used as part of the GatewayAPI backendRef for configuring routes. For more information about multicluster service API follow [sig documentation](https://multicluster.sigs.k8s.io/concepts/multicluster-services-api/). + +We will use [Submariner project](https://github.com/submariner-io/submariner) for setting up the multicluster environment for exporting the service to be routed from peer clusters. + +## Setting KIND clusters and installing Submariner. + +- We will be using KIND clusters to demonstrate this example. + +```shell +git clone https://github.com/submariner-io/submariner-operator +cd submariner-operator +make clusters +``` + +Note: remain in submariner-operator directory for the rest of the steps in this section + +- Install subctl: + +```shell +curl -Ls https://get.submariner.io | VERSION=v0.14.6 bash +``` + +- Set up multicluster service API and submariner for cross cluster traffic using ServiceImport + +```shell +subctl deploy-broker --kubeconfig output/kubeconfigs/kind-config-cluster1 --globalnet +subctl join --kubeconfig output/kubeconfigs/kind-config-cluster1 broker-info.subm --clusterid cluster1 --natt=false +subctl join --kubeconfig output/kubeconfigs/kind-config-cluster2 broker-info.subm --clusterid cluster2 --natt=false +``` + +Once the above steps are done and all the pods are up in both the clusters. We are ready for installing envoy gateway. + +## Install EnvoyGateway + +Install the Gateway API CRDs and Envoy Gateway in cluster1: + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.6.0 -n envoy-gateway-system --create-namespace --kubeconfig output/kubeconfigs/kind-config-cluster1 +``` + +Wait for Envoy Gateway to become available: + +```shell +kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available --kubeconfig output/kubeconfigs/kind-config-cluster1 +``` + +## Install Application + +Install the backend application in cluster2 and export it through subctl command. + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/application.yaml --kubeconfig output/kubeconfigs/kind-config-cluster2 +subctl export service backend --namespace default --kubeconfig output/kubeconfigs/kind-config-cluster2 +``` + +## Create Gateway API Objects + +Create the Gateway API objects GatewayClass, Gateway and HTTPRoute in cluster1 to set up the routing. + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/multicluster-service.yaml --kubeconfig output/kubeconfigs/kind-config-cluster1 +``` + +## Testing the Configuration + +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}') +``` + +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://localhost:8888/get +``` diff --git a/site/content/en/v0.6.0/user/proxy-observability.md b/site/content/en/v0.6.0/user/proxy-observability.md new file mode 100644 index 00000000000..8601a0de7a8 --- /dev/null +++ b/site/content/en/v0.6.0/user/proxy-observability.md @@ -0,0 +1,134 @@ +--- +title: "Proxy Observability" +--- + +Envoy Gateway provides observability for the ControlPlane and the underlying EnvoyProxy instances. +This guide show you how to config proxy observability, includes metrics, logs, and traces. + +## Prerequisites + +Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +[FluentBit](https://fluentbit.io/) is used to collect logs from the EnvoyProxy instances and forward them to Loki. Install FluentBit: + +```shell +helm repo add fluent https://fluent.github.io/helm-charts +helm repo update +helm upgrade --install fluent-bit fluent/fluent-bit -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/fluent-bit/helm-values.yaml -n monitoring --create-namespace --version 0.30.4 +``` + +[Loki](https://grafana.com/oss/loki/) is used to store logs. Install Loki: + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/loki/loki.yaml -n monitoring +``` + +[Tempo](https://grafana.com/oss/tempo/) is used to store traces. Install Tempo: + +```shell +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +helm upgrade --install tempo grafana/tempo -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/tempo/helm-values.yaml -n monitoring --create-namespace --version 1.3.1 +``` + +[OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) offers a vendor-agnostic implementation of how to receive, process and export telemetry data. +Install OTel-Collector: + +```shell +helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts +helm repo update +helm upgrade --install otel-collector open-telemetry/opentelemetry-collector -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/otel-collector/helm-values.yaml -n monitoring --create-namespace --version 0.60.0 +``` + +Expose endpoints: + +```shell +LOKI_IP=$(kubectl get svc loki -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +TEMPO_IP=$(kubectl get svc tempo -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +``` + +## Metrics + +By default, Envoy Gateway expose metrics with prometheus endpoint. + +Verify metrics: + +```shell +export ENVOY_POD_NAME=$(kubectl get pod -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 port-forward pod/$ENVOY_POD_NAME -n envoy-gateway-system 19001:19001 + +# check metrics +curl localhost:19001/stats/prometheus | grep "default/backend/rule/0/match/0-www" +``` + +You can disable metrics by setting the `telemetry.metrics.prometheus.disable` to `true` in the `EnvoyProxy` CRD. + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/metric/disable-prometheus.yaml +``` + +Envoy Gateway can send metrics to OpenTelemetry Sink. +Send metrics to OTel-Collector: + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/metric/otel-sink.yaml +``` + +Verify OTel-Collector metrics: + +```shell +export OTEL_POD_NAME=$(kubectl get pod -n monitoring --selector=app.kubernetes.io/name=opentelemetry-collector -o jsonpath='{.items[0].metadata.name}') +kubectl port-forward pod/$OTEL_POD_NAME -n monitoring 19001:19001 + +# check metrics +curl localhost:19001/metrics | grep "default/backend/rule/0/match/0-www" +``` + +## Logs + +By default, Envoy Gateway send logs to stdout in [default text format](https://www.envoyproxy.io/docs/envoy/v0.6.0/configuration/observability/access_log/usage.html#default-format-string). +Verify logs from loki: + +```shell +curl -s "http://$LOKI_IP:3100/loki/api/v1/query_range" --data-urlencode "query={job=\"fluentbit\"}" | jq '.data.result[0].values' +``` + +If you want to disable it, set the `telemetry.accesslog.disable` to `true` in the `EnvoyProxy` CRD. + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/accesslog/disable-accesslog.yaml +``` + +Envoy Gateway can send logs to OpenTelemetry Sink. + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/accesslog/otel-accesslog.yaml +``` + +Verify logs from loki: + +```shell +curl -s "http://$LOKI_IP:3100/loki/api/v1/query_range" --data-urlencode "query={exporter=\"OTLP\"}" | jq '.data.result[0].values' +``` + +## Traces + +By default, Envoy Gateway doesn't send traces to OpenTelemetry Sink. +You can enable traces by setting the `telemetry.tracing` in the `EnvoyProxy` CRD. + +***Note:*** Envoy Gateway use 100% sample rate, which means all requests will be traced. This may cause performance issues. + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/v0.6.0/examples/kubernetes/tracing/default.yaml +``` + +Verify traces from tempo: + +```shell +curl -s "http://$TEMPO_IP:3100/api/search" --data-urlencode "q={ component=envoy }" | jq .traces +``` + +```shell +curl -s "http://$TEMPO_IP:3100/api/traces/" | jq +``` diff --git a/site/content/en/v0.6.0/user/quickstart.md b/site/content/en/v0.6.0/user/quickstart.md new file mode 100644 index 00000000000..2e47dd6f26b --- /dev/null +++ b/site/content/en/v0.6.0/user/quickstart.md @@ -0,0 +1,103 @@ +--- +title: "Quickstart" +weight: 1 +--- + +This guide will help you get started with Envoy Gateway in a few simple steps. + +## Prerequisites + +A Kubernetes cluster. + +__Note:__ Refer to the [Compatibility Matrix](/blog/2022/10/01/versions/) for supported Kubernetes versions. + +__Note:__ In case your Kubernetes cluster, does not have a LoadBalancer implementation, we recommend installing one +so the `Gateway` resource has an Address associated with it. We recommend using [MetalLB](https://metallb.universe.tf/installation/). + +## Installation + +Install the Gateway API CRDs and Envoy Gateway: + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.6.0 -n envoy-gateway-system --create-namespace +``` + +Wait for Envoy Gateway to become available: + +```shell +kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available +``` + +Install the GatewayClass, Gateway, HTTPRoute and example app: + +```shell +kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v0.6.0/quickstart.yaml -n default +``` + +**Note**: [`quickstart.yaml`] defines that Envoy Gateway will listen for +traffic on port 80 on its globally-routable IP address, to make it easy to use +browsers to test Envoy Gateway. When Envoy Gateway sees that its Listener is +using a privileged port (<1024), it will map this internally to an +unprivileged port, so that Envoy Gateway doesn't need additional privileges. +It's important to be aware of this mapping, since you may need to take it into +consideration when debugging. + +[`quickstart.yaml`]: https://github.com/envoyproxy/gateway/releases/download/v0.6.0/quickstart.yaml + +## Testing the Configuration + +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}') +``` + +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://localhost:8888/get +``` + +### 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: + +```shell +export GATEWAY_HOST=$(kubectl get svc/${ENVOY_SERVICE} -n envoy-gateway-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +``` + +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://$GATEWAY_HOST/get +``` + +## Clean-Up + +Use the steps in this section to uninstall everything from the quickstart guide. + +Delete the GatewayClass, Gateway, HTTPRoute and Example App: + +```shell +kubectl delete -f https://github.com/envoyproxy/gateway/releases/download/v0.6.0/quickstart.yaml --ignore-not-found=true +``` + +Delete the Gateway API CRDs and Envoy Gateway: + +```shell +helm uninstall eg -n envoy-gateway-system +``` + +## Next Steps + +Checkout the [Developer Guide](../../contributions/develop/) to get involved in the project. diff --git a/site/content/en/v0.6.0/user/rate-limit.md b/site/content/en/v0.6.0/user/rate-limit.md new file mode 100644 index 00000000000..027a26cd69e --- /dev/null +++ b/site/content/en/v0.6.0/user/rate-limit.md @@ -0,0 +1,829 @@ +--- +title: "Rate Limit" +--- + +Rate limit is a feature that allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. + +Here are some reasons why you may want to implement Rate limits + +* To prevent malicious activity such as DDoS attacks. +* To prevent applications and its resources (such as a database) from getting overloaded. +* To create API limits based on user entitlements. + +Envoy Gateway supports [Global rate limiting][], where the rate limit is common across all the instances of Envoy proxies where its applied +i.e. if the data plane has 2 replicas of Envoy running, and the rate limit is 10 requests/second, this limit is common and will be hit +if 5 requests pass through the first replica and 5 requests pass through the second replica within the same second. + +Envoy Gateway introduces a new CRD called [BackendTrafficPolicy][] that allows the user to describe their rate limit intent. This instantiated resource +can be linked to a [Gateway][], [HTTPRoute][] or [GRPCRoute][] resource. + +## Prerequisites + +### Install Envoy Gateway + +* Follow the steps from the [Quickstart Guide](../quickstart) to install Envoy Gateway and the HTTPRoute example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +### Install Redis + +* The global rate limit feature is based on [Envoy Ratelimit][] which requires a Redis instance as its caching layer. +Lets install a Redis deployment in the `redis-system` namespce. + +```shell +cat <> DiG 9.18.1-1ubuntu1.1-Ubuntu <<>> @49.51.177.138 -p 5300 foo.bar.com +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58125 +;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 3 +;; WARNING: recursion requested but not available + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 1232 +; COOKIE: 24fb86eba96ebf62 (echoed) +;; QUESTION SECTION: +;foo.bar.com. IN A + +;; ADDITIONAL SECTION: +foo.bar.com. 0 IN A 10.244.0.19 +_udp.foo.bar.com. 0 IN SRV 0 0 42376 . + +;; Query time: 1 msec +;; SERVER: 49.51.177.138#5300(49.51.177.138) (UDP) +;; WHEN: Fri Jan 13 10:20:34 UTC 2023 +;; MSG SIZE rcvd: 114 +``` + +## Clean-Up + +Follow the steps from the [Quickstart Guide](../quickstart) to uninstall Envoy Gateway. + +Delete the CoreDNS example manifest and the UDPRoute: + +```shell +kubectl delete deploy/coredns +kubectl delete service/coredns +kubectl delete cm/coredns +kubectl delete udproute/coredns +``` + +## Next Steps + +Checkout the [Developer Guide](../../contributions/develop/) to get involved in the project. + +[UDPRoute]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.UDPRoute +[UDP proxy documentation]: https://www.envoyproxy.io/docs/envoy/v0.6.0/configuration/listeners/udp_filters/udp_proxy diff --git a/site/hugo.toml b/site/hugo.toml index 56aea0c18d4..446caa88d21 100644 --- a/site/hugo.toml +++ b/site/hugo.toml @@ -225,7 +225,7 @@ enable = true name = "Documentation" weight = -101 pre = "" - url = "/v0.5.0" + url = "/v0.6.0" [[params.versions]] version = "latest" @@ -246,3 +246,6 @@ enable = true [[params.versions]] version = "v0.5.0" url = "/v0.5.0" +[[params.versions]] + version = "v0.6.0" + url = "/v0.6.0" From 4c57d8f1d9b701ab264c01f2f1e871641629babb Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Thu, 2 Nov 2023 10:45:19 +0800 Subject: [PATCH 45/55] fix: matrix link in release note (#2157) Signed-off-by: bitliu --- site/content/en/blog/releases/v0.2.md | 2 +- site/content/en/blog/releases/v0.3.md | 2 +- site/content/en/blog/releases/v0.4.md | 2 +- site/content/en/blog/releases/v0.5.md | 2 +- site/content/en/blog/releases/v0.6.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/site/content/en/blog/releases/v0.2.md b/site/content/en/blog/releases/v0.2.md index 2328a4a4bb5..c4b7bc3da0c 100644 --- a/site/content/en/blog/releases/v0.2.md +++ b/site/content/en/blog/releases/v0.2.md @@ -37,7 +37,7 @@ Envoy Gateway will be at [EnvoyCon NA][] this October in Detroit. Don't miss [o release and future direction of the project. [Release Notes]: https://github.com/envoyproxy/gateway/blob/main/release-notes/v0.2.0.yaml -[matrix]: https://gateway.envoyproxy.io/intro/compatibility.html +[matrix]: https://gateway.envoyproxy.io/blog/2022/10/01/versions [docs]: https://gateway.envoyproxy.io/index.html [Download]: https://github.com/envoyproxy/gateway/releases/tag/v0.2.0 [conformance tests]: https://gateway-api.sigs.k8s.io/concepts/conformance/?h=conformance diff --git a/site/content/en/blog/releases/v0.3.md b/site/content/en/blog/releases/v0.3.md index 6be5b392a8a..ae620a2c98e 100644 --- a/site/content/en/blog/releases/v0.3.md +++ b/site/content/en/blog/releases/v0.3.md @@ -41,6 +41,6 @@ The release adds a ton of features and functionality. Here are some highlights: + Added Support for Request Authentication [Release Notes]: https://github.com/envoyproxy/gateway/blob/main/release-notes/v0.3.0.yaml -[matrix]: https://gateway.envoyproxy.io/v0.3.0/intro/compatibility.html +[matrix]: https://gateway.envoyproxy.io/blog/2022/10/01/versions [docs]: https://gateway.envoyproxy.io/v0.3.0/index.html [Download]: https://github.com/envoyproxy/gateway/releases/tag/v0.3.0 diff --git a/site/content/en/blog/releases/v0.4.md b/site/content/en/blog/releases/v0.4.md index 1ad763f35b4..b5faae47e6d 100644 --- a/site/content/en/blog/releases/v0.4.md +++ b/site/content/en/blog/releases/v0.4.md @@ -52,6 +52,6 @@ The release adds a ton of features and functionality. Here are some highlights: + Added EDS Support [Release Notes]: https://github.com/envoyproxy/gateway/blob/main/release-notes/v0.4.0.yaml -[matrix]: https://gateway.envoyproxy.io/v0.4.0/intro/compatibility.html +[matrix]: https://gateway.envoyproxy.io/blog/2022/10/01/versions [docs]: https://gateway.envoyproxy.io/v0.4.0/index.html [Download]: https://github.com/envoyproxy/gateway/releases/tag/v0.4.0 diff --git a/site/content/en/blog/releases/v0.5.md b/site/content/en/blog/releases/v0.5.md index 1bf1d6ed8c6..e23ae419231 100644 --- a/site/content/en/blog/releases/v0.5.md +++ b/site/content/en/blog/releases/v0.5.md @@ -52,6 +52,6 @@ The release adds a ton of features and functionality. Here are some highlights: + Added Best Practices Default Edge Settings to Xds Resources [Release Notes]: https://github.com/envoyproxy/gateway/blob/main/release-notes/v0.5.0.yaml -[matrix]: https://gateway.envoyproxy.io/v0.5.0/intro/compatibility.html +[matrix]: https://gateway.envoyproxy.io/blog/2022/10/01/versions [docs]: https://gateway.envoyproxy.io/v0.5.0/index.html [Download]: https://github.com/envoyproxy/gateway/releases/tag/v0.5.0 diff --git a/site/content/en/blog/releases/v0.6.md b/site/content/en/blog/releases/v0.6.md index 987862d2100..754adda218b 100644 --- a/site/content/en/blog/releases/v0.6.md +++ b/site/content/en/blog/releases/v0.6.md @@ -77,6 +77,6 @@ The release adds a ton of features and functionality. Here are some highlights: + Converted the `bootstrap` field within `EnvoyProxy` into a struct to support merge operations. [Release Notes]: https://github.com/envoyproxy/gateway/blob/main/release-notes/v0.6.0.yaml -[matrix]: https://gateway.envoyproxy.io/v0.6.0/intro/compatibility.html +[matrix]: https://gateway.envoyproxy.io/blog/2022/10/01/versions [docs]: https://gateway.envoyproxy.io/v0.6.0/index.html [Download]: https://github.com/envoyproxy/gateway/releases/tag/v0.6.0 From fb9cb18c94b03751a3dbcae9dcfa639d1d61213a Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Fri, 3 Nov 2023 00:54:50 +0800 Subject: [PATCH 46/55] docs: move announcements on top (#2158) move announcements on top Signed-off-by: bitliu --- .../en/{blog/releases => announcements}/_index.md | 11 ++++++++--- .../en/{blog/releases => announcements}/v0.2.md | 0 .../en/{blog/releases => announcements}/v0.3.md | 0 .../en/{blog/releases => announcements}/v0.4.md | 0 .../en/{blog/releases => announcements}/v0.5.md | 0 .../en/{blog/releases => announcements}/v0.6.md | 0 site/hugo.toml | 12 ++++++------ 7 files changed, 14 insertions(+), 9 deletions(-) rename site/content/en/{blog/releases => announcements}/_index.md (94%) rename site/content/en/{blog/releases => announcements}/v0.2.md (100%) rename site/content/en/{blog/releases => announcements}/v0.3.md (100%) rename site/content/en/{blog/releases => announcements}/v0.4.md (100%) rename site/content/en/{blog/releases => announcements}/v0.5.md (100%) rename site/content/en/{blog/releases => announcements}/v0.6.md (100%) diff --git a/site/content/en/blog/releases/_index.md b/site/content/en/announcements/_index.md similarity index 94% rename from site/content/en/blog/releases/_index.md rename to site/content/en/announcements/_index.md index fa3640ba5a9..219bf8ae46d 100644 --- a/site/content/en/blog/releases/_index.md +++ b/site/content/en/announcements/_index.md @@ -1,6 +1,11 @@ ---- -title: "Release Announcement" ---- ++++ +title = "Release Announcement" +description = "Envoy Gateway Release Announcement" +linktitle = "Announcement" + +[[cascade]] +type = "docs" ++++ This document provides details for Envoy Gateway releases. Envoy Gateway follows the Semantic Versioning [v2.0.0 spec][] for release versioning. Since Envoy Gateway is a new project, minor releases are the only defined releases. Envoy diff --git a/site/content/en/blog/releases/v0.2.md b/site/content/en/announcements/v0.2.md similarity index 100% rename from site/content/en/blog/releases/v0.2.md rename to site/content/en/announcements/v0.2.md diff --git a/site/content/en/blog/releases/v0.3.md b/site/content/en/announcements/v0.3.md similarity index 100% rename from site/content/en/blog/releases/v0.3.md rename to site/content/en/announcements/v0.3.md diff --git a/site/content/en/blog/releases/v0.4.md b/site/content/en/announcements/v0.4.md similarity index 100% rename from site/content/en/blog/releases/v0.4.md rename to site/content/en/announcements/v0.4.md diff --git a/site/content/en/blog/releases/v0.5.md b/site/content/en/announcements/v0.5.md similarity index 100% rename from site/content/en/blog/releases/v0.5.md rename to site/content/en/announcements/v0.5.md diff --git a/site/content/en/blog/releases/v0.6.md b/site/content/en/announcements/v0.6.md similarity index 100% rename from site/content/en/blog/releases/v0.6.md rename to site/content/en/announcements/v0.6.md diff --git a/site/hugo.toml b/site/hugo.toml index 446caa88d21..2c60c9e85b6 100644 --- a/site/hugo.toml +++ b/site/hugo.toml @@ -208,7 +208,7 @@ enable = true [menu] [[menu.main]] name = "Blog" - weight = -100 + weight = -99 pre = "" url = "/blog" [[menu.main]] @@ -217,13 +217,13 @@ enable = true pre = "" url = "/about" [[menu.main]] - name = "GitHub" - weight = -99 - pre = "" - url = "https://github.com/envoyproxy/gateway" + name = "Announcements" + weight = -101 + pre = "" + url = "/announcements" [[menu.main]] name = "Documentation" - weight = -101 + weight = -102 pre = "" url = "/v0.6.0" From 46bb51a1fe2d4054e2bcdb1b3b885bb2489db9bc Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Mon, 6 Nov 2023 09:29:20 -0800 Subject: [PATCH 47/55] chore: refactor string match (#2102) * refactor: string match Signed-off-by: huabing zhao * use shared string match for rate limit Signed-off-by: huabing zhao * revert Rate Limit HeaderMatch Signed-off-by: huabing zhao * use common string match for stats match Signed-off-by: huabing zhao * fix generate Signed-off-by: huabing zhao --------- Signed-off-by: huabing zhao Signed-off-by: Huabing Zhao --- api/v1alpha1/envoyproxy_metric_types.go | 19 +------ api/v1alpha1/shared_types.go | 14 ++--- api/v1alpha1/zz_generated.deepcopy.go | 23 ++------ .../gateway.envoyproxy.io_envoyproxies.yaml | 15 ++++-- internal/gatewayapi/securitypolicy.go | 10 ++-- internal/xds/bootstrap/bootstrap.go | 16 ++++-- internal/xds/bootstrap/bootstrap.yaml.tpl | 3 ++ internal/xds/bootstrap/bootstrap_test.go | 15 ++++-- .../testdata/custom-stats-matcher.yaml | 1 + site/content/en/latest/api/extension_types.md | 53 +++++-------------- 10 files changed, 69 insertions(+), 100 deletions(-) diff --git a/api/v1alpha1/envoyproxy_metric_types.go b/api/v1alpha1/envoyproxy_metric_types.go index 6cf486ac4b6..2dce4655ecd 100644 --- a/api/v1alpha1/envoyproxy_metric_types.go +++ b/api/v1alpha1/envoyproxy_metric_types.go @@ -23,7 +23,7 @@ type ProxyMetrics struct { // `cluster..membership_degraded`,reference https://github.com/envoyproxy/envoy/issues/9856, // https://github.com/envoyproxy/envoy/issues/14610 // - Matches []Match `json:"matches,omitempty"` + Matches []StringMatch `json:"matches,omitempty"` // EnableVirtualHostStats enables envoy stat metrics for virtual hosts. EnableVirtualHostStats bool `json:"enableVirtualHostStats,omitempty"` @@ -58,20 +58,3 @@ type ProxyPrometheusProvider struct { // Disable the Prometheus endpoint. Disable bool `json:"disable,omitempty"` } - -// Match defines the stats match configuration. -type Match struct { // TODO: zhaohuabing this type should be renamed to StatsMatch - // MatcherType defines the stats matcher type - // - // +kubebuilder:validation:Enum=RegularExpression;Prefix;Suffix - Type MatcherType `json:"type"` - Value string `json:"value"` -} - -type MatcherType string - -const ( // TODO: zhaohuabing the const types should be prefixed with StatsMatch - Prefix MatcherType = "Prefix" - RegularExpression MatcherType = "RegularExpression" - Suffix MatcherType = "Suffix" -) diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index 84938be0585..532d4001b4c 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -244,7 +244,7 @@ type StringMatch struct { // // +optional // +kubebuilder:default=Exact - Type *MatchType `json:"type,omitempty"` + Type *StringMatchType `json:"type,omitempty"` // Value specifies the string value that the match must have. // @@ -253,25 +253,25 @@ type StringMatch struct { Value string `json:"value"` } -// MatchType specifies the semantics of how a string value should be compared. +// StringMatchType specifies the semantics of how a string value should be compared. // Valid MatchType values are "Exact", "Prefix", "Suffix", "RegularExpression". // // +kubebuilder:validation:Enum=Exact;Prefix;Suffix;RegularExpression -type MatchType string +type StringMatchType string const ( // MatchExact :the input string must match exactly the match value. - MatchExact MatchType = "Exact" + StringMatchExact StringMatchType = "Exact" // MatchPrefix :the input string must start with the match value. - MatchPrefix MatchType = "Prefix" + StringMatchPrefix StringMatchType = "Prefix" // MatchSuffix :the input string must end with the match value. - MatchSuffix MatchType = "Suffix" + StringMatchSuffix StringMatchType = "Suffix" // MatchRegularExpression :The input string must match the regular expression // specified in the match value. // The regex string must adhere to the syntax documented in // https://github.com/google/re2/wiki/Syntax. - MatchRegularExpression MatchType = "RegularExpression" + StringMatchRegularExpression StringMatchType = "RegularExpression" ) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index cfbcad0acb7..60ad334e9a5 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1522,21 +1522,6 @@ func (in *LoadBalancer) DeepCopy() *LoadBalancer { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Match) DeepCopyInto(out *Match) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Match. -func (in *Match) DeepCopy() *Match { - if in == nil { - return nil - } - out := new(Match) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenTelemetryEnvoyProxyAccessLog) DeepCopyInto(out *OpenTelemetryEnvoyProxyAccessLog) { *out = *in @@ -1735,8 +1720,10 @@ func (in *ProxyMetrics) DeepCopyInto(out *ProxyMetrics) { } if in.Matches != nil { in, out := &in.Matches, &out.Matches - *out = make([]Match, len(*in)) - copy(*out, *in) + *out = make([]StringMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } } @@ -2171,7 +2158,7 @@ func (in *StringMatch) DeepCopyInto(out *StringMatch) { *out = *in if in.Type != nil { in, out := &in.Type, &out.Type - *out = new(MatchType) + *out = new(StringMatchType) **out = **in } } 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 71699ffb5b3..17f135598e2 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -5424,19 +5424,26 @@ spec: `cluster..membership_degraded`,reference https://github.com/envoyproxy/envoy/issues/9856, https://github.com/envoyproxy/envoy/issues/14610' items: - description: Match defines the stats match configuration. + description: StringMatch defines how to match any strings. + This is a general purpose match condition that can be + used by other EG APIs that need to match against a string. properties: type: - description: MatcherType defines the stats matcher type + default: Exact + description: Type specifies how to match against a string. enum: - - RegularExpression + - Exact - Prefix - Suffix + - RegularExpression type: string value: + description: Value specifies the string value that the + match must have. + maxLength: 1024 + minLength: 1 type: string required: - - type - value type: object type: array diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 0866275203d..801f2837078 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -296,26 +296,26 @@ func (t *Translator) buildCORS(policy *egv1a1.SecurityPolicy) *ir.CORS { origin := origin.DeepCopy() // matchType default to exact - matchType := egv1a1.MatchExact + matchType := egv1a1.StringMatchExact if origin.Type != nil { matchType = *origin.Type } // TODO zhaohuabing: extract a utils function to build StringMatch switch matchType { - case egv1a1.MatchExact: + case egv1a1.StringMatchExact: allowOrigins = append(allowOrigins, &ir.StringMatch{ Exact: &origin.Value, }) - case egv1a1.MatchPrefix: + case egv1a1.StringMatchPrefix: allowOrigins = append(allowOrigins, &ir.StringMatch{ Prefix: &origin.Value, }) - case egv1a1.MatchSuffix: + case egv1a1.StringMatchSuffix: allowOrigins = append(allowOrigins, &ir.StringMatch{ Suffix: &origin.Value, }) - case egv1a1.MatchRegularExpression: + case egv1a1.StringMatchRegularExpression: allowOrigins = append(allowOrigins, &ir.StringMatch{ SafeRegex: &origin.Value, // TODO zhaohuabing: check if the value is a valid regex }) diff --git a/internal/xds/bootstrap/bootstrap.go b/internal/xds/bootstrap/bootstrap.go index 3ed28e05010..f8418e0e750 100644 --- a/internal/xds/bootstrap/bootstrap.go +++ b/internal/xds/bootstrap/bootstrap.go @@ -103,6 +103,7 @@ type readyServerParameters struct { } type StatsMatcherParameters struct { + Exacts []string Prefixs []string Suffixs []string RegularExpressions []string @@ -154,12 +155,19 @@ func GetRenderedBootstrapConfig(proxyMetrics *egv1a1.ProxyMetrics) (string, erro if proxyMetrics.Matches != nil { // Add custom envoy proxy stats for _, match := range proxyMetrics.Matches { - switch match.Type { - case egv1a1.Prefix: + // matchType default to exact + matchType := egv1a1.StringMatchExact + if match.Type != nil { + matchType = *match.Type + } + switch matchType { + case egv1a1.StringMatchExact: + StatsMatcher.Exacts = append(StatsMatcher.Exacts, match.Value) + case egv1a1.StringMatchPrefix: StatsMatcher.Prefixs = append(StatsMatcher.Prefixs, match.Value) - case egv1a1.Suffix: + case egv1a1.StringMatchSuffix: StatsMatcher.Suffixs = append(StatsMatcher.Suffixs, match.Value) - case egv1a1.RegularExpression: + case egv1a1.StringMatchRegularExpression: StatsMatcher.RegularExpressions = append(StatsMatcher.RegularExpressions, match.Value) } } diff --git a/internal/xds/bootstrap/bootstrap.yaml.tpl b/internal/xds/bootstrap/bootstrap.yaml.tpl index 4828729a816..ab6a3516510 100644 --- a/internal/xds/bootstrap/bootstrap.yaml.tpl +++ b/internal/xds/bootstrap/bootstrap.yaml.tpl @@ -13,6 +13,9 @@ stats_config: stats_matcher: inclusion_list: patterns: + {{- range $_, $item := .StatsMatcher.Exacts }} + - exact: {{$item}} + {{- end}} {{- range $_, $item := .StatsMatcher.Prefixs }} - prefix: {{$item}} {{- end}} diff --git a/internal/xds/bootstrap/bootstrap_test.go b/internal/xds/bootstrap/bootstrap_test.go index b145045a8b3..4b5a3d81cd7 100644 --- a/internal/xds/bootstrap/bootstrap_test.go +++ b/internal/xds/bootstrap/bootstrap_test.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/utils/ptr" ) func TestGetRenderedBootstrapConfig(t *testing.T) { @@ -55,21 +56,25 @@ func TestGetRenderedBootstrapConfig(t *testing.T) { { name: "custom-stats-matcher", proxyMetrics: &egv1a1.ProxyMetrics{ - Matches: []egv1a1.Match{ + Matches: []egv1a1.StringMatch{ { - Type: egv1a1.Prefix, + Type: ptr.To(egv1a1.StringMatchExact), + Value: "http.foo.bar.cluster.upstream_rq", + }, + { + Type: ptr.To(egv1a1.StringMatchPrefix), Value: "http", }, { - Type: egv1a1.Suffix, + Type: ptr.To(egv1a1.StringMatchSuffix), Value: "upstream_rq", }, { - Type: egv1a1.RegularExpression, + Type: ptr.To(egv1a1.StringMatchRegularExpression), Value: "virtual.*", }, { - Type: egv1a1.Prefix, + Type: ptr.To(egv1a1.StringMatchPrefix), Value: "cluster", }, }, diff --git a/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml b/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml index 9fac5a316c5..c8376470146 100644 --- a/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml +++ b/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml @@ -12,6 +12,7 @@ stats_config: stats_matcher: inclusion_list: patterns: + - exact: http.foo.bar.cluster.upstream_rq - prefix: http - prefix: cluster - suffix: upstream_rq diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 08b53e29c85..174ab89e45a 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -1059,43 +1059,6 @@ _Appears in:_ -#### Match - - - -Match defines the stats match configuration. - -_Appears in:_ -- [ProxyMetrics](#proxymetrics) - -| Field | Description | -| --- | --- | -| `type` _[MatcherType](#matchertype)_ | MatcherType defines the stats matcher type | -| `value` _string_ | | - - -#### MatchType - -_Underlying type:_ `string` - -MatchType specifies the semantics of how a string value should be compared. Valid MatchType values are "Exact", "Prefix", "Suffix", "RegularExpression". - -_Appears in:_ -- [StringMatch](#stringmatch) - - - -#### MatcherType - -_Underlying type:_ `string` - - - -_Appears in:_ -- [Match](#match) - - - #### MetricSinkType _Underlying type:_ `string` @@ -1288,7 +1251,7 @@ _Appears in:_ | --- | --- | | `prometheus` _[ProxyPrometheusProvider](#proxyprometheusprovider)_ | Prometheus defines the configuration for Admin endpoint `/stats/prometheus`. | | `sinks` _[ProxyMetricSink](#proxymetricsink) array_ | Sinks defines the metric sinks where metrics are sent to. | -| `matches` _[Match](#match) array_ | Matches defines configuration for selecting specific metrics instead of generating all metrics stats that are enabled by default. This helps reduce CPU and memory overhead in Envoy, but eliminating some stats may after critical functionality. Here are the stats that we strongly recommend not disabling: `cluster_manager.warming_clusters`, `cluster..membership_total`,`cluster..membership_healthy`, `cluster..membership_degraded`,reference https://github.com/envoyproxy/envoy/issues/9856, https://github.com/envoyproxy/envoy/issues/14610 | +| `matches` _[StringMatch](#stringmatch) array_ | Matches defines configuration for selecting specific metrics instead of generating all metrics stats that are enabled by default. This helps reduce CPU and memory overhead in Envoy, but eliminating some stats may after critical functionality. Here are the stats that we strongly recommend not disabling: `cluster_manager.warming_clusters`, `cluster..membership_total`,`cluster..membership_healthy`, `cluster..membership_degraded`,reference https://github.com/envoyproxy/envoy/issues/9856, https://github.com/envoyproxy/envoy/issues/14610 | | `enableVirtualHostStats` _boolean_ | EnableVirtualHostStats enables envoy stat metrics for virtual hosts. | @@ -1628,13 +1591,25 @@ StringMatch defines how to match any strings. This is a general purpose match co _Appears in:_ - [CORS](#cors) +- [ProxyMetrics](#proxymetrics) | Field | Description | | --- | --- | -| `type` _[MatchType](#matchtype)_ | Type specifies how to match against a string. | +| `type` _[StringMatchType](#stringmatchtype)_ | Type specifies how to match against a string. | | `value` _string_ | Value specifies the string value that the match must have. | +#### StringMatchType + +_Underlying type:_ `string` + +StringMatchType specifies the semantics of how a string value should be compared. Valid MatchType values are "Exact", "Prefix", "Suffix", "RegularExpression". + +_Appears in:_ +- [StringMatch](#stringmatch) + + + #### TCPKeepalive From 706dbc74af85f1b4a88c38d8662ab85eff631f14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 07:26:33 -0800 Subject: [PATCH 48/55] build(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0 (#2161) Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/spf13/cobra/releases) - [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: github.com/spf13/cobra dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 5e39e1b2ad4..569f2137e26 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/grafana/tempo v1.5.0 github.com/pkg/errors v0.9.1 github.com/prometheus/common v0.45.0 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7 diff --git a/go.sum b/go.sum index ac8b12b981f..23cac074b05 100644 --- a/go.sum +++ b/go.sum @@ -68,7 +68,7 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfc github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= @@ -435,8 +435,8 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= From ad38383ba218ea55f960bc62c8f6cc881082a183 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 07:26:58 -0800 Subject: [PATCH 49/55] build(deps): bump github.com/go-logr/zapr from 1.2.4 to 1.3.0 (#2162) Bumps [github.com/go-logr/zapr](https://github.com/go-logr/zapr) from 1.2.4 to 1.3.0. - [Release notes](https://github.com/go-logr/zapr/releases) - [Commits](https://github.com/go-logr/zapr/compare/v1.2.4...v1.3.0) --- updated-dependencies: - dependency-name: github.com/go-logr/zapr dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 569f2137e26..c732dc5f222 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/evanphx/json-patch/v5 v5.7.0 github.com/go-logfmt/logfmt v0.6.0 github.com/go-logr/logr v1.3.0 - github.com/go-logr/zapr v1.2.4 + github.com/go-logr/zapr v1.3.0 github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.5.3 github.com/google/go-cmp v0.6.0 diff --git a/go.sum b/go.sum index 23cac074b05..a1a711994bb 100644 --- a/go.sum +++ b/go.sum @@ -31,7 +31,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -131,14 +130,13 @@ github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -483,7 +481,6 @@ github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -516,16 +513,12 @@ go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93V go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -546,10 +539,8 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -573,7 +564,6 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= @@ -589,7 +579,6 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -618,8 +607,6 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -662,7 +649,6 @@ golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= From 8b5cc95e908ea024e88970b92230f67e60d5ce59 Mon Sep 17 00:00:00 2001 From: sh2 Date: Sat, 11 Nov 2023 02:23:20 +0800 Subject: [PATCH 50/55] docs: fix invalid title in cors (#2173) fix cors doc format Signed-off-by: sh2 --- site/content/en/latest/user/cors.md | 1 - site/content/en/v0.6.0/user/cors.md | 1 - 2 files changed, 2 deletions(-) diff --git a/site/content/en/latest/user/cors.md b/site/content/en/latest/user/cors.md index b86a983a7a9..f05cbf6ec18 100644 --- a/site/content/en/latest/user/cors.md +++ b/site/content/en/latest/user/cors.md @@ -99,7 +99,6 @@ to access the limited resource in another domains. The browsers are supposed to determine whether to send the actual request or not. The CORS filter only response to the preflight requests according to its configuration. It won't deny any requests. The browsers are responsible for enforcing the CORS policy. -```shell ## Clean-Up diff --git a/site/content/en/v0.6.0/user/cors.md b/site/content/en/v0.6.0/user/cors.md index eaa92c874a9..05481aa44b2 100644 --- a/site/content/en/v0.6.0/user/cors.md +++ b/site/content/en/v0.6.0/user/cors.md @@ -99,7 +99,6 @@ to access the limited resource in another domains. The browsers are supposed to determine whether to send the actual request or not. The CORS filter only response to the preflight requests according to its configuration. It won't deny any requests. The browsers are responsible for enforcing the CORS policy. -```shell ## Clean-Up From 3b12946506b37d6f0f66cc105d8893d8ef79d9f2 Mon Sep 17 00:00:00 2001 From: Ardika Bagus S Date: Sat, 11 Nov 2023 01:26:01 +0700 Subject: [PATCH 51/55] test: add e2e test for CORS (#2169) Signed-off-by: Ardika Bagus --- test/e2e/testdata/cors.yaml | 49 ++++++++++++++ test/e2e/tests/cors.go | 128 ++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 test/e2e/testdata/cors.yaml create mode 100644 test/e2e/tests/cors.go diff --git a/test/e2e/testdata/cors.yaml b/test/e2e/testdata/cors.yaml new file mode 100644 index 00000000000..1967fc96288 --- /dev/null +++ b/test/e2e/testdata/cors.yaml @@ -0,0 +1,49 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: cors-example + namespace: gateway-conformance-infra +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: http-with-cors + namespace: gateway-conformance-infra + cors: + allowOrigins: + - type: Exact + value: "https://www.foo.com" + - type: Exact + value: "https://www.bar.com" + - type: RegularExpression + value: "https://[a-zA-Z0-9]+.foobar.com" + allowMethods: + - GET + - POST + - PUT + - PATCH + - DELETE + - OPTIONS + allowHeaders: + - "x-header-1" + - "x-header-2" + exposeHeaders: + - "x-header-3" + - "x-header-4" +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-with-cors + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /cors + backendRefs: + - name: infra-backend-v1 + port: 8080 diff --git a/test/e2e/tests/cors.go b/test/e2e/tests/cors.go new file mode 100644 index 00000000000..4b4e54bcc8f --- /dev/null +++ b/test/e2e/tests/cors.go @@ -0,0 +1,128 @@ +// 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/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, CorsTest) +} + +var CorsTest = suite.ConformanceTest{ + ShortName: "Cors", + Description: "Resource with CORS enabled", + Manifests: []string{"testdata/cors.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("should enable cors with Allow Origin Exact", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-with-cors", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/cors", + Headers: map[string]string{ + "Origin": "https://www.foo.com", + }, + }, + Response: http.Response{ + StatusCode: 200, + Headers: map[string]string{ + "access-control-allow-origin": "https://www.foo.com", + "access-control-expose-headers": "x-header-3, x-header-4", + }, + }, + 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) + } + }) + + t.Run("should enable cors with Allow Origin Regex", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-with-cors", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/cors", + Method: "OPTIONS", + Headers: map[string]string{ + "Origin": "https://anydomain.foobar.com", + }, + }, + Response: http.Response{ + StatusCode: 200, + Headers: map[string]string{ + "access-control-allow-origin": "https://anydomain.foobar.com", + "access-control-expose-headers": "x-header-3, x-header-4", + }, + }, + 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) + } + }) + + t.Run("should not contain cors headers when Origin not registered", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-with-cors", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/cors", + Headers: map[string]string{ + "Origin": "https://unknown.foo.com", + }, + }, + Response: http.Response{ + AbsentHeaders: []string{"access-control-allow-origin", "access-control-expose-headers"}, + }, + 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) + } + }) + }, +} From c7f9e2230664354652845e61ad816ca190b48259 Mon Sep 17 00:00:00 2001 From: Fabrice Aneche Date: Fri, 10 Nov 2023 13:38:05 -0500 Subject: [PATCH 52/55] docs: fix typo in bootstrap example (#2171) Fix documentation for bootstrap Signed-off-by: Fabrice Aneche --- site/content/en/latest/user/customize-envoyproxy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/en/latest/user/customize-envoyproxy.md b/site/content/en/latest/user/customize-envoyproxy.md index b0ece5dd2be..278989d53b5 100644 --- a/site/content/en/latest/user/customize-envoyproxy.md +++ b/site/content/en/latest/user/customize-envoyproxy.md @@ -236,7 +236,7 @@ metadata: spec: bootstrap: type: Replace - bootstrap: | + value: | admin: access_log: - name: envoy.access_loggers.file From 72fc329fa2b5068687a431674012c07c471865e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 11:40:18 -0800 Subject: [PATCH 53/55] build(deps): bump github.com/golangci/golangci-lint from 1.55.1 to 1.55.2 in /tools/src/golangci-lint (#2164) build(deps): bump github.com/golangci/golangci-lint Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.55.1 to 1.55.2. - [Release notes](https://github.com/golangci/golangci-lint/releases) - [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md) - [Commits](https://github.com/golangci/golangci-lint/compare/v1.55.1...v1.55.2) --- updated-dependencies: - dependency-name: github.com/golangci/golangci-lint dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/src/golangci-lint/go.mod | 6 +++--- tools/src/golangci-lint/go.sum | 32 ++++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/tools/src/golangci-lint/go.mod b/tools/src/golangci-lint/go.mod index 35588a57d89..dfd11cf4b25 100644 --- a/tools/src/golangci-lint/go.mod +++ b/tools/src/golangci-lint/go.mod @@ -2,7 +2,7 @@ module local go 1.21 -require github.com/golangci/golangci-lint v1.55.1 +require github.com/golangci/golangci-lint v1.55.2 require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect @@ -29,7 +29,7 @@ require ( github.com/bombsimon/wsl/v3 v3.4.0 // indirect github.com/breml/bidichk v0.2.7 // indirect github.com/breml/errchkjson v0.3.6 // indirect - github.com/butuzov/ireturn v0.2.1 // indirect + github.com/butuzov/ireturn v0.2.2 // indirect github.com/butuzov/mirror v1.1.0 // indirect github.com/catenacyber/perfsprint v0.2.0 // indirect github.com/ccojocar/zxcvbn-go v1.0.1 // indirect @@ -112,7 +112,7 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.11.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.14.0 // indirect + github.com/nunnatsa/ginkgolinter v0.14.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect diff --git a/tools/src/golangci-lint/go.sum b/tools/src/golangci-lint/go.sum index 44df080f2e0..8c0d284fc64 100644 --- a/tools/src/golangci-lint/go.sum +++ b/tools/src/golangci-lint/go.sum @@ -63,9 +63,11 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0 github.com/OpenPeeDeeP/depguard/v2 v2.1.0 h1:aQl70G173h/GZYhWf36aE5H0KaujXfVMnn/f1kSDVYY= github.com/OpenPeeDeeP/depguard/v2 v2.1.0/go.mod h1:PUBgk35fX4i7JDmwzlJwJ+GMe6NfO1723wmJMgPThNQ= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= +github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/go-check-sumtype v0.1.3 h1:M+tqMxB68hcgccRXBMVCPI4UJ+QUfdSx0xdbypKCqA8= github.com/alecthomas/go-check-sumtype v0.1.3/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= +github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -82,6 +84,7 @@ github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1 github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -96,8 +99,8 @@ github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY= github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ= github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA= github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U= -github.com/butuzov/ireturn v0.2.1 h1:w5Ks4tnfeFDZskGJ2x1GAkx5gaQV+kdU3NKNr3NEBzY= -github.com/butuzov/ireturn v0.2.1/go.mod h1:RfGHUvvAuFFxoHKf4Z8Yxuh6OjlCw1KvR2zM1NFHeBk= +github.com/butuzov/ireturn v0.2.2 h1:jWI36dxXwVrI+RnXDwux2IZOewpmfv930OuIRfaBUJ0= +github.com/butuzov/ireturn v0.2.2/go.mod h1:RfGHUvvAuFFxoHKf4Z8Yxuh6OjlCw1KvR2zM1NFHeBk= github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE= github.com/catenacyber/perfsprint v0.2.0 h1:azOocHLscPjqXVJ7Mf14Zjlkn4uNua0+Hcg1wTR6vUo= @@ -146,6 +149,7 @@ github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4 github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= @@ -164,8 +168,10 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= @@ -178,6 +184,7 @@ github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlN github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= @@ -226,8 +233,8 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6 github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e h1:ULcKCDV1LOZPFxGZaA6TlQbiM3J2GCPnkx/bGF6sX/g= github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e/go.mod h1:Pm5KhLPA8gSnQwrQ6ukebRcapGb/BG9iUkdaiCcGHJM= -github.com/golangci/golangci-lint v1.55.1 h1:DL2j9Eeapg1N3WEkKnQFX5L40SYtjZZJjGVdyEgNrDc= -github.com/golangci/golangci-lint v1.55.1/go.mod h1:z00biPRqjo5MISKV1+RWgONf2KvrPDmfqxHpHKB6bI4= +github.com/golangci/golangci-lint v1.55.2 h1:yllEIsSJ7MtlDBwDJ9IMBkyEUz2fYE0b5B8IUgO1oP8= +github.com/golangci/golangci-lint v1.55.2/go.mod h1:H60CZ0fuqoTwlTvnbyjhpZPWp7KmsjwV2yupIMiMXbM= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= @@ -269,6 +276,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -287,6 +295,7 @@ github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3 github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -333,9 +342,11 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= github.com/kunwardeep/paralleltest v1.0.8 h1:Ul2KsqtzFxTlSU7IP0JusWlLiNqQaloB9vguyjbE558= @@ -391,18 +402,22 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nishanths/exhaustive v0.11.0 h1:T3I8nUGhl/Cwu5Z2hfc92l0e04D2GEW6e0l8pzda2l0= github.com/nishanths/exhaustive v0.11.0/go.mod h1:RqwDsZ1xY0dNdqHho2z6X+bgzizwbLYOWnZbbl2wLB4= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.14.0 h1:XQPNmw+kZz5cC/HbFK3mQutpjzAQv1dHregRA+4CGGg= -github.com/nunnatsa/ginkgolinter v0.14.0/go.mod h1:cm2xaqCUCRd7qcP4DqbVvpcyEMkuLM9CF0wY6VASohk= +github.com/nunnatsa/ginkgolinter v0.14.1 h1:khx0CqR5U4ghsscjJ+lZVthp3zjIFytRXPTaQ/TMiyA= +github.com/nunnatsa/ginkgolinter v0.14.1/go.mod h1:nY0pafUSst7v7F637e7fymaMlQqI9c0Wka2fGsDkzWg= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= +github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.11.0 h1:OKBD80J/mLBrwnzXqGtFCzprFSGioo30JcmR4APsNwc= +github.com/otiai10/copy v1.11.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= @@ -452,6 +467,7 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4l github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= @@ -558,6 +574,7 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t gitlab.com/bosi/decorder v0.4.1 h1:VdsdfxhstabyhZovHafFw+9eJ6eU0d2CkFNJcZz/NU4= gitlab.com/bosi/decorder v0.4.1/go.mod h1:jecSqWUew6Yle1pCr2eLWTensJMmsxHsBwt+PVbkAqA= go-simpler.org/assert v0.6.0 h1:QxSrXa4oRuo/1eHMXSBFHKvJIpWABayzKldqZyugG7E= +go-simpler.org/assert v0.6.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go-simpler.org/sloglint v0.1.2 h1:IjdhF8NPxyn0Ckn2+fuIof7ntSnVUAqBFcQRrnG9AiM= go-simpler.org/sloglint v0.1.2/go.mod h1:2LL+QImPfTslD5muNPydAEYmpXIj6o/WYcqnJjLi4o4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -571,6 +588,7 @@ go.tmz.dev/musttag v0.7.2/go.mod h1:m6q5NiiSKMnQYokefa2xGoyoXnrswCbJ0AWYzf4Zs28= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= @@ -675,6 +693,7 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -953,6 +972,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= From 8acb1ee0ab375221fb82dc7fe034ef6dded9ac6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 11:40:37 -0800 Subject: [PATCH 54/55] build(deps): bump envoyproxy/toolshed from actions-v0.1.2 to 0.1.15 (#2163) Bumps [envoyproxy/toolshed](https://github.com/envoyproxy/toolshed) from actions-v0.1.2 to 0.1.15. This release includes the previously tagged commit. - [Release notes](https://github.com/envoyproxy/toolshed/releases) - [Commits](https://github.com/envoyproxy/toolshed/compare/actions-v0.1.2...actions-v0.1.15) --- updated-dependencies: - dependency-name: envoyproxy/toolshed dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/retest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/retest.yaml b/.github/workflows/retest.yaml index 4acd9584681..74470a84ff1 100644 --- a/.github/workflows/retest.yaml +++ b/.github/workflows/retest.yaml @@ -22,6 +22,6 @@ jobs: pull-requests: write actions: write steps: - - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.1.2 + - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.1.15 with: token: ${{ secrets.GITHUB_TOKEN }} From c85f0e438ec3c41048739e794f27f3a33e853df0 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Sat, 11 Nov 2023 04:10:59 +0800 Subject: [PATCH 55/55] opt: move gateway namespace mode to common helper (#2129) opt: codes Signed-off-by: bitliu --- api/v1alpha1/envoygateway_helpers.go | 9 +++++++++ internal/provider/kubernetes/kubernetes.go | 9 +-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/api/v1alpha1/envoygateway_helpers.go b/api/v1alpha1/envoygateway_helpers.go index ef9ab69706b..25866ed1203 100644 --- a/api/v1alpha1/envoygateway_helpers.go +++ b/api/v1alpha1/envoygateway_helpers.go @@ -76,6 +76,15 @@ func (e *EnvoyGateway) GetEnvoyGatewayAdminAddress() string { return "" } +// NamespaceMode returns if uses namespace mode. +func (e *EnvoyGateway) NamespaceMode() bool { + return e.Provider != nil && + e.Provider.Kubernetes != nil && + e.Provider.Kubernetes.Watch != nil && + e.Provider.Kubernetes.Watch.Type == KubernetesWatchModeTypeNamespaces && + len(e.Provider.Kubernetes.Watch.Namespaces) > 0 +} + // DefaultGateway returns a new Gateway with default configuration parameters. func DefaultGateway() *Gateway { return &Gateway{ diff --git a/internal/provider/kubernetes/kubernetes.go b/internal/provider/kubernetes/kubernetes.go index f9bfc6d73cf..104400f2b05 100644 --- a/internal/provider/kubernetes/kubernetes.go +++ b/internal/provider/kubernetes/kubernetes.go @@ -16,7 +16,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway" "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/message" @@ -43,13 +42,7 @@ func New(cfg *rest.Config, svr *config.Server, resources *message.ProviderResour } // TODO: implement config validation on the watch mode config - namespacedMode := - svr.EnvoyGateway.Provider != nil && - svr.EnvoyGateway.Provider.Kubernetes != nil && - (svr.EnvoyGateway.Provider.Kubernetes.Watch != nil) && - (svr.EnvoyGateway.Provider.Kubernetes.Watch.Type == v1alpha1.KubernetesWatchModeTypeNamespaces) && - (len(svr.EnvoyGateway.Provider.Kubernetes.Watch.Namespaces) > 0) - if namespacedMode { + if svr.EnvoyGateway.NamespaceMode() { mgrOpts.Cache.DefaultNamespaces = make(map[string]cache.Config) for _, watchNS := range svr.EnvoyGateway.Provider.Kubernetes.Watch.Namespaces { mgrOpts.Cache.DefaultNamespaces[watchNS] = cache.Config{}