-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
ext_proc: metadata and attributes #29069
Conversation
Hi @jbohanon, welcome and thank you for your contribution. We will try to review your Pull Request as quickly as possible. In the meantime, please take a look at the contribution guidelines if you have not done so already. |
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
/assign @tyxia |
// | ||
// It works in a way similar to ``metadata_context_namespaces`` but allows envoy and external processing server to share the protobuf message definition | ||
// in order to do a safe parsing. | ||
repeated string typed_metadata_context_namespaces = 17; |
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.
Updated comment after really reading the comments..
We could collapse both into a single field cant we?
metadata_namespaces_to_forward
untyped:
- namespaces
typed:
- namespaces
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've updated the proto changes to enable route-level overrides and in the process cleaned up this naming a bit.
encoder_callbacks_->connection()->streamInfo().dynamicMetadata().filter_metadata(); | ||
const auto& request_encoder_metadata = | ||
encoder_callbacks_->streamInfo().dynamicMetadata().filter_metadata(); | ||
for (const auto& context_key : config_->metadataContextNamespaces()) { |
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.
So we have four sources for {typed, }metadata.
What if they context_key is found in multiple sources?
Can we consider to have some sort of finer grained filtering list, that way you could also save unnecessary dict look ups.
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 have cut the lookups at least in half by dynamically determining from which callbacks we should be fetching the stream info to access the metadata. Currently, as stated in the comments, the request metadata will have precedent over the connection metadata.
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.
Thanks for working on it!
*req.mutable_metadata_context() = metadata_context; | ||
} | ||
|
||
void setDynamicMetadata(std::string ns, Http::StreamFilterCallbacks* cb, |
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.
This assumes we fully trust whatever is sent from the external server, can we add knobs to control (disable, filter ) what could be added into Envoy?
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 don't think this is necessary for a few reasons:
- The external processing filter is listed as unknown security posture, only to be used with both trusted upstreams and downstreams
- The external processing server has nearly arbitrary control over the request/response as it is, so I think it is safe to assume that it should be a trusted piece of code, at least as trusted as a custom Envoy filter which would be able to write dynamic metadata
- The returned metadata is only able to be written into dynamic metadata in the ext_proc filter's own namespace.
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.
- its going to change soon. We have been vetting it and @yanjunxiang-google is going to flip this to trusted filter soon
- Not true.. if you look at all the knobs we have added recently, we are really tying to limit what an external server can and cannot do so that those who want to use it against trusted systems can do so without knobs but those who need to use it against untrusted systems can rely on the knobs to tightly control what can/cannot be done.
- follows 2 above in case of untrusted servers
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've added the ability to disable writing the returned metadata. I think this is a good level of control for this initial implementation, but if more granularity is required for this work to merge, can you please point me to another similar implementation of the filtering?
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.
Thanks for adding the control knob. Yes, that's right. We are going to flip this filter to be robust to untrusted downstream/upstream soon.
@@ -158,7 +161,6 @@ message ProcessingResponse { | |||
ImmediateResponse immediate_response = 7; | |||
} | |||
|
|||
// [#not-implemented-hide:] | |||
// Optional metadata that will be emitted as dynamic metadata to be consumed by the next | |||
// filter. This metadata will be placed in the namespace ``envoy.filters.http.ext_proc``. | |||
google.protobuf.Struct dynamic_metadata = 8; |
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.
Could we please add a knob for disabling this on Envoy side? just like disable immediate response etc..
Given the growing list of knobs, I wonder if this is an opportunity to consolidate all these enable/disable toggles into a message called serverCapabilities that has header mutation rules, allow_immediate_response, allow_dynamic_metadata, mode overrides, etc. And this capability proto should technically be advertised in the ProcessingRequest as well so that the ext_proc server knows what is and what is not allowed by the server.
Even if there is no appetite to do this capability thingy, we really need a boolean guard for every new piece of data that we will allow Envoy to accept from the Ext proc server. Some of our products use this filter to talk to untrusted services and we would like to be strict about what things our data plane ingests from a remote ext_proc server. Hence the reason for toggles like immediate response, mode overrides, etc.
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 am happy to add a setting to allow disabling returned metadata to be written. I think that adding a capabilities message is outside the scope of this piece of work though
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.
Given that this is already live in our systems, could you please turn this into a "enable_foo" knob rather than disable_foo ?
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.
Yes I have changed it to opt-in
90c4b39
to
e7fb495
Compare
e7fb495
to
f0324c3
Compare
/assign @htuch |
3123bf4
to
1df3763
Compare
|
||
// If set to true, metadata returned from the external processing server will | ||
// be written into the stream's dynamic metadata. | ||
bool enable_returned_metadata = 2; |
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.
why cant this be namespaces_to_forward, namespaces_to_accept ?
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.
Is it desired to allow writing to arbitrary metadata namespaces?
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.
Is there a specific use-case you're thinking of? It seems to me that it is safer and more consistent to keep all of the returned metadata under the ext_proc namespace to prevent the external service from overwriting internal filters' data
@rshriram long time! Can we meet so we can move this forward and make sure we are not stepping on each other toes as it looks like both of our teams are working in this area. |
seems this has some design decisions to work through in the meantime @jbohanon the CI fails look real /wait |
69385a5
to
f17e7d7
Compare
Signed-off-by: Jacob Bohanon <jacob.bohanon@solo.io>
…in the codebase Signed-off-by: Jacob Bohanon <jacob.bohanon@solo.io>
Signed-off-by: Jacob Bohanon <jacob.bohanon@solo.io>
5899892
to
a3eeec6
Compare
Signed-off-by: Jacob Bohanon <jacob.bohanon@solo.io>
/retest |
@tyxia @yanjunxiang-google bumping this request. |
The API changes LGTM. Thanks for accommodating our requests. |
Apologize for delay. I will take a look this week if that is OK. I think introducing CEL is ok but i think there is a better way of introducing it to ext_proc. I will comment with more details once I get the chance to take a close look of full PR. |
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 just looked at the matching part. I think we should introduce xds.type.matcher.v3.Matcher
(i.e. Unified Matcher API) to ext_proc rather than CEL-only approach here, because:
- It will be more powerful and flexible: With matching API, it not only supports the CEL, but
also supports various matching API such as stringMatcher, etc. Also, it provides linear
and sublinear matching. Thus, the matching mechanism can be customized by ext_proc
end-user based on their use case. - It avoids expressive operations like CEL parsing(and checking if needed) in dataplane.
CEL team recommend doing this in control plane - It will be a much cleaner implementation. I think the CEL related functionalities in this PR
are already available in the shared cel_input and cel_match extension. It can be reused in ext_proc by several lines of code.
You can refer to match_delegate and rate_limit_quota for examples. They are http filters using CEL already.
Furthermore, I think the matching-related stuff is technically separated from the main objective of this PR –- send/receive dynamic metadata and attributes. Therefore, I would recommend making this PR more self-contained and smaller by splitting the matching to a separate PR, if possible. This will also help robustness and review of this pr, which help move this PR forward.
@rshriram I am on parental leave for a couple weeks more but I will ping my team to check on our priority for this |
/lgtm api |
I don't agree that this would be an appropriate place to introduce the Unified Matcher API. Primarily because we are not taking user-provided predicates and performing a disparate action based on the outcome, rather we are utilizing CEL to look up the values represented by these attributes and send them to the processing server.
It is not relevant to support alternate methods of matching because Attributes are implemented explicitly in CEL and not anywhere else
The expression parsing as implemented in this PR is done at config-time rather than at request-time. If absolutely necessary, we could look into parsing on the control plane and passing a parsed expression in via config, but this seems like it would add unnecessary readability issues into the config provided to Envoy. I admit the added complexity of the
IF we were to pass in parsed expressions, it is possible that we could use the cel_input's
Each of these filters are using CEL to achieve a different result than we need here. Again, the goal here is to access the actual data which the attribute represents, not to assess it against a pre-determined predicate |
Signed-off-by: Jacob Bohanon <jacob.bohanon@solo.io>
Signed-off-by: Jacob Bohanon <jacob.bohanon@solo.io>
@jbohanon Sorry i have been busy with other projects and haven't got a chance to really look into this PR. But a few things from quick scan regarding your last comment: ---> "this seems like it would add unnecessary readability issues into the config provided to Envoy" Back to the motivation of using CEL: you are using CEL is only because Attributes are implemented explicitly in CEL and you use CEL for attributes look up? |
Signed-off-by: Jacob Bohanon <jacob.bohanon@solo.io>
Signed-off-by: Jacob Bohanon <jacob.bohanon@solo.io>
…a-unmerged extract metadata changes from envoyproxy#29069
Commit Message:
Introduce the ability to send dynamic metadata and attributes in the External Processing Request. Also implements the API for returning dynamic metadata as part of the External Processing Response
Additional Description:
Risk Level:
Low
Testing:
Docs Changes: TODO
Release Notes: N/A
Platform Specific Features: N/A
Fixes #19881