diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go
index a8bb1505717..6fcc35e18ca 100644
--- a/api/v1alpha1/envoyproxy_types.go
+++ b/api/v1alpha1/envoyproxy_types.go
@@ -86,8 +86,92 @@ type EnvoyProxySpec struct {
//
// +optional
Shutdown *ShutdownConfig `json:"shutdown,omitempty"`
+
+ // FilterOrder defines the order of filters in the Envoy proxy's HTTP filter chain.
+ // If unspecified, the default filter order is applied.
+ // Default filter order is:
+ //
+ // - envoy.filters.http.fault
+ //
+ // - envoy.filters.http.cors
+ //
+ // - envoy.filters.http.ext_authz
+ //
+ // - envoy.filters.http.basic_authn
+ //
+ // - envoy.filters.http.oauth2
+ //
+ // - envoy.filters.http.jwt_authn
+ //
+ // - envoy.filters.http.ext_proc
+ //
+ // - envoy.filters.http.wasm
+ //
+ // - envoy.filters.http.local_ratelimit
+ //
+ // - envoy.filters.http.ratelimit
+ //
+ // - envoy.filters.http.router
+ //
+ // +optional
+ // +notImplementedHide
+ FilterOrder []FilterPosition `json:"filterOrder,omitempty"`
}
+// FilterPosition defines the position of an Envoy HTTP filter in the filter chain.
+// +kubebuilder:validation:XValidation:rule="(has(self.before) || has(self.after))",message="one of before or after must be specified"
+// +kubebuilder:validation:XValidation:rule="(has(self.before) && !has(self.after)) || (!has(self.before) && has(self.after))",message="only one of before or after can be specified"
+type FilterPosition struct {
+ // Name of the filter.
+ Name EnvoyFilter `json:"filter"`
+
+ // Before defines the filter that should come before the filter.
+ // Only one of Before or After must be set.
+ Before *EnvoyFilter `json:"before,omitempty"`
+
+ // After defines the filter that should come after the filter.
+ // Only one of Before or After must be set.
+ After *EnvoyFilter `json:"after,omitempty"`
+}
+
+// EnvoyFilter defines the type of Envoy HTTP filter.
+// +kubebuilder:validation:Enum=envoy.filters.http.cors;envoy.filters.http.ext_authz;envoy.filters.http.basic_authn;envoy.filters.http.oauth2;envoy.filters.http.jwt_authn;envoy.filters.http.fault;envoy.filters.http.local_ratelimit;envoy.filters.http.ratelimit;envoy.filters.http.wasm;envoy.filters.http.ext_proc
+type EnvoyFilter string
+
+const (
+ // EnvoyFilterFault defines the Envoy HTTP fault filter.
+ EnvoyFilterFault EnvoyFilter = "envoy.filters.http.fault"
+ // EnvoyFilterCORS defines the Envoy HTTP CORS filter.
+ EnvoyFilterCORS EnvoyFilter = "envoy.filters.http.cors"
+
+ // EnvoyFilterExtAuthz defines the Envoy HTTP external authorization filter.
+ EnvoyFilterExtAuthz EnvoyFilter = "envoy.filters.http.ext_authz"
+
+ // EnvoyFilterBasicAuthn defines the Envoy HTTP basic authentication filter.
+ EnvoyFilterBasicAuthn EnvoyFilter = "envoy.filters.http.basic_authn"
+
+ // EnvoyFilterOAuth2 defines the Envoy HTTP OAuth2 filter.
+ EnvoyFilterOAuth2 EnvoyFilter = "envoy.filters.http.oauth2"
+
+ // EnvoyFilterJWTAuthn defines the Envoy HTTP JWT authentication filter.
+ EnvoyFilterJWTAuthn EnvoyFilter = "envoy.filters.http.jwt_authn"
+
+ // EnvoyFilterExtProc defines the Envoy HTTP external process filter.
+ EnvoyFilterExtProc EnvoyFilter = "envoy.filters.http.ext_proc"
+
+ // EnvoyFilterWasm defines the Envoy HTTP WebAssembly filter.
+ EnvoyFilterWasm EnvoyFilter = "envoy.filters.http.wasm"
+
+ // EnvoyFilterLocalRateLimit defines the Envoy HTTP local rate limit filter.
+ EnvoyFilterLocalRateLimit EnvoyFilter = "envoy.filters.http.local_ratelimit"
+
+ // EnvoyFilterRateLimit defines the Envoy HTTP rate limit filter.
+ EnvoyFilterRateLimit EnvoyFilter = "envoy.filters.http.ratelimit"
+
+ // EnvoyFilterRouter defines the Envoy HTTP router filter.
+ EnvoyFilterRouter EnvoyFilter = "envoy.filters.http.router"
+)
+
type ProxyTelemetry struct {
// AccessLogs defines accesslog parameters for managed proxies.
// If unspecified, will send default format to stdout.
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 0055d7669f1..a1a7ca77f73 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -1507,6 +1507,13 @@ func (in *EnvoyProxySpec) DeepCopyInto(out *EnvoyProxySpec) {
*out = new(ShutdownConfig)
(*in).DeepCopyInto(*out)
}
+ if in.FilterOrder != nil {
+ in, out := &in.FilterOrder, &out.FilterOrder
+ *out = make([]FilterPosition, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxySpec.
@@ -1814,6 +1821,31 @@ func (in *FileEnvoyProxyAccessLog) DeepCopy() *FileEnvoyProxyAccessLog {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *FilterPosition) DeepCopyInto(out *FilterPosition) {
+ *out = *in
+ if in.Before != nil {
+ in, out := &in.Before, &out.Before
+ *out = new(EnvoyFilter)
+ **out = **in
+ }
+ if in.After != nil {
+ in, out := &in.After, &out.After
+ *out = new(EnvoyFilter)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FilterPosition.
+func (in *FilterPosition) DeepCopy() *FilterPosition {
+ if in == nil {
+ return nil
+ }
+ out := new(FilterPosition)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GRPCExtAuthService) DeepCopyInto(out *GRPCExtAuthService) {
*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 76d96eccaea..beecbf18eb3 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
@@ -85,6 +85,104 @@ spec:
items:
type: string
type: array
+ filterOrder:
+ description: |-
+ FilterOrder defines the order of filters in the Envoy proxy's HTTP filter chain.
+ If unspecified, the default filter order is applied.
+ Default filter order is:
+
+
+ - envoy.filters.http.fault
+
+
+ - envoy.filters.http.cors
+
+
+ - envoy.filters.http.ext_authz
+
+
+ - envoy.filters.http.basic_authn
+
+
+ - envoy.filters.http.oauth2
+
+
+ - envoy.filters.http.jwt_authn
+
+
+ - envoy.filters.http.ext_proc
+
+
+ - envoy.filters.http.wasm
+
+
+ - envoy.filters.http.local_ratelimit
+
+
+ - envoy.filters.http.ratelimit
+
+
+ - envoy.filters.http.router
+ items:
+ description: FilterPosition defines the position of an Envoy HTTP
+ filter in the filter chain.
+ properties:
+ after:
+ description: |-
+ After defines the filter that should come after the filter.
+ Only one of Before or After must be set.
+ enum:
+ - envoy.filters.http.cors
+ - envoy.filters.http.ext_authz
+ - envoy.filters.http.basic_authn
+ - envoy.filters.http.oauth2
+ - envoy.filters.http.jwt_authn
+ - envoy.filters.http.fault
+ - envoy.filters.http.local_ratelimit
+ - envoy.filters.http.ratelimit
+ - envoy.filters.http.wasm
+ - envoy.filters.http.ext_proc
+ type: string
+ before:
+ description: |-
+ Before defines the filter that should come before the filter.
+ Only one of Before or After must be set.
+ enum:
+ - envoy.filters.http.cors
+ - envoy.filters.http.ext_authz
+ - envoy.filters.http.basic_authn
+ - envoy.filters.http.oauth2
+ - envoy.filters.http.jwt_authn
+ - envoy.filters.http.fault
+ - envoy.filters.http.local_ratelimit
+ - envoy.filters.http.ratelimit
+ - envoy.filters.http.wasm
+ - envoy.filters.http.ext_proc
+ type: string
+ filter:
+ description: Name of the filter.
+ enum:
+ - envoy.filters.http.cors
+ - envoy.filters.http.ext_authz
+ - envoy.filters.http.basic_authn
+ - envoy.filters.http.oauth2
+ - envoy.filters.http.jwt_authn
+ - envoy.filters.http.fault
+ - envoy.filters.http.local_ratelimit
+ - envoy.filters.http.ratelimit
+ - envoy.filters.http.wasm
+ - envoy.filters.http.ext_proc
+ type: string
+ required:
+ - filter
+ type: object
+ x-kubernetes-validations:
+ - message: one of before or after must be specified
+ rule: (has(self.before) || has(self.after))
+ - message: only one of before or after can be specified
+ rule: (has(self.before) && !has(self.after)) || (!has(self.before)
+ && has(self.after))
+ type: array
logging:
default:
level:
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index a9847ac0645..526e8012502 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -648,6 +648,30 @@ _Appears in:_
| `extProc` | _[ExtProc](#extproc) array_ | true | ExtProc is an ordered list of external processing filters
that should added to the envoy filter chain |
+#### EnvoyFilter
+
+_Underlying type:_ _string_
+
+EnvoyFilter defines the type of Envoy HTTP filter.
+
+_Appears in:_
+- [FilterPosition](#filterposition)
+
+| Value | Description |
+| ----- | ----------- |
+| `envoy.filters.http.fault` | EnvoyFilterFault defines the Envoy HTTP fault filter.
|
+| `envoy.filters.http.cors` | EnvoyFilterCORS defines the Envoy HTTP CORS filter.
|
+| `envoy.filters.http.ext_authz` | EnvoyFilterExtAuthz defines the Envoy HTTP external authorization filter.
|
+| `envoy.filters.http.basic_authn` | EnvoyFilterBasicAuthn defines the Envoy HTTP basic authentication filter.
|
+| `envoy.filters.http.oauth2` | EnvoyFilterOAuth2 defines the Envoy HTTP OAuth2 filter.
|
+| `envoy.filters.http.jwt_authn` | EnvoyFilterJWTAuthn defines the Envoy HTTP JWT authentication filter.
|
+| `envoy.filters.http.ext_proc` | EnvoyFilterExtProc defines the Envoy HTTP external process filter.
|
+| `envoy.filters.http.wasm` | EnvoyFilterWasm defines the Envoy HTTP WebAssembly filter.
|
+| `envoy.filters.http.local_ratelimit` | EnvoyFilterLocalRateLimit defines the Envoy HTTP local rate limit filter.
|
+| `envoy.filters.http.ratelimit` | EnvoyFilterRateLimit defines the Envoy HTTP rate limit filter.
|
+| `envoy.filters.http.router` | EnvoyFilterRouter defines the Envoy HTTP router filter.
|
+
+
#### EnvoyGateway
@@ -1302,6 +1326,22 @@ _Appears in:_
| `path` | _string_ | true | Path defines the file path used to expose envoy access log(e.g. /dev/stdout). |
+#### FilterPosition
+
+
+
+FilterPosition defines the position of an Envoy HTTP filter in the filter chain.
+
+_Appears in:_
+- [EnvoyProxySpec](#envoyproxyspec)
+
+| Field | Type | Required | Description |
+| --- | --- | --- | --- |
+| `filter` | _[EnvoyFilter](#envoyfilter)_ | true | Name of the filter. |
+| `before` | _[EnvoyFilter](#envoyfilter)_ | true | Before defines the filter that should come before the filter.
Only one of Before or After must be set. |
+| `after` | _[EnvoyFilter](#envoyfilter)_ | true | After defines the filter that should come after the filter.
Only one of Before or After must be set. |
+
+
#### GRPCExtAuthService
diff --git a/test/cel-validation/envoyproxy_test.go b/test/cel-validation/envoyproxy_test.go
index 3b2785f713d..e6d88ff2c77 100644
--- a/test/cel-validation/envoyproxy_test.go
+++ b/test/cel-validation/envoyproxy_test.go
@@ -1219,6 +1219,62 @@ func TestEnvoyProxyProvider(t *testing.T) {
}
},
},
+ {
+ desc: "ProxyFilterOrder-with-before-and-after",
+ mutate: func(envoy *egv1a1.EnvoyProxy) {
+ envoy.Spec = egv1a1.EnvoyProxySpec{
+ FilterOrder: []egv1a1.FilterPosition{
+ {
+ Name: egv1a1.EnvoyFilterRateLimit,
+ Before: ptr.To(egv1a1.EnvoyFilterCORS),
+ After: ptr.To(egv1a1.EnvoyFilterBasicAuthn),
+ },
+ },
+ }
+ },
+ wantErrors: []string{"only one of before or after can be specified"},
+ },
+ {
+ desc: "ProxyFilterOrder-without-before-or-after",
+ mutate: func(envoy *egv1a1.EnvoyProxy) {
+ envoy.Spec = egv1a1.EnvoyProxySpec{
+ FilterOrder: []egv1a1.FilterPosition{
+ {
+ Name: egv1a1.EnvoyFilterRateLimit,
+ },
+ },
+ }
+ },
+ wantErrors: []string{"one of before or after must be specified"},
+ },
+ {
+ desc: "ProxyFilterOrder-with-before",
+ mutate: func(envoy *egv1a1.EnvoyProxy) {
+ envoy.Spec = egv1a1.EnvoyProxySpec{
+ FilterOrder: []egv1a1.FilterPosition{
+ {
+ Name: egv1a1.EnvoyFilterRateLimit,
+ Before: ptr.To(egv1a1.EnvoyFilterCORS),
+ },
+ },
+ }
+ },
+ wantErrors: []string{},
+ },
+ {
+ desc: "ProxyFilterOrder-with-after",
+ mutate: func(envoy *egv1a1.EnvoyProxy) {
+ envoy.Spec = egv1a1.EnvoyProxySpec{
+ FilterOrder: []egv1a1.FilterPosition{
+ {
+ Name: egv1a1.EnvoyFilterRateLimit,
+ After: ptr.To(egv1a1.EnvoyFilterBasicAuthn),
+ },
+ },
+ }
+ },
+ wantErrors: []string{},
+ },
}
for _, tc := range cases {
@@ -1237,7 +1293,7 @@ func TestEnvoyProxyProvider(t *testing.T) {
}
if (len(tc.wantErrors) != 0) != (err != nil) {
- t.Fatalf("Unexpected response while creating EnvoyProxy; got err=\n%v\n;want error=%v", err, tc.wantErrors != nil)
+ t.Fatalf("Unexpected response while creating EnvoyProxy; got err=\n%v\n;want error=%v", err, tc.wantErrors)
}
var missingErrorStrings []string