-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
tcp tunneling: optionally move response header to downstream info #23118
Conversation
Signed-off-by: Kuat Yessenov <kuat@google.com>
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
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 picking this up!
Now that I think about it this could be useful for the http11 connect filter: @Augustyniak was just writing an EM integraion test which added to CONNECT response headers and there was no way to validate them elsewhere. If we end up sticking with per-header-name configuration I think it may be worth defining the message somewhere in the base codec protos rather than in the tcp proxy proto for eventual reuse.
/wait
source/common/tcp_proxy/upstream.h
Outdated
@@ -166,6 +166,7 @@ class HttpUpstream : public GenericUpstream, protected Http::StreamCallbacks { | |||
// Http::ResponseDecoder | |||
void decode1xxHeaders(Http::ResponseHeaderMapPtr&&) override {} | |||
void decodeHeaders(Http::ResponseHeaderMapPtr&& headers, bool end_stream) override { | |||
parent_.config_.copyResponseHeaders(*headers, parent_.downstream_info_.filterState()); |
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.
Once we finish this function, don't we largely throw the headers away?
Would it make sense just to move the entire headers in the filter, with a well known name, rather than coping one bit of metadata at a time?
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.
Yeah, I think we could do that with little performance impact. One annoying issue is that we don't have a generic way to traverse the filter state that is a map of string to string. That latter issue has been a long standing blocker for replacing dynamic metadata with filter state so maybe we should just fix that as well.
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.
do we need a map of string to string? we could just create a filter state object "connect_headers" which we std::move the headers into?
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, that's what I want to do. But then, for example, access log printers can only print it as a whole. It's not a problem for internal filter consumption, just generic inspectors like access log, etc.
// Defines the mapping from the header value to a filter state object key. | ||
message HeaderToFilterState { | ||
// Filter state object key, prefixed with ``envoy.tcp_proxy.tunnel_response_header.``. | ||
string key = 1 [(validate.rules).string = {min_len: 1}]; |
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.
If we do with putting in individual headers, is there value in being able to configure the key rather than just sticking header name at the end of the string?
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'll try a complete bag copy, and in that case we can use one key for all of them.
@@ -68,6 +68,16 @@ message TcpProxy { | |||
option (udpa.annotations.versioning).previous_message_type = | |||
"envoy.config.filter.network.tcp_proxy.v2.TcpProxy.TunnelingConfig"; | |||
|
|||
// Defines the mapping from the header value to a filter state object key. | |||
message HeaderToFilterState { |
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.
probably want a release note for this one once we've settled on API
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.
Done
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.
/wait
|
||
// Emit response headers to the downstream info filter state for consumption | ||
// by the network filters. The filter state key is ``envoy.tcp_proxy.tunnel_response_headers``. | ||
bool emit_response_headers = 4; |
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'd lean towards something akin to
save_connect_headers but I'll defer to api shephards on this one :-)
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.
@markdroth For API review and deciding on naming.
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.
How about calling this propagate_response_headers
?
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.
Renamed.
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 (though I still don't love emit - @markdroth ?)
Passing to Greg for !google pass
Signed-off-by: Kuat Yessenov <kuat@google.com>
/lgtm api |
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.
Yeah I like this better - thanks for your patience with naming
CI looks unhappy?
/wait
@@ -99,6 +99,10 @@ message TcpProxy { | |||
// Neither ``:-prefixed`` pseudo-headers nor the Host: header can be overridden. | |||
repeated config.core.v3.HeaderValueOption headers_to_add = 3 | |||
[(validate.rules).repeated = {max_items: 1000}]; | |||
|
|||
// Save the response headers to the downstream info filter state for consumption | |||
// by the network filters. The filter state key is ``envoy.tcp_proxy.tunnel_response_headers``. |
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 make the key propagate as well?
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.
Done.
changelogs/current.yaml
Outdated
@@ -223,6 +223,11 @@ new_features: | |||
- area: redis | |||
change: | | |||
added support for quit command to the redis proxy. | |||
- area: tcp_proxy | |||
change: | | |||
added support for emitting the response headers in :ref:`TunnelingConfig |
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.
emitting -> propagating ?
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.
Done.
/lgtm api |
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.
over to @ggreenway !
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.
Please add a test validating that headers are not propagated when the new setting is disabled.
/wait
|
||
// Save the response headers to the downstream info filter state for consumption | ||
// by the network filters. The filter state key is ``envoy.tcp_proxy.propagate_response_headers``. | ||
bool propagate_response_headers = 4; |
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 not do this unconditionally? Performance?
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, for long-living streams, we're adding extra memory per stream since the filter state lives till connection closes.
Signed-off-by: Kuat Yessenov <kuat@google.com>
Signed-off-by: Kuat Yessenov kuat@google.com
Commit Message: Add support to save response headers from CONNECT tunnels in
tcp_proxy
. Fixes #23116Additional Description: The use case is saving "baggage" header which provides additional metadata about the upstream endpoint for telemetry purposes.
Risk Level: low (opt-in)
Testing: unit, integration
Docs Changes: none
Release Notes: yes