Skip to content
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: fix ssl_redirect on external #8664

Merged
merged 4 commits into from
Oct 23, 2019
Merged

http: fix ssl_redirect on external #8664

merged 4 commits into from
Oct 23, 2019

Conversation

lambdai
Copy link
Contributor

@lambdai lambdai commented Oct 18, 2019

Description: ssl_redirect on external only is not doing as declared
The reason is that it doesn't determines whether the request is internal in the common approach.
Expect: check the header exists and the value is "true" as everywhere else in the code base.

Risk Level: HIGH, maybe. Since require_tls: EXTERNAL_ONLY user may see different(but correct!) behavior.

Testing:
Docs Changes:
Signed-off-by: Yuchen Dai silentdai@gmail.com

Signed-off-by: Yuchen Dai <silentdai@gmail.com>
@@ -1003,7 +1003,8 @@ RouteConstSharedPtr VirtualHostImpl::getRouteFromEntries(const Http::HeaderMap&
if (ssl_requirements_ == SslRequirements::ALL && forwarded_proto_header->value() != "https") {
return SSL_REDIRECT_ROUTE;
} else if (ssl_requirements_ == SslRequirements::EXTERNAL_ONLY &&
forwarded_proto_header->value() != "https" && !headers.EnvoyInternalRequest()) {
forwarded_proto_header->value() != "https" &&
not Http::HeaderUtility::isEnvoyInternalRequest(headers)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the core fix

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Nit: please use standard predicate syntax ! instead of this new-fangled one that is pretty confusing to most C/C++ folks.

Signed-off-by: Yuchen Dai <silentdai@gmail.com>
@lambdai
Copy link
Contributor Author

lambdai commented Oct 18, 2019

/assign @htuch

@lambdai
Copy link
Contributor Author

lambdai commented Oct 22, 2019

ping @htuch
This is an easy one. The core change is one line as I popped in the comment. Thanks!

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks like the right fix. Can you add a regression test and then we can ship?
/wait

@@ -128,7 +129,7 @@ class ConnectionManagerUtilityTest : public testing::Test {
random_, local_info_)
->asString();
ConnectionManagerUtility::mutateTracingRequestHeader(headers, runtime_, config_, &route_);
ret.internal_ = headers.EnvoyInternalRequest() != nullptr;
ret.internal_ = HeaderUtility::isEnvoyInternalRequest(headers);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test that covers the actual regression being fixed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not. This is test.cc. I guess we don't need another test for test.cc :)
Here is the no brain fix.

I add a test case in router/config_impl_test.cc to cover the core change.

@@ -1003,7 +1003,8 @@ RouteConstSharedPtr VirtualHostImpl::getRouteFromEntries(const Http::HeaderMap&
if (ssl_requirements_ == SslRequirements::ALL && forwarded_proto_header->value() != "https") {
return SSL_REDIRECT_ROUTE;
} else if (ssl_requirements_ == SslRequirements::EXTERNAL_ONLY &&
forwarded_proto_header->value() != "https" && !headers.EnvoyInternalRequest()) {
forwarded_proto_header->value() != "https" &&
not Http::HeaderUtility::isEnvoyInternalRequest(headers)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Nit: please use standard predicate syntax ! instead of this new-fangled one that is pretty confusing to most C/C++ folks.

@lambdai
Copy link
Contributor Author

lambdai commented Oct 22, 2019

Thanks! Will add integration test and fix the nits

Signed-off-by: Yuchen Dai <silentdai@gmail.com>
Copy link
Contributor Author

@lambdai lambdai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the test case to cover the product code change.

@@ -128,7 +129,7 @@ class ConnectionManagerUtilityTest : public testing::Test {
random_, local_info_)
->asString();
ConnectionManagerUtility::mutateTracingRequestHeader(headers, runtime_, config_, &route_);
ret.internal_ = headers.EnvoyInternalRequest() != nullptr;
ret.internal_ = HeaderUtility::isEnvoyInternalRequest(headers);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not. This is test.cc. I guess we don't need another test for test.cc :)
Here is the no brain fix.

I add a test case in router/config_impl_test.cc to cover the core change.

@@ -3639,6 +3645,12 @@ name: foo
EXPECT_EQ("https://api.lyft.com/foo",
config.route(headers, 0)->directResponseEntry()->newPath(headers));
}
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case to cover the core 1 line change

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks!

@htuch htuch merged commit 19f7871 into envoyproxy:master Oct 23, 2019
@lambdai lambdai deleted the iheader branch October 23, 2019 16:41
@mattklein123
Copy link
Member

@lambdai thanks this is a nice cleanup. I just want to clarify for my own understanding though that I don't think there was any actual bug here? The internal header was always sanitized and the only value it was ever filled with was true, so I don't think there should be any actual user behavior change here unless some trusted intermediary was actually changing the value to something else, correct?

spenceral added a commit to spenceral/envoy that referenced this pull request Oct 23, 2019
* master: (54 commits)
  Update dependencies - Go, Bazel toos, xxHash, nanopb, rules_go, curl, protobuf, Jinja, yaml-cpp, re2 (envoyproxy#8728)
  test: increase coverage of listener_manager_impl.cc (envoyproxy#8737)
  test: modify some macros to reduce number of uncovered lines reported (envoyproxy#8725)
  build: add a script to setup clang (envoyproxy#8682)
  http: fix ssl_redirect on external (envoyproxy#8664)
  docs: update fedora build requirements (envoyproxy#8641)
  fix draining listener removal logs (envoyproxy#8733)
  dubbo: fix router doc (envoyproxy#8734)
  server: provide server health status when stats disabled (envoyproxy#8482)
  router: adding a knob to configure a cap on buffering for shadowing/retries (envoyproxy#8574)
  tcp proxy: add default 1 hour idle timeout (envoyproxy#8705)
  thrift: fix filter names in docs (envoyproxy#8726)
  Quiche changes to avoid gcc flags on Windows (envoyproxy#8514)
  test: increase test coverage in Router::HeaderParser (envoyproxy#8721)
  admin: add drain listeners endpoint  (envoyproxy#8415)
  buffer filter: add content-length when ending stream with trailers (envoyproxy#8609)
  clarify draining option docs (envoyproxy#8712)
  build: ignore go-control-plane mirror git commit error code (envoyproxy#8703)
  api: remove API type database from checked in artifacts. (envoyproxy#8716)
  admin: correct help strings (envoyproxy#8710)
  ...

Signed-off-by: Spencer Lewis <slewis@squareup.com>
derekargueta pushed a commit to derekargueta/envoy that referenced this pull request Oct 24, 2019
ssl_redirect on external only is not doing as declared
The reason is that it doesn't determines whether the request is internal in the common approach.
Expect: check the header exists and the value is "true" as everywhere else in the code base.

Risk Level: HIGH, maybe. Since require_tls: EXTERNAL_ONLY user may see different(but correct!) behavior.
Testing: Unit test added.

Signed-off-by: Yuchen Dai <silentdai@gmail.com>
@lambdai
Copy link
Contributor Author

lambdai commented Oct 24, 2019

@mattklein123 Thanks!

The internal header was always sanitized and the only value it was ever filled with was true, so I don't think there should be any actual user behavior change here unless some trusted intermediary was actually changing the value to something else, correct?

That's a good point. No other components should set "X-envoy-internal" to false. We should assume the assert since require_tls: EXTERNAL_ONLY should be applied only behind trusted LB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants