-
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
ip-tagging filter: add support for an optional ip-tag-header field #36434
ip-tagging filter: add support for an optional ip-tag-header field #36434
Conversation
Signed-off-by: Radha Kumari <[email protected]>
Signed-off-by: Radha Kumari <[email protected]>
Signed-off-by: Radha Kumari <[email protected]>
Signed-off-by: Radha Kumari <[email protected]>
Signed-off-by: Radha Kumari <[email protected]>
Signed-off-by: Radha Kumari <[email protected]>
rest Signed-off-by: Radha Kumari <[email protected]>
Signed-off-by: Radha Kumari <[email protected]>
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!
Overall LGTM, left a few minor comments.
Please also add a release note as this is a user-facing change.
api/envoy/extensions/filters/http/ip_tagging/v3/ip_tagging.proto
Outdated
Show resolved
Hide resolved
@@ -71,6 +73,7 @@ class IpTaggingFilterConfig { | |||
const Stats::StatName total_; | |||
const Stats::StatName unknown_tag_; | |||
std::unique_ptr<Network::LcTrie::LcTrie<std::string>> trie_; | |||
const Http::LowerCaseString header_; |
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.
nit: rename to alt_header_
or something ip_tag_header_
to make it more readable.
test/extensions/filters/http/ip_tagging/ip_tagging_filter_test.cc
Outdated
Show resolved
Hide resolved
@@ -39,6 +39,8 @@ class IpTaggingFilterConfig { | |||
FilterRequestType requestType() const { return request_type_; } | |||
const Network::LcTrie::LcTrie<std::string>& trie() const { return *trie_; } | |||
|
|||
const Http::LowerCaseString& ip_tag_header() const { return header_; } |
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 comment here, stating that empty string implies that no ip_tag_header
is set.
I do wonder if it just makes more sense to return the correct ip_tag_header
here (either the default or the alternative). On the one hand I think it may make the code a bit more readable, but then the calls to the headers.append will need to be a bit different.
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 added the conditional in decodeHeaders
as first, it was easier and second the decision on which header to use is made when we are appending the tags but I'm open to returning the correct header from ip_tag_header()
. I will have to see how involved that change is but let me know if that's what you prefer.
Co-authored-by: Adi (Suissa) Peleg <[email protected]> Signed-off-by: Radha <[email protected]>
Signed-off-by: Radha Kumari <[email protected]>
Almost forgot, don't really know how to add release notes but will check the docs 🙇🏽♀️ |
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!
A release note should be added here: https://github.com/envoyproxy/envoy/blob/main/changelogs/current.yaml
Assigning @alyssawilk for code-owner review
/assign @alyssawilk
api/envoy/extensions/filters/http/ip_tagging/v3/ip_tagging.proto
Outdated
Show resolved
Hide resolved
Co-authored-by: Adi (Suissa) Peleg <[email protected]> Signed-off-by: Radha <[email protected]>
weird, that assign didn't work. |
Signed-off-by: Radha Kumari <[email protected]>
ci fails
|
Signed-off-by: Radha Kumari <[email protected]>
i'll review after ci is happy but this looks like a replacement of #35628 |
headers.appendEnvoyIpTags(tags_join, ","); | ||
|
||
// Use the optional header instead of x-envoy-ip-tags if it's not empty. | ||
if (!config_->ip_tag_header().get().empty()) { |
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 think we need to sanitize this header so others can not spoof it. When you configure ip_tag_header as x-foo-tags, and the requests come in with x-foo-tags header, if the requests does not get any tag from envoy ip tagging filter, they still have x-foo-tags header and the value can be anything.
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.
at least we want to default to sanitize otherwise we need to set security level to untrusted downstream. I didn't check metadata tho.
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.
@JuniorHsu @cqi1217 I think @nahratzah meant to post #36434 (comment) here. let me know what you folks think about this.
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.
@alyssawilk we hit a dilemma here.
currently ip_tagging is robust to untrusted downstream
security_posture: robust_to_untrusted_downstream |
however my understanding is non x-
prefixed header won't be sanitized by envoy, which is vulnerable, so appending header could downgrade the security_posture.
However, @nahratzah mention the asymmetric behavior in #36434 (comment)
What do you think?
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.
it'd help if I had clarity around why the user wants a custom header. was it to bypass the x-envoy checks? If it's just "we want a custom header" we could require an x-envoy prefix. If they want a non-x-envoy header I agree this would be changing the security model and either that needs to be fixed, or (if intentioanl) needs a lot more documentation
@JuniorHsu Apologies but the CI failures looks to be Java exceptions and looks unrelated to the change unless I'm mistaken.
Also, wasn't really aware of #35628 before you mentioned. Looks like it was closed due to inactivity. Let me make the change to docs. |
Please try to merge latest main. There's ongoing work migrating the CI infra in the last couple of weeks. |
Test failure appears unrelated, and to be due to a connection-timed-out while downloading `kafka_server_binary`.
|
OptRef<const Http::LowerCaseString> header_name = config_->ip_tag_header(); | ||
|
||
if (tags.empty()) { | ||
bool mustSanitize = |
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 isn't really mustSanitize given we'll only do it if there's a header name configured. Also snake case for Envoy variables
maybe_sanitize?
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 wish there was a linter for this.) <3
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.
Looks good - just a few more nits and you're good to go
/wait
@@ -39,6 +42,14 @@ class IpTaggingFilterConfig { | |||
FilterRequestType requestType() const { return request_type_; } | |||
const Network::LcTrie::LcTrie<std::string>& trie() const { return *trie_; } | |||
|
|||
OptRef<const Http::LowerCaseString> ip_tag_header() const { |
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.
and for functions ipTagHeader and ipTagHeaderAction
// (DEFAULT) The header specified in :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>` | ||
// will be dropped, before the tags are applied. Sanitize will be run regardless of if the source is a trusted IP or not. | ||
// | ||
// Note that the header will be visible unsanitized to any filters downstream of the ip-tag-header filter. |
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.
oh, mind adding
unless it has an x-envoy prefix
initializeFilter(internal_request_yaml); | ||
|
||
Http::TestRequestHeaderMapImpl request_headers{ | ||
{"x-envoy-internal", "true"}, {"x-envoy-optional-header", "foo"}}; // foo will be removed |
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.
mind adding multiple just so we regression test that rmove does remove all?
Signed-off-by: Ariane van der Steldt <[email protected]>
Signed-off-by: Ariane van der Steldt <[email protected]>
Signed-off-by: Ariane van der Steldt <[email protected]>
Signed-off-by: Ariane van der Steldt <[email protected]>
Updated the PR. <3 |
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.
wohoo!
@adisuissa any final shepherd comments? |
// Control if the header in :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>` | ||
// will be sanitized, or be appended to. | ||
// | ||
// This is ignored if :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>` is empty. |
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.
As this field is closely related to the ip_tag_header
field, it will be better to have them both under the same message type, and make the ip_tag_header
field in that message type required (and probably move the HeaderAction
to that inner message as well).
// Describes how to apply the tags to the headers. | ||
enum HeaderAction { | ||
// (DEFAULT) The header specified in :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>` | ||
// will be dropped, before the tags are applied. Sanitize will be run regardless of if the source is a trusted IP or not. |
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.
// will be dropped, before the tags are applied. Sanitize will be run regardless of if the source is a trusted IP or not. | |
// will be dropped, before the tags are applied. The incoming header will be "sanitized" regardless of whether the request is an internal or external. |
I'm trying to stick to the same terminology introduced in https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/header_sanitizing. I'm assuming that is the goal, and if so, I suggest trying to stick with the same terms.
// (DEFAULT) The header specified in :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>` | ||
// will be dropped, before the tags are applied. Sanitize will be run regardless of if the source is a trusted IP or not. | ||
// | ||
// Note that the header will be visible unsanitized to any filters downstream of the ip-tag-header filter, unless it has an *x-envoy* prefix. |
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 word "downstream" may be ambiguous here.
I'm assuming it implies the filters that are invoked after this filter, but I'm not sure. Can you clarify it (probably by not using the word "downstream")?
// :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>`, | ||
// leaving original values in place. |
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.
// :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>`, | |
// leaving original values in place. | |
// :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>`. |
// :ref:`ip_tag_header <envoy_v3_api_field_extensions.filters.http.ip_tagging.v3.IPTagging.ip_tag_header>`, | ||
// leaving original values in place. | ||
// | ||
// Please note that this could cause the header to retain values set by the http client even if the client is from an untrusted IP. |
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.
RE "untrusted IP", see comment above regarding the terms.
// leaving original values in place. | ||
// | ||
// Please note that this could cause the header to retain values set by the http client even if the client is from an untrusted IP. | ||
APPEND_FORWARD = 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.
What does "FORWARD" imply?
I'm assuming the goal is to have something similar to APPEND_IF_EXISTS_OR_ADD. Will it make sense to either use the same enum (probably not as the one suggested adds sanitization), or use the same enum name?
Signed-off-by: Ariane van der Steldt <[email protected]>
Signed-off-by: Ariane van der Steldt <[email protected]>
Signed-off-by: Ariane van der Steldt <[email protected]>
Signed-off-by: Ariane van der Steldt <[email protected]>
…hat we want. Signed-off-by: Ariane van der Steldt <[email protected]>
Signed-off-by: Ariane van der Steldt <[email protected]>
Signed-off-by: Ariane van der Steldt <[email protected]>
I applied the changes. <3 |
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
Signed-off-by: Ariane van der Steldt <[email protected]>
Description
This change adds support for specifying an optional header to ip-tagging filter instead of the default header that it uses (
x-envoy-ip-tags
).example
Why
Currently, the ip-tagging filter always writes its output into the
x-envoy-ip-tags
header. When this filter is used for more than one purpose in the same filter chain which we do at Slack in our production environment, we do need to take care of cleaning up the header in between which has been proven a bit tricky sometimes. Leaking the values in between the filter chain is bad so we try to avoid that.We would like this to be configurable. This way we can use the optional header instead of trying the use the same header however many times the same filter is used on the same filter chain in a listener.
Risk Level
this is a new feature, doesn't affect the existing functionality so guessing low but open to changing if I'm wrong.
Testing
added test
Docs Changes: Added, alongside release notes
Co-authored-by: Ariane van der Steldt [email protected]
Signed-off-by: Radha Kumari [email protected]