-
Notifications
You must be signed in to change notification settings - Fork 360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API: HTTP Filter ordering #2993
Conversation
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2993 +/- ##
==========================================
- Coverage 66.51% 64.55% -1.96%
==========================================
Files 161 121 -40
Lines 22673 21235 -1438
==========================================
- Hits 15080 13709 -1371
+ Misses 6720 6672 -48
+ Partials 873 854 -19 ☔ View full report in Codecov by Sentry. |
f304b14
to
75d7042
Compare
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
75d7042
to
fd26a09
Compare
api/v1alpha1/envoyproxy_types.go
Outdated
// FilterOrder defines the order of filters in the Envoy proxy's HTTP filter chain. | ||
// If unspecified, the default order of filters is applied. | ||
// Default order of filters: | ||
// - envoy.filters.http.cors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can expose a more high-level filter name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used the Envoy filter name so these const variables can be directly used in the code for comparison.
But they could be simplified, maybe just the last part, eg, cors, ext_authz, local_ratelimit, oauth2, etc.
WDYT?
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
defer to @arkodg |
I really like how simple this API is, great stuff @zhaohuabing ! |
api/v1alpha1/envoyproxy_types.go
Outdated
FilterPriority []FilterPriority `json:"filterPriority,omitempty"` | ||
} | ||
|
||
// FilterPriority defines the order of filters in the Envoy proxy's HTTP filter chain. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the API looks good, but lets take a little more time to make sure if we
- agree on this default order
- should we leave a gap for any upcoming feature like
rbac
orcompression
filter or is the 100 gap enough to handle these future cases ?
we cannot change these default priority values going forward
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we leave a gap for any upcoming feature like rbac or compression filter or is the 100 gap enough to handle these future cases ?
We could list all the filters that EG is likely to use.
default order:
The default order of EG: cors ext_authz basic_authn oauth2 jwt_authn fault local_ratelimit ratelimit
The order of envoy filters in Isito: ext_auth jwt_authn rbac fault cors
I think it makes sense to put cors at the last since users probably need to apply fault injection and rate limit to preflight requests as well.
I do think this's a blocker of #2877, a wasm filter can be inserted anywhere in the filter chain. |
Yah, that's correct. But we need more input to make sure we do the API right. In the first iteration of wasm/extproc impl, the priority will be removed to make this none-blocking. We will revisit it right after the wasm extension implementation. |
api/v1alpha1/envoyproxy_types.go
Outdated
// FilterPriority defines the order of filters in the Envoy proxy's HTTP filter chain. | ||
// | ||
// +optional | ||
FilterPriority []FilterPriority `json:"filterPriority,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to clarify the API: as I read it, it's all-or-nothing (you either set a filter order, in which case you need to set every filter you want executed, or you get the default) -- is that correct?
I think that's a reasonable API, but it makes simple things ("add a WASM filter before authn, please") as hard as hard things ("totally re-order how policy is applied, including my WASM, ext_proc, ext_authz, and rate limiting"). It's also very copy+paste heavy: you look up the official order and copy+paste it to start editing, and next time you copy+paste your edited version for the new one, and so on. This winds up making it more expensive to iterate on APIs as a project.
Instead it might be easier to have a split API, along the lines of:
FilterPriority []FilterPriority `json:"filterPriority,omitempty"` | |
type FilterOrder struct { | |
Add []FilterPriority `json:"add,omitempty"` | |
Custom []FilterPriority `json:"custom,omitempty"` | |
} | |
FilterOrder FilterOrder `json:"filterOrder,omitempty"` |
Then for small changes a user can add
, or for total control they can use custom
:
filterOrder:
add:
- filter: envoy.filters.http.wasm
priority: 10
filterOrder:
custom:
- filter: envoy.filters.http.cors
priority: 901
- filter: envoy.filters.http.ext_authz
priority: 801
- filter: envoy.filters.http.basic_authn
priority: 701
- filter: envoy.filters.http.oauth2
priority: 601
- filter: envoy.filters.http.jwt_authn
priority: 501
- filter: envoy.filters.http.fault
priority: 401
- filter: envoy.filters.http.local_ratelimit
priority: 301
- filter: envoy.filters.http.ratelimit
priority: 201
And of course we'd expect the two to work together as well:
# these are the same
filterOrder:
add:
- filter: envoy.filters.http.wasm
priority: 10
custom:
- filter: envoy.filters.http.cors
priority: 901
- filter: envoy.filters.http.ext_authz
priority: 801
- filter: envoy.filters.http.basic_authn
priority: 701
- filter: envoy.filters.http.oauth2
priority: 601
- filter: envoy.filters.http.jwt_authn
priority: 501
- filter: envoy.filters.http.fault
priority: 401
- filter: envoy.filters.http.local_ratelimit
priority: 301
- filter: envoy.filters.http.ratelimit
priority: 201
---
filterOrder:
custom:
- filter: envoy.filters.http.cors
priority: 901
- filter: envoy.filters.http.ext_authz
priority: 801
- filter: envoy.filters.http.basic_authn
priority: 701
- filter: envoy.filters.http.oauth2
priority: 601
- filter: envoy.filters.http.jwt_authn
priority: 501
- filter: envoy.filters.http.fault
priority: 401
- filter: envoy.filters.http.local_ratelimit
priority: 301
- filter: envoy.filters.http.ratelimit
priority: 201
- filter: envoy.filters.http.wasm
priority: 10
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ZackButcher It doesn't have to be a full list.
Each filter comes with a default priority, as the comment shows:
// - envoy.filters.http.cors 0
//
// - envoy.filters.http.ext_authz 100
//
// - envoy.filters.http.basic_authn 200
//
// - envoy.filters.http.oauth2 300
//
// - envoy.filters.http.jwt_authn 400
//
// - envoy.filters.http.fault 500
//
// - envoy.filters.http.local_ratelimit 600
//
// - envoy.filters.http.ratelimit 700
If we need to adjust the oauth2 filter's priority to sit between cors and ext_auth, we can do so with this configuration:
filterPriority:
envoy.filters.http.oauth2: 50
For custom extensions like wasm, lua, and extproc, etc., we're planning to introduce a priority field in their specs since there can be more than one filter per type for an HTTPRoute. For example:
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: EnvoyExtensionPolicy
metadata:
name: app-extensions
spec:
targetRef:
kind: HTTPRoute
name: backend
wasm:
- name: my_plugin_1
priority: 450
code:
image: # the oci image that contains wasm code
url: <oci-registry>.foo.bar.com/my_plugin_1:v1
pullSecret: wasmPullSecret
...
- name: my_plugin_2
priority: 250
code:
image: # the oci image that contains wasm code
url: <oci-registry>.foo.bar.com/my_plugin_2:v1
pullSecret: wasmPullSecret
...
This means my_plugin_1 will be positioned between jwt_authn and fault, and my_plugin_2 will come between basic_authn and jwt_authn.
So, the final order of these filters will be:
cors - 0
oauth2 - 50
basic_authn - 200
wasm_my_plugin_2 - 250
jwt_authn - 400
wasm_my_plugin_1 - 450
fault - 500
local_ratelimit - 600
ratelimit - 700
blocked on #3046 |
hey @zhaohuabing , we brought this up in the community meeting yesterday and @davidalger had a great alternate suggestion - to use
this does improve readability of intent. Flattening this intent out, may result in a loop, which needs to be avoided and flagged in the status (but thats an internal detail) this API can look similar inside the WASM API
this will require us to rely on priority field in EEP to create order across EEPs |
LGreatTM! |
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
API for HCM HTTP filter ordering. This is a global-level config for all the HTTP listeners in Envoy proxy. If the Listener/HTTPRoute level filter ordering is required in the future, we can define a fine-grained API targeting Listener/HTTPRoute.
This is a blocker for #2877
Related issue: #2571