-
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
http: forwarding x-forwarded-proto from trusted proxies #7995
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,6 +85,9 @@ Network::Address::InstanceConstSharedPtr ConnectionManagerUtility::mutateRequest | |
Network::Address::InstanceConstSharedPtr final_remote_address; | ||
bool single_xff_address; | ||
const uint32_t xff_num_trusted_hops = config.xffNumTrustedHops(); | ||
bool trusted_forwarded_proto = | ||
Runtime::runtimeFeatureEnabled("envoy.reloadable_features.trusted_forwarded_proto"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not make this true by default? I guess do we have a documented procedure of the sequence for these type of features? false by default -> true by default -> remove old code path? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, generally false -> true -> remove, but for bugfixes and low risk code I think it's fine to set true by default so done. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not related to this PR, but do your scripts track this somehow? I think this is all awesome, I just want to make sure that we don't forget about the sequence of things we need to do upon each release? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, the scripts grep through the whole code base and add any flags which aren't already defaulted true. |
||
|
||
if (config.useRemoteAddress()) { | ||
single_xff_address = request_headers.ForwardedFor() == nullptr; | ||
// If there are any trusted proxies in front of this Envoy instance (as indicated by | ||
|
@@ -107,8 +110,17 @@ Network::Address::InstanceConstSharedPtr ConnectionManagerUtility::mutateRequest | |
Utility::appendXff(request_headers, *connection.remoteAddress()); | ||
} | ||
} | ||
request_headers.insertForwardedProto().value().setReference( | ||
connection.ssl() ? Headers::get().SchemeValues.Https : Headers::get().SchemeValues.Http); | ||
if (trusted_forwarded_proto) { | ||
mattklein123 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Set x-forwarded-proto unless it already exists and was forwarded on by a trusted proxy. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can you rephrase this comment to read more in line with the logic that follows (i.e. or vs. and, etc.). Normally I wouldn't be picky like this but this code is so hard to understand as it is that any comments hopefully should follow pretty closely. (I'm having a bit of a hard time groking what is happening here.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Also note that I could just overwrite if num_trusted_hops is 0 and allow the logic at :139 to set proto if absent if you prefer that. I felt it was more clear to have it in one place than fall through, but that may just be me :-) |
||
if (xff_num_trusted_hops == 0 || request_headers.ForwardedProto() == nullptr) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this respect There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thinking was that But if you think that's fine, then it's fine. I just wanted to make sure you didn't miss this. The code is definitely an improvement over what we have now. Thanks! |
||
request_headers.insertForwardedProto().value().setReference( | ||
connection.ssl() ? Headers::get().SchemeValues.Https | ||
: Headers::get().SchemeValues.Http); | ||
} | ||
} else { | ||
request_headers.insertForwardedProto().value().setReference( | ||
connection.ssl() ? Headers::get().SchemeValues.Https : Headers::get().SchemeValues.Http); | ||
} | ||
} else { | ||
// If we are not using remote address, attempt to pull a valid IPv4 or IPv6 address out of XFF. | ||
// If we find one, it will be used as the downstream address for logging. It may or may not be | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// A simple test utility to easily allow for runtime feature overloads in unit tests. | ||
// | ||
// As long as this class is in scope one can do runtime feature overrides: | ||
// | ||
// TestScopedRuntime scoped_runtime; | ||
// Runtime::LoaderSingleton::getExisting()->mergeValues( | ||
// {{"envoy.reloadable_features.test_feature_true", "false"}}); | ||
|
||
#pragma once | ||
|
||
#include "common/runtime/runtime_impl.h" | ||
#include "common/stats/isolated_store_impl.h" | ||
|
||
#include "test/mocks/event/mocks.h" | ||
#include "test/mocks/init/mocks.h" | ||
#include "test/mocks/local_info/mocks.h" | ||
#include "test/mocks/protobuf/mocks.h" | ||
#include "test/mocks/runtime/mocks.h" | ||
#include "test/mocks/thread_local/mocks.h" | ||
|
||
#include "gmock/gmock.h" | ||
|
||
namespace Envoy { | ||
|
||
// TODO(alyssawilk) move existing runtime tests over to using this. | ||
class TestScopedRuntime { | ||
public: | ||
TestScopedRuntime() : api_(Api::createApiForTest()) { | ||
envoy::config::bootstrap::v2::LayeredRuntime config; | ||
config.add_layers()->mutable_admin_layer(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a small comment that this is required for mergeValues() to work? This wasn't immediately clear to me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I meant to add a comment above this line along the lines of "the existence of an admin layer is required for mergeValues() to work" |
||
|
||
loader_ = std::make_unique<Runtime::ScopedLoaderSingleton>(Runtime::LoaderPtr{ | ||
new Runtime::LoaderImpl(dispatcher_, tls_, config, local_info_, init_manager_, store_, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: make_unique |
||
generator_, validation_visitor_, *api_)}); | ||
} | ||
|
||
private: | ||
Event::MockDispatcher dispatcher_; | ||
testing::NiceMock<ThreadLocal::MockInstance> tls_; | ||
Stats::IsolatedStoreImpl store_; | ||
Runtime::MockRandomGenerator generator_; | ||
Api::ApiPtr api_; | ||
testing::NiceMock<LocalInfo::MockLocalInfo> local_info_; | ||
Init::MockManager init_manager_; | ||
testing::NiceMock<ProtobufMessage::MockValidationVisitor> validation_visitor_; | ||
std::unique_ptr<Runtime::ScopedLoaderSingleton> loader_; | ||
}; | ||
|
||
} // namespace 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.
nit: const